aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/Kconfig3
-rw-r--r--security/selinux/avc.c2
-rw-r--r--security/selinux/hooks.c62
-rw-r--r--security/selinux/include/avc.h4
-rw-r--r--security/selinux/include/security.h15
-rw-r--r--security/selinux/ss/avtab.c8
-rw-r--r--security/selinux/ss/conditional.c18
-rw-r--r--security/selinux/ss/conditional.h2
-rw-r--r--security/selinux/ss/ebitmap.c4
-rw-r--r--security/selinux/ss/hashtab.c6
-rw-r--r--security/selinux/ss/mls.c14
-rw-r--r--security/selinux/ss/policydb.c225
-rw-r--r--security/selinux/ss/policydb.h5
-rw-r--r--security/selinux/ss/services.c180
-rw-r--r--security/selinux/ss/sidtab.c12
15 files changed, 470 insertions, 90 deletions
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index a436d1cfa88b..26301dd651d3 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -6,9 +6,6 @@ config SECURITY_SELINUX
6 help 6 help
7 This selects NSA Security-Enhanced Linux (SELinux). 7 This selects NSA Security-Enhanced Linux (SELinux).
8 You will also need a policy configuration and a labeled filesystem. 8 You will also need a policy configuration and a labeled filesystem.
9 You can obtain the policy compiler (checkpolicy), the utility for
10 labeling filesystems (setfiles), and an example policy configuration
11 from <http://www.nsa.gov/selinux/>.
12 If you are unsure how to answer this question, answer N. 9 If you are unsure how to answer this question, answer N.
13 10
14config SECURITY_SELINUX_BOOTPARAM 11config SECURITY_SELINUX_BOOTPARAM
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 114b4b4c97b2..cb30c7e350b3 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -136,7 +136,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
136 * @tclass: target security class 136 * @tclass: target security class
137 * @av: access vector 137 * @av: access vector
138 */ 138 */
139static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) 139void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
140{ 140{
141 const char **common_pts = NULL; 141 const char **common_pts = NULL;
142 u32 common_base = 0; 142 u32 common_base = 0;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 3aa811eba25b..c679ba653e1d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -958,7 +958,8 @@ out_err:
958 return rc; 958 return rc;
959} 959}
960 960
961void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts) 961static void selinux_write_opts(struct seq_file *m,
962 struct security_mnt_opts *opts)
962{ 963{
963 int i; 964 int i;
964 char *prefix; 965 char *prefix;
@@ -1291,7 +1292,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent
1291 /* Default to the fs superblock SID. */ 1292 /* Default to the fs superblock SID. */
1292 isec->sid = sbsec->sid; 1293 isec->sid = sbsec->sid;
1293 1294
1294 if (sbsec->proc) { 1295 if (sbsec->proc && !S_ISLNK(inode->i_mode)) {
1295 struct proc_inode *proci = PROC_I(inode); 1296 struct proc_inode *proci = PROC_I(inode);
1296 if (proci->pde) { 1297 if (proci->pde) {
1297 isec->sclass = inode_mode_to_security_class(inode->i_mode); 1298 isec->sclass = inode_mode_to_security_class(inode->i_mode);
@@ -3549,38 +3550,44 @@ out:
3549#endif /* IPV6 */ 3550#endif /* IPV6 */
3550 3551
3551static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, 3552static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad,
3552 char **addrp, int src, u8 *proto) 3553 char **_addrp, int src, u8 *proto)
3553{ 3554{
3554 int ret = 0; 3555 char *addrp;
3556 int ret;
3555 3557
3556 switch (ad->u.net.family) { 3558 switch (ad->u.net.family) {
3557 case PF_INET: 3559 case PF_INET:
3558 ret = selinux_parse_skb_ipv4(skb, ad, proto); 3560 ret = selinux_parse_skb_ipv4(skb, ad, proto);
3559 if (ret || !addrp) 3561 if (ret)
3560 break; 3562 goto parse_error;
3561 *addrp = (char *)(src ? &ad->u.net.v4info.saddr : 3563 addrp = (char *)(src ? &ad->u.net.v4info.saddr :
3562 &ad->u.net.v4info.daddr); 3564 &ad->u.net.v4info.daddr);
3563 break; 3565 goto okay;
3564 3566
3565#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) 3567#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
3566 case PF_INET6: 3568 case PF_INET6:
3567 ret = selinux_parse_skb_ipv6(skb, ad, proto); 3569 ret = selinux_parse_skb_ipv6(skb, ad, proto);
3568 if (ret || !addrp) 3570 if (ret)
3569 break; 3571 goto parse_error;
3570 *addrp = (char *)(src ? &ad->u.net.v6info.saddr : 3572 addrp = (char *)(src ? &ad->u.net.v6info.saddr :
3571 &ad->u.net.v6info.daddr); 3573 &ad->u.net.v6info.daddr);
3572 break; 3574 goto okay;
3573#endif /* IPV6 */ 3575#endif /* IPV6 */
3574 default: 3576 default:
3575 break; 3577 addrp = NULL;
3578 goto okay;
3576 } 3579 }
3577 3580
3578 if (unlikely(ret)) 3581parse_error:
3579 printk(KERN_WARNING 3582 printk(KERN_WARNING
3580 "SELinux: failure in selinux_parse_skb()," 3583 "SELinux: failure in selinux_parse_skb(),"
3581 " unable to parse packet\n"); 3584 " unable to parse packet\n");
3582
3583 return ret; 3585 return ret;
3586
3587okay:
3588 if (_addrp)
3589 *_addrp = addrp;
3590 return 0;
3584} 3591}
3585 3592
3586/** 3593/**
@@ -5321,8 +5328,12 @@ static int selinux_setprocattr(struct task_struct *p,
5321 5328
5322 if (sid == 0) 5329 if (sid == 0)
5323 return -EINVAL; 5330 return -EINVAL;
5324 5331 /*
5325 /* Only allow single threaded processes to change context */ 5332 * SELinux allows to change context in the following case only.
5333 * - Single threaded processes.
5334 * - Multi threaded processes intend to change its context into
5335 * more restricted domain (defined by TYPEBOUNDS statement).
5336 */
5326 if (atomic_read(&p->mm->mm_users) != 1) { 5337 if (atomic_read(&p->mm->mm_users) != 1) {
5327 struct task_struct *g, *t; 5338 struct task_struct *g, *t;
5328 struct mm_struct *mm = p->mm; 5339 struct mm_struct *mm = p->mm;
@@ -5330,11 +5341,16 @@ static int selinux_setprocattr(struct task_struct *p,
5330 do_each_thread(g, t) { 5341 do_each_thread(g, t) {
5331 if (t->mm == mm && t != p) { 5342 if (t->mm == mm && t != p) {
5332 read_unlock(&tasklist_lock); 5343 read_unlock(&tasklist_lock);
5333 return -EPERM; 5344 error = security_bounded_transition(tsec->sid, sid);
5345 if (!error)
5346 goto boundary_ok;
5347
5348 return error;
5334 } 5349 }
5335 } while_each_thread(g, t); 5350 } while_each_thread(g, t);
5336 read_unlock(&tasklist_lock); 5351 read_unlock(&tasklist_lock);
5337 } 5352 }
5353boundary_ok:
5338 5354
5339 /* Check permissions for the transition. */ 5355 /* Check permissions for the transition. */
5340 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS, 5356 error = avc_has_perm(tsec->sid, sid, SECCLASS_PROCESS,
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 7b9769f5e775..d12ff1a9c0aa 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -12,6 +12,7 @@
12#include <linux/kdev_t.h> 12#include <linux/kdev_t.h>
13#include <linux/spinlock.h> 13#include <linux/spinlock.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/audit.h>
15#include <linux/in6.h> 16#include <linux/in6.h>
16#include <linux/path.h> 17#include <linux/path.h>
17#include <asm/system.h> 18#include <asm/system.h>
@@ -126,6 +127,9 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
126 u32 events, u32 ssid, u32 tsid, 127 u32 events, u32 ssid, u32 tsid,
127 u16 tclass, u32 perms); 128 u16 tclass, u32 perms);
128 129
130/* Shows permission in human readable form */
131void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);
132
129/* Exported to selinuxfs */ 133/* Exported to selinuxfs */
130int avc_get_hash_stats(char *page); 134int avc_get_hash_stats(char *page);
131extern unsigned int avc_cache_threshold; 135extern unsigned int avc_cache_threshold;
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 7c543003d653..72447370bc95 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -27,13 +27,14 @@
27#define POLICYDB_VERSION_RANGETRANS 21 27#define POLICYDB_VERSION_RANGETRANS 21
28#define POLICYDB_VERSION_POLCAP 22 28#define POLICYDB_VERSION_POLCAP 22
29#define POLICYDB_VERSION_PERMISSIVE 23 29#define POLICYDB_VERSION_PERMISSIVE 23
30#define POLICYDB_VERSION_BOUNDARY 24
30 31
31/* Range of policy versions we understand*/ 32/* Range of policy versions we understand*/
32#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 33#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
33#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 34#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
34#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 35#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
35#else 36#else
36#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE 37#define POLICYDB_VERSION_MAX POLICYDB_VERSION_BOUNDARY
37#endif 38#endif
38 39
39#define CONTEXT_MNT 0x01 40#define CONTEXT_MNT 0x01
@@ -62,6 +63,16 @@ enum {
62extern int selinux_policycap_netpeer; 63extern int selinux_policycap_netpeer;
63extern int selinux_policycap_openperm; 64extern int selinux_policycap_openperm;
64 65
66/*
67 * type_datum properties
68 * available at the kernel policy version >= POLICYDB_VERSION_BOUNDARY
69 */
70#define TYPEDATUM_PROPERTY_PRIMARY 0x0001
71#define TYPEDATUM_PROPERTY_ATTRIBUTE 0x0002
72
73/* limitation of boundary depth */
74#define POLICYDB_BOUNDS_MAXDEPTH 4
75
65int security_load_policy(void *data, size_t len); 76int security_load_policy(void *data, size_t len);
66 77
67int security_policycap_supported(unsigned int req_cap); 78int security_policycap_supported(unsigned int req_cap);
@@ -117,6 +128,8 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
117int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, 128int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
118 u16 tclass); 129 u16 tclass);
119 130
131int security_bounded_transition(u32 oldsid, u32 newsid);
132
120int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); 133int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
121 134
122int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, 135int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index a1be97f8beea..1215b8e47dba 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -98,7 +98,7 @@ struct avtab_node *
98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum) 98avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datum *datum)
99{ 99{
100 int hvalue; 100 int hvalue;
101 struct avtab_node *prev, *cur, *newnode; 101 struct avtab_node *prev, *cur;
102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); 102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
103 103
104 if (!h || !h->htable) 104 if (!h || !h->htable)
@@ -122,9 +122,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu
122 key->target_class < cur->key.target_class) 122 key->target_class < cur->key.target_class)
123 break; 123 break;
124 } 124 }
125 newnode = avtab_insert_node(h, hvalue, prev, cur, key, datum); 125 return avtab_insert_node(h, hvalue, prev, cur, key, datum);
126
127 return newnode;
128} 126}
129 127
130struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) 128struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
@@ -231,7 +229,7 @@ void avtab_destroy(struct avtab *h)
231 229
232 for (i = 0; i < h->nslot; i++) { 230 for (i = 0; i < h->nslot; i++) {
233 cur = h->htable[i]; 231 cur = h->htable[i];
234 while (cur != NULL) { 232 while (cur) {
235 temp = cur; 233 temp = cur;
236 cur = cur->next; 234 cur = cur->next;
237 kmem_cache_free(avtab_node_cachep, temp); 235 kmem_cache_free(avtab_node_cachep, temp);
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index fb4efe4f4bc8..4a4e35cac22b 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -29,7 +29,7 @@ static int cond_evaluate_expr(struct policydb *p, struct cond_expr *expr)
29 int s[COND_EXPR_MAXDEPTH]; 29 int s[COND_EXPR_MAXDEPTH];
30 int sp = -1; 30 int sp = -1;
31 31
32 for (cur = expr; cur != NULL; cur = cur->next) { 32 for (cur = expr; cur; cur = cur->next) {
33 switch (cur->expr_type) { 33 switch (cur->expr_type) {
34 case COND_BOOL: 34 case COND_BOOL:
35 if (sp == (COND_EXPR_MAXDEPTH - 1)) 35 if (sp == (COND_EXPR_MAXDEPTH - 1))
@@ -97,14 +97,14 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
97 if (new_state == -1) 97 if (new_state == -1)
98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n"); 98 printk(KERN_ERR "SELinux: expression result was undefined - disabling all rules.\n");
99 /* turn the rules on or off */ 99 /* turn the rules on or off */
100 for (cur = node->true_list; cur != NULL; cur = cur->next) { 100 for (cur = node->true_list; cur; cur = cur->next) {
101 if (new_state <= 0) 101 if (new_state <= 0)
102 cur->node->key.specified &= ~AVTAB_ENABLED; 102 cur->node->key.specified &= ~AVTAB_ENABLED;
103 else 103 else
104 cur->node->key.specified |= AVTAB_ENABLED; 104 cur->node->key.specified |= AVTAB_ENABLED;
105 } 105 }
106 106
107 for (cur = node->false_list; cur != NULL; cur = cur->next) { 107 for (cur = node->false_list; cur; cur = cur->next) {
108 /* -1 or 1 */ 108 /* -1 or 1 */
109 if (new_state) 109 if (new_state)
110 cur->node->key.specified &= ~AVTAB_ENABLED; 110 cur->node->key.specified &= ~AVTAB_ENABLED;
@@ -128,7 +128,7 @@ int cond_policydb_init(struct policydb *p)
128static void cond_av_list_destroy(struct cond_av_list *list) 128static void cond_av_list_destroy(struct cond_av_list *list)
129{ 129{
130 struct cond_av_list *cur, *next; 130 struct cond_av_list *cur, *next;
131 for (cur = list; cur != NULL; cur = next) { 131 for (cur = list; cur; cur = next) {
132 next = cur->next; 132 next = cur->next;
133 /* the avtab_ptr_t node is destroy by the avtab */ 133 /* the avtab_ptr_t node is destroy by the avtab */
134 kfree(cur); 134 kfree(cur);
@@ -139,7 +139,7 @@ static void cond_node_destroy(struct cond_node *node)
139{ 139{
140 struct cond_expr *cur_expr, *next_expr; 140 struct cond_expr *cur_expr, *next_expr;
141 141
142 for (cur_expr = node->expr; cur_expr != NULL; cur_expr = next_expr) { 142 for (cur_expr = node->expr; cur_expr; cur_expr = next_expr) {
143 next_expr = cur_expr->next; 143 next_expr = cur_expr->next;
144 kfree(cur_expr); 144 kfree(cur_expr);
145 } 145 }
@@ -155,7 +155,7 @@ static void cond_list_destroy(struct cond_node *list)
155 if (list == NULL) 155 if (list == NULL)
156 return; 156 return;
157 157
158 for (cur = list; cur != NULL; cur = next) { 158 for (cur = list; cur; cur = next) {
159 next = cur->next; 159 next = cur->next;
160 cond_node_destroy(cur); 160 cond_node_destroy(cur);
161 } 161 }
@@ -239,7 +239,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
239 rc = next_entry(key, fp, len); 239 rc = next_entry(key, fp, len);
240 if (rc < 0) 240 if (rc < 0)
241 goto err; 241 goto err;
242 key[len] = 0; 242 key[len] = '\0';
243 if (hashtab_insert(h, key, booldatum)) 243 if (hashtab_insert(h, key, booldatum))
244 goto err; 244 goto err;
245 245
@@ -291,7 +291,7 @@ static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum
291 goto err; 291 goto err;
292 } 292 }
293 found = 0; 293 found = 0;
294 for (cur = other; cur != NULL; cur = cur->next) { 294 for (cur = other; cur; cur = cur->next) {
295 if (cur->node == node_ptr) { 295 if (cur->node == node_ptr) {
296 found = 1; 296 found = 1;
297 break; 297 break;
@@ -485,7 +485,7 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
485 if (!ctab || !key || !avd) 485 if (!ctab || !key || !avd)
486 return; 486 return;
487 487
488 for (node = avtab_search_node(ctab, key); node != NULL; 488 for (node = avtab_search_node(ctab, key); node;
489 node = avtab_search_node_next(node, key->specified)) { 489 node = avtab_search_node_next(node, key->specified)) {
490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) == 490 if ((u16)(AVTAB_ALLOWED|AVTAB_ENABLED) ==
491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) 491 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
diff --git a/security/selinux/ss/conditional.h b/security/selinux/ss/conditional.h
index 65b9f8366e9c..53ddb013ae57 100644
--- a/security/selinux/ss/conditional.h
+++ b/security/selinux/ss/conditional.h
@@ -28,7 +28,7 @@ struct cond_expr {
28#define COND_XOR 5 /* bool ^ bool */ 28#define COND_XOR 5 /* bool ^ bool */
29#define COND_EQ 6 /* bool == bool */ 29#define COND_EQ 6 /* bool == bool */
30#define COND_NEQ 7 /* bool != bool */ 30#define COND_NEQ 7 /* bool != bool */
31#define COND_LAST 8 31#define COND_LAST COND_NEQ
32 __u32 expr_type; 32 __u32 expr_type;
33 __u32 bool; 33 __u32 bool;
34 struct cond_expr *next; 34 struct cond_expr *next;
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ddc275490af8..68c7348d1acc 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -109,7 +109,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
109 *catmap = c_iter; 109 *catmap = c_iter;
110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); 110 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
111 111
112 while (e_iter != NULL) { 112 while (e_iter) {
113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) { 113 for (i = 0; i < EBITMAP_UNIT_NUMS; i++) {
114 unsigned int delta, e_startbit, c_endbit; 114 unsigned int delta, e_startbit, c_endbit;
115 115
@@ -197,7 +197,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
197 } 197 }
198 } 198 }
199 c_iter = c_iter->next; 199 c_iter = c_iter->next;
200 } while (c_iter != NULL); 200 } while (c_iter);
201 if (e_iter != NULL) 201 if (e_iter != NULL)
202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE; 202 ebmap->highbit = e_iter->startbit + EBITMAP_SIZE;
203 else 203 else
diff --git a/security/selinux/ss/hashtab.c b/security/selinux/ss/hashtab.c
index 2e7788e13213..933e735bb185 100644
--- a/security/selinux/ss/hashtab.c
+++ b/security/selinux/ss/hashtab.c
@@ -81,7 +81,7 @@ void *hashtab_search(struct hashtab *h, const void *key)
81 81
82 hvalue = h->hash_value(h, key); 82 hvalue = h->hash_value(h, key);
83 cur = h->htable[hvalue]; 83 cur = h->htable[hvalue];
84 while (cur != NULL && h->keycmp(h, key, cur->key) > 0) 84 while (cur && h->keycmp(h, key, cur->key) > 0)
85 cur = cur->next; 85 cur = cur->next;
86 86
87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0)) 87 if (cur == NULL || (h->keycmp(h, key, cur->key) != 0))
@@ -100,7 +100,7 @@ void hashtab_destroy(struct hashtab *h)
100 100
101 for (i = 0; i < h->size; i++) { 101 for (i = 0; i < h->size; i++) {
102 cur = h->htable[i]; 102 cur = h->htable[i];
103 while (cur != NULL) { 103 while (cur) {
104 temp = cur; 104 temp = cur;
105 cur = cur->next; 105 cur = cur->next;
106 kfree(temp); 106 kfree(temp);
@@ -127,7 +127,7 @@ int hashtab_map(struct hashtab *h,
127 127
128 for (i = 0; i < h->size; i++) { 128 for (i = 0; i < h->size; i++) {
129 cur = h->htable[i]; 129 cur = h->htable[i];
130 while (cur != NULL) { 130 while (cur) {
131 ret = apply(cur->key, cur->datum, args); 131 ret = apply(cur->key, cur->datum, args);
132 if (ret) 132 if (ret)
133 return ret; 133 return ret;
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 77d745da48bb..b5407f16c2a4 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -283,8 +283,8 @@ int mls_context_to_sid(struct policydb *pol,
283 p++; 283 p++;
284 284
285 delim = *p; 285 delim = *p;
286 if (delim != 0) 286 if (delim != '\0')
287 *p++ = 0; 287 *p++ = '\0';
288 288
289 for (l = 0; l < 2; l++) { 289 for (l = 0; l < 2; l++) {
290 levdatum = hashtab_search(pol->p_levels.table, scontextp); 290 levdatum = hashtab_search(pol->p_levels.table, scontextp);
@@ -302,14 +302,14 @@ int mls_context_to_sid(struct policydb *pol,
302 while (*p && *p != ',' && *p != '-') 302 while (*p && *p != ',' && *p != '-')
303 p++; 303 p++;
304 delim = *p; 304 delim = *p;
305 if (delim != 0) 305 if (delim != '\0')
306 *p++ = 0; 306 *p++ = '\0';
307 307
308 /* Separate into range if exists */ 308 /* Separate into range if exists */
309 rngptr = strchr(scontextp, '.'); 309 rngptr = strchr(scontextp, '.');
310 if (rngptr != NULL) { 310 if (rngptr != NULL) {
311 /* Remove '.' */ 311 /* Remove '.' */
312 *rngptr++ = 0; 312 *rngptr++ = '\0';
313 } 313 }
314 314
315 catdatum = hashtab_search(pol->p_cats.table, 315 catdatum = hashtab_search(pol->p_cats.table,
@@ -357,8 +357,8 @@ int mls_context_to_sid(struct policydb *pol,
357 p++; 357 p++;
358 358
359 delim = *p; 359 delim = *p;
360 if (delim != 0) 360 if (delim != '\0')
361 *p++ = 0; 361 *p++ = '\0';
362 } else 362 } else
363 break; 363 break;
364 } 364 }
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 2391761ae422..72e4a54973aa 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -30,6 +30,7 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/string.h> 31#include <linux/string.h>
32#include <linux/errno.h> 32#include <linux/errno.h>
33#include <linux/audit.h>
33#include "security.h" 34#include "security.h"
34 35
35#include "policydb.h" 36#include "policydb.h"
@@ -116,7 +117,12 @@ static struct policydb_compat_info policydb_compat[] = {
116 .version = POLICYDB_VERSION_PERMISSIVE, 117 .version = POLICYDB_VERSION_PERMISSIVE,
117 .sym_num = SYM_NUM, 118 .sym_num = SYM_NUM,
118 .ocon_num = OCON_NUM, 119 .ocon_num = OCON_NUM,
119 } 120 },
121 {
122 .version = POLICYDB_VERSION_BOUNDARY,
123 .sym_num = SYM_NUM,
124 .ocon_num = OCON_NUM,
125 },
120}; 126};
121 127
122static struct policydb_compat_info *policydb_lookup_compat(int version) 128static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -254,7 +260,9 @@ static int role_index(void *key, void *datum, void *datap)
254 260
255 role = datum; 261 role = datum;
256 p = datap; 262 p = datap;
257 if (!role->value || role->value > p->p_roles.nprim) 263 if (!role->value
264 || role->value > p->p_roles.nprim
265 || role->bounds > p->p_roles.nprim)
258 return -EINVAL; 266 return -EINVAL;
259 p->p_role_val_to_name[role->value - 1] = key; 267 p->p_role_val_to_name[role->value - 1] = key;
260 p->role_val_to_struct[role->value - 1] = role; 268 p->role_val_to_struct[role->value - 1] = role;
@@ -270,9 +278,12 @@ static int type_index(void *key, void *datum, void *datap)
270 p = datap; 278 p = datap;
271 279
272 if (typdatum->primary) { 280 if (typdatum->primary) {
273 if (!typdatum->value || typdatum->value > p->p_types.nprim) 281 if (!typdatum->value
282 || typdatum->value > p->p_types.nprim
283 || typdatum->bounds > p->p_types.nprim)
274 return -EINVAL; 284 return -EINVAL;
275 p->p_type_val_to_name[typdatum->value - 1] = key; 285 p->p_type_val_to_name[typdatum->value - 1] = key;
286 p->type_val_to_struct[typdatum->value - 1] = typdatum;
276 } 287 }
277 288
278 return 0; 289 return 0;
@@ -285,7 +296,9 @@ static int user_index(void *key, void *datum, void *datap)
285 296
286 usrdatum = datum; 297 usrdatum = datum;
287 p = datap; 298 p = datap;
288 if (!usrdatum->value || usrdatum->value > p->p_users.nprim) 299 if (!usrdatum->value
300 || usrdatum->value > p->p_users.nprim
301 || usrdatum->bounds > p->p_users.nprim)
289 return -EINVAL; 302 return -EINVAL;
290 p->p_user_val_to_name[usrdatum->value - 1] = key; 303 p->p_user_val_to_name[usrdatum->value - 1] = key;
291 p->user_val_to_struct[usrdatum->value - 1] = usrdatum; 304 p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
@@ -438,6 +451,14 @@ static int policydb_index_others(struct policydb *p)
438 goto out; 451 goto out;
439 } 452 }
440 453
454 p->type_val_to_struct =
455 kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)),
456 GFP_KERNEL);
457 if (!p->type_val_to_struct) {
458 rc = -ENOMEM;
459 goto out;
460 }
461
441 if (cond_init_bool_indexes(p)) { 462 if (cond_init_bool_indexes(p)) {
442 rc = -ENOMEM; 463 rc = -ENOMEM;
443 goto out; 464 goto out;
@@ -625,6 +646,7 @@ void policydb_destroy(struct policydb *p)
625 kfree(p->class_val_to_struct); 646 kfree(p->class_val_to_struct);
626 kfree(p->role_val_to_struct); 647 kfree(p->role_val_to_struct);
627 kfree(p->user_val_to_struct); 648 kfree(p->user_val_to_struct);
649 kfree(p->type_val_to_struct);
628 650
629 avtab_destroy(&p->te_avtab); 651 avtab_destroy(&p->te_avtab);
630 652
@@ -932,7 +954,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
932 rc = next_entry(key, fp, len); 954 rc = next_entry(key, fp, len);
933 if (rc < 0) 955 if (rc < 0)
934 goto bad; 956 goto bad;
935 key[len] = 0; 957 key[len] = '\0';
936 958
937 rc = hashtab_insert(h, key, perdatum); 959 rc = hashtab_insert(h, key, perdatum);
938 if (rc) 960 if (rc)
@@ -979,7 +1001,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
979 rc = next_entry(key, fp, len); 1001 rc = next_entry(key, fp, len);
980 if (rc < 0) 1002 if (rc < 0)
981 goto bad; 1003 goto bad;
982 key[len] = 0; 1004 key[len] = '\0';
983 1005
984 for (i = 0; i < nel; i++) { 1006 for (i = 0; i < nel; i++) {
985 rc = perm_read(p, comdatum->permissions.table, fp); 1007 rc = perm_read(p, comdatum->permissions.table, fp);
@@ -1117,7 +1139,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1117 rc = next_entry(key, fp, len); 1139 rc = next_entry(key, fp, len);
1118 if (rc < 0) 1140 if (rc < 0)
1119 goto bad; 1141 goto bad;
1120 key[len] = 0; 1142 key[len] = '\0';
1121 1143
1122 if (len2) { 1144 if (len2) {
1123 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL); 1145 cladatum->comkey = kmalloc(len2 + 1, GFP_KERNEL);
@@ -1128,7 +1150,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
1128 rc = next_entry(cladatum->comkey, fp, len2); 1150 rc = next_entry(cladatum->comkey, fp, len2);
1129 if (rc < 0) 1151 if (rc < 0)
1130 goto bad; 1152 goto bad;
1131 cladatum->comkey[len2] = 0; 1153 cladatum->comkey[len2] = '\0';
1132 1154
1133 cladatum->comdatum = hashtab_search(p->p_commons.table, 1155 cladatum->comdatum = hashtab_search(p->p_commons.table,
1134 cladatum->comkey); 1156 cladatum->comkey);
@@ -1176,8 +1198,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1176{ 1198{
1177 char *key = NULL; 1199 char *key = NULL;
1178 struct role_datum *role; 1200 struct role_datum *role;
1179 int rc; 1201 int rc, to_read = 2;
1180 __le32 buf[2]; 1202 __le32 buf[3];
1181 u32 len; 1203 u32 len;
1182 1204
1183 role = kzalloc(sizeof(*role), GFP_KERNEL); 1205 role = kzalloc(sizeof(*role), GFP_KERNEL);
@@ -1186,12 +1208,17 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1186 goto out; 1208 goto out;
1187 } 1209 }
1188 1210
1189 rc = next_entry(buf, fp, sizeof buf); 1211 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1212 to_read = 3;
1213
1214 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1190 if (rc < 0) 1215 if (rc < 0)
1191 goto bad; 1216 goto bad;
1192 1217
1193 len = le32_to_cpu(buf[0]); 1218 len = le32_to_cpu(buf[0]);
1194 role->value = le32_to_cpu(buf[1]); 1219 role->value = le32_to_cpu(buf[1]);
1220 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1221 role->bounds = le32_to_cpu(buf[2]);
1195 1222
1196 key = kmalloc(len + 1, GFP_KERNEL); 1223 key = kmalloc(len + 1, GFP_KERNEL);
1197 if (!key) { 1224 if (!key) {
@@ -1201,7 +1228,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
1201 rc = next_entry(key, fp, len); 1228 rc = next_entry(key, fp, len);
1202 if (rc < 0) 1229 if (rc < 0)
1203 goto bad; 1230 goto bad;
1204 key[len] = 0; 1231 key[len] = '\0';
1205 1232
1206 rc = ebitmap_read(&role->dominates, fp); 1233 rc = ebitmap_read(&role->dominates, fp);
1207 if (rc) 1234 if (rc)
@@ -1236,8 +1263,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1236{ 1263{
1237 char *key = NULL; 1264 char *key = NULL;
1238 struct type_datum *typdatum; 1265 struct type_datum *typdatum;
1239 int rc; 1266 int rc, to_read = 3;
1240 __le32 buf[3]; 1267 __le32 buf[4];
1241 u32 len; 1268 u32 len;
1242 1269
1243 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL); 1270 typdatum = kzalloc(sizeof(*typdatum), GFP_KERNEL);
@@ -1246,13 +1273,27 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1246 return rc; 1273 return rc;
1247 } 1274 }
1248 1275
1249 rc = next_entry(buf, fp, sizeof buf); 1276 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1277 to_read = 4;
1278
1279 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1250 if (rc < 0) 1280 if (rc < 0)
1251 goto bad; 1281 goto bad;
1252 1282
1253 len = le32_to_cpu(buf[0]); 1283 len = le32_to_cpu(buf[0]);
1254 typdatum->value = le32_to_cpu(buf[1]); 1284 typdatum->value = le32_to_cpu(buf[1]);
1255 typdatum->primary = le32_to_cpu(buf[2]); 1285 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY) {
1286 u32 prop = le32_to_cpu(buf[2]);
1287
1288 if (prop & TYPEDATUM_PROPERTY_PRIMARY)
1289 typdatum->primary = 1;
1290 if (prop & TYPEDATUM_PROPERTY_ATTRIBUTE)
1291 typdatum->attribute = 1;
1292
1293 typdatum->bounds = le32_to_cpu(buf[3]);
1294 } else {
1295 typdatum->primary = le32_to_cpu(buf[2]);
1296 }
1256 1297
1257 key = kmalloc(len + 1, GFP_KERNEL); 1298 key = kmalloc(len + 1, GFP_KERNEL);
1258 if (!key) { 1299 if (!key) {
@@ -1262,7 +1303,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
1262 rc = next_entry(key, fp, len); 1303 rc = next_entry(key, fp, len);
1263 if (rc < 0) 1304 if (rc < 0)
1264 goto bad; 1305 goto bad;
1265 key[len] = 0; 1306 key[len] = '\0';
1266 1307
1267 rc = hashtab_insert(h, key, typdatum); 1308 rc = hashtab_insert(h, key, typdatum);
1268 if (rc) 1309 if (rc)
@@ -1309,8 +1350,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1309{ 1350{
1310 char *key = NULL; 1351 char *key = NULL;
1311 struct user_datum *usrdatum; 1352 struct user_datum *usrdatum;
1312 int rc; 1353 int rc, to_read = 2;
1313 __le32 buf[2]; 1354 __le32 buf[3];
1314 u32 len; 1355 u32 len;
1315 1356
1316 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL); 1357 usrdatum = kzalloc(sizeof(*usrdatum), GFP_KERNEL);
@@ -1319,12 +1360,17 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1319 goto out; 1360 goto out;
1320 } 1361 }
1321 1362
1322 rc = next_entry(buf, fp, sizeof buf); 1363 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1364 to_read = 3;
1365
1366 rc = next_entry(buf, fp, sizeof(buf[0]) * to_read);
1323 if (rc < 0) 1367 if (rc < 0)
1324 goto bad; 1368 goto bad;
1325 1369
1326 len = le32_to_cpu(buf[0]); 1370 len = le32_to_cpu(buf[0]);
1327 usrdatum->value = le32_to_cpu(buf[1]); 1371 usrdatum->value = le32_to_cpu(buf[1]);
1372 if (p->policyvers >= POLICYDB_VERSION_BOUNDARY)
1373 usrdatum->bounds = le32_to_cpu(buf[2]);
1328 1374
1329 key = kmalloc(len + 1, GFP_KERNEL); 1375 key = kmalloc(len + 1, GFP_KERNEL);
1330 if (!key) { 1376 if (!key) {
@@ -1334,7 +1380,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
1334 rc = next_entry(key, fp, len); 1380 rc = next_entry(key, fp, len);
1335 if (rc < 0) 1381 if (rc < 0)
1336 goto bad; 1382 goto bad;
1337 key[len] = 0; 1383 key[len] = '\0';
1338 1384
1339 rc = ebitmap_read(&usrdatum->roles, fp); 1385 rc = ebitmap_read(&usrdatum->roles, fp);
1340 if (rc) 1386 if (rc)
@@ -1388,7 +1434,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
1388 rc = next_entry(key, fp, len); 1434 rc = next_entry(key, fp, len);
1389 if (rc < 0) 1435 if (rc < 0)
1390 goto bad; 1436 goto bad;
1391 key[len] = 0; 1437 key[len] = '\0';
1392 1438
1393 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC); 1439 levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
1394 if (!levdatum->level) { 1440 if (!levdatum->level) {
@@ -1440,7 +1486,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
1440 rc = next_entry(key, fp, len); 1486 rc = next_entry(key, fp, len);
1441 if (rc < 0) 1487 if (rc < 0)
1442 goto bad; 1488 goto bad;
1443 key[len] = 0; 1489 key[len] = '\0';
1444 1490
1445 rc = hashtab_insert(h, key, catdatum); 1491 rc = hashtab_insert(h, key, catdatum);
1446 if (rc) 1492 if (rc)
@@ -1465,6 +1511,133 @@ static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp)
1465 cat_read, 1511 cat_read,
1466}; 1512};
1467 1513
1514static int user_bounds_sanity_check(void *key, void *datum, void *datap)
1515{
1516 struct user_datum *upper, *user;
1517 struct policydb *p = datap;
1518 int depth = 0;
1519
1520 upper = user = datum;
1521 while (upper->bounds) {
1522 struct ebitmap_node *node;
1523 unsigned long bit;
1524
1525 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1526 printk(KERN_ERR "SELinux: user %s: "
1527 "too deep or looped boundary",
1528 (char *) key);
1529 return -EINVAL;
1530 }
1531
1532 upper = p->user_val_to_struct[upper->bounds - 1];
1533 ebitmap_for_each_positive_bit(&user->roles, node, bit) {
1534 if (ebitmap_get_bit(&upper->roles, bit))
1535 continue;
1536
1537 printk(KERN_ERR
1538 "SELinux: boundary violated policy: "
1539 "user=%s role=%s bounds=%s\n",
1540 p->p_user_val_to_name[user->value - 1],
1541 p->p_role_val_to_name[bit],
1542 p->p_user_val_to_name[upper->value - 1]);
1543
1544 return -EINVAL;
1545 }
1546 }
1547
1548 return 0;
1549}
1550
1551static int role_bounds_sanity_check(void *key, void *datum, void *datap)
1552{
1553 struct role_datum *upper, *role;
1554 struct policydb *p = datap;
1555 int depth = 0;
1556
1557 upper = role = datum;
1558 while (upper->bounds) {
1559 struct ebitmap_node *node;
1560 unsigned long bit;
1561
1562 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1563 printk(KERN_ERR "SELinux: role %s: "
1564 "too deep or looped bounds\n",
1565 (char *) key);
1566 return -EINVAL;
1567 }
1568
1569 upper = p->role_val_to_struct[upper->bounds - 1];
1570 ebitmap_for_each_positive_bit(&role->types, node, bit) {
1571 if (ebitmap_get_bit(&upper->types, bit))
1572 continue;
1573
1574 printk(KERN_ERR
1575 "SELinux: boundary violated policy: "
1576 "role=%s type=%s bounds=%s\n",
1577 p->p_role_val_to_name[role->value - 1],
1578 p->p_type_val_to_name[bit],
1579 p->p_role_val_to_name[upper->value - 1]);
1580
1581 return -EINVAL;
1582 }
1583 }
1584
1585 return 0;
1586}
1587
1588static int type_bounds_sanity_check(void *key, void *datum, void *datap)
1589{
1590 struct type_datum *upper, *type;
1591 struct policydb *p = datap;
1592 int depth = 0;
1593
1594 upper = type = datum;
1595 while (upper->bounds) {
1596 if (++depth == POLICYDB_BOUNDS_MAXDEPTH) {
1597 printk(KERN_ERR "SELinux: type %s: "
1598 "too deep or looped boundary\n",
1599 (char *) key);
1600 return -EINVAL;
1601 }
1602
1603 upper = p->type_val_to_struct[upper->bounds - 1];
1604 if (upper->attribute) {
1605 printk(KERN_ERR "SELinux: type %s: "
1606 "bounded by attribute %s",
1607 (char *) key,
1608 p->p_type_val_to_name[upper->value - 1]);
1609 return -EINVAL;
1610 }
1611 }
1612
1613 return 0;
1614}
1615
1616static int policydb_bounds_sanity_check(struct policydb *p)
1617{
1618 int rc;
1619
1620 if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
1621 return 0;
1622
1623 rc = hashtab_map(p->p_users.table,
1624 user_bounds_sanity_check, p);
1625 if (rc)
1626 return rc;
1627
1628 rc = hashtab_map(p->p_roles.table,
1629 role_bounds_sanity_check, p);
1630 if (rc)
1631 return rc;
1632
1633 rc = hashtab_map(p->p_types.table,
1634 type_bounds_sanity_check, p);
1635 if (rc)
1636 return rc;
1637
1638 return 0;
1639}
1640
1468extern int ss_initialized; 1641extern int ss_initialized;
1469 1642
1470/* 1643/*
@@ -1523,7 +1696,7 @@ int policydb_read(struct policydb *p, void *fp)
1523 kfree(policydb_str); 1696 kfree(policydb_str);
1524 goto bad; 1697 goto bad;
1525 } 1698 }
1526 policydb_str[len] = 0; 1699 policydb_str[len] = '\0';
1527 if (strcmp(policydb_str, POLICYDB_STRING)) { 1700 if (strcmp(policydb_str, POLICYDB_STRING)) {
1528 printk(KERN_ERR "SELinux: policydb string %s does not match " 1701 printk(KERN_ERR "SELinux: policydb string %s does not match "
1529 "my string %s\n", policydb_str, POLICYDB_STRING); 1702 "my string %s\n", policydb_str, POLICYDB_STRING);
@@ -1961,6 +2134,10 @@ int policydb_read(struct policydb *p, void *fp)
1961 goto bad; 2134 goto bad;
1962 } 2135 }
1963 2136
2137 rc = policydb_bounds_sanity_check(p);
2138 if (rc)
2139 goto bad;
2140
1964 rc = 0; 2141 rc = 0;
1965out: 2142out:
1966 return rc; 2143 return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 4253370fda6a..55152d498b53 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -61,6 +61,7 @@ struct class_datum {
61/* Role attributes */ 61/* Role attributes */
62struct role_datum { 62struct role_datum {
63 u32 value; /* internal role value */ 63 u32 value; /* internal role value */
64 u32 bounds; /* boundary of role */
64 struct ebitmap dominates; /* set of roles dominated by this role */ 65 struct ebitmap dominates; /* set of roles dominated by this role */
65 struct ebitmap types; /* set of authorized types for role */ 66 struct ebitmap types; /* set of authorized types for role */
66}; 67};
@@ -81,12 +82,15 @@ struct role_allow {
81/* Type attributes */ 82/* Type attributes */
82struct type_datum { 83struct type_datum {
83 u32 value; /* internal type value */ 84 u32 value; /* internal type value */
85 u32 bounds; /* boundary of type */
84 unsigned char primary; /* primary name? */ 86 unsigned char primary; /* primary name? */
87 unsigned char attribute;/* attribute ?*/
85}; 88};
86 89
87/* User attributes */ 90/* User attributes */
88struct user_datum { 91struct user_datum {
89 u32 value; /* internal user value */ 92 u32 value; /* internal user value */
93 u32 bounds; /* bounds of user */
90 struct ebitmap roles; /* set of authorized roles for user */ 94 struct ebitmap roles; /* set of authorized roles for user */
91 struct mls_range range; /* MLS range (min - max) for user */ 95 struct mls_range range; /* MLS range (min - max) for user */
92 struct mls_level dfltlevel; /* default login MLS level for user */ 96 struct mls_level dfltlevel; /* default login MLS level for user */
@@ -209,6 +213,7 @@ struct policydb {
209 struct class_datum **class_val_to_struct; 213 struct class_datum **class_val_to_struct;
210 struct role_datum **role_val_to_struct; 214 struct role_datum **role_val_to_struct;
211 struct user_datum **user_val_to_struct; 215 struct user_datum **user_val_to_struct;
216 struct type_datum **type_val_to_struct;
212 217
213 /* type enforcement access vectors and transitions */ 218 /* type enforcement access vectors and transitions */
214 struct avtab te_avtab; 219 struct avtab te_avtab;
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index ed0ca649d7db..343c8ab14af0 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -88,6 +88,11 @@ static u32 latest_granting;
88static int context_struct_to_string(struct context *context, char **scontext, 88static int context_struct_to_string(struct context *context, char **scontext,
89 u32 *scontext_len); 89 u32 *scontext_len);
90 90
91static int context_struct_compute_av(struct context *scontext,
92 struct context *tcontext,
93 u16 tclass,
94 u32 requested,
95 struct av_decision *avd);
91/* 96/*
92 * Return the boolean value of a constraint expression 97 * Return the boolean value of a constraint expression
93 * when it is applied to the specified source and target 98 * when it is applied to the specified source and target
@@ -274,6 +279,100 @@ mls_ops:
274} 279}
275 280
276/* 281/*
282 * security_boundary_permission - drops violated permissions
283 * on boundary constraint.
284 */
285static void type_attribute_bounds_av(struct context *scontext,
286 struct context *tcontext,
287 u16 tclass,
288 u32 requested,
289 struct av_decision *avd)
290{
291 struct context lo_scontext;
292 struct context lo_tcontext;
293 struct av_decision lo_avd;
294 struct type_datum *source
295 = policydb.type_val_to_struct[scontext->type - 1];
296 struct type_datum *target
297 = policydb.type_val_to_struct[tcontext->type - 1];
298 u32 masked = 0;
299
300 if (source->bounds) {
301 memset(&lo_avd, 0, sizeof(lo_avd));
302
303 memcpy(&lo_scontext, scontext, sizeof(lo_scontext));
304 lo_scontext.type = source->bounds;
305
306 context_struct_compute_av(&lo_scontext,
307 tcontext,
308 tclass,
309 requested,
310 &lo_avd);
311 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
312 return; /* no masked permission */
313 masked = ~lo_avd.allowed & avd->allowed;
314 }
315
316 if (target->bounds) {
317 memset(&lo_avd, 0, sizeof(lo_avd));
318
319 memcpy(&lo_tcontext, tcontext, sizeof(lo_tcontext));
320 lo_tcontext.type = target->bounds;
321
322 context_struct_compute_av(scontext,
323 &lo_tcontext,
324 tclass,
325 requested,
326 &lo_avd);
327 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
328 return; /* no masked permission */
329 masked = ~lo_avd.allowed & avd->allowed;
330 }
331
332 if (source->bounds && target->bounds) {
333 memset(&lo_avd, 0, sizeof(lo_avd));
334 /*
335 * lo_scontext and lo_tcontext are already
336 * set up.
337 */
338
339 context_struct_compute_av(&lo_scontext,
340 &lo_tcontext,
341 tclass,
342 requested,
343 &lo_avd);
344 if ((lo_avd.allowed & avd->allowed) == avd->allowed)
345 return; /* no masked permission */
346 masked = ~lo_avd.allowed & avd->allowed;
347 }
348
349 if (masked) {
350 struct audit_buffer *ab;
351 char *stype_name
352 = policydb.p_type_val_to_name[source->value - 1];
353 char *ttype_name
354 = policydb.p_type_val_to_name[target->value - 1];
355 char *tclass_name
356 = policydb.p_class_val_to_name[tclass - 1];
357
358 /* mask violated permissions */
359 avd->allowed &= ~masked;
360
361 /* notice to userspace via audit message */
362 ab = audit_log_start(current->audit_context,
363 GFP_ATOMIC, AUDIT_SELINUX_ERR);
364 if (!ab)
365 return;
366
367 audit_log_format(ab, "av boundary violation: "
368 "source=%s target=%s tclass=%s",
369 stype_name, ttype_name, tclass_name);
370 avc_dump_av(ab, tclass, masked);
371 audit_log_end(ab);
372 }
373}
374
375/*
277 * Compute access vectors based on a context structure pair for 376 * Compute access vectors based on a context structure pair for
278 * the permissions in a particular class. 377 * the permissions in a particular class.
279 */ 378 */
@@ -356,7 +455,7 @@ static int context_struct_compute_av(struct context *scontext,
356 avkey.source_type = i + 1; 455 avkey.source_type = i + 1;
357 avkey.target_type = j + 1; 456 avkey.target_type = j + 1;
358 for (node = avtab_search_node(&policydb.te_avtab, &avkey); 457 for (node = avtab_search_node(&policydb.te_avtab, &avkey);
359 node != NULL; 458 node;
360 node = avtab_search_node_next(node, avkey.specified)) { 459 node = avtab_search_node_next(node, avkey.specified)) {
361 if (node->key.specified == AVTAB_ALLOWED) 460 if (node->key.specified == AVTAB_ALLOWED)
362 avd->allowed |= node->datum.data; 461 avd->allowed |= node->datum.data;
@@ -404,6 +503,14 @@ static int context_struct_compute_av(struct context *scontext,
404 PROCESS__DYNTRANSITION); 503 PROCESS__DYNTRANSITION);
405 } 504 }
406 505
506 /*
507 * If the given source and target types have boundary
508 * constraint, lazy checks have to mask any violated
509 * permission and notice it to userspace via audit.
510 */
511 type_attribute_bounds_av(scontext, tcontext,
512 tclass, requested, avd);
513
407 return 0; 514 return 0;
408 515
409inval_class: 516inval_class:
@@ -549,6 +656,69 @@ out:
549 return rc; 656 return rc;
550} 657}
551 658
659/*
660 * security_bounded_transition - check whether the given
661 * transition is directed to bounded, or not.
662 * It returns 0, if @newsid is bounded by @oldsid.
663 * Otherwise, it returns error code.
664 *
665 * @oldsid : current security identifier
666 * @newsid : destinated security identifier
667 */
668int security_bounded_transition(u32 old_sid, u32 new_sid)
669{
670 struct context *old_context, *new_context;
671 struct type_datum *type;
672 int index;
673 int rc = -EINVAL;
674
675 read_lock(&policy_rwlock);
676
677 old_context = sidtab_search(&sidtab, old_sid);
678 if (!old_context) {
679 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
680 __func__, old_sid);
681 goto out;
682 }
683
684 new_context = sidtab_search(&sidtab, new_sid);
685 if (!new_context) {
686 printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
687 __func__, new_sid);
688 goto out;
689 }
690
691 /* type/domain unchaned */
692 if (old_context->type == new_context->type) {
693 rc = 0;
694 goto out;
695 }
696
697 index = new_context->type;
698 while (true) {
699 type = policydb.type_val_to_struct[index - 1];
700 BUG_ON(!type);
701
702 /* not bounded anymore */
703 if (!type->bounds) {
704 rc = -EPERM;
705 break;
706 }
707
708 /* @newsid is bounded by @oldsid */
709 if (type->bounds == old_context->type) {
710 rc = 0;
711 break;
712 }
713 index = type->bounds;
714 }
715out:
716 read_unlock(&policy_rwlock);
717
718 return rc;
719}
720
721
552/** 722/**
553 * security_compute_av - Compute access vector decisions. 723 * security_compute_av - Compute access vector decisions.
554 * @ssid: source security identifier 724 * @ssid: source security identifier
@@ -794,7 +964,7 @@ static int string_to_context_struct(struct policydb *pol,
794 *p++ = 0; 964 *p++ = 0;
795 965
796 typdatum = hashtab_search(pol->p_types.table, scontextp); 966 typdatum = hashtab_search(pol->p_types.table, scontextp);
797 if (!typdatum) 967 if (!typdatum || typdatum->attribute)
798 goto out; 968 goto out;
799 969
800 ctx->type = typdatum->value; 970 ctx->type = typdatum->value;
@@ -1037,7 +1207,7 @@ static int security_compute_sid(u32 ssid,
1037 /* If no permanent rule, also check for enabled conditional rules */ 1207 /* If no permanent rule, also check for enabled conditional rules */
1038 if (!avdatum) { 1208 if (!avdatum) {
1039 node = avtab_search_node(&policydb.te_cond_avtab, &avkey); 1209 node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
1040 for (; node != NULL; node = avtab_search_node_next(node, specified)) { 1210 for (; node; node = avtab_search_node_next(node, specified)) {
1041 if (node->key.specified & AVTAB_ENABLED) { 1211 if (node->key.specified & AVTAB_ENABLED) {
1042 avdatum = &node->datum; 1212 avdatum = &node->datum;
1043 break; 1213 break;
@@ -2050,7 +2220,7 @@ int security_set_bools(int len, int *values)
2050 policydb.bool_val_to_struct[i]->state = 0; 2220 policydb.bool_val_to_struct[i]->state = 0;
2051 } 2221 }
2052 2222
2053 for (cur = policydb.cond_list; cur != NULL; cur = cur->next) { 2223 for (cur = policydb.cond_list; cur; cur = cur->next) {
2054 rc = evaluate_cond_node(&policydb, cur); 2224 rc = evaluate_cond_node(&policydb, cur);
2055 if (rc) 2225 if (rc)
2056 goto out; 2226 goto out;
@@ -2102,7 +2272,7 @@ static int security_preserve_bools(struct policydb *p)
2102 if (booldatum) 2272 if (booldatum)
2103 booldatum->state = bvalues[i]; 2273 booldatum->state = bvalues[i];
2104 } 2274 }
2105 for (cur = p->cond_list; cur != NULL; cur = cur->next) { 2275 for (cur = p->cond_list; cur; cur = cur->next) {
2106 rc = evaluate_cond_node(p, cur); 2276 rc = evaluate_cond_node(p, cur);
2107 if (rc) 2277 if (rc)
2108 goto out; 2278 goto out;
diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c
index a81ded104129..e817989764cd 100644
--- a/security/selinux/ss/sidtab.c
+++ b/security/selinux/ss/sidtab.c
@@ -43,7 +43,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
43 hvalue = SIDTAB_HASH(sid); 43 hvalue = SIDTAB_HASH(sid);
44 prev = NULL; 44 prev = NULL;
45 cur = s->htable[hvalue]; 45 cur = s->htable[hvalue];
46 while (cur != NULL && sid > cur->sid) { 46 while (cur && sid > cur->sid) {
47 prev = cur; 47 prev = cur;
48 cur = cur->next; 48 cur = cur->next;
49 } 49 }
@@ -92,7 +92,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
92 92
93 hvalue = SIDTAB_HASH(sid); 93 hvalue = SIDTAB_HASH(sid);
94 cur = s->htable[hvalue]; 94 cur = s->htable[hvalue];
95 while (cur != NULL && sid > cur->sid) 95 while (cur && sid > cur->sid)
96 cur = cur->next; 96 cur = cur->next;
97 97
98 if (force && cur && sid == cur->sid && cur->context.len) 98 if (force && cur && sid == cur->sid && cur->context.len)
@@ -103,7 +103,7 @@ static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
103 sid = SECINITSID_UNLABELED; 103 sid = SECINITSID_UNLABELED;
104 hvalue = SIDTAB_HASH(sid); 104 hvalue = SIDTAB_HASH(sid);
105 cur = s->htable[hvalue]; 105 cur = s->htable[hvalue];
106 while (cur != NULL && sid > cur->sid) 106 while (cur && sid > cur->sid)
107 cur = cur->next; 107 cur = cur->next;
108 if (!cur || sid != cur->sid) 108 if (!cur || sid != cur->sid)
109 return NULL; 109 return NULL;
@@ -136,7 +136,7 @@ int sidtab_map(struct sidtab *s,
136 136
137 for (i = 0; i < SIDTAB_SIZE; i++) { 137 for (i = 0; i < SIDTAB_SIZE; i++) {
138 cur = s->htable[i]; 138 cur = s->htable[i];
139 while (cur != NULL) { 139 while (cur) {
140 rc = apply(cur->sid, &cur->context, args); 140 rc = apply(cur->sid, &cur->context, args);
141 if (rc) 141 if (rc)
142 goto out; 142 goto out;
@@ -155,7 +155,7 @@ static inline u32 sidtab_search_context(struct sidtab *s,
155 155
156 for (i = 0; i < SIDTAB_SIZE; i++) { 156 for (i = 0; i < SIDTAB_SIZE; i++) {
157 cur = s->htable[i]; 157 cur = s->htable[i];
158 while (cur != NULL) { 158 while (cur) {
159 if (context_cmp(&cur->context, context)) 159 if (context_cmp(&cur->context, context))
160 return cur->sid; 160 return cur->sid;
161 cur = cur->next; 161 cur = cur->next;
@@ -242,7 +242,7 @@ void sidtab_destroy(struct sidtab *s)
242 242
243 for (i = 0; i < SIDTAB_SIZE; i++) { 243 for (i = 0; i < SIDTAB_SIZE; i++) {
244 cur = s->htable[i]; 244 cur = s->htable[i];
245 while (cur != NULL) { 245 while (cur) {
246 temp = cur; 246 temp = cur;
247 cur = cur->next; 247 cur = cur->next;
248 context_destroy(&temp->context); 248 context_destroy(&temp->context);