diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 75 |
1 files changed, 66 insertions, 9 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 6100fc023055..03140edf97a3 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -292,6 +292,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
292 | struct class_datum *tclass_datum; | 292 | struct class_datum *tclass_datum; |
293 | struct ebitmap *sattr, *tattr; | 293 | struct ebitmap *sattr, *tattr; |
294 | struct ebitmap_node *snode, *tnode; | 294 | struct ebitmap_node *snode, *tnode; |
295 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
295 | unsigned int i, j; | 296 | unsigned int i, j; |
296 | 297 | ||
297 | /* | 298 | /* |
@@ -305,13 +306,6 @@ static int context_struct_compute_av(struct context *scontext, | |||
305 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | 306 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) |
306 | tclass = SECCLASS_NETLINK_SOCKET; | 307 | tclass = SECCLASS_NETLINK_SOCKET; |
307 | 308 | ||
308 | if (!tclass || tclass > policydb.p_classes.nprim) { | ||
309 | printk(KERN_ERR "security_compute_av: unrecognized class %d\n", | ||
310 | tclass); | ||
311 | return -EINVAL; | ||
312 | } | ||
313 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | ||
314 | |||
315 | /* | 309 | /* |
316 | * Initialize the access vectors to the default values. | 310 | * Initialize the access vectors to the default values. |
317 | */ | 311 | */ |
@@ -322,6 +316,36 @@ static int context_struct_compute_av(struct context *scontext, | |||
322 | avd->seqno = latest_granting; | 316 | avd->seqno = latest_granting; |
323 | 317 | ||
324 | /* | 318 | /* |
319 | * Check for all the invalid cases. | ||
320 | * - tclass 0 | ||
321 | * - tclass > policy and > kernel | ||
322 | * - tclass > policy but is a userspace class | ||
323 | * - tclass > policy but we do not allow unknowns | ||
324 | */ | ||
325 | if (unlikely(!tclass)) | ||
326 | goto inval_class; | ||
327 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
328 | if (tclass > kdefs->cts_len || | ||
329 | !kdefs->class_to_string[tclass - 1] || | ||
330 | !policydb.allow_unknown) | ||
331 | goto inval_class; | ||
332 | |||
333 | /* | ||
334 | * Kernel class and we allow unknown so pad the allow decision | ||
335 | * the pad will be all 1 for unknown classes. | ||
336 | */ | ||
337 | if (tclass <= kdefs->cts_len && policydb.allow_unknown) | ||
338 | avd->allowed = policydb.undefined_perms[tclass - 1]; | ||
339 | |||
340 | /* | ||
341 | * Not in policy. Since decision is completed (all 1 or all 0) return. | ||
342 | */ | ||
343 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
344 | return 0; | ||
345 | |||
346 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | ||
347 | |||
348 | /* | ||
325 | * If a specific type enforcement rule was defined for | 349 | * If a specific type enforcement rule was defined for |
326 | * this permission check, then use it. | 350 | * this permission check, then use it. |
327 | */ | 351 | */ |
@@ -387,6 +411,10 @@ static int context_struct_compute_av(struct context *scontext, | |||
387 | } | 411 | } |
388 | 412 | ||
389 | return 0; | 413 | return 0; |
414 | |||
415 | inval_class: | ||
416 | printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass); | ||
417 | return -EINVAL; | ||
390 | } | 418 | } |
391 | 419 | ||
392 | static int security_validtrans_handle_fail(struct context *ocontext, | 420 | static int security_validtrans_handle_fail(struct context *ocontext, |
@@ -1054,6 +1082,13 @@ static int validate_classes(struct policydb *p) | |||
1054 | const char *def_class, *def_perm, *pol_class; | 1082 | const char *def_class, *def_perm, *pol_class; |
1055 | struct symtab *perms; | 1083 | struct symtab *perms; |
1056 | 1084 | ||
1085 | if (p->allow_unknown) { | ||
1086 | u32 num_classes = kdefs->cts_len; | ||
1087 | p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL); | ||
1088 | if (!p->undefined_perms) | ||
1089 | return -ENOMEM; | ||
1090 | } | ||
1091 | |||
1057 | for (i = 1; i < kdefs->cts_len; i++) { | 1092 | for (i = 1; i < kdefs->cts_len; i++) { |
1058 | def_class = kdefs->class_to_string[i]; | 1093 | def_class = kdefs->class_to_string[i]; |
1059 | if (!def_class) | 1094 | if (!def_class) |
@@ -1062,6 +1097,10 @@ static int validate_classes(struct policydb *p) | |||
1062 | printk(KERN_INFO | 1097 | printk(KERN_INFO |
1063 | "security: class %s not defined in policy\n", | 1098 | "security: class %s not defined in policy\n", |
1064 | def_class); | 1099 | def_class); |
1100 | if (p->reject_unknown) | ||
1101 | return -EINVAL; | ||
1102 | if (p->allow_unknown) | ||
1103 | p->undefined_perms[i-1] = ~0U; | ||
1065 | continue; | 1104 | continue; |
1066 | } | 1105 | } |
1067 | pol_class = p->p_class_val_to_name[i-1]; | 1106 | pol_class = p->p_class_val_to_name[i-1]; |
@@ -1087,12 +1126,16 @@ static int validate_classes(struct policydb *p) | |||
1087 | printk(KERN_INFO | 1126 | printk(KERN_INFO |
1088 | "security: permission %s in class %s not defined in policy\n", | 1127 | "security: permission %s in class %s not defined in policy\n", |
1089 | def_perm, pol_class); | 1128 | def_perm, pol_class); |
1129 | if (p->reject_unknown) | ||
1130 | return -EINVAL; | ||
1131 | if (p->allow_unknown) | ||
1132 | p->undefined_perms[class_val-1] |= perm_val; | ||
1090 | continue; | 1133 | continue; |
1091 | } | 1134 | } |
1092 | perdatum = hashtab_search(perms->table, def_perm); | 1135 | perdatum = hashtab_search(perms->table, def_perm); |
1093 | if (perdatum == NULL) { | 1136 | if (perdatum == NULL) { |
1094 | printk(KERN_ERR | 1137 | printk(KERN_ERR |
1095 | "security: permission %s in class %s not found in policy\n", | 1138 | "security: permission %s in class %s not found in policy, bad policy\n", |
1096 | def_perm, pol_class); | 1139 | def_perm, pol_class); |
1097 | return -EINVAL; | 1140 | return -EINVAL; |
1098 | } | 1141 | } |
@@ -1130,12 +1173,16 @@ static int validate_classes(struct policydb *p) | |||
1130 | printk(KERN_INFO | 1173 | printk(KERN_INFO |
1131 | "security: permission %s in class %s not defined in policy\n", | 1174 | "security: permission %s in class %s not defined in policy\n", |
1132 | def_perm, pol_class); | 1175 | def_perm, pol_class); |
1176 | if (p->reject_unknown) | ||
1177 | return -EINVAL; | ||
1178 | if (p->allow_unknown) | ||
1179 | p->undefined_perms[class_val-1] |= (1 << j); | ||
1133 | continue; | 1180 | continue; |
1134 | } | 1181 | } |
1135 | perdatum = hashtab_search(perms->table, def_perm); | 1182 | perdatum = hashtab_search(perms->table, def_perm); |
1136 | if (perdatum == NULL) { | 1183 | if (perdatum == NULL) { |
1137 | printk(KERN_ERR | 1184 | printk(KERN_ERR |
1138 | "security: permission %s in class %s not found in policy\n", | 1185 | "security: permission %s in class %s not found in policy, bad policy\n", |
1139 | def_perm, pol_class); | 1186 | def_perm, pol_class); |
1140 | return -EINVAL; | 1187 | return -EINVAL; |
1141 | } | 1188 | } |
@@ -2102,6 +2149,16 @@ err: | |||
2102 | return rc; | 2149 | return rc; |
2103 | } | 2150 | } |
2104 | 2151 | ||
2152 | int security_get_reject_unknown(void) | ||
2153 | { | ||
2154 | return policydb.reject_unknown; | ||
2155 | } | ||
2156 | |||
2157 | int security_get_allow_unknown(void) | ||
2158 | { | ||
2159 | return policydb.allow_unknown; | ||
2160 | } | ||
2161 | |||
2105 | struct selinux_audit_rule { | 2162 | struct selinux_audit_rule { |
2106 | u32 au_seqno; | 2163 | u32 au_seqno; |
2107 | struct context au_ctxt; | 2164 | struct context au_ctxt; |