| From 5df275cd4cf51c86d49009f1397132f284ba515e Mon Sep 17 00:00:00 2001 |
| From: Ondrej Mosnacek <omosnace@redhat.com> |
| Date: Tue, 23 Oct 2018 09:02:17 +0200 |
| Subject: selinux: policydb - fix byte order and alignment issues |
| |
| From: Ondrej Mosnacek <omosnace@redhat.com> |
| |
| commit 5df275cd4cf51c86d49009f1397132f284ba515e upstream. |
| |
| Do the LE conversions before doing the Infiniband-related range checks. |
| The incorrect checks are otherwise causing a failure to load any policy |
| with an ibendportcon rule on BE systems. This can be reproduced by |
| running (on e.g. ppc64): |
| |
| cat >my_module.cil <<EOF |
| (type test_ibendport_t) |
| (roletype object_r test_ibendport_t) |
| (ibendportcon mlx4_0 1 (system_u object_r test_ibendport_t ((s0) (s0)))) |
| EOF |
| semodule -i my_module.cil |
| |
| Also, fix loading/storing the 64-bit subnet prefix for OCON_IBPKEY to |
| use a correctly aligned buffer. |
| |
| Finally, do not use the 'nodebuf' (u32) buffer where 'buf' (__le32) |
| should be used instead. |
| |
| Tested internally on a ppc64 machine with a RHEL 7 kernel with this |
| patch applied. |
| |
| Cc: Daniel Jurgens <danielj@mellanox.com> |
| Cc: Eli Cohen <eli@mellanox.com> |
| Cc: James Morris <jmorris@namei.org> |
| Cc: Doug Ledford <dledford@redhat.com> |
| Cc: <stable@vger.kernel.org> # 4.13+ |
| Fixes: a806f7a1616f ("selinux: Create policydb version for Infiniband support") |
| Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com> |
| Acked-by: Stephen Smalley <sds@tycho.nsa.gov> |
| Signed-off-by: Paul Moore <paul@paul-moore.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| security/selinux/ss/policydb.c | 51 ++++++++++++++++++++++++++++------------- |
| 1 file changed, 36 insertions(+), 15 deletions(-) |
| |
| --- a/security/selinux/ss/policydb.c |
| +++ b/security/selinux/ss/policydb.c |
| @@ -2108,6 +2108,7 @@ static int ocontext_read(struct policydb |
| { |
| int i, j, rc; |
| u32 nel, len; |
| + __be64 prefixbuf[1]; |
| __le32 buf[3]; |
| struct ocontext *l, *c; |
| u32 nodebuf[8]; |
| @@ -2217,21 +2218,30 @@ static int ocontext_read(struct policydb |
| goto out; |
| break; |
| } |
| - case OCON_IBPKEY: |
| - rc = next_entry(nodebuf, fp, sizeof(u32) * 4); |
| + case OCON_IBPKEY: { |
| + u32 pkey_lo, pkey_hi; |
| + |
| + rc = next_entry(prefixbuf, fp, sizeof(u64)); |
| + if (rc) |
| + goto out; |
| + |
| + /* we need to have subnet_prefix in CPU order */ |
| + c->u.ibpkey.subnet_prefix = be64_to_cpu(prefixbuf[0]); |
| + |
| + rc = next_entry(buf, fp, sizeof(u32) * 2); |
| if (rc) |
| goto out; |
| |
| - c->u.ibpkey.subnet_prefix = be64_to_cpu(*((__be64 *)nodebuf)); |
| + pkey_lo = le32_to_cpu(buf[0]); |
| + pkey_hi = le32_to_cpu(buf[1]); |
| |
| - if (nodebuf[2] > 0xffff || |
| - nodebuf[3] > 0xffff) { |
| + if (pkey_lo > U16_MAX || pkey_hi > U16_MAX) { |
| rc = -EINVAL; |
| goto out; |
| } |
| |
| - c->u.ibpkey.low_pkey = le32_to_cpu(nodebuf[2]); |
| - c->u.ibpkey.high_pkey = le32_to_cpu(nodebuf[3]); |
| + c->u.ibpkey.low_pkey = pkey_lo; |
| + c->u.ibpkey.high_pkey = pkey_hi; |
| |
| rc = context_read_and_validate(&c->context[0], |
| p, |
| @@ -2239,7 +2249,10 @@ static int ocontext_read(struct policydb |
| if (rc) |
| goto out; |
| break; |
| - case OCON_IBENDPORT: |
| + } |
| + case OCON_IBENDPORT: { |
| + u32 port; |
| + |
| rc = next_entry(buf, fp, sizeof(u32) * 2); |
| if (rc) |
| goto out; |
| @@ -2249,12 +2262,13 @@ static int ocontext_read(struct policydb |
| if (rc) |
| goto out; |
| |
| - if (buf[1] > 0xff || buf[1] == 0) { |
| + port = le32_to_cpu(buf[1]); |
| + if (port > U8_MAX || port == 0) { |
| rc = -EINVAL; |
| goto out; |
| } |
| |
| - c->u.ibendport.port = le32_to_cpu(buf[1]); |
| + c->u.ibendport.port = port; |
| |
| rc = context_read_and_validate(&c->context[0], |
| p, |
| @@ -2262,7 +2276,8 @@ static int ocontext_read(struct policydb |
| if (rc) |
| goto out; |
| break; |
| - } |
| + } /* end case */ |
| + } /* end switch */ |
| } |
| } |
| rc = 0; |
| @@ -3105,6 +3120,7 @@ static int ocontext_write(struct policyd |
| { |
| unsigned int i, j, rc; |
| size_t nel, len; |
| + __be64 prefixbuf[1]; |
| __le32 buf[3]; |
| u32 nodebuf[8]; |
| struct ocontext *c; |
| @@ -3192,12 +3208,17 @@ static int ocontext_write(struct policyd |
| return rc; |
| break; |
| case OCON_IBPKEY: |
| - *((__be64 *)nodebuf) = cpu_to_be64(c->u.ibpkey.subnet_prefix); |
| + /* subnet_prefix is in CPU order */ |
| + prefixbuf[0] = cpu_to_be64(c->u.ibpkey.subnet_prefix); |
| |
| - nodebuf[2] = cpu_to_le32(c->u.ibpkey.low_pkey); |
| - nodebuf[3] = cpu_to_le32(c->u.ibpkey.high_pkey); |
| + rc = put_entry(prefixbuf, sizeof(u64), 1, fp); |
| + if (rc) |
| + return rc; |
| + |
| + buf[0] = cpu_to_le32(c->u.ibpkey.low_pkey); |
| + buf[1] = cpu_to_le32(c->u.ibpkey.high_pkey); |
| |
| - rc = put_entry(nodebuf, sizeof(u32), 4, fp); |
| + rc = put_entry(buf, sizeof(u32), 2, fp); |
| if (rc) |
| return rc; |
| rc = context_write(p, &c->context[0], fp); |