]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
SELinux: fix selinuxfs policy file on big endian systems
authorEric Paris <eparis@redhat.com>
Tue, 23 Jul 2013 21:38:42 +0000 (17:38 -0400)
committerJiri Slaby <jslaby@suse.cz>
Mon, 16 Feb 2015 15:10:58 +0000 (16:10 +0100)
commitebf1059f4bc4e12a6878c44137f95fafc1fe55b3
tree0b3ce4fc897d54c381ace95fbc9f797c9f8a1709
parentdac05cc7cc144635946cdc6ed38a6734424c2683
SELinux: fix selinuxfs policy file on big endian systems

commit b138004ea0382bdc6d02599c39392651b4f63889 upstream.

The /sys/fs/selinux/policy file is not valid on big endian systems like
ppc64 or s390.  Let's see why:

static int hashtab_cnt(void *key, void *data, void *ptr)
{
int *cnt = ptr;
*cnt = *cnt + 1;

return 0;
}

static int range_write(struct policydb *p, void *fp)
{
size_t nel;
[...]
/* count the number of entries in the hashtab */
nel = 0;
rc = hashtab_map(p->range_tr, hashtab_cnt, &nel);
if (rc)
return rc;
buf[0] = cpu_to_le32(nel);
rc = put_entry(buf, sizeof(u32), 1, fp);

So size_t is 64 bits.  But then we pass a pointer to it as we do to
hashtab_cnt.  hashtab_cnt thinks it is a 32 bit int and only deals with
the first 4 bytes.  On x86_64 which is little endian, those first 4
bytes and the least significant, so this works out fine.  On ppc64/s390
those first 4 bytes of memory are the high order bits.  So at the end of
the call to hashtab_map nel has a HUGE number.  But the least
significant 32 bits are all 0's.

We then pass that 64 bit number to cpu_to_le32() which happily truncates
it to a 32 bit number and does endian swapping.  But the low 32 bits are
all 0's.  So no matter how many entries are in the hashtab, big endian
systems always say there are 0 entries because I screwed up the
counting.

The fix is easy.  Use a 32 bit int, as the hashtab_cnt expects, for nel.

Signed-off-by: Eric Paris <eparis@redhat.com>
Signed-off-by: Paul Moore <pmoore@redhat.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
security/selinux/ss/policydb.c