* [PATCH-v3] SELinux: introduce permissive types
@ 2008-03-10 22:35 Eric Paris
2008-03-11 15:18 ` Stephen Smalley
0 siblings, 1 reply; 5+ messages in thread
From: Eric Paris @ 2008-03-10 22:35 UTC (permalink / raw)
To: selinux; +Cc: sds, jmorris, Paul Moore
Introduce the concept of a permissive type. A new ebitmap is introduced
to the policy database which indicates if a given type has the
permissive bit set or not. This bit is tested for the scontext of any
denial. The bit is meaningless on types which only appear as the target
of a decision and never the source. A domain running with a permissive
type will be allowed to perform any action similarly to when the system
is globally set permissive.
Signed-off-by: Eric Paris <eparis@redhat.com>
---
- Threw out all of the atomic stuff. Either the sid is going to get
mapped to unlabeled or to the right context in the new policydb and will
be the new type number and all will be well. As usual I was just making
things harder on myself.
- moved !requested into its own handling
- dropped unlikely() around the permissive sid, because really, if we
get a denial and we are selinux_enforcing its actually not all that
unlikely that we might not have a permissive domain. Just let the
compiler do its thing.
- dropped the test for the existence of node. avc_update_node might
return -ENOENT, but really who cares? We are on a slow code path here
so it seems to be needless complexity. Isn't this code nice and clear
now? I can add it in, but its just a slight perf win and not much
else..
security/selinux/Kconfig | 2 +-
security/selinux/avc.c | 18 +++++++++++++-----
security/selinux/include/security.h | 5 ++++-
security/selinux/ss/policydb.c | 11 +++++++++++
security/selinux/ss/policydb.h | 2 ++
security/selinux/ss/services.c | 21 +++++++++++++++++++++
6 files changed, 52 insertions(+), 7 deletions(-)
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index 2b517d6..a436d1c 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
int "NSA SELinux maximum supported policy format version value"
depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
- range 15 22
+ range 15 23
default 19
help
This option sets the value for the maximum policy format version
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 187964e..8d78b88 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -890,13 +890,21 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
denied = requested & ~(p_ae->avd.allowed);
- if (!requested || denied) {
- if (selinux_enforcing || (flags & AVC_STRICT))
+ if (unlikely(!requested)) {
+ printk(KERN_ERR "%s: found !requested, fix me\n", __func__);
+ WARN_ON(1);
+ if (selinux_enforcing)
rc = -EACCES;
+ }
+
+ if (denied) {
+ if (flags & AVC_STRICT)
+ rc = -EACCES;
+ else if (!selinux_enforcing || security_permissive_sid(ssid))
+ avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
+ tsid, tclass);
else
- if (node)
- avc_update_node(AVC_CALLBACK_GRANT,requested,
- ssid,tsid,tclass);
+ rc = -EACCES;
}
rcu_read_unlock();
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index f7d2f03..fde8690 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -26,13 +26,14 @@
#define POLICYDB_VERSION_AVTAB 20
#define POLICYDB_VERSION_RANGETRANS 21
#define POLICYDB_VERSION_POLCAP 22
+#define POLICYDB_VERSION_PERMISSIVE 23
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
#endif
#define CONTEXT_MNT 0x01
@@ -67,6 +68,8 @@ struct av_decision {
u32 seqno;
};
+int security_permissive_sid(u32 sid);
+
int security_compute_av(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index bd7d6a0..84dbab9 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = {
.version = POLICYDB_VERSION_POLCAP,
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
+ },
+ {
+ .version = POLICYDB_VERSION_PERMISSIVE,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NUM,
}
};
@@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p)
goto out_free_symtab;
ebitmap_init(&p->policycaps);
+ ebitmap_init(&p->permissive_map);
out:
return rc;
@@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
kfree(p->type_attr_map);
kfree(p->undefined_perms);
ebitmap_destroy(&p->policycaps);
+ ebitmap_destroy(&p->permissive_map);
return;
}
@@ -1570,6 +1577,10 @@ int policydb_read(struct policydb *p, void *fp)
ebitmap_read(&p->policycaps, fp) != 0)
goto bad;
+ if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
+ ebitmap_read(&p->permissive_map, fp) != 0)
+ goto bad;
+
info = policydb_lookup_compat(p->policyvers);
if (!info) {
printk(KERN_ERR "security: unable to find policy compat info "
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index c4ce996..ba593a3 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -243,6 +243,8 @@ struct policydb {
struct ebitmap policycaps;
+ struct ebitmap permissive_map;
+
unsigned int policyvers;
unsigned int reject_unknown : 1;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index f374186..f5d1dcc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -416,6 +416,27 @@ inval_class:
return -EINVAL;
}
+/*
+ * Given a sid find if the type has the permissive flag set
+ */
+int security_permissive_sid(u32 sid)
+{
+ struct context *context;
+ u32 type;
+ int rc;
+
+ POLICY_RDLOCK;
+
+ context = sidtab_search(&sidtab, sid);
+ BUG_ON(!context);
+
+ type = context->type;
+ rc = ebitmap_get_bit(&policydb.permissive_map, type);
+
+ POLICY_RDUNLOCK;
+ return rc;
+}
+
static int security_validtrans_handle_fail(struct context *ocontext,
struct context *ncontext,
struct context *tcontext,
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH-v3] SELinux: introduce permissive types
2008-03-10 22:35 [PATCH-v3] SELinux: introduce permissive types Eric Paris
@ 2008-03-11 15:18 ` Stephen Smalley
2008-03-11 17:08 ` Semanage return codes Hasan Rezaul-CHR010
2008-03-12 2:30 ` [PATCH-v3] SELinux: introduce permissive types Daniel J Walsh
0 siblings, 2 replies; 5+ messages in thread
From: Stephen Smalley @ 2008-03-11 15:18 UTC (permalink / raw)
To: Eric Paris; +Cc: selinux, jmorris, Paul Moore
On Mon, 2008-03-10 at 18:35 -0400, Eric Paris wrote:
> Introduce the concept of a permissive type. A new ebitmap is introduced
> to the policy database which indicates if a given type has the
> permissive bit set or not. This bit is tested for the scontext of any
> denial. The bit is meaningless on types which only appear as the target
> of a decision and never the source. A domain running with a permissive
> type will be allowed to perform any action similarly to when the system
> is globally set permissive.
>
> Signed-off-by: Eric Paris <eparis@redhat.com>
>
> ---
>
> - Threw out all of the atomic stuff. Either the sid is going to get
> mapped to unlabeled or to the right context in the new policydb and will
> be the new type number and all will be well. As usual I was just making
> things harder on myself.
Technically, the following could still happen:
- policy has domain marked as permissive and does not allow an access,
- the AVC determines that the access is denied and is following the
permissive code path but has not yet taken the policy rdlock,
- policy is reloaded with domain marked as non-permissive with access
allowed,
- security_permissive_sid is called and takes the policy rdlock,
- the domain is found to be non-permissive,
- the AVC denies the access.
Particularly if we do something like:
- insert policy module that just makes a domain permissive,
- run for a while collecting audit messages,
- generate new policy module from audit messages,
- replace the permissive policy module with the one that contains the
allows.
Don't know if you are concerned about the above, but it could create
mysterious breakage.
> - moved !requested into its own handling
Separate patch, put it first, and I think BUG_ON is cleaner there.
> - dropped unlikely() around the permissive sid, because really, if we
> get a denial and we are selinux_enforcing its actually not all that
> unlikely that we might not have a permissive domain. Just let the
> compiler do its thing.
Ok.
> - dropped the test for the existence of node. avc_update_node might
> return -ENOENT, but really who cares? We are on a slow code path here
> so it seems to be needless complexity. Isn't this code nice and clear
> now? I can add it in, but its just a slight perf win and not much
> else..
Seems fine - we will rarely not have a node (requires that there not
already be a node for the key, and that the allocation of a new node
fail), and it is harmless to proceed.
>
> security/selinux/Kconfig | 2 +-
> security/selinux/avc.c | 18 +++++++++++++-----
> security/selinux/include/security.h | 5 ++++-
> security/selinux/ss/policydb.c | 11 +++++++++++
> security/selinux/ss/policydb.h | 2 ++
> security/selinux/ss/services.c | 21 +++++++++++++++++++++
> 6 files changed, 52 insertions(+), 7 deletions(-)
>
> diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
> index 2b517d6..a436d1c 100644
> --- a/security/selinux/Kconfig
> +++ b/security/selinux/Kconfig
> @@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
> config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
> int "NSA SELinux maximum supported policy format version value"
> depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
> - range 15 22
> + range 15 23
> default 19
> help
> This option sets the value for the maximum policy format version
> diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> index 187964e..8d78b88 100644
> --- a/security/selinux/avc.c
> +++ b/security/selinux/avc.c
> @@ -890,13 +890,21 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
>
> denied = requested & ~(p_ae->avd.allowed);
>
> - if (!requested || denied) {
> - if (selinux_enforcing || (flags & AVC_STRICT))
> + if (unlikely(!requested)) {
> + printk(KERN_ERR "%s: found !requested, fix me\n", __func__);
Likely want SELinux somewhere in that message for clarity.
> + WARN_ON(1);
> + if (selinux_enforcing)
> rc = -EACCES;
Simpler as a BUG_ON, and correct.
> + }
> +
> + if (denied) {
> + if (flags & AVC_STRICT)
> + rc = -EACCES;
> + else if (!selinux_enforcing || security_permissive_sid(ssid))
> + avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
> + tsid, tclass);
> else
> - if (node)
> - avc_update_node(AVC_CALLBACK_GRANT,requested,
> - ssid,tsid,tclass);
> + rc = -EACCES;
> }
>
> rcu_read_unlock();
> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index f7d2f03..fde8690 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -26,13 +26,14 @@
> #define POLICYDB_VERSION_AVTAB 20
> #define POLICYDB_VERSION_RANGETRANS 21
> #define POLICYDB_VERSION_POLCAP 22
> +#define POLICYDB_VERSION_PERMISSIVE 23
>
> /* Range of policy versions we understand*/
> #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
> #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
> #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
> #else
> -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
> +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
> #endif
>
> #define CONTEXT_MNT 0x01
> @@ -67,6 +68,8 @@ struct av_decision {
> u32 seqno;
> };
>
> +int security_permissive_sid(u32 sid);
> +
> int security_compute_av(u32 ssid, u32 tsid,
> u16 tclass, u32 requested,
> struct av_decision *avd);
> diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
> index bd7d6a0..84dbab9 100644
> --- a/security/selinux/ss/policydb.c
> +++ b/security/selinux/ss/policydb.c
> @@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = {
> .version = POLICYDB_VERSION_POLCAP,
> .sym_num = SYM_NUM,
> .ocon_num = OCON_NUM,
> + },
> + {
> + .version = POLICYDB_VERSION_PERMISSIVE,
> + .sym_num = SYM_NUM,
> + .ocon_num = OCON_NUM,
> }
> };
>
> @@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p)
> goto out_free_symtab;
>
> ebitmap_init(&p->policycaps);
> + ebitmap_init(&p->permissive_map);
>
> out:
> return rc;
> @@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
> kfree(p->type_attr_map);
> kfree(p->undefined_perms);
> ebitmap_destroy(&p->policycaps);
> + ebitmap_destroy(&p->permissive_map);
>
> return;
> }
> @@ -1570,6 +1577,10 @@ int policydb_read(struct policydb *p, void *fp)
> ebitmap_read(&p->policycaps, fp) != 0)
> goto bad;
>
> + if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
> + ebitmap_read(&p->permissive_map, fp) != 0)
> + goto bad;
> +
> info = policydb_lookup_compat(p->policyvers);
> if (!info) {
> printk(KERN_ERR "security: unable to find policy compat info "
> diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
> index c4ce996..ba593a3 100644
> --- a/security/selinux/ss/policydb.h
> +++ b/security/selinux/ss/policydb.h
> @@ -243,6 +243,8 @@ struct policydb {
>
> struct ebitmap policycaps;
>
> + struct ebitmap permissive_map;
> +
> unsigned int policyvers;
>
> unsigned int reject_unknown : 1;
> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
> index f374186..f5d1dcc 100644
> --- a/security/selinux/ss/services.c
> +++ b/security/selinux/ss/services.c
> @@ -416,6 +416,27 @@ inval_class:
> return -EINVAL;
> }
>
> +/*
> + * Given a sid find if the type has the permissive flag set
> + */
> +int security_permissive_sid(u32 sid)
> +{
> + struct context *context;
> + u32 type;
> + int rc;
> +
> + POLICY_RDLOCK;
> +
> + context = sidtab_search(&sidtab, sid);
> + BUG_ON(!context);
> +
> + type = context->type;
> + rc = ebitmap_get_bit(&policydb.permissive_map, type);
Maybe a comment then to note that we are intentionally not using (type -
1) here due to possibly global use of that bit - otherwise it is a
confusing inconsistency with other ebitmap_get_bit calls.
> +
> + POLICY_RDUNLOCK;
> + return rc;
> +}
> +
> static int security_validtrans_handle_fail(struct context *ocontext,
> struct context *ncontext,
> struct context *tcontext,
>
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Semanage return codes...
2008-03-11 15:18 ` Stephen Smalley
@ 2008-03-11 17:08 ` Hasan Rezaul-CHR010
2008-03-11 17:17 ` Stephen Smalley
2008-03-12 2:30 ` [PATCH-v3] SELinux: introduce permissive types Daniel J Walsh
1 sibling, 1 reply; 5+ messages in thread
From: Hasan Rezaul-CHR010 @ 2008-03-11 17:08 UTC (permalink / raw)
To: Stephen Smalley; +Cc: selinux
Hi All,
Have a weird question...
I run the semanage command inside a script to create/delete user
mappings as follows:
-------------------------------------
semanage login -a -s staff_u Admin
ret_code = $?
semanage login -d Admin
ret_code = $?
--------------------------------------
Almost always the return_code is ZERO after the command executes.
However, I have noticed, sometimes the creation or deletion of the user
mapping actually "seems" to succeed, BUT the return_code of the semanage
command is Non-Zero ?!? I cant understand why ? Does this make sense ?
Is there a man page or something out there that shows the various
possible return/error codes of the semanage command(s) ?
Thanks,
- Rezaul.
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: Semanage return codes...
2008-03-11 17:08 ` Semanage return codes Hasan Rezaul-CHR010
@ 2008-03-11 17:17 ` Stephen Smalley
0 siblings, 0 replies; 5+ messages in thread
From: Stephen Smalley @ 2008-03-11 17:17 UTC (permalink / raw)
To: Hasan Rezaul-CHR010; +Cc: selinux
On Tue, 2008-03-11 at 13:08 -0400, Hasan Rezaul-CHR010 wrote:
> Hi All,
>
> Have a weird question...
>
> I run the semanage command inside a script to create/delete user
> mappings as follows:
>
> -------------------------------------
> semanage login -a -s staff_u Admin
> ret_code = $?
>
> semanage login -d Admin
> ret_code = $?
> --------------------------------------
>
> Almost always the return_code is ZERO after the command executes.
>
> However, I have noticed, sometimes the creation or deletion of the user
> mapping actually "seems" to succeed, BUT the return_code of the semanage
> command is Non-Zero ?!? I cant understand why ? Does this make sense ?
>
> Is there a man page or something out there that shows the various
> possible return/error codes of the semanage command(s) ?
What version of policycoreutils?
Should always exit with status 0 (success) or 1 (error).
Can you provide a specific example of when this has happened to you,
including output?
Are you running other processes simultaneously that are operating on the
policy store?
--
Stephen Smalley
National Security Agency
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH-v3] SELinux: introduce permissive types
2008-03-11 15:18 ` Stephen Smalley
2008-03-11 17:08 ` Semanage return codes Hasan Rezaul-CHR010
@ 2008-03-12 2:30 ` Daniel J Walsh
1 sibling, 0 replies; 5+ messages in thread
From: Daniel J Walsh @ 2008-03-12 2:30 UTC (permalink / raw)
To: Stephen Smalley; +Cc: Eric Paris, selinux, jmorris, Paul Moore
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Stephen Smalley wrote:
> On Mon, 2008-03-10 at 18:35 -0400, Eric Paris wrote:
>> Introduce the concept of a permissive type. A new ebitmap is introduced
>> to the policy database which indicates if a given type has the
>> permissive bit set or not. This bit is tested for the scontext of any
>> denial. The bit is meaningless on types which only appear as the target
>> of a decision and never the source. A domain running with a permissive
>> type will be allowed to perform any action similarly to when the system
>> is globally set permissive.
>>
>> Signed-off-by: Eric Paris <eparis@redhat.com>
>>
>> ---
>>
>> - Threw out all of the atomic stuff. Either the sid is going to get
>> mapped to unlabeled or to the right context in the new policydb and will
>> be the new type number and all will be well. As usual I was just making
>> things harder on myself.
>
> Technically, the following could still happen:
> - policy has domain marked as permissive and does not allow an access,
> - the AVC determines that the access is denied and is following the
> permissive code path but has not yet taken the policy rdlock,
> - policy is reloaded with domain marked as non-permissive with access
> allowed,
> - security_permissive_sid is called and takes the policy rdlock,
> - the domain is found to be non-permissive,
> - the AVC denies the access.
>
> Particularly if we do something like:
> - insert policy module that just makes a domain permissive,
> - run for a while collecting audit messages,
> - generate new policy module from audit messages,
> - replace the permissive policy module with the one that contains the
> allows.
>
> Don't know if you are concerned about the above, but it could create
> mysterious breakage.
I think this is highly unlikely. I believe the standard way to use
permissive domains, would be to ship a policy. Once you have gone a
considerable amount of time without any AVC messages, you would reload
the policy with the permissive domain removed. So I don't think this
race is likely to happen unless forced.
>
>> - moved !requested into its own handling
>
> Separate patch, put it first, and I think BUG_ON is cleaner there.
>
>> - dropped unlikely() around the permissive sid, because really, if we
>> get a denial and we are selinux_enforcing its actually not all that
>> unlikely that we might not have a permissive domain. Just let the
>> compiler do its thing.
>
> Ok.
>
>> - dropped the test for the existence of node. avc_update_node might
>> return -ENOENT, but really who cares? We are on a slow code path here
>> so it seems to be needless complexity. Isn't this code nice and clear
>> now? I can add it in, but its just a slight perf win and not much
>> else..
>
> Seems fine - we will rarely not have a node (requires that there not
> already be a node for the key, and that the allocation of a new node
> fail), and it is harmless to proceed.
>> security/selinux/Kconfig | 2 +-
>> security/selinux/avc.c | 18 +++++++++++++-----
>> security/selinux/include/security.h | 5 ++++-
>> security/selinux/ss/policydb.c | 11 +++++++++++
>> security/selinux/ss/policydb.h | 2 ++
>> security/selinux/ss/services.c | 21 +++++++++++++++++++++
>> 6 files changed, 52 insertions(+), 7 deletions(-)
>>
>> diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
>> index 2b517d6..a436d1c 100644
>> --- a/security/selinux/Kconfig
>> +++ b/security/selinux/Kconfig
>> @@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX
>> config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
>> int "NSA SELinux maximum supported policy format version value"
>> depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX
>> - range 15 22
>> + range 15 23
>> default 19
>> help
>> This option sets the value for the maximum policy format version
>> diff --git a/security/selinux/avc.c b/security/selinux/avc.c
>> index 187964e..8d78b88 100644
>> --- a/security/selinux/avc.c
>> +++ b/security/selinux/avc.c
>> @@ -890,13 +890,21 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
>>
>> denied = requested & ~(p_ae->avd.allowed);
>>
>> - if (!requested || denied) {
>> - if (selinux_enforcing || (flags & AVC_STRICT))
>> + if (unlikely(!requested)) {
>> + printk(KERN_ERR "%s: found !requested, fix me\n", __func__);
>
> Likely want SELinux somewhere in that message for clarity.
>
>> + WARN_ON(1);
>> + if (selinux_enforcing)
>> rc = -EACCES;
>
> Simpler as a BUG_ON, and correct.
>
>> + }
>> +
>> + if (denied) {
>> + if (flags & AVC_STRICT)
>> + rc = -EACCES;
>> + else if (!selinux_enforcing || security_permissive_sid(ssid))
>> + avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
>> + tsid, tclass);
>> else
>> - if (node)
>> - avc_update_node(AVC_CALLBACK_GRANT,requested,
>> - ssid,tsid,tclass);
>> + rc = -EACCES;
>> }
>>
>> rcu_read_unlock();
>> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
>> index f7d2f03..fde8690 100644
>> --- a/security/selinux/include/security.h
>> +++ b/security/selinux/include/security.h
>> @@ -26,13 +26,14 @@
>> #define POLICYDB_VERSION_AVTAB 20
>> #define POLICYDB_VERSION_RANGETRANS 21
>> #define POLICYDB_VERSION_POLCAP 22
>> +#define POLICYDB_VERSION_PERMISSIVE 23
>>
>> /* Range of policy versions we understand*/
>> #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
>> #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
>> #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
>> #else
>> -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP
>> +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE
>> #endif
>>
>> #define CONTEXT_MNT 0x01
>> @@ -67,6 +68,8 @@ struct av_decision {
>> u32 seqno;
>> };
>>
>> +int security_permissive_sid(u32 sid);
>> +
>> int security_compute_av(u32 ssid, u32 tsid,
>> u16 tclass, u32 requested,
>> struct av_decision *avd);
>> diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
>> index bd7d6a0..84dbab9 100644
>> --- a/security/selinux/ss/policydb.c
>> +++ b/security/selinux/ss/policydb.c
>> @@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = {
>> .version = POLICYDB_VERSION_POLCAP,
>> .sym_num = SYM_NUM,
>> .ocon_num = OCON_NUM,
>> + },
>> + {
>> + .version = POLICYDB_VERSION_PERMISSIVE,
>> + .sym_num = SYM_NUM,
>> + .ocon_num = OCON_NUM,
>> }
>> };
>>
>> @@ -194,6 +199,7 @@ static int policydb_init(struct policydb *p)
>> goto out_free_symtab;
>>
>> ebitmap_init(&p->policycaps);
>> + ebitmap_init(&p->permissive_map);
>>
>> out:
>> return rc;
>> @@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p)
>> kfree(p->type_attr_map);
>> kfree(p->undefined_perms);
>> ebitmap_destroy(&p->policycaps);
>> + ebitmap_destroy(&p->permissive_map);
>>
>> return;
>> }
>> @@ -1570,6 +1577,10 @@ int policydb_read(struct policydb *p, void *fp)
>> ebitmap_read(&p->policycaps, fp) != 0)
>> goto bad;
>>
>> + if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE &&
>> + ebitmap_read(&p->permissive_map, fp) != 0)
>> + goto bad;
>> +
>> info = policydb_lookup_compat(p->policyvers);
>> if (!info) {
>> printk(KERN_ERR "security: unable to find policy compat info "
>> diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
>> index c4ce996..ba593a3 100644
>> --- a/security/selinux/ss/policydb.h
>> +++ b/security/selinux/ss/policydb.h
>> @@ -243,6 +243,8 @@ struct policydb {
>>
>> struct ebitmap policycaps;
>>
>> + struct ebitmap permissive_map;
>> +
>> unsigned int policyvers;
>>
>> unsigned int reject_unknown : 1;
>> diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
>> index f374186..f5d1dcc 100644
>> --- a/security/selinux/ss/services.c
>> +++ b/security/selinux/ss/services.c
>> @@ -416,6 +416,27 @@ inval_class:
>> return -EINVAL;
>> }
>>
>> +/*
>> + * Given a sid find if the type has the permissive flag set
>> + */
>> +int security_permissive_sid(u32 sid)
>> +{
>> + struct context *context;
>> + u32 type;
>> + int rc;
>> +
>> + POLICY_RDLOCK;
>> +
>> + context = sidtab_search(&sidtab, sid);
>> + BUG_ON(!context);
>> +
>> + type = context->type;
>> + rc = ebitmap_get_bit(&policydb.permissive_map, type);
>
> Maybe a comment then to note that we are intentionally not using (type -
> 1) here due to possibly global use of that bit - otherwise it is a
> confusing inconsistency with other ebitmap_get_bit calls.
>
>> +
>> + POLICY_RDUNLOCK;
>> + return rc;
>> +}
>> +
>> static int security_validtrans_handle_fail(struct context *ocontext,
>> struct context *ncontext,
>> struct context *tcontext,
>>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iEYEARECAAYFAkfXQEIACgkQrlYvE4MpobNsBgCffHW2x1Pq3g8ArEcgSF3HfUBG
nEgAoOMQlwnm0+g4VwC3IAF5vPgwTCkF
=wSvv
-----END PGP SIGNATURE-----
--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-03-12 2:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-10 22:35 [PATCH-v3] SELinux: introduce permissive types Eric Paris
2008-03-11 15:18 ` Stephen Smalley
2008-03-11 17:08 ` Semanage return codes Hasan Rezaul-CHR010
2008-03-11 17:17 ` Stephen Smalley
2008-03-12 2:30 ` [PATCH-v3] SELinux: introduce permissive types Daniel J Walsh
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.