aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2007-09-21 14:37:10 -0400
committerJames Morris <jmorris@namei.org>2007-10-16 18:59:33 -0400
commit3f12070e27b4a213d62607d2bff139793089a77d (patch)
treeb6b614737f916c7c3102f66e6ad9e682b9c9bf04 /security/selinux/ss
parent788e7dd4c22e6f41b3a118fd8c291f831f6fddbb (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')
-rw-r--r--security/selinux/ss/policydb.c4
-rw-r--r--security/selinux/ss/policydb.h8
-rw-r--r--security/selinux/ss/services.c75
3 files changed, 78 insertions, 9 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 5ecbad7d8b9f..539828b229b2 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -674,6 +674,8 @@ void policydb_destroy(struct policydb *p)
674 } 674 }
675 kfree(p->type_attr_map); 675 kfree(p->type_attr_map);
676 676
677 kfree(p->undefined_perms);
678
677 return; 679 return;
678} 680}
679 681
@@ -1527,6 +1529,8 @@ int policydb_read(struct policydb *p, void *fp)
1527 goto bad; 1529 goto bad;
1528 } 1530 }
1529 } 1531 }
1532 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
1533 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
1530 1534
1531 info = policydb_lookup_compat(p->policyvers); 1535 info = policydb_lookup_compat(p->policyvers);
1532 if (!info) { 1536 if (!info) {
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 8319d5ff5944..844d310f4f1b 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -242,6 +242,10 @@ struct policydb {
242 struct ebitmap *type_attr_map; 242 struct ebitmap *type_attr_map;
243 243
244 unsigned int policyvers; 244 unsigned int policyvers;
245
246 unsigned int reject_unknown : 1;
247 unsigned int allow_unknown : 1;
248 u32 *undefined_perms;
245}; 249};
246 250
247extern void policydb_destroy(struct policydb *p); 251extern void policydb_destroy(struct policydb *p);
@@ -253,6 +257,10 @@ extern int policydb_read(struct policydb *p, void *fp);
253 257
254#define POLICYDB_CONFIG_MLS 1 258#define POLICYDB_CONFIG_MLS 1
255 259
260/* the config flags related to unknown classes/perms are bits 2 and 3 */
261#define REJECT_UNKNOWN 0x00000002
262#define ALLOW_UNKNOWN 0x00000004
263
256#define OBJECT_R "object_r" 264#define OBJECT_R "object_r"
257#define OBJECT_R_VAL 1 265#define OBJECT_R_VAL 1
258 266
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
415inval_class:
416 printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass);
417 return -EINVAL;
390} 418}
391 419
392static int security_validtrans_handle_fail(struct context *ocontext, 420static 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
2152int security_get_reject_unknown(void)
2153{
2154 return policydb.reject_unknown;
2155}
2156
2157int security_get_allow_unknown(void)
2158{
2159 return policydb.allow_unknown;
2160}
2161
2105struct selinux_audit_rule { 2162struct selinux_audit_rule {
2106 u32 au_seqno; 2163 u32 au_seqno;
2107 struct context au_ctxt; 2164 struct context au_ctxt;