aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/open.c4
-rw-r--r--include/linux/security.h18
-rw-r--r--security/dummy.c6
-rw-r--r--security/selinux/avc.c5
-rw-r--r--security/selinux/hooks.c53
-rw-r--r--security/selinux/include/avc.h2
-rw-r--r--security/selinux/include/objsec.h2
-rw-r--r--security/selinux/include/security.h2
-rw-r--r--security/selinux/selinuxfs.c26
-rw-r--r--security/selinux/ss/avtab.c91
-rw-r--r--security/selinux/ss/avtab.h16
-rw-r--r--security/selinux/ss/conditional.c4
-rw-r--r--security/selinux/ss/ebitmap.c282
-rw-r--r--security/selinux/ss/ebitmap.h89
-rw-r--r--security/selinux/ss/mls.c156
-rw-r--r--security/selinux/ss/policydb.c11
-rw-r--r--security/selinux/ss/policydb.h8
-rw-r--r--security/selinux/ss/services.c91
18 files changed, 582 insertions, 284 deletions
diff --git a/fs/open.c b/fs/open.c
index 1d9e5e98bf4e..044bfa891c94 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -757,6 +757,10 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
757 f->f_op = fops_get(inode->i_fop); 757 f->f_op = fops_get(inode->i_fop);
758 file_move(f, &inode->i_sb->s_files); 758 file_move(f, &inode->i_sb->s_files);
759 759
760 error = security_dentry_open(f);
761 if (error)
762 goto cleanup_all;
763
760 if (!open && f->f_op) 764 if (!open && f->f_op)
761 open = f->f_op->open; 765 open = f->f_op->open;
762 if (open) { 766 if (open) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 1a15526e9f67..928d4793c6f4 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -504,6 +504,13 @@ struct request_sock;
504 * @file contains the file structure being received. 504 * @file contains the file structure being received.
505 * Return 0 if permission is granted. 505 * Return 0 if permission is granted.
506 * 506 *
507 * Security hook for dentry
508 *
509 * @dentry_open
510 * Save open-time permission checking state for later use upon
511 * file_permission, and recheck access if anything has changed
512 * since inode_permission.
513 *
507 * Security hooks for task operations. 514 * Security hooks for task operations.
508 * 515 *
509 * @task_create: 516 * @task_create:
@@ -1256,6 +1263,7 @@ struct security_operations {
1256 int (*file_send_sigiotask) (struct task_struct * tsk, 1263 int (*file_send_sigiotask) (struct task_struct * tsk,
1257 struct fown_struct * fown, int sig); 1264 struct fown_struct * fown, int sig);
1258 int (*file_receive) (struct file * file); 1265 int (*file_receive) (struct file * file);
1266 int (*dentry_open) (struct file *file);
1259 1267
1260 int (*task_create) (unsigned long clone_flags); 1268 int (*task_create) (unsigned long clone_flags);
1261 int (*task_alloc_security) (struct task_struct * p); 1269 int (*task_alloc_security) (struct task_struct * p);
@@ -1864,6 +1872,11 @@ static inline int security_file_receive (struct file *file)
1864 return security_ops->file_receive (file); 1872 return security_ops->file_receive (file);
1865} 1873}
1866 1874
1875static inline int security_dentry_open (struct file *file)
1876{
1877 return security_ops->dentry_open (file);
1878}
1879
1867static inline int security_task_create (unsigned long clone_flags) 1880static inline int security_task_create (unsigned long clone_flags)
1868{ 1881{
1869 return security_ops->task_create (clone_flags); 1882 return security_ops->task_create (clone_flags);
@@ -2546,6 +2559,11 @@ static inline int security_file_receive (struct file *file)
2546 return 0; 2559 return 0;
2547} 2560}
2548 2561
2562static inline int security_dentry_open (struct file *file)
2563{
2564 return 0;
2565}
2566
2549static inline int security_task_create (unsigned long clone_flags) 2567static inline int security_task_create (unsigned long clone_flags)
2550{ 2568{
2551 return 0; 2569 return 0;
diff --git a/security/dummy.c b/security/dummy.c
index 853ec2292798..64b647a0d9a6 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -463,6 +463,11 @@ static int dummy_file_receive (struct file *file)
463 return 0; 463 return 0;
464} 464}
465 465
466static int dummy_dentry_open (struct file *file)
467{
468 return 0;
469}
470
466static int dummy_task_create (unsigned long clone_flags) 471static int dummy_task_create (unsigned long clone_flags)
467{ 472{
468 return 0; 473 return 0;
@@ -1033,6 +1038,7 @@ void security_fixup_ops (struct security_operations *ops)
1033 set_to_dummy_if_null(ops, file_set_fowner); 1038 set_to_dummy_if_null(ops, file_set_fowner);
1034 set_to_dummy_if_null(ops, file_send_sigiotask); 1039 set_to_dummy_if_null(ops, file_send_sigiotask);
1035 set_to_dummy_if_null(ops, file_receive); 1040 set_to_dummy_if_null(ops, file_receive);
1041 set_to_dummy_if_null(ops, dentry_open);
1036 set_to_dummy_if_null(ops, task_create); 1042 set_to_dummy_if_null(ops, task_create);
1037 set_to_dummy_if_null(ops, task_alloc_security); 1043 set_to_dummy_if_null(ops, task_alloc_security);
1038 set_to_dummy_if_null(ops, task_free_security); 1044 set_to_dummy_if_null(ops, task_free_security);
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 0e69adf63bdb..81b3dff3cbf0 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -916,3 +916,8 @@ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
916 avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); 916 avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
917 return rc; 917 return rc;
918} 918}
919
920u32 avc_policy_seqno(void)
921{
922 return avc_cache.latest_notif;
923}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index cf76150e623e..97b7e2738097 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -14,6 +14,8 @@
14 * <dgoeddel@trustedcs.com> 14 * <dgoeddel@trustedcs.com>
15 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P. 15 * Copyright (C) 2006 Hewlett-Packard Development Company, L.P.
16 * Paul Moore, <paul.moore@hp.com> 16 * Paul Moore, <paul.moore@hp.com>
17 * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd.
18 * Yuichi Nakamura <ynakam@hitachisoft.jp>
17 * 19 *
18 * This program is free software; you can redistribute it and/or modify 20 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License version 2, 21 * it under the terms of the GNU General Public License version 2,
@@ -2464,7 +2466,7 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
2464 2466
2465/* file security operations */ 2467/* file security operations */
2466 2468
2467static int selinux_file_permission(struct file *file, int mask) 2469static int selinux_revalidate_file_permission(struct file *file, int mask)
2468{ 2470{
2469 int rc; 2471 int rc;
2470 struct inode *inode = file->f_path.dentry->d_inode; 2472 struct inode *inode = file->f_path.dentry->d_inode;
@@ -2486,6 +2488,25 @@ static int selinux_file_permission(struct file *file, int mask)
2486 return selinux_netlbl_inode_permission(inode, mask); 2488 return selinux_netlbl_inode_permission(inode, mask);
2487} 2489}
2488 2490
2491static int selinux_file_permission(struct file *file, int mask)
2492{
2493 struct inode *inode = file->f_path.dentry->d_inode;
2494 struct task_security_struct *tsec = current->security;
2495 struct file_security_struct *fsec = file->f_security;
2496 struct inode_security_struct *isec = inode->i_security;
2497
2498 if (!mask) {
2499 /* No permission to check. Existence test. */
2500 return 0;
2501 }
2502
2503 if (tsec->sid == fsec->sid && fsec->isid == isec->sid
2504 && fsec->pseqno == avc_policy_seqno())
2505 return selinux_netlbl_inode_permission(inode, mask);
2506
2507 return selinux_revalidate_file_permission(file, mask);
2508}
2509
2489static int selinux_file_alloc_security(struct file *file) 2510static int selinux_file_alloc_security(struct file *file)
2490{ 2511{
2491 return file_alloc_security(file); 2512 return file_alloc_security(file);
@@ -2725,6 +2746,34 @@ static int selinux_file_receive(struct file *file)
2725 return file_has_perm(current, file, file_to_av(file)); 2746 return file_has_perm(current, file, file_to_av(file));
2726} 2747}
2727 2748
2749static int selinux_dentry_open(struct file *file)
2750{
2751 struct file_security_struct *fsec;
2752 struct inode *inode;
2753 struct inode_security_struct *isec;
2754 inode = file->f_path.dentry->d_inode;
2755 fsec = file->f_security;
2756 isec = inode->i_security;
2757 /*
2758 * Save inode label and policy sequence number
2759 * at open-time so that selinux_file_permission
2760 * can determine whether revalidation is necessary.
2761 * Task label is already saved in the file security
2762 * struct as its SID.
2763 */
2764 fsec->isid = isec->sid;
2765 fsec->pseqno = avc_policy_seqno();
2766 /*
2767 * Since the inode label or policy seqno may have changed
2768 * between the selinux_inode_permission check and the saving
2769 * of state above, recheck that access is still permitted.
2770 * Otherwise, access might never be revalidated against the
2771 * new inode label or new policy.
2772 * This check is not redundant - do not remove.
2773 */
2774 return inode_has_perm(current, inode, file_to_av(file), NULL);
2775}
2776
2728/* task security operations */ 2777/* task security operations */
2729 2778
2730static int selinux_task_create(unsigned long clone_flags) 2779static int selinux_task_create(unsigned long clone_flags)
@@ -4794,6 +4843,8 @@ static struct security_operations selinux_ops = {
4794 .file_send_sigiotask = selinux_file_send_sigiotask, 4843 .file_send_sigiotask = selinux_file_send_sigiotask,
4795 .file_receive = selinux_file_receive, 4844 .file_receive = selinux_file_receive,
4796 4845
4846 .dentry_open = selinux_dentry_open,
4847
4797 .task_create = selinux_task_create, 4848 .task_create = selinux_task_create,
4798 .task_alloc_security = selinux_task_alloc_security, 4849 .task_alloc_security = selinux_task_alloc_security,
4799 .task_free_security = selinux_task_free_security, 4850 .task_free_security = selinux_task_free_security,
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index e145f6e13b0b..553607a19e92 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -112,6 +112,8 @@ int avc_has_perm(u32 ssid, u32 tsid,
112 u16 tclass, u32 requested, 112 u16 tclass, u32 requested,
113 struct avc_audit_data *auditdata); 113 struct avc_audit_data *auditdata);
114 114
115u32 avc_policy_seqno(void);
116
115#define AVC_CALLBACK_GRANT 1 117#define AVC_CALLBACK_GRANT 1
116#define AVC_CALLBACK_TRY_REVOKE 2 118#define AVC_CALLBACK_TRY_REVOKE 2
117#define AVC_CALLBACK_REVOKE 4 119#define AVC_CALLBACK_REVOKE 4
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 91b88f0ba20c..642a9fd319ad 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -53,6 +53,8 @@ struct file_security_struct {
53 struct file *file; /* back pointer to file object */ 53 struct file *file; /* back pointer to file object */
54 u32 sid; /* SID of open file description */ 54 u32 sid; /* SID of open file description */
55 u32 fown_sid; /* SID of file owner (for SIGIO) */ 55 u32 fown_sid; /* SID of file owner (for SIGIO) */
56 u32 isid; /* SID of inode at the time of file open */
57 u32 pseqno; /* Policy seqno at the time of file open */
56}; 58};
57 59
58struct superblock_security_struct { 60struct superblock_security_struct {
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/avtab.c b/security/selinux/ss/avtab.c
index 85705eb289e0..7551af1f7899 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -12,24 +12,25 @@
12 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, version 2. 14 * the Free Software Foundation, version 2.
15 *
16 * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
17 * Tuned number of hash slots for avtab to reduce memory usage
15 */ 18 */
16 19
17#include <linux/kernel.h> 20#include <linux/kernel.h>
18#include <linux/slab.h> 21#include <linux/slab.h>
19#include <linux/vmalloc.h>
20#include <linux/errno.h> 22#include <linux/errno.h>
21
22#include "avtab.h" 23#include "avtab.h"
23#include "policydb.h" 24#include "policydb.h"
24 25
25#define AVTAB_HASH(keyp) \
26((keyp->target_class + \
27 (keyp->target_type << 2) + \
28 (keyp->source_type << 9)) & \
29 AVTAB_HASH_MASK)
30
31static struct kmem_cache *avtab_node_cachep; 26static struct kmem_cache *avtab_node_cachep;
32 27
28static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
29{
30 return ((keyp->target_class + (keyp->target_type << 2) +
31 (keyp->source_type << 9)) & mask);
32}
33
33static struct avtab_node* 34static struct avtab_node*
34avtab_insert_node(struct avtab *h, int hvalue, 35avtab_insert_node(struct avtab *h, int hvalue,
35 struct avtab_node * prev, struct avtab_node * cur, 36 struct avtab_node * prev, struct avtab_node * cur,
@@ -59,10 +60,10 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
59 struct avtab_node *prev, *cur, *newnode; 60 struct avtab_node *prev, *cur, *newnode;
60 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 61 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
61 62
62 if (!h) 63 if (!h || !h->htable)
63 return -EINVAL; 64 return -EINVAL;
64 65
65 hvalue = AVTAB_HASH(key); 66 hvalue = avtab_hash(key, h->mask);
66 for (prev = NULL, cur = h->htable[hvalue]; 67 for (prev = NULL, cur = h->htable[hvalue];
67 cur; 68 cur;
68 prev = cur, cur = cur->next) { 69 prev = cur, cur = cur->next) {
@@ -100,9 +101,9 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
100 struct avtab_node *prev, *cur, *newnode; 101 struct avtab_node *prev, *cur, *newnode;
101 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
102 103
103 if (!h) 104 if (!h || !h->htable)
104 return NULL; 105 return NULL;
105 hvalue = AVTAB_HASH(key); 106 hvalue = avtab_hash(key, h->mask);
106 for (prev = NULL, cur = h->htable[hvalue]; 107 for (prev = NULL, cur = h->htable[hvalue];
107 cur; 108 cur;
108 prev = cur, cur = cur->next) { 109 prev = cur, cur = cur->next) {
@@ -132,10 +133,10 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
132 struct avtab_node *cur; 133 struct avtab_node *cur;
133 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 134 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
134 135
135 if (!h) 136 if (!h || !h->htable)
136 return NULL; 137 return NULL;
137 138
138 hvalue = AVTAB_HASH(key); 139 hvalue = avtab_hash(key, h->mask);
139 for (cur = h->htable[hvalue]; cur; cur = cur->next) { 140 for (cur = h->htable[hvalue]; cur; cur = cur->next) {
140 if (key->source_type == cur->key.source_type && 141 if (key->source_type == cur->key.source_type &&
141 key->target_type == cur->key.target_type && 142 key->target_type == cur->key.target_type &&
@@ -167,10 +168,10 @@ avtab_search_node(struct avtab *h, struct avtab_key *key)
167 struct avtab_node *cur; 168 struct avtab_node *cur;
168 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 169 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
169 170
170 if (!h) 171 if (!h || !h->htable)
171 return NULL; 172 return NULL;
172 173
173 hvalue = AVTAB_HASH(key); 174 hvalue = avtab_hash(key, h->mask);
174 for (cur = h->htable[hvalue]; cur; cur = cur->next) { 175 for (cur = h->htable[hvalue]; cur; cur = cur->next) {
175 if (key->source_type == cur->key.source_type && 176 if (key->source_type == cur->key.source_type &&
176 key->target_type == cur->key.target_type && 177 key->target_type == cur->key.target_type &&
@@ -228,7 +229,7 @@ void avtab_destroy(struct avtab *h)
228 if (!h || !h->htable) 229 if (!h || !h->htable)
229 return; 230 return;
230 231
231 for (i = 0; i < AVTAB_SIZE; i++) { 232 for (i = 0; i < h->nslot; i++) {
232 cur = h->htable[i]; 233 cur = h->htable[i];
233 while (cur != NULL) { 234 while (cur != NULL) {
234 temp = cur; 235 temp = cur;
@@ -237,32 +238,63 @@ void avtab_destroy(struct avtab *h)
237 } 238 }
238 h->htable[i] = NULL; 239 h->htable[i] = NULL;
239 } 240 }
240 vfree(h->htable); 241 kfree(h->htable);
241 h->htable = NULL; 242 h->htable = NULL;
243 h->nslot = 0;
244 h->mask = 0;
242} 245}
243 246
244
245int avtab_init(struct avtab *h) 247int avtab_init(struct avtab *h)
246{ 248{
247 int i; 249 h->htable = NULL;
250 h->nel = 0;
251 return 0;
252}
253
254int avtab_alloc(struct avtab *h, u32 nrules)
255{
256 u16 mask = 0;
257 u32 shift = 0;
258 u32 work = nrules;
259 u32 nslot = 0;
260
261 if (nrules == 0)
262 goto avtab_alloc_out;
248 263
249 h->htable = vmalloc(sizeof(*(h->htable)) * AVTAB_SIZE); 264 while (work) {
265 work = work >> 1;
266 shift++;
267 }
268 if (shift > 2)
269 shift = shift - 2;
270 nslot = 1 << shift;
271 if (nslot > MAX_AVTAB_SIZE)
272 nslot = MAX_AVTAB_SIZE;
273 mask = nslot - 1;
274
275 h->htable = kcalloc(nslot, sizeof(*(h->htable)), GFP_KERNEL);
250 if (!h->htable) 276 if (!h->htable)
251 return -ENOMEM; 277 return -ENOMEM;
252 for (i = 0; i < AVTAB_SIZE; i++) 278
253 h->htable[i] = NULL; 279 avtab_alloc_out:
254 h->nel = 0; 280 h->nel = 0;
281 h->nslot = nslot;
282 h->mask = mask;
283 printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated."
284 "Num of rules:%d\n", h->nslot, nrules);
255 return 0; 285 return 0;
256} 286}
257 287
258void avtab_hash_eval(struct avtab *h, char *tag) 288void avtab_hash_eval(struct avtab *h, char *tag)
259{ 289{
260 int i, chain_len, slots_used, max_chain_len; 290 int i, chain_len, slots_used, max_chain_len;
291 unsigned long long chain2_len_sum;
261 struct avtab_node *cur; 292 struct avtab_node *cur;
262 293
263 slots_used = 0; 294 slots_used = 0;
264 max_chain_len = 0; 295 max_chain_len = 0;
265 for (i = 0; i < AVTAB_SIZE; i++) { 296 chain2_len_sum = 0;
297 for (i = 0; i < h->nslot; i++) {
266 cur = h->htable[i]; 298 cur = h->htable[i];
267 if (cur) { 299 if (cur) {
268 slots_used++; 300 slots_used++;
@@ -274,12 +306,14 @@ void avtab_hash_eval(struct avtab *h, char *tag)
274 306
275 if (chain_len > max_chain_len) 307 if (chain_len > max_chain_len)
276 max_chain_len = chain_len; 308 max_chain_len = chain_len;
309 chain2_len_sum += chain_len * chain_len;
277 } 310 }
278 } 311 }
279 312
280 printk(KERN_DEBUG "%s: %d entries and %d/%d buckets used, longest " 313 printk(KERN_DEBUG "%s: %d entries and %d/%d buckets used, longest "
281 "chain length %d\n", tag, h->nel, slots_used, AVTAB_SIZE, 314 "chain length %d sum of chain length^2 %Lu\n",
282 max_chain_len); 315 tag, h->nel, slots_used, h->nslot, max_chain_len,
316 chain2_len_sum);
283} 317}
284 318
285static uint16_t spec_order[] = { 319static uint16_t spec_order[] = {
@@ -419,6 +453,11 @@ int avtab_read(struct avtab *a, void *fp, u32 vers)
419 rc = -EINVAL; 453 rc = -EINVAL;
420 goto bad; 454 goto bad;
421 } 455 }
456
457 rc = avtab_alloc(a, nel);
458 if (rc)
459 goto bad;
460
422 for (i = 0; i < nel; i++) { 461 for (i = 0; i < nel; i++) {
423 rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL); 462 rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
424 if (rc) { 463 if (rc) {
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 0a90d939af93..d8edf8ca56d1 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -16,6 +16,9 @@
16 * This program is free software; you can redistribute it and/or modify 16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, version 2. 18 * the Free Software Foundation, version 2.
19 *
20 * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
21 * Tuned number of hash slots for avtab to reduce memory usage
19 */ 22 */
20#ifndef _SS_AVTAB_H_ 23#ifndef _SS_AVTAB_H_
21#define _SS_AVTAB_H_ 24#define _SS_AVTAB_H_
@@ -50,9 +53,13 @@ struct avtab_node {
50struct avtab { 53struct avtab {
51 struct avtab_node **htable; 54 struct avtab_node **htable;
52 u32 nel; /* number of elements */ 55 u32 nel; /* number of elements */
56 u32 nslot; /* number of hash slots */
57 u16 mask; /* mask to compute hash func */
58
53}; 59};
54 60
55int avtab_init(struct avtab *); 61int avtab_init(struct avtab *);
62int avtab_alloc(struct avtab *, u32);
56struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k); 63struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
57void avtab_destroy(struct avtab *h); 64void avtab_destroy(struct avtab *h);
58void avtab_hash_eval(struct avtab *h, char *tag); 65void avtab_hash_eval(struct avtab *h, char *tag);
@@ -74,11 +81,10 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified
74void avtab_cache_init(void); 81void avtab_cache_init(void);
75void avtab_cache_destroy(void); 82void avtab_cache_destroy(void);
76 83
77#define AVTAB_HASH_BITS 15 84#define MAX_AVTAB_HASH_BITS 13
78#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS) 85#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
79#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1) 86#define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)
80 87#define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS
81#define AVTAB_SIZE AVTAB_HASH_BUCKETS
82 88
83#endif /* _SS_AVTAB_H_ */ 89#endif /* _SS_AVTAB_H_ */
84 90
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index d2737edba541..45b93a827c80 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -456,6 +456,10 @@ int cond_read_list(struct policydb *p, void *fp)
456 456
457 len = le32_to_cpu(buf[0]); 457 len = le32_to_cpu(buf[0]);
458 458
459 rc = avtab_alloc(&(p->te_cond_avtab), p->te_avtab.nel);
460 if (rc)
461 goto err;
462
459 for (i = 0; i < len; i++) { 463 for (i = 0; i < len; i++) {
460 node = kzalloc(sizeof(struct cond_node), GFP_KERNEL); 464 node = kzalloc(sizeof(struct cond_node), GFP_KERNEL);
461 if (!node) 465 if (!node)
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ce492a6b38ed..c1a6b22d48d9 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -10,6 +10,10 @@
10 * 10 *
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
12 */ 12 */
13/*
14 * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
15 * Applied standard bit operations to improve bitmap scanning.
16 */
13 17
14#include <linux/kernel.h> 18#include <linux/kernel.h>
15#include <linux/slab.h> 19#include <linux/slab.h>
@@ -29,7 +33,7 @@ int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
29 n2 = e2->node; 33 n2 = e2->node;
30 while (n1 && n2 && 34 while (n1 && n2 &&
31 (n1->startbit == n2->startbit) && 35 (n1->startbit == n2->startbit) &&
32 (n1->map == n2->map)) { 36 !memcmp(n1->maps, n2->maps, EBITMAP_SIZE / 8)) {
33 n1 = n1->next; 37 n1 = n1->next;
34 n2 = n2->next; 38 n2 = n2->next;
35 } 39 }
@@ -54,7 +58,7 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src)
54 return -ENOMEM; 58 return -ENOMEM;
55 } 59 }
56 new->startbit = n->startbit; 60 new->startbit = n->startbit;
57 new->map = n->map; 61 memcpy(new->maps, n->maps, EBITMAP_SIZE / 8);
58 new->next = NULL; 62 new->next = NULL;
59 if (prev) 63 if (prev)
60 prev->next = new; 64 prev->next = new;
@@ -84,13 +88,15 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
84{ 88{
85 struct ebitmap_node *e_iter = ebmap->node; 89 struct ebitmap_node *e_iter = ebmap->node;
86 struct netlbl_lsm_secattr_catmap *c_iter; 90 struct netlbl_lsm_secattr_catmap *c_iter;
87 u32 cmap_idx; 91 u32 cmap_idx, cmap_sft;
92 int i;
88 93
89 /* This function is a much simpler because SELinux's MAPTYPE happens 94 /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
90 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is 95 * however, it is not always compatible with an array of unsigned long
91 * changed from a u64 this function will most likely need to be changed 96 * in ebitmap_node.
92 * as well. It's not ideal but I think the tradeoff in terms of 97 * In addition, you should pay attention the following implementation
93 * neatness and speed is worth it. */ 98 * assumes unsigned long has a width equal with or less than 64-bit.
99 */
94 100
95 if (e_iter == NULL) { 101 if (e_iter == NULL) {
96 *catmap = NULL; 102 *catmap = NULL;
@@ -104,19 +110,27 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
104 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); 110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
105 111
106 while (e_iter != NULL) { 112 while (e_iter != NULL) {
107 if (e_iter->startbit >= 113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
108 (c_iter->startbit + NETLBL_CATMAP_SIZE)) { 114 unsigned int delta, e_startbit, c_endbit;
109 c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC); 115
110 if (c_iter->next == NULL) 116 e_startbit = e_iter->startbit + i * EBITMAP_UNIT_SIZE;
111 goto netlbl_export_failure; 117 c_endbit = c_iter->startbit + NETLBL_CATMAP_SIZE;
112 c_iter = c_iter->next; 118 if (e_startbit >= c_endbit) {
113 c_iter->startbit = e_iter->startbit & 119 c_iter->next
114 ~(NETLBL_CATMAP_SIZE - 1); 120 = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
121 if (c_iter->next == NULL)
122 goto netlbl_export_failure;
123 c_iter = c_iter->next;
124 c_iter->startbit
125 = e_startbit & ~(NETLBL_CATMAP_SIZE - 1);
126 }
127 delta = e_startbit - c_iter->startbit;
128 cmap_idx = delta / NETLBL_CATMAP_MAPSIZE;
129 cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
130 c_iter->bitmap[cmap_idx]
131 |= e_iter->maps[cmap_idx] << cmap_sft;
132 e_iter = e_iter->next;
115 } 133 }
116 cmap_idx = (e_iter->startbit - c_iter->startbit) /
117 NETLBL_CATMAP_MAPSIZE;
118 c_iter->bitmap[cmap_idx] = e_iter->map;
119 e_iter = e_iter->next;
120 } 134 }
121 135
122 return 0; 136 return 0;
@@ -128,7 +142,7 @@ netlbl_export_failure:
128 142
129/** 143/**
130 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap 144 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
131 * @ebmap: the ebitmap to export 145 * @ebmap: the ebitmap to import
132 * @catmap: the NetLabel category bitmap 146 * @catmap: the NetLabel category bitmap
133 * 147 *
134 * Description: 148 * Description:
@@ -142,36 +156,50 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
142 struct ebitmap_node *e_iter = NULL; 156 struct ebitmap_node *e_iter = NULL;
143 struct ebitmap_node *emap_prev = NULL; 157 struct ebitmap_node *emap_prev = NULL;
144 struct netlbl_lsm_secattr_catmap *c_iter = catmap; 158 struct netlbl_lsm_secattr_catmap *c_iter = catmap;
145 u32 c_idx; 159 u32 c_idx, c_pos, e_idx, e_sft;
146 160
147 /* This function is a much simpler because SELinux's MAPTYPE happens 161 /* NetLabel's NETLBL_CATMAP_MAPTYPE is defined as an array of u64,
148 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is 162 * however, it is not always compatible with an array of unsigned long
149 * changed from a u64 this function will most likely need to be changed 163 * in ebitmap_node.
150 * as well. It's not ideal but I think the tradeoff in terms of 164 * In addition, you should pay attention the following implementation
151 * neatness and speed is worth it. */ 165 * assumes unsigned long has a width equal with or less than 64-bit.
166 */
152 167
153 do { 168 do {
154 for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) { 169 for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
155 if (c_iter->bitmap[c_idx] == 0) 170 unsigned int delta;
171 u64 map = c_iter->bitmap[c_idx];
172
173 if (!map)
156 continue; 174 continue;
157 175
158 e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC); 176 c_pos = c_iter->startbit
159 if (e_iter == NULL) 177 + c_idx * NETLBL_CATMAP_MAPSIZE;
160 goto netlbl_import_failure; 178 if (!e_iter
161 if (emap_prev == NULL) 179 || c_pos >= e_iter->startbit + EBITMAP_SIZE) {
162 ebmap->node = e_iter; 180 e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
163 else 181 if (!e_iter)
164 emap_prev->next = e_iter; 182 goto netlbl_import_failure;
165 emap_prev = e_iter; 183 e_iter->startbit
166 184 = c_pos - (c_pos % EBITMAP_SIZE);
167 e_iter->startbit = c_iter->startbit + 185 if (emap_prev == NULL)
168 NETLBL_CATMAP_MAPSIZE * c_idx; 186 ebmap->node = e_iter;
169 e_iter->map = c_iter->bitmap[c_idx]; 187 else
188 emap_prev->next = e_iter;
189 emap_prev = e_iter;
190 }
191 delta = c_pos - e_iter->startbit;
192 e_idx = delta / EBITMAP_UNIT_SIZE;
193 e_sft = delta % EBITMAP_UNIT_SIZE;
194 while (map) {
195 e_iter->maps[e_idx++] |= map & (-1UL);
196 map = EBITMAP_SHIFT_UNIT_SIZE(map);
197 }
170 } 198 }
171 c_iter = c_iter->next; 199 c_iter = c_iter->next;
172 } while (c_iter != NULL); 200 } while (c_iter != NULL);
173 if (e_iter != NULL) 201 if (e_iter != NULL)
174 ebmap->highbit = e_iter->startbit + MAPSIZE; 202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
175 else 203 else
176 ebitmap_destroy(ebmap); 204 ebitmap_destroy(ebmap);
177 205
@@ -186,6 +214,7 @@ netlbl_import_failure:
186int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) 214int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
187{ 215{
188 struct ebitmap_node *n1, *n2; 216 struct ebitmap_node *n1, *n2;
217 int i;
189 218
190 if (e1->highbit < e2->highbit) 219 if (e1->highbit < e2->highbit)
191 return 0; 220 return 0;
@@ -197,8 +226,10 @@ int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
197 n1 = n1->next; 226 n1 = n1->next;
198 continue; 227 continue;
199 } 228 }
200 if ((n1->map & n2->map) != n2->map) 229 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
201 return 0; 230 if ((n1->maps[i] & n2->maps[i]) != n2->maps[i])
231 return 0;
232 }
202 233
203 n1 = n1->next; 234 n1 = n1->next;
204 n2 = n2->next; 235 n2 = n2->next;
@@ -219,12 +250,8 @@ int ebitmap_get_bit(struct ebitmap *e, unsigned long bit)
219 250
220 n = e->node; 251 n = e->node;
221 while (n && (n->startbit <= bit)) { 252 while (n && (n->startbit <= bit)) {
222 if ((n->startbit + MAPSIZE) > bit) { 253 if ((n->startbit + EBITMAP_SIZE) > bit)
223 if (n->map & (MAPBIT << (bit - n->startbit))) 254 return ebitmap_node_get_bit(n, bit);
224 return 1;
225 else
226 return 0;
227 }
228 n = n->next; 255 n = n->next;
229 } 256 }
230 257
@@ -238,31 +265,35 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
238 prev = NULL; 265 prev = NULL;
239 n = e->node; 266 n = e->node;
240 while (n && n->startbit <= bit) { 267 while (n && n->startbit <= bit) {
241 if ((n->startbit + MAPSIZE) > bit) { 268 if ((n->startbit + EBITMAP_SIZE) > bit) {
242 if (value) { 269 if (value) {
243 n->map |= (MAPBIT << (bit - n->startbit)); 270 ebitmap_node_set_bit(n, bit);
244 } else { 271 } else {
245 n->map &= ~(MAPBIT << (bit - n->startbit)); 272 unsigned int s;
246 if (!n->map) { 273
247 /* drop this node from the bitmap */ 274 ebitmap_node_clr_bit(n, bit);
248 275
249 if (!n->next) { 276 s = find_first_bit(n->maps, EBITMAP_SIZE);
250 /* 277 if (s < EBITMAP_SIZE)
251 * this was the highest map 278 return 0;
252 * within the bitmap 279
253 */ 280 /* drop this node from the bitmap */
254 if (prev) 281 if (!n->next) {
255 e->highbit = prev->startbit + MAPSIZE; 282 /*
256 else 283 * this was the highest map
257 e->highbit = 0; 284 * within the bitmap
258 } 285 */
259 if (prev) 286 if (prev)
260 prev->next = n->next; 287 e->highbit = prev->startbit
288 + EBITMAP_SIZE;
261 else 289 else
262 e->node = n->next; 290 e->highbit = 0;
263
264 kfree(n);
265 } 291 }
292 if (prev)
293 prev->next = n->next;
294 else
295 e->node = n->next;
296 kfree(n);
266 } 297 }
267 return 0; 298 return 0;
268 } 299 }
@@ -277,12 +308,12 @@ int ebitmap_set_bit(struct ebitmap *e, unsigned long bit, int value)
277 if (!new) 308 if (!new)
278 return -ENOMEM; 309 return -ENOMEM;
279 310
280 new->startbit = bit & ~(MAPSIZE - 1); 311 new->startbit = bit - (bit % EBITMAP_SIZE);
281 new->map = (MAPBIT << (bit - new->startbit)); 312 ebitmap_node_set_bit(new, bit);
282 313
283 if (!n) 314 if (!n)
284 /* this node will be the highest map within the bitmap */ 315 /* this node will be the highest map within the bitmap */
285 e->highbit = new->startbit + MAPSIZE; 316 e->highbit = new->startbit + EBITMAP_SIZE;
286 317
287 if (prev) { 318 if (prev) {
288 new->next = prev->next; 319 new->next = prev->next;
@@ -316,11 +347,11 @@ void ebitmap_destroy(struct ebitmap *e)
316 347
317int ebitmap_read(struct ebitmap *e, void *fp) 348int ebitmap_read(struct ebitmap *e, void *fp)
318{ 349{
319 int rc; 350 struct ebitmap_node *n = NULL;
320 struct ebitmap_node *n, *l; 351 u32 mapunit, count, startbit, index;
352 u64 map;
321 __le32 buf[3]; 353 __le32 buf[3];
322 u32 mapsize, count, i; 354 int rc, i;
323 __le64 map;
324 355
325 ebitmap_init(e); 356 ebitmap_init(e);
326 357
@@ -328,85 +359,88 @@ int ebitmap_read(struct ebitmap *e, void *fp)
328 if (rc < 0) 359 if (rc < 0)
329 goto out; 360 goto out;
330 361
331 mapsize = le32_to_cpu(buf[0]); 362 mapunit = le32_to_cpu(buf[0]);
332 e->highbit = le32_to_cpu(buf[1]); 363 e->highbit = le32_to_cpu(buf[1]);
333 count = le32_to_cpu(buf[2]); 364 count = le32_to_cpu(buf[2]);
334 365
335 if (mapsize != MAPSIZE) { 366 if (mapunit != sizeof(u64) * 8) {
336 printk(KERN_ERR "security: ebitmap: map size %u does not " 367 printk(KERN_ERR "security: ebitmap: map size %u does not "
337 "match my size %Zd (high bit was %d)\n", mapsize, 368 "match my size %Zd (high bit was %d)\n",
338 MAPSIZE, e->highbit); 369 mapunit, sizeof(u64) * 8, e->highbit);
339 goto bad; 370 goto bad;
340 } 371 }
372
373 /* round up e->highbit */
374 e->highbit += EBITMAP_SIZE - 1;
375 e->highbit -= (e->highbit % EBITMAP_SIZE);
376
341 if (!e->highbit) { 377 if (!e->highbit) {
342 e->node = NULL; 378 e->node = NULL;
343 goto ok; 379 goto ok;
344 } 380 }
345 if (e->highbit & (MAPSIZE - 1)) { 381
346 printk(KERN_ERR "security: ebitmap: high bit (%d) is not a "
347 "multiple of the map size (%Zd)\n", e->highbit, MAPSIZE);
348 goto bad;
349 }
350 l = NULL;
351 for (i = 0; i < count; i++) { 382 for (i = 0; i < count; i++) {
352 rc = next_entry(buf, fp, sizeof(u32)); 383 rc = next_entry(&startbit, fp, sizeof(u32));
353 if (rc < 0) { 384 if (rc < 0) {
354 printk(KERN_ERR "security: ebitmap: truncated map\n"); 385 printk(KERN_ERR "security: ebitmap: truncated map\n");
355 goto bad; 386 goto bad;
356 } 387 }
357 n = kzalloc(sizeof(*n), GFP_KERNEL); 388 startbit = le32_to_cpu(startbit);
358 if (!n) {
359 printk(KERN_ERR "security: ebitmap: out of memory\n");
360 rc = -ENOMEM;
361 goto bad;
362 }
363
364 n->startbit = le32_to_cpu(buf[0]);
365 389
366 if (n->startbit & (MAPSIZE - 1)) { 390 if (startbit & (mapunit - 1)) {
367 printk(KERN_ERR "security: ebitmap start bit (%d) is " 391 printk(KERN_ERR "security: ebitmap start bit (%d) is "
368 "not a multiple of the map size (%Zd)\n", 392 "not a multiple of the map unit size (%u)\n",
369 n->startbit, MAPSIZE); 393 startbit, mapunit);
370 goto bad_free; 394 goto bad;
371 } 395 }
372 if (n->startbit > (e->highbit - MAPSIZE)) { 396 if (startbit > e->highbit - mapunit) {
373 printk(KERN_ERR "security: ebitmap start bit (%d) is " 397 printk(KERN_ERR "security: ebitmap start bit (%d) is "
374 "beyond the end of the bitmap (%Zd)\n", 398 "beyond the end of the bitmap (%u)\n",
375 n->startbit, (e->highbit - MAPSIZE)); 399 startbit, (e->highbit - mapunit));
376 goto bad_free; 400 goto bad;
401 }
402
403 if (!n || startbit >= n->startbit + EBITMAP_SIZE) {
404 struct ebitmap_node *tmp;
405 tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
406 if (!tmp) {
407 printk(KERN_ERR
408 "security: ebitmap: out of memory\n");
409 rc = -ENOMEM;
410 goto bad;
411 }
412 /* round down */
413 tmp->startbit = startbit - (startbit % EBITMAP_SIZE);
414 if (n) {
415 n->next = tmp;
416 } else {
417 e->node = tmp;
418 }
419 n = tmp;
420 } else if (startbit <= n->startbit) {
421 printk(KERN_ERR "security: ebitmap: start bit %d"
422 " comes after start bit %d\n",
423 startbit, n->startbit);
424 goto bad;
377 } 425 }
426
378 rc = next_entry(&map, fp, sizeof(u64)); 427 rc = next_entry(&map, fp, sizeof(u64));
379 if (rc < 0) { 428 if (rc < 0) {
380 printk(KERN_ERR "security: ebitmap: truncated map\n"); 429 printk(KERN_ERR "security: ebitmap: truncated map\n");
381 goto bad_free; 430 goto bad;
382 } 431 }
383 n->map = le64_to_cpu(map); 432 map = le64_to_cpu(map);
384 433
385 if (!n->map) { 434 index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE;
386 printk(KERN_ERR "security: ebitmap: null map in " 435 while (map) {
387 "ebitmap (startbit %d)\n", n->startbit); 436 n->maps[index++] = map & (-1UL);
388 goto bad_free; 437 map = EBITMAP_SHIFT_UNIT_SIZE(map);
389 } 438 }
390 if (l) {
391 if (n->startbit <= l->startbit) {
392 printk(KERN_ERR "security: ebitmap: start "
393 "bit %d comes after start bit %d\n",
394 n->startbit, l->startbit);
395 goto bad_free;
396 }
397 l->next = n;
398 } else
399 e->node = n;
400
401 l = n;
402 } 439 }
403
404ok: 440ok:
405 rc = 0; 441 rc = 0;
406out: 442out:
407 return rc; 443 return rc;
408bad_free:
409 kfree(n);
410bad: 444bad:
411 if (!rc) 445 if (!rc)
412 rc = -EINVAL; 446 rc = -EINVAL;
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 1270e34b61c1..f283b4367f54 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -16,14 +16,18 @@
16 16
17#include <net/netlabel.h> 17#include <net/netlabel.h>
18 18
19#define MAPTYPE u64 /* portion of bitmap in each node */ 19#define EBITMAP_UNIT_NUMS ((32 - sizeof(void *) - sizeof(u32)) \
20#define MAPSIZE (sizeof(MAPTYPE) * 8) /* number of bits in node bitmap */ 20 / sizeof(unsigned long))
21#define MAPBIT 1ULL /* a bit in the node bitmap */ 21#define EBITMAP_UNIT_SIZE BITS_PER_LONG
22#define EBITMAP_SIZE (EBITMAP_UNIT_NUMS * EBITMAP_UNIT_SIZE)
23#define EBITMAP_BIT 1ULL
24#define EBITMAP_SHIFT_UNIT_SIZE(x) \
25 (((x) >> EBITMAP_UNIT_SIZE / 2) >> EBITMAP_UNIT_SIZE / 2)
22 26
23struct ebitmap_node { 27struct ebitmap_node {
24 u32 startbit; /* starting position in the total bitmap */
25 MAPTYPE map; /* this node's portion of the bitmap */
26 struct ebitmap_node *next; 28 struct ebitmap_node *next;
29 unsigned long maps[EBITMAP_UNIT_NUMS];
30 u32 startbit;
27}; 31};
28 32
29struct ebitmap { 33struct ebitmap {
@@ -34,11 +38,17 @@ struct ebitmap {
34#define ebitmap_length(e) ((e)->highbit) 38#define ebitmap_length(e) ((e)->highbit)
35#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) 39#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
36 40
37static inline unsigned int ebitmap_start(struct ebitmap *e, 41static inline unsigned int ebitmap_start_positive(struct ebitmap *e,
38 struct ebitmap_node **n) 42 struct ebitmap_node **n)
39{ 43{
40 *n = e->node; 44 unsigned int ofs;
41 return ebitmap_startbit(e); 45
46 for (*n = e->node; *n; *n = (*n)->next) {
47 ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
48 if (ofs < EBITMAP_SIZE)
49 return (*n)->startbit + ofs;
50 }
51 return ebitmap_length(e);
42} 52}
43 53
44static inline void ebitmap_init(struct ebitmap *e) 54static inline void ebitmap_init(struct ebitmap *e)
@@ -46,28 +56,65 @@ static inline void ebitmap_init(struct ebitmap *e)
46 memset(e, 0, sizeof(*e)); 56 memset(e, 0, sizeof(*e));
47} 57}
48 58
49static inline unsigned int ebitmap_next(struct ebitmap_node **n, 59static inline unsigned int ebitmap_next_positive(struct ebitmap *e,
50 unsigned int bit) 60 struct ebitmap_node **n,
61 unsigned int bit)
51{ 62{
52 if ((bit == ((*n)->startbit + MAPSIZE - 1)) && 63 unsigned int ofs;
53 (*n)->next) { 64
54 *n = (*n)->next; 65 ofs = find_next_bit((*n)->maps, EBITMAP_SIZE, bit - (*n)->startbit + 1);
55 return (*n)->startbit; 66 if (ofs < EBITMAP_SIZE)
56 } 67 return ofs + (*n)->startbit;
57 68
58 return (bit+1); 69 for (*n = (*n)->next; *n; *n = (*n)->next) {
70 ofs = find_first_bit((*n)->maps, EBITMAP_SIZE);
71 if (ofs < EBITMAP_SIZE)
72 return ofs + (*n)->startbit;
73 }
74 return ebitmap_length(e);
59} 75}
60 76
61static inline int ebitmap_node_get_bit(struct ebitmap_node * n, 77#define EBITMAP_NODE_INDEX(node, bit) \
78 (((bit) - (node)->startbit) / EBITMAP_UNIT_SIZE)
79#define EBITMAP_NODE_OFFSET(node, bit) \
80 (((bit) - (node)->startbit) % EBITMAP_UNIT_SIZE)
81
82static inline int ebitmap_node_get_bit(struct ebitmap_node *n,
62 unsigned int bit) 83 unsigned int bit)
63{ 84{
64 if (n->map & (MAPBIT << (bit - n->startbit))) 85 unsigned int index = EBITMAP_NODE_INDEX(n, bit);
86 unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
87
88 BUG_ON(index >= EBITMAP_UNIT_NUMS);
89 if ((n->maps[index] & (EBITMAP_BIT << ofs)))
65 return 1; 90 return 1;
66 return 0; 91 return 0;
67} 92}
68 93
69#define ebitmap_for_each_bit(e, n, bit) \ 94static inline void ebitmap_node_set_bit(struct ebitmap_node *n,
70 for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \ 95 unsigned int bit)
96{
97 unsigned int index = EBITMAP_NODE_INDEX(n, bit);
98 unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
99
100 BUG_ON(index >= EBITMAP_UNIT_NUMS);
101 n->maps[index] |= (EBITMAP_BIT << ofs);
102}
103
104static inline void ebitmap_node_clr_bit(struct ebitmap_node *n,
105 unsigned int bit)
106{
107 unsigned int index = EBITMAP_NODE_INDEX(n, bit);
108 unsigned int ofs = EBITMAP_NODE_OFFSET(n, bit);
109
110 BUG_ON(index >= EBITMAP_UNIT_NUMS);
111 n->maps[index] &= ~(EBITMAP_BIT << ofs);
112}
113
114#define ebitmap_for_each_positive_bit(e, n, bit) \
115 for (bit = ebitmap_start_positive(e, &n); \
116 bit < ebitmap_length(e); \
117 bit = ebitmap_next_positive(e, &n, bit)) \
71 118
72int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); 119int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
73int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); 120int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 4a8bab2f3c71..9a11deaaa9e7 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -34,7 +34,9 @@
34 */ 34 */
35int mls_compute_context_len(struct context * context) 35int mls_compute_context_len(struct context * context)
36{ 36{
37 int i, l, len, range; 37 int i, l, len, head, prev;
38 char *nm;
39 struct ebitmap *e;
38 struct ebitmap_node *node; 40 struct ebitmap_node *node;
39 41
40 if (!selinux_mls_enabled) 42 if (!selinux_mls_enabled)
@@ -42,31 +44,33 @@ int mls_compute_context_len(struct context * context)
42 44
43 len = 1; /* for the beginning ":" */ 45 len = 1; /* for the beginning ":" */
44 for (l = 0; l < 2; l++) { 46 for (l = 0; l < 2; l++) {
45 range = 0; 47 int index_sens = context->range.level[l].sens;
46 len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); 48 len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
47
48 ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
49 if (ebitmap_node_get_bit(node, i)) {
50 if (range) {
51 range++;
52 continue;
53 }
54 49
55 len += strlen(policydb.p_cat_val_to_name[i]) + 1; 50 /* categories */
56 range++; 51 head = -2;
57 } else { 52 prev = -2;
58 if (range > 1) 53 e = &context->range.level[l].cat;
59 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; 54 ebitmap_for_each_positive_bit(e, node, i) {
60 range = 0; 55 if (i - prev > 1) {
56 /* one or more negative bits are skipped */
57 if (head != prev) {
58 nm = policydb.p_cat_val_to_name[prev];
59 len += strlen(nm) + 1;
60 }
61 nm = policydb.p_cat_val_to_name[i];
62 len += strlen(nm) + 1;
63 head = i;
61 } 64 }
65 prev = i;
66 }
67 if (prev != head) {
68 nm = policydb.p_cat_val_to_name[prev];
69 len += strlen(nm) + 1;
62 } 70 }
63 /* Handle case where last category is the end of range */
64 if (range > 1)
65 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
66
67 if (l == 0) { 71 if (l == 0) {
68 if (mls_level_eq(&context->range.level[0], 72 if (mls_level_eq(&context->range.level[0],
69 &context->range.level[1])) 73 &context->range.level[1]))
70 break; 74 break;
71 else 75 else
72 len++; 76 len++;
@@ -84,8 +88,9 @@ int mls_compute_context_len(struct context * context)
84void mls_sid_to_context(struct context *context, 88void mls_sid_to_context(struct context *context,
85 char **scontext) 89 char **scontext)
86{ 90{
87 char *scontextp; 91 char *scontextp, *nm;
88 int i, l, range, wrote_sep; 92 int i, l, head, prev;
93 struct ebitmap *e;
89 struct ebitmap_node *node; 94 struct ebitmap_node *node;
90 95
91 if (!selinux_mls_enabled) 96 if (!selinux_mls_enabled)
@@ -97,61 +102,54 @@ void mls_sid_to_context(struct context *context,
97 scontextp++; 102 scontextp++;
98 103
99 for (l = 0; l < 2; l++) { 104 for (l = 0; l < 2; l++) {
100 range = 0;
101 wrote_sep = 0;
102 strcpy(scontextp, 105 strcpy(scontextp,
103 policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); 106 policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
104 scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); 107 scontextp += strlen(scontextp);
105 108
106 /* categories */ 109 /* categories */
107 ebitmap_for_each_bit(&context->range.level[l].cat, node, i) { 110 head = -2;
108 if (ebitmap_node_get_bit(node, i)) { 111 prev = -2;
109 if (range) { 112 e = &context->range.level[l].cat;
110 range++; 113 ebitmap_for_each_positive_bit(e, node, i) {
111 continue; 114 if (i - prev > 1) {
112 } 115 /* one or more negative bits are skipped */
113 116 if (prev != head) {
114 if (!wrote_sep) { 117 if (prev - head > 1)
115 *scontextp++ = ':';
116 wrote_sep = 1;
117 } else
118 *scontextp++ = ',';
119 strcpy(scontextp, policydb.p_cat_val_to_name[i]);
120 scontextp += strlen(policydb.p_cat_val_to_name[i]);
121 range++;
122 } else {
123 if (range > 1) {
124 if (range > 2)
125 *scontextp++ = '.'; 118 *scontextp++ = '.';
126 else 119 else
127 *scontextp++ = ','; 120 *scontextp++ = ',';
128 121 nm = policydb.p_cat_val_to_name[prev];
129 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); 122 strcpy(scontextp, nm);
130 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); 123 scontextp += strlen(nm);
131 } 124 }
132 range = 0; 125 if (prev < 0)
126 *scontextp++ = ':';
127 else
128 *scontextp++ = ',';
129 nm = policydb.p_cat_val_to_name[i];
130 strcpy(scontextp, nm);
131 scontextp += strlen(nm);
132 head = i;
133 } 133 }
134 prev = i;
134 } 135 }
135 136
136 /* Handle case where last category is the end of range */ 137 if (prev != head) {
137 if (range > 1) { 138 if (prev - head > 1)
138 if (range > 2)
139 *scontextp++ = '.'; 139 *scontextp++ = '.';
140 else 140 else
141 *scontextp++ = ','; 141 *scontextp++ = ',';
142 142 nm = policydb.p_cat_val_to_name[prev];
143 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); 143 strcpy(scontextp, nm);
144 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); 144 scontextp += strlen(nm);
145 } 145 }
146 146
147 if (l == 0) { 147 if (l == 0) {
148 if (mls_level_eq(&context->range.level[0], 148 if (mls_level_eq(&context->range.level[0],
149 &context->range.level[1])) 149 &context->range.level[1]))
150 break; 150 break;
151 else { 151 else
152 *scontextp = '-'; 152 *scontextp++ = '-';
153 scontextp++;
154 }
155 } 153 }
156 } 154 }
157 155
@@ -190,17 +188,15 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
190 if (!levdatum) 188 if (!levdatum)
191 return 0; 189 return 0;
192 190
193 ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { 191 ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
194 if (ebitmap_node_get_bit(node, i)) { 192 if (i > p->p_cats.nprim)
195 if (i > p->p_cats.nprim) 193 return 0;
196 return 0; 194 if (!ebitmap_get_bit(&levdatum->level->cat, i))
197 if (!ebitmap_get_bit(&levdatum->level->cat, i)) 195 /*
198 /* 196 * Category may not be associated with
199 * Category may not be associated with 197 * sensitivity in low level.
200 * sensitivity in low level. 198 */
201 */ 199 return 0;
202 return 0;
203 }
204 } 200 }
205 } 201 }
206 202
@@ -485,18 +481,16 @@ int mls_convert_context(struct policydb *oldp,
485 c->range.level[l].sens = levdatum->level->sens; 481 c->range.level[l].sens = levdatum->level->sens;
486 482
487 ebitmap_init(&bitmap); 483 ebitmap_init(&bitmap);
488 ebitmap_for_each_bit(&c->range.level[l].cat, node, i) { 484 ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
489 if (ebitmap_node_get_bit(node, i)) { 485 int rc;
490 int rc; 486
491 487 catdatum = hashtab_search(newp->p_cats.table,
492 catdatum = hashtab_search(newp->p_cats.table, 488 oldp->p_cat_val_to_name[i]);
493 oldp->p_cat_val_to_name[i]); 489 if (!catdatum)
494 if (!catdatum) 490 return -EINVAL;
495 return -EINVAL; 491 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
496 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); 492 if (rc)
497 if (rc) 493 return rc;
498 return rc;
499 }
500 } 494 }
501 ebitmap_destroy(&c->range.level[l].cat); 495 ebitmap_destroy(&c->range.level[l].cat);
502 c->range.level[l].cat = bitmap; 496 c->range.level[l].cat = bitmap;
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index f05f97a2bc3a..539828b229b2 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -177,18 +177,15 @@ static int policydb_init(struct policydb *p)
177 177
178 rc = roles_init(p); 178 rc = roles_init(p);
179 if (rc) 179 if (rc)
180 goto out_free_avtab; 180 goto out_free_symtab;
181 181
182 rc = cond_policydb_init(p); 182 rc = cond_policydb_init(p);
183 if (rc) 183 if (rc)
184 goto out_free_avtab; 184 goto out_free_symtab;
185 185
186out: 186out:
187 return rc; 187 return rc;
188 188
189out_free_avtab:
190 avtab_destroy(&p->te_avtab);
191
192out_free_symtab: 189out_free_symtab:
193 for (i = 0; i < SYM_NUM; i++) 190 for (i = 0; i < SYM_NUM; i++)
194 hashtab_destroy(p->symtab[i].table); 191 hashtab_destroy(p->symtab[i].table);
@@ -677,6 +674,8 @@ void policydb_destroy(struct policydb *p)
677 } 674 }
678 kfree(p->type_attr_map); 675 kfree(p->type_attr_map);
679 676
677 kfree(p->undefined_perms);
678
680 return; 679 return;
681} 680}
682 681
@@ -1530,6 +1529,8 @@ int policydb_read(struct policydb *p, void *fp)
1530 goto bad; 1529 goto bad;
1531 } 1530 }
1532 } 1531 }
1532 p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN);
1533 p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN);
1533 1534
1534 info = policydb_lookup_compat(p->policyvers); 1535 info = policydb_lookup_compat(p->policyvers);
1535 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..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
411inval_class:
412 printk(KERN_ERR "%s: unrecognized class %d\n", __FUNCTION__, tclass);
413 return -EINVAL;
390} 414}
391 415
392static int security_validtrans_handle_fail(struct context *ocontext, 416static 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
2144int security_get_reject_unknown(void)
2145{
2146 return policydb.reject_unknown;
2147}
2148
2149int security_get_allow_unknown(void)
2150{
2151 return policydb.allow_unknown;
2152}
2153
2105struct selinux_audit_rule { 2154struct selinux_audit_rule {
2106 u32 au_seqno; 2155 u32 au_seqno;
2107 struct context au_ctxt; 2156 struct context au_ctxt;