[PATCH 3.12 119/122] SELinux: fix selinuxfs policy file on big endian systems

From: Jiri Slaby
Date: Tue Feb 17 2015 - 06:36:31 EST


From: Eric Paris <eparis@xxxxxxxxxx>

3.12-stable review patch. If anyone has any objections, please let me know.

===============

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@xxxxxxxxxx>
Signed-off-by: Paul Moore <pmoore@xxxxxxxxxx>
Signed-off-by: Jiri Slaby <jslaby@xxxxxxx>
---
security/selinux/ss/policydb.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 4d35eb75f129..ee53ddca587b 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -3215,9 +3215,8 @@ static int range_write_helper(void *key, void *data, void *ptr)

static int range_write(struct policydb *p, void *fp)
{
- size_t nel;
__le32 buf[1];
- int rc;
+ int rc, nel;
struct policy_data pd;

pd.p = p;
--
2.2.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/