diff options
author | Eric Paris <eparis@redhat.com> | 2007-09-21 14:37:10 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2007-10-16 18:59:33 -0400 |
commit | 3f12070e27b4a213d62607d2bff139793089a77d (patch) | |
tree | b6b614737f916c7c3102f66e6ad9e682b9c9bf04 /security/selinux/ss/services.c | |
parent | 788e7dd4c22e6f41b3a118fd8c291f831f6fddbb (diff) |
SELinux: policy selectable handling of unknown classes and perms
Allow policy to select, in much the same way as it selects MLS support, how
the kernel should handle access decisions which contain either unknown
classes or unknown permissions in known classes. The three choices for the
policy flags are
0 - Deny unknown security access. (default)
2 - reject loading policy if it does not contain all definitions
4 - allow unknown security access
The policy's choice is exported through 2 booleans in
selinuxfs. /selinux/deny_unknown and /selinux/reject_unknown.
Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
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; |