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>
This commit is contained in:
Eric Paris 2009-02-12 14:50:11 -05:00 committed by James Morris
parent 4cb912f1d1
commit a5dda68332

View file

@ -742,13 +742,15 @@ static inline int avc_sidcmp(u32 x, u32 y)
* @event : Updating event * @event : Updating event
* @perms : Permission mask bits * @perms : Permission mask bits
* @ssid,@tsid,@tclass : identifier of an AVC entry * @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 a valid AVC entry doesn't exist,this function returns -ENOENT.
* if kmalloc() called internal returns NULL, this function returns -ENOMEM. * if kmalloc() called internal returns NULL, this function returns -ENOMEM.
* otherwise, this function update the AVC entry. The original AVC-entry object * otherwise, this function update the AVC entry. The original AVC-entry object
* will release later by RCU. * 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; int hvalue, rc = 0;
unsigned long flag; 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) { list_for_each_entry(pos, &avc_cache.slots[hvalue], list) {
if (ssid == pos->ae.ssid && if (ssid == pos->ae.ssid &&
tsid == pos->ae.tsid && tsid == pos->ae.tsid &&
tclass == pos->ae.tclass){ tclass == pos->ae.tclass &&
seqno == pos->ae.avd.seqno){
orig = pos; orig = pos;
break; break;
} }
@ -908,7 +911,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
rc = -EACCES; rc = -EACCES;
else if (!selinux_enforcing || security_permissive_sid(ssid)) else if (!selinux_enforcing || security_permissive_sid(ssid))
avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
tsid, tclass); tsid, tclass, p_ae->avd.seqno);
else else
rc = -EACCES; rc = -EACCES;
} }