diff options
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r-- | security/selinux/ss/services.c | 91 |
1 files changed, 70 insertions, 21 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 6100fc023055..d572dc908f31 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 | */ |
@@ -329,12 +353,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
329 | avkey.specified = AVTAB_AV; | 353 | avkey.specified = AVTAB_AV; |
330 | sattr = &policydb.type_attr_map[scontext->type - 1]; | 354 | sattr = &policydb.type_attr_map[scontext->type - 1]; |
331 | tattr = &policydb.type_attr_map[tcontext->type - 1]; | 355 | tattr = &policydb.type_attr_map[tcontext->type - 1]; |
332 | ebitmap_for_each_bit(sattr, snode, i) { | 356 | ebitmap_for_each_positive_bit(sattr, snode, i) { |
333 | if (!ebitmap_node_get_bit(snode, i)) | 357 | ebitmap_for_each_positive_bit(tattr, tnode, j) { |
334 | continue; | ||
335 | ebitmap_for_each_bit(tattr, tnode, j) { | ||
336 | if (!ebitmap_node_get_bit(tnode, j)) | ||
337 | continue; | ||
338 | avkey.source_type = i + 1; | 358 | avkey.source_type = i + 1; |
339 | avkey.target_type = j + 1; | 359 | avkey.target_type = j + 1; |
340 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); | 360 | for (node = avtab_search_node(&policydb.te_avtab, &avkey); |
@@ -387,6 +407,10 @@ static int context_struct_compute_av(struct context *scontext, | |||
387 | } | 407 | } |
388 | 408 | ||
389 | return 0; | 409 | return 0; |
410 | |||
411 | inval_class: | ||
412 | printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass); | ||
413 | return -EINVAL; | ||
390 | } | 414 | } |
391 | 415 | ||
392 | static int security_validtrans_handle_fail(struct context *ocontext, | 416 | static int security_validtrans_handle_fail(struct context *ocontext, |
@@ -1054,6 +1078,13 @@ static int validate_classes(struct policydb *p) | |||
1054 | const char *def_class, *def_perm, *pol_class; | 1078 | const char *def_class, *def_perm, *pol_class; |
1055 | struct symtab *perms; | 1079 | struct symtab *perms; |
1056 | 1080 | ||
1081 | if (p->allow_unknown) { | ||
1082 | u32 num_classes = kdefs->cts_len; | ||
1083 | p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL); | ||
1084 | if (!p->undefined_perms) | ||
1085 | return -ENOMEM; | ||
1086 | } | ||
1087 | |||
1057 | for (i = 1; i < kdefs->cts_len; i++) { | 1088 | for (i = 1; i < kdefs->cts_len; i++) { |
1058 | def_class = kdefs->class_to_string[i]; | 1089 | def_class = kdefs->class_to_string[i]; |
1059 | if (!def_class) | 1090 | if (!def_class) |
@@ -1062,6 +1093,10 @@ static int validate_classes(struct policydb *p) | |||
1062 | printk(KERN_INFO | 1093 | printk(KERN_INFO |
1063 | "security: class %s not defined in policy\n", | 1094 | "security: class %s not defined in policy\n", |
1064 | def_class); | 1095 | def_class); |
1096 | if (p->reject_unknown) | ||
1097 | return -EINVAL; | ||
1098 | if (p->allow_unknown) | ||
1099 | p->undefined_perms[i-1] = ~0U; | ||
1065 | continue; | 1100 | continue; |
1066 | } | 1101 | } |
1067 | pol_class = p->p_class_val_to_name[i-1]; | 1102 | pol_class = p->p_class_val_to_name[i-1]; |
@@ -1087,12 +1122,16 @@ static int validate_classes(struct policydb *p) | |||
1087 | printk(KERN_INFO | 1122 | printk(KERN_INFO |
1088 | "security: permission %s in class %s not defined in policy\n", | 1123 | "security: permission %s in class %s not defined in policy\n", |
1089 | def_perm, pol_class); | 1124 | def_perm, pol_class); |
1125 | if (p->reject_unknown) | ||
1126 | return -EINVAL; | ||
1127 | if (p->allow_unknown) | ||
1128 | p->undefined_perms[class_val-1] |= perm_val; | ||
1090 | continue; | 1129 | continue; |
1091 | } | 1130 | } |
1092 | perdatum = hashtab_search(perms->table, def_perm); | 1131 | perdatum = hashtab_search(perms->table, def_perm); |
1093 | if (perdatum == NULL) { | 1132 | if (perdatum == NULL) { |
1094 | printk(KERN_ERR | 1133 | printk(KERN_ERR |
1095 | "security: permission %s in class %s not found in policy\n", | 1134 | "security: permission %s in class %s not found in policy, bad policy\n", |
1096 | def_perm, pol_class); | 1135 | def_perm, pol_class); |
1097 | return -EINVAL; | 1136 | return -EINVAL; |
1098 | } | 1137 | } |
@@ -1130,12 +1169,16 @@ static int validate_classes(struct policydb *p) | |||
1130 | printk(KERN_INFO | 1169 | printk(KERN_INFO |
1131 | "security: permission %s in class %s not defined in policy\n", | 1170 | "security: permission %s in class %s not defined in policy\n", |
1132 | def_perm, pol_class); | 1171 | def_perm, pol_class); |
1172 | if (p->reject_unknown) | ||
1173 | return -EINVAL; | ||
1174 | if (p->allow_unknown) | ||
1175 | p->undefined_perms[class_val-1] |= (1 << j); | ||
1133 | continue; | 1176 | continue; |
1134 | } | 1177 | } |
1135 | perdatum = hashtab_search(perms->table, def_perm); | 1178 | perdatum = hashtab_search(perms->table, def_perm); |
1136 | if (perdatum == NULL) { | 1179 | if (perdatum == NULL) { |
1137 | printk(KERN_ERR | 1180 | printk(KERN_ERR |
1138 | "security: permission %s in class %s not found in policy\n", | 1181 | "security: permission %s in class %s not found in policy, bad policy\n", |
1139 | def_perm, pol_class); | 1182 | def_perm, pol_class); |
1140 | return -EINVAL; | 1183 | return -EINVAL; |
1141 | } | 1184 | } |
@@ -1621,14 +1664,10 @@ int security_get_user_sids(u32 fromsid, | |||
1621 | goto out_unlock; | 1664 | goto out_unlock; |
1622 | } | 1665 | } |
1623 | 1666 | ||
1624 | ebitmap_for_each_bit(&user->roles, rnode, i) { | 1667 | ebitmap_for_each_positive_bit(&user->roles, rnode, i) { |
1625 | if (!ebitmap_node_get_bit(rnode, i)) | ||
1626 | continue; | ||
1627 | role = policydb.role_val_to_struct[i]; | 1668 | role = policydb.role_val_to_struct[i]; |
1628 | usercon.role = i+1; | 1669 | usercon.role = i+1; |
1629 | ebitmap_for_each_bit(&role->types, tnode, j) { | 1670 | ebitmap_for_each_positive_bit(&role->types, tnode, j) { |
1630 | if (!ebitmap_node_get_bit(tnode, j)) | ||
1631 | continue; | ||
1632 | usercon.type = j+1; | 1671 | usercon.type = j+1; |
1633 | 1672 | ||
1634 | if (mls_setup_user_range(fromcon, user, &usercon)) | 1673 | if (mls_setup_user_range(fromcon, user, &usercon)) |
@@ -2102,6 +2141,16 @@ err: | |||
2102 | return rc; | 2141 | return rc; |
2103 | } | 2142 | } |
2104 | 2143 | ||
2144 | int security_get_reject_unknown(void) | ||
2145 | { | ||
2146 | return policydb.reject_unknown; | ||
2147 | } | ||
2148 | |||
2149 | int security_get_allow_unknown(void) | ||
2150 | { | ||
2151 | return policydb.allow_unknown; | ||
2152 | } | ||
2153 | |||
2105 | struct selinux_audit_rule { | 2154 | struct selinux_audit_rule { |
2106 | u32 au_seqno; | 2155 | u32 au_seqno; |
2107 | struct context au_ctxt; | 2156 | struct context au_ctxt; |