aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/include/security.h2
-rw-r--r--security/selinux/selinuxfs.c26
-rw-r--r--security/selinux/ss/policydb.c4
-rw-r--r--security/selinux/ss/policydb.h8
-rw-r--r--security/selinux/ss/services.c75
5 files changed, 106 insertions, 9 deletions
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 83bdd4d2a29e..39337afffec2 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -90,6 +90,8 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
90 90
91int security_get_classes(char ***classes, int *nclasses); 91int security_get_classes(char ***classes, int *nclasses);
92int security_get_permissions(char *class, char ***perms, int *nperms); 92int security_get_permissions(char *class, char ***perms, int *nperms);
93int security_get_reject_unknown(void);
94int security_get_allow_unknown(void);
93 95
94#define SECURITY_FS_USE_XATTR 1 /* use xattr */ 96#define SECURITY_FS_USE_XATTR 1 /* use xattr */
95#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */ 97#define SECURITY_FS_USE_TRANS 2 /* use transition SIDs, e.g. devpts/tmpfs */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c9e92daedee2..f5f3e6da5da7 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -103,6 +103,8 @@ enum sel_inos {
103 SEL_MEMBER, /* compute polyinstantiation membership decision */ 103 SEL_MEMBER, /* compute polyinstantiation membership decision */
104 SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */ 104 SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
105 SEL_COMPAT_NET, /* whether to use old compat network packet controls */ 105 SEL_COMPAT_NET, /* whether to use old compat network packet controls */
106 SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
107 SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
106 SEL_INO_NEXT, /* The next inode number to use */ 108 SEL_INO_NEXT, /* The next inode number to use */
107}; 109};
108 110
@@ -177,6 +179,23 @@ static const struct file_operations sel_enforce_ops = {
177 .write = sel_write_enforce, 179 .write = sel_write_enforce,
178}; 180};
179 181
182static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
183 size_t count, loff_t *ppos)
184{
185 char tmpbuf[TMPBUFLEN];
186 ssize_t length;
187 ino_t ino = filp->f_path.dentry->d_inode->i_ino;
188 int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ?
189 security_get_reject_unknown() : !security_get_allow_unknown();
190
191 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown);
192 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
193}
194
195static const struct file_operations sel_handle_unknown_ops = {
196 .read = sel_read_handle_unknown,
197};
198
180#ifdef CONFIG_SECURITY_SELINUX_DISABLE 199#ifdef CONFIG_SECURITY_SELINUX_DISABLE
181static ssize_t sel_write_disable(struct file * file, const char __user * buf, 200static ssize_t sel_write_disable(struct file * file, const char __user * buf,
182 size_t count, loff_t *ppos) 201 size_t count, loff_t *ppos)
@@ -309,6 +328,11 @@ static ssize_t sel_write_load(struct file * file, const char __user * buf,
309 length = count; 328 length = count;
310 329
311out1: 330out1:
331
332 printk(KERN_INFO "SELinux: policy loaded with handle_unknown=%s\n",
333 (security_get_reject_unknown() ? "reject" :
334 (security_get_allow_unknown() ? "allow" : "deny")));
335
312 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD, 336 audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
313 "policy loaded auid=%u", 337 "policy loaded auid=%u",
314 audit_get_loginuid(current->audit_context)); 338 audit_get_loginuid(current->audit_context));
@@ -1575,6 +1599,8 @@ static int sel_fill_super(struct super_block * sb, void * data, int silent)
1575 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO}, 1599 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
1576 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR}, 1600 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
1577 [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR}, 1601 [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR},
1602 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
1603 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
1578 /* last one */ {""} 1604 /* last one */ {""}
1579 }; 1605 };
1580 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); 1606 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
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;