diff options
author | Ondrej Mosnacek <omosnace@redhat.com> | 2018-10-23 03:02:17 -0400 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2018-11-05 15:25:50 -0500 |
commit | 5df275cd4cf51c86d49009f1397132f284ba515e (patch) | |
tree | 7670bfeb837a0449796067ab3e5ef154888fb569 | |
parent | 651022382c7f8da46cb4872a545ee1da6d097d2a (diff) |
selinux: policydb - fix byte order and alignment issues
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>
-rw-r--r-- | security/selinux/ss/policydb.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index f4eadd3f7350..b63ef865ce1e 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -2108,6 +2108,7 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
2108 | { | 2108 | { |
2109 | int i, j, rc; | 2109 | int i, j, rc; |
2110 | u32 nel, len; | 2110 | u32 nel, len; |
2111 | __be64 prefixbuf[1]; | ||
2111 | __le32 buf[3]; | 2112 | __le32 buf[3]; |
2112 | struct ocontext *l, *c; | 2113 | struct ocontext *l, *c; |
2113 | u32 nodebuf[8]; | 2114 | u32 nodebuf[8]; |
@@ -2217,21 +2218,30 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
2217 | goto out; | 2218 | goto out; |
2218 | break; | 2219 | break; |
2219 | } | 2220 | } |
2220 | case OCON_IBPKEY: | 2221 | case OCON_IBPKEY: { |
2221 | rc = next_entry(nodebuf, fp, sizeof(u32) * 4); | 2222 | u32 pkey_lo, pkey_hi; |
2223 | |||
2224 | rc = next_entry(prefixbuf, fp, sizeof(u64)); | ||
2225 | if (rc) | ||
2226 | goto out; | ||
2227 | |||
2228 | /* we need to have subnet_prefix in CPU order */ | ||
2229 | c->u.ibpkey.subnet_prefix = be64_to_cpu(prefixbuf[0]); | ||
2230 | |||
2231 | rc = next_entry(buf, fp, sizeof(u32) * 2); | ||
2222 | if (rc) | 2232 | if (rc) |
2223 | goto out; | 2233 | goto out; |
2224 | 2234 | ||
2225 | c->u.ibpkey.subnet_prefix = be64_to_cpu(*((__be64 *)nodebuf)); | 2235 | pkey_lo = le32_to_cpu(buf[0]); |
2236 | pkey_hi = le32_to_cpu(buf[1]); | ||
2226 | 2237 | ||
2227 | if (nodebuf[2] > 0xffff || | 2238 | if (pkey_lo > U16_MAX || pkey_hi > U16_MAX) { |
2228 | nodebuf[3] > 0xffff) { | ||
2229 | rc = -EINVAL; | 2239 | rc = -EINVAL; |
2230 | goto out; | 2240 | goto out; |
2231 | } | 2241 | } |
2232 | 2242 | ||
2233 | c->u.ibpkey.low_pkey = le32_to_cpu(nodebuf[2]); | 2243 | c->u.ibpkey.low_pkey = pkey_lo; |
2234 | c->u.ibpkey.high_pkey = le32_to_cpu(nodebuf[3]); | 2244 | c->u.ibpkey.high_pkey = pkey_hi; |
2235 | 2245 | ||
2236 | rc = context_read_and_validate(&c->context[0], | 2246 | rc = context_read_and_validate(&c->context[0], |
2237 | p, | 2247 | p, |
@@ -2239,7 +2249,10 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
2239 | if (rc) | 2249 | if (rc) |
2240 | goto out; | 2250 | goto out; |
2241 | break; | 2251 | break; |
2242 | case OCON_IBENDPORT: | 2252 | } |
2253 | case OCON_IBENDPORT: { | ||
2254 | u32 port; | ||
2255 | |||
2243 | rc = next_entry(buf, fp, sizeof(u32) * 2); | 2256 | rc = next_entry(buf, fp, sizeof(u32) * 2); |
2244 | if (rc) | 2257 | if (rc) |
2245 | goto out; | 2258 | goto out; |
@@ -2249,12 +2262,13 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
2249 | if (rc) | 2262 | if (rc) |
2250 | goto out; | 2263 | goto out; |
2251 | 2264 | ||
2252 | if (buf[1] > 0xff || buf[1] == 0) { | 2265 | port = le32_to_cpu(buf[1]); |
2266 | if (port > U8_MAX || port == 0) { | ||
2253 | rc = -EINVAL; | 2267 | rc = -EINVAL; |
2254 | goto out; | 2268 | goto out; |
2255 | } | 2269 | } |
2256 | 2270 | ||
2257 | c->u.ibendport.port = le32_to_cpu(buf[1]); | 2271 | c->u.ibendport.port = port; |
2258 | 2272 | ||
2259 | rc = context_read_and_validate(&c->context[0], | 2273 | rc = context_read_and_validate(&c->context[0], |
2260 | p, | 2274 | p, |
@@ -2262,7 +2276,8 @@ static int ocontext_read(struct policydb *p, struct policydb_compat_info *info, | |||
2262 | if (rc) | 2276 | if (rc) |
2263 | goto out; | 2277 | goto out; |
2264 | break; | 2278 | break; |
2265 | } | 2279 | } /* end case */ |
2280 | } /* end switch */ | ||
2266 | } | 2281 | } |
2267 | } | 2282 | } |
2268 | rc = 0; | 2283 | rc = 0; |
@@ -3105,6 +3120,7 @@ static int ocontext_write(struct policydb *p, struct policydb_compat_info *info, | |||
3105 | { | 3120 | { |
3106 | unsigned int i, j, rc; | 3121 | unsigned int i, j, rc; |
3107 | size_t nel, len; | 3122 | size_t nel, len; |
3123 | __be64 prefixbuf[1]; | ||
3108 | __le32 buf[3]; | 3124 | __le32 buf[3]; |
3109 | u32 nodebuf[8]; | 3125 | u32 nodebuf[8]; |
3110 | struct ocontext *c; | 3126 | struct ocontext *c; |
@@ -3192,12 +3208,17 @@ static int ocontext_write(struct policydb *p, struct policydb_compat_info *info, | |||
3192 | return rc; | 3208 | return rc; |
3193 | break; | 3209 | break; |
3194 | case OCON_IBPKEY: | 3210 | case OCON_IBPKEY: |
3195 | *((__be64 *)nodebuf) = cpu_to_be64(c->u.ibpkey.subnet_prefix); | 3211 | /* subnet_prefix is in CPU order */ |
3212 | prefixbuf[0] = cpu_to_be64(c->u.ibpkey.subnet_prefix); | ||
3196 | 3213 | ||
3197 | nodebuf[2] = cpu_to_le32(c->u.ibpkey.low_pkey); | 3214 | rc = put_entry(prefixbuf, sizeof(u64), 1, fp); |
3198 | nodebuf[3] = cpu_to_le32(c->u.ibpkey.high_pkey); | 3215 | if (rc) |
3216 | return rc; | ||
3217 | |||
3218 | buf[0] = cpu_to_le32(c->u.ibpkey.low_pkey); | ||
3219 | buf[1] = cpu_to_le32(c->u.ibpkey.high_pkey); | ||
3199 | 3220 | ||
3200 | rc = put_entry(nodebuf, sizeof(u32), 4, fp); | 3221 | rc = put_entry(buf, sizeof(u32), 2, fp); |
3201 | if (rc) | 3222 | if (rc) |
3202 | return rc; | 3223 | return rc; |
3203 | rc = context_write(p, &c->context[0], fp); | 3224 | rc = context_write(p, &c->context[0], fp); |