diff options
author | Eric Paris <eparis@redhat.com> | 2009-02-12 14:50:11 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-02-14 09:22:34 +1100 |
commit | a5dda683328f99c781f92c66cc52ffc0639bef58 (patch) | |
tree | 2432f51e505fd9242f7081d5bf4e21ff322b73d6 /security | |
parent | 4cb912f1d1447077160ace9ce3b3a10696dd74e5 (diff) | |
download | linux-3.10-a5dda683328f99c781f92c66cc52ffc0639bef58.tar.gz linux-3.10-a5dda683328f99c781f92c66cc52ffc0639bef58.tar.bz2 linux-3.10-a5dda683328f99c781f92c66cc52ffc0639bef58.zip |
SELinux: check seqno when updating an avc_node
The avc update node callbacks do not check the seqno of the caller with the
seqno of the node found. It is possible that a policy change could happen
(although almost impossibly unlikely) in which a permissive or
permissive_domain decision is not valid for the entry found. Simply pass
and check that the seqno of the caller and the seqno of the node found
match.
Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/avc.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index eb41f43e277..0d00f4874f3 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -742,13 +742,15 @@ static inline int avc_sidcmp(u32 x, u32 y) * @event : Updating event * @perms : Permission mask bits * @ssid,@tsid,@tclass : identifier of an AVC entry + * @seqno : sequence number when decision was made * * if a valid AVC entry doesn't exist,this function returns -ENOENT. * if kmalloc() called internal returns NULL, this function returns -ENOMEM. * otherwise, this function update the AVC entry. The original AVC-entry object * will release later by RCU. */ -static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass) +static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, + u32 seqno) { int hvalue, rc = 0; unsigned long flag; @@ -767,7 +769,8 @@ static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass) list_for_each_entry(pos, &avc_cache.slots[hvalue], list) { if (ssid == pos->ae.ssid && tsid == pos->ae.tsid && - tclass == pos->ae.tclass){ + tclass == pos->ae.tclass && + seqno == pos->ae.avd.seqno){ orig = pos; break; } @@ -908,7 +911,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, rc = -EACCES; else if (!selinux_enforcing || security_permissive_sid(ssid)) avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, - tsid, tclass); + tsid, tclass, p_ae->avd.seqno); else rc = -EACCES; } |