aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2005-09-03 18:55:16 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:05:50 -0400
commit782ebb992ec20b5afdd5786ee8c2f1b58b631f24 (patch)
treeadf0af44fa591d803ec6b9ab7541ff3e5745dd93 /security/selinux
parent720d6c29e146e96cca858057469951e91e0e6850 (diff)
[PATCH] selinux: Reduce memory use by avtab
This patch improves memory use by SELinux by both reducing the avtab node size and reducing the number of avtab nodes. The memory savings are substantial, e.g. on a 64-bit system after boot, James Morris reported the following data for the targeted and strict policies: #objs objsize kernmem Targeted: Before: 237888 40 9.1MB After: 19968 24 468KB Strict: Before: 571680 40 21.81MB After: 221052 24 5.06MB The improvement in memory use comes at a cost in the speed of security server computations of access vectors, but these computations are only required on AVC cache misses, and performance measurements by James Morris using a number of benchmarks have shown that the change does not cause any significant degradation. Note that a rebuilt policy via an updated policy toolchain (libsepol/checkpolicy) is required in order to gain the full benefits of this patch, although some memory savings benefits are immediately applied even to older policies (in particular, the reduction in avtab node size). Sources for the updated toolchain are presently available from the sourceforge CVS tree (http://sourceforge.net/cvs/?group_id=21266), and tarballs are available from http://www.flux.utah.edu/~sds. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security/selinux')
-rw-r--r--security/selinux/include/security.h3
-rw-r--r--security/selinux/ss/avtab.c192
-rw-r--r--security/selinux/ss/avtab.h37
-rw-r--r--security/selinux/ss/conditional.c205
-rw-r--r--security/selinux/ss/ebitmap.h30
-rw-r--r--security/selinux/ss/mls.c42
-rw-r--r--security/selinux/ss/policydb.c47
-rw-r--r--security/selinux/ss/policydb.h3
-rw-r--r--security/selinux/ss/services.c76
9 files changed, 400 insertions, 235 deletions
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 71c0a19c9753..5f016c98056f 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -23,10 +23,11 @@
23#define POLICYDB_VERSION_NLCLASS 18 23#define POLICYDB_VERSION_NLCLASS 18
24#define POLICYDB_VERSION_VALIDATETRANS 19 24#define POLICYDB_VERSION_VALIDATETRANS 19
25#define POLICYDB_VERSION_MLS 19 25#define POLICYDB_VERSION_MLS 19
26#define POLICYDB_VERSION_AVTAB 20
26 27
27/* Range of policy versions we understand*/ 28/* Range of policy versions we understand*/
28#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE 29#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
29#define POLICYDB_VERSION_MAX POLICYDB_VERSION_MLS 30#define POLICYDB_VERSION_MAX POLICYDB_VERSION_AVTAB
30 31
31#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM 32#ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
32extern int selinux_enabled; 33extern int selinux_enabled;
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index f238c034c44e..2e71af67b5d8 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -58,6 +58,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
58{ 58{
59 int hvalue; 59 int hvalue;
60 struct avtab_node *prev, *cur, *newnode; 60 struct avtab_node *prev, *cur, *newnode;
61 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
61 62
62 if (!h) 63 if (!h)
63 return -EINVAL; 64 return -EINVAL;
@@ -69,7 +70,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat
69 if (key->source_type == cur->key.source_type && 70 if (key->source_type == cur->key.source_type &&
70 key->target_type == cur->key.target_type && 71 key->target_type == cur->key.target_type &&
71 key->target_class == cur->key.target_class && 72 key->target_class == cur->key.target_class &&
72 (datum->specified & cur->datum.specified)) 73 (specified & cur->key.specified))
73 return -EEXIST; 74 return -EEXIST;
74 if (key->source_type < cur->key.source_type) 75 if (key->source_type < cur->key.source_type)
75 break; 76 break;
@@ -98,6 +99,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
98{ 99{
99 int hvalue; 100 int hvalue;
100 struct avtab_node *prev, *cur, *newnode; 101 struct avtab_node *prev, *cur, *newnode;
102 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
101 103
102 if (!h) 104 if (!h)
103 return NULL; 105 return NULL;
@@ -108,7 +110,7 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
108 if (key->source_type == cur->key.source_type && 110 if (key->source_type == cur->key.source_type &&
109 key->target_type == cur->key.target_type && 111 key->target_type == cur->key.target_type &&
110 key->target_class == cur->key.target_class && 112 key->target_class == cur->key.target_class &&
111 (datum->specified & cur->datum.specified)) 113 (specified & cur->key.specified))
112 break; 114 break;
113 if (key->source_type < cur->key.source_type) 115 if (key->source_type < cur->key.source_type)
114 break; 116 break;
@@ -125,10 +127,11 @@ avtab_insert_nonunique(struct avtab * h, struct avtab_key * key, struct avtab_da
125 return newnode; 127 return newnode;
126} 128}
127 129
128struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified) 130struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key)
129{ 131{
130 int hvalue; 132 int hvalue;
131 struct avtab_node *cur; 133 struct avtab_node *cur;
134 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
132 135
133 if (!h) 136 if (!h)
134 return NULL; 137 return NULL;
@@ -138,7 +141,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe
138 if (key->source_type == cur->key.source_type && 141 if (key->source_type == cur->key.source_type &&
139 key->target_type == cur->key.target_type && 142 key->target_type == cur->key.target_type &&
140 key->target_class == cur->key.target_class && 143 key->target_class == cur->key.target_class &&
141 (specified & cur->datum.specified)) 144 (specified & cur->key.specified))
142 return &cur->datum; 145 return &cur->datum;
143 146
144 if (key->source_type < cur->key.source_type) 147 if (key->source_type < cur->key.source_type)
@@ -159,10 +162,11 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int spe
159 * conjunction with avtab_search_next_node() 162 * conjunction with avtab_search_next_node()
160 */ 163 */
161struct avtab_node* 164struct avtab_node*
162avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) 165avtab_search_node(struct avtab *h, struct avtab_key *key)
163{ 166{
164 int hvalue; 167 int hvalue;
165 struct avtab_node *cur; 168 struct avtab_node *cur;
169 u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
166 170
167 if (!h) 171 if (!h)
168 return NULL; 172 return NULL;
@@ -172,7 +176,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key, int specified)
172 if (key->source_type == cur->key.source_type && 176 if (key->source_type == cur->key.source_type &&
173 key->target_type == cur->key.target_type && 177 key->target_type == cur->key.target_type &&
174 key->target_class == cur->key.target_class && 178 key->target_class == cur->key.target_class &&
175 (specified & cur->datum.specified)) 179 (specified & cur->key.specified))
176 return cur; 180 return cur;
177 181
178 if (key->source_type < cur->key.source_type) 182 if (key->source_type < cur->key.source_type)
@@ -196,11 +200,12 @@ avtab_search_node_next(struct avtab_node *node, int specified)
196 if (!node) 200 if (!node)
197 return NULL; 201 return NULL;
198 202
203 specified &= ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD);
199 for (cur = node->next; cur; cur = cur->next) { 204 for (cur = node->next; cur; cur = cur->next) {
200 if (node->key.source_type == cur->key.source_type && 205 if (node->key.source_type == cur->key.source_type &&
201 node->key.target_type == cur->key.target_type && 206 node->key.target_type == cur->key.target_type &&
202 node->key.target_class == cur->key.target_class && 207 node->key.target_class == cur->key.target_class &&
203 (specified & cur->datum.specified)) 208 (specified & cur->key.specified))
204 return cur; 209 return cur;
205 210
206 if (node->key.source_type < cur->key.source_type) 211 if (node->key.source_type < cur->key.source_type)
@@ -278,75 +283,126 @@ void avtab_hash_eval(struct avtab *h, char *tag)
278 max_chain_len); 283 max_chain_len);
279} 284}
280 285
281int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) 286static uint16_t spec_order[] = {
287 AVTAB_ALLOWED,
288 AVTAB_AUDITDENY,
289 AVTAB_AUDITALLOW,
290 AVTAB_TRANSITION,
291 AVTAB_CHANGE,
292 AVTAB_MEMBER
293};
294
295int avtab_read_item(void *fp, u32 vers, struct avtab *a,
296 int (*insertf)(struct avtab *a, struct avtab_key *k,
297 struct avtab_datum *d, void *p),
298 void *p)
282{ 299{
283 u32 buf[7]; 300 u16 buf16[4], enabled;
284 u32 items, items2; 301 u32 buf32[7], items, items2, val;
285 int rc; 302 struct avtab_key key;
303 struct avtab_datum datum;
304 int i, rc;
305
306 memset(&key, 0, sizeof(struct avtab_key));
307 memset(&datum, 0, sizeof(struct avtab_datum));
308
309 if (vers < POLICYDB_VERSION_AVTAB) {
310 rc = next_entry(buf32, fp, sizeof(u32));
311 if (rc < 0) {
312 printk(KERN_ERR "security: avtab: truncated entry\n");
313 return -1;
314 }
315 items2 = le32_to_cpu(buf32[0]);
316 if (items2 > ARRAY_SIZE(buf32)) {
317 printk(KERN_ERR "security: avtab: entry overflow\n");
318 return -1;
286 319
287 memset(avkey, 0, sizeof(struct avtab_key)); 320 }
288 memset(avdatum, 0, sizeof(struct avtab_datum)); 321 rc = next_entry(buf32, fp, sizeof(u32)*items2);
322 if (rc < 0) {
323 printk(KERN_ERR "security: avtab: truncated entry\n");
324 return -1;
325 }
326 items = 0;
289 327
290 rc = next_entry(buf, fp, sizeof(u32)); 328 val = le32_to_cpu(buf32[items++]);
291 if (rc < 0) { 329 key.source_type = (u16)val;
292 printk(KERN_ERR "security: avtab: truncated entry\n"); 330 if (key.source_type != val) {
293 goto bad; 331 printk("security: avtab: truncated source type\n");
294 } 332 return -1;
295 items2 = le32_to_cpu(buf[0]); 333 }
296 if (items2 > ARRAY_SIZE(buf)) { 334 val = le32_to_cpu(buf32[items++]);
297 printk(KERN_ERR "security: avtab: entry overflow\n"); 335 key.target_type = (u16)val;
298 goto bad; 336 if (key.target_type != val) {
337 printk("security: avtab: truncated target type\n");
338 return -1;
339 }
340 val = le32_to_cpu(buf32[items++]);
341 key.target_class = (u16)val;
342 if (key.target_class != val) {
343 printk("security: avtab: truncated target class\n");
344 return -1;
345 }
346
347 val = le32_to_cpu(buf32[items++]);
348 enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0;
349
350 if (!(val & (AVTAB_AV | AVTAB_TYPE))) {
351 printk("security: avtab: null entry\n");
352 return -1;
353 }
354 if ((val & AVTAB_AV) &&
355 (val & AVTAB_TYPE)) {
356 printk("security: avtab: entry has both access vectors and types\n");
357 return -1;
358 }
359
360 for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) {
361 if (val & spec_order[i]) {
362 key.specified = spec_order[i] | enabled;
363 datum.data = le32_to_cpu(buf32[items++]);
364 rc = insertf(a, &key, &datum, p);
365 if (rc) return rc;
366 }
367 }
368
369 if (items != items2) {
370 printk("security: avtab: entry only had %d items, expected %d\n", items2, items);
371 return -1;
372 }
373 return 0;
299 } 374 }
300 rc = next_entry(buf, fp, sizeof(u32)*items2); 375
376 rc = next_entry(buf16, fp, sizeof(u16)*4);
301 if (rc < 0) { 377 if (rc < 0) {
302 printk(KERN_ERR "security: avtab: truncated entry\n"); 378 printk("security: avtab: truncated entry\n");
303 goto bad; 379 return -1;
304 } 380 }
381
305 items = 0; 382 items = 0;
306 avkey->source_type = le32_to_cpu(buf[items++]); 383 key.source_type = le16_to_cpu(buf16[items++]);
307 avkey->target_type = le32_to_cpu(buf[items++]); 384 key.target_type = le16_to_cpu(buf16[items++]);
308 avkey->target_class = le32_to_cpu(buf[items++]); 385 key.target_class = le16_to_cpu(buf16[items++]);
309 avdatum->specified = le32_to_cpu(buf[items++]); 386 key.specified = le16_to_cpu(buf16[items++]);
310 if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) { 387
311 printk(KERN_ERR "security: avtab: null entry\n"); 388 rc = next_entry(buf32, fp, sizeof(u32));
312 goto bad; 389 if (rc < 0) {
313 } 390 printk("security: avtab: truncated entry\n");
314 if ((avdatum->specified & AVTAB_AV) && 391 return -1;
315 (avdatum->specified & AVTAB_TYPE)) {
316 printk(KERN_ERR "security: avtab: entry has both access vectors and types\n");
317 goto bad;
318 }
319 if (avdatum->specified & AVTAB_AV) {
320 if (avdatum->specified & AVTAB_ALLOWED)
321 avtab_allowed(avdatum) = le32_to_cpu(buf[items++]);
322 if (avdatum->specified & AVTAB_AUDITDENY)
323 avtab_auditdeny(avdatum) = le32_to_cpu(buf[items++]);
324 if (avdatum->specified & AVTAB_AUDITALLOW)
325 avtab_auditallow(avdatum) = le32_to_cpu(buf[items++]);
326 } else {
327 if (avdatum->specified & AVTAB_TRANSITION)
328 avtab_transition(avdatum) = le32_to_cpu(buf[items++]);
329 if (avdatum->specified & AVTAB_CHANGE)
330 avtab_change(avdatum) = le32_to_cpu(buf[items++]);
331 if (avdatum->specified & AVTAB_MEMBER)
332 avtab_member(avdatum) = le32_to_cpu(buf[items++]);
333 }
334 if (items != items2) {
335 printk(KERN_ERR "security: avtab: entry only had %d items, expected %d\n",
336 items2, items);
337 goto bad;
338 } 392 }
393 datum.data = le32_to_cpu(*buf32);
394 return insertf(a, &key, &datum, p);
395}
339 396
340 return 0; 397static int avtab_insertf(struct avtab *a, struct avtab_key *k,
341bad: 398 struct avtab_datum *d, void *p)
342 return -1; 399{
400 return avtab_insert(a, k, d);
343} 401}
344 402
345int avtab_read(struct avtab *a, void *fp, u32 config) 403int avtab_read(struct avtab *a, void *fp, u32 vers)
346{ 404{
347 int rc; 405 int rc;
348 struct avtab_key avkey;
349 struct avtab_datum avdatum;
350 u32 buf[1]; 406 u32 buf[1];
351 u32 nel, i; 407 u32 nel, i;
352 408
@@ -363,16 +419,14 @@ int avtab_read(struct avtab *a, void *fp, u32 config)
363 goto bad; 419 goto bad;
364 } 420 }
365 for (i = 0; i < nel; i++) { 421 for (i = 0; i < nel; i++) {
366 if (avtab_read_item(fp, &avdatum, &avkey)) { 422 rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
367 rc = -EINVAL;
368 goto bad;
369 }
370 rc = avtab_insert(a, &avkey, &avdatum);
371 if (rc) { 423 if (rc) {
372 if (rc == -ENOMEM) 424 if (rc == -ENOMEM)
373 printk(KERN_ERR "security: avtab: out of memory\n"); 425 printk(KERN_ERR "security: avtab: out of memory\n");
374 if (rc == -EEXIST) 426 else if (rc == -EEXIST)
375 printk(KERN_ERR "security: avtab: duplicate entry\n"); 427 printk(KERN_ERR "security: avtab: duplicate entry\n");
428 else
429 rc = -EINVAL;
376 goto bad; 430 goto bad;
377 } 431 }
378 } 432 }
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h
index 519d4f6dc655..0a90d939af93 100644
--- a/security/selinux/ss/avtab.h
+++ b/security/selinux/ss/avtab.h
@@ -21,12 +21,9 @@
21#define _SS_AVTAB_H_ 21#define _SS_AVTAB_H_
22 22
23struct avtab_key { 23struct avtab_key {
24 u32 source_type; /* source type */ 24 u16 source_type; /* source type */
25 u32 target_type; /* target type */ 25 u16 target_type; /* target type */
26 u32 target_class; /* target object class */ 26 u16 target_class; /* target object class */
27};
28
29struct avtab_datum {
30#define AVTAB_ALLOWED 1 27#define AVTAB_ALLOWED 1
31#define AVTAB_AUDITALLOW 2 28#define AVTAB_AUDITALLOW 2
32#define AVTAB_AUDITDENY 4 29#define AVTAB_AUDITDENY 4
@@ -35,15 +32,13 @@ struct avtab_datum {
35#define AVTAB_MEMBER 32 32#define AVTAB_MEMBER 32
36#define AVTAB_CHANGE 64 33#define AVTAB_CHANGE 64
37#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE) 34#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
38#define AVTAB_ENABLED 0x80000000 /* reserved for used in cond_avtab */ 35#define AVTAB_ENABLED_OLD 0x80000000 /* reserved for used in cond_avtab */
39 u32 specified; /* what fields are specified */ 36#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
40 u32 data[3]; /* access vectors or types */ 37 u16 specified; /* what field is specified */
41#define avtab_allowed(x) (x)->data[0] 38};
42#define avtab_auditdeny(x) (x)->data[1] 39
43#define avtab_auditallow(x) (x)->data[2] 40struct avtab_datum {
44#define avtab_transition(x) (x)->data[0] 41 u32 data; /* access vector or type value */
45#define avtab_change(x) (x)->data[1]
46#define avtab_member(x) (x)->data[2]
47}; 42};
48 43
49struct avtab_node { 44struct avtab_node {
@@ -58,17 +53,21 @@ struct avtab {
58}; 53};
59 54
60int avtab_init(struct avtab *); 55int avtab_init(struct avtab *);
61struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified); 56struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
62void avtab_destroy(struct avtab *h); 57void avtab_destroy(struct avtab *h);
63void avtab_hash_eval(struct avtab *h, char *tag); 58void avtab_hash_eval(struct avtab *h, char *tag);
64 59
65int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey); 60int avtab_read_item(void *fp, uint32_t vers, struct avtab *a,
66int avtab_read(struct avtab *a, void *fp, u32 config); 61 int (*insert)(struct avtab *a, struct avtab_key *k,
62 struct avtab_datum *d, void *p),
63 void *p);
64
65int avtab_read(struct avtab *a, void *fp, u32 vers);
67 66
68struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, 67struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
69 struct avtab_datum *datum); 68 struct avtab_datum *datum);
70 69
71struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified); 70struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key);
72 71
73struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); 72struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified);
74 73
diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c
index e2057f5a411a..b81cd6688978 100644
--- a/security/selinux/ss/conditional.c
+++ b/security/selinux/ss/conditional.c
@@ -100,18 +100,18 @@ int evaluate_cond_node(struct policydb *p, struct cond_node *node)
100 /* turn the rules on or off */ 100 /* turn the rules on or off */
101 for (cur = node->true_list; cur != NULL; cur = cur->next) { 101 for (cur = node->true_list; cur != NULL; cur = cur->next) {
102 if (new_state <= 0) { 102 if (new_state <= 0) {
103 cur->node->datum.specified &= ~AVTAB_ENABLED; 103 cur->node->key.specified &= ~AVTAB_ENABLED;
104 } else { 104 } else {
105 cur->node->datum.specified |= AVTAB_ENABLED; 105 cur->node->key.specified |= AVTAB_ENABLED;
106 } 106 }
107 } 107 }
108 108
109 for (cur = node->false_list; cur != NULL; cur = cur->next) { 109 for (cur = node->false_list; cur != NULL; cur = cur->next) {
110 /* -1 or 1 */ 110 /* -1 or 1 */
111 if (new_state) { 111 if (new_state) {
112 cur->node->datum.specified &= ~AVTAB_ENABLED; 112 cur->node->key.specified &= ~AVTAB_ENABLED;
113 } else { 113 } else {
114 cur->node->datum.specified |= AVTAB_ENABLED; 114 cur->node->key.specified |= AVTAB_ENABLED;
115 } 115 }
116 } 116 }
117 } 117 }
@@ -252,104 +252,126 @@ err:
252 return -1; 252 return -1;
253} 253}
254 254
255static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, 255struct cond_insertf_data
256 struct cond_av_list *other)
257{ 256{
258 struct cond_av_list *list, *last = NULL, *cur; 257 struct policydb *p;
259 struct avtab_key key; 258 struct cond_av_list *other;
260 struct avtab_datum datum; 259 struct cond_av_list *head;
260 struct cond_av_list *tail;
261};
262
263static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr)
264{
265 struct cond_insertf_data *data = ptr;
266 struct policydb *p = data->p;
267 struct cond_av_list *other = data->other, *list, *cur;
261 struct avtab_node *node_ptr; 268 struct avtab_node *node_ptr;
262 int rc;
263 u32 buf[1], i, len;
264 u8 found; 269 u8 found;
265 270
266 *ret_list = NULL;
267
268 len = 0;
269 rc = next_entry(buf, fp, sizeof buf);
270 if (rc < 0)
271 return -1;
272
273 len = le32_to_cpu(buf[0]);
274 if (len == 0) {
275 return 0;
276 }
277 271
278 for (i = 0; i < len; i++) { 272 /*
279 if (avtab_read_item(fp, &datum, &key)) 273 * For type rules we have to make certain there aren't any
274 * conflicting rules by searching the te_avtab and the
275 * cond_te_avtab.
276 */
277 if (k->specified & AVTAB_TYPE) {
278 if (avtab_search(&p->te_avtab, k)) {
279 printk("security: type rule already exists outside of a conditional.");
280 goto err; 280 goto err;
281 281 }
282 /* 282 /*
283 * For type rules we have to make certain there aren't any 283 * If we are reading the false list other will be a pointer to
284 * conflicting rules by searching the te_avtab and the 284 * the true list. We can have duplicate entries if there is only
285 * cond_te_avtab. 285 * 1 other entry and it is in our true list.
286 *
287 * If we are reading the true list (other == NULL) there shouldn't
288 * be any other entries.
286 */ 289 */
287 if (datum.specified & AVTAB_TYPE) { 290 if (other) {
288 if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) { 291 node_ptr = avtab_search_node(&p->te_cond_avtab, k);
289 printk("security: type rule already exists outside of a conditional."); 292 if (node_ptr) {
290 goto err; 293 if (avtab_search_node_next(node_ptr, k->specified)) {
291 } 294 printk("security: too many conflicting type rules.");
292 /* 295 goto err;
293 * If we are reading the false list other will be a pointer to 296 }
294 * the true list. We can have duplicate entries if there is only 297 found = 0;
295 * 1 other entry and it is in our true list. 298 for (cur = other; cur != NULL; cur = cur->next) {
296 * 299 if (cur->node == node_ptr) {
297 * If we are reading the true list (other == NULL) there shouldn't 300 found = 1;
298 * be any other entries. 301 break;
299 */
300 if (other) {
301 node_ptr = avtab_search_node(&p->te_cond_avtab, &key, AVTAB_TYPE);
302 if (node_ptr) {
303 if (avtab_search_node_next(node_ptr, AVTAB_TYPE)) {
304 printk("security: too many conflicting type rules.");
305 goto err;
306 }
307 found = 0;
308 for (cur = other; cur != NULL; cur = cur->next) {
309 if (cur->node == node_ptr) {
310 found = 1;
311 break;
312 }
313 }
314 if (!found) {
315 printk("security: conflicting type rules.");
316 goto err;
317 } 302 }
318 } 303 }
319 } else { 304 if (!found) {
320 if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) { 305 printk("security: conflicting type rules.\n");
321 printk("security: conflicting type rules when adding type rule for true.");
322 goto err; 306 goto err;
323 } 307 }
324 } 308 }
309 } else {
310 if (avtab_search(&p->te_cond_avtab, k)) {
311 printk("security: conflicting type rules when adding type rule for true.\n");
312 goto err;
313 }
325 } 314 }
326 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum); 315 }
327 if (!node_ptr) {
328 printk("security: could not insert rule.");
329 goto err;
330 }
331
332 list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
333 if (!list)
334 goto err;
335 memset(list, 0, sizeof(struct cond_av_list));
336
337 list->node = node_ptr;
338 if (i == 0)
339 *ret_list = list;
340 else
341 last->next = list;
342 last = list;
343 316
317 node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d);
318 if (!node_ptr) {
319 printk("security: could not insert rule.");
320 goto err;
344 } 321 }
345 322
323 list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL);
324 if (!list)
325 goto err;
326 memset(list, 0, sizeof(*list));
327
328 list->node = node_ptr;
329 if (!data->head)
330 data->head = list;
331 else
332 data->tail->next = list;
333 data->tail = list;
346 return 0; 334 return 0;
335
347err: 336err:
348 cond_av_list_destroy(*ret_list); 337 cond_av_list_destroy(data->head);
349 *ret_list = NULL; 338 data->head = NULL;
350 return -1; 339 return -1;
351} 340}
352 341
342static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other)
343{
344 int i, rc;
345 u32 buf[1], len;
346 struct cond_insertf_data data;
347
348 *ret_list = NULL;
349
350 len = 0;
351 rc = next_entry(buf, fp, sizeof(u32));
352 if (rc < 0)
353 return -1;
354
355 len = le32_to_cpu(buf[0]);
356 if (len == 0) {
357 return 0;
358 }
359
360 data.p = p;
361 data.other = other;
362 data.head = NULL;
363 data.tail = NULL;
364 for (i = 0; i < len; i++) {
365 rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data);
366 if (rc)
367 return rc;
368
369 }
370
371 *ret_list = data.head;
372 return 0;
373}
374
353static int expr_isvalid(struct policydb *p, struct cond_expr *expr) 375static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
354{ 376{
355 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { 377 if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) {
@@ -452,6 +474,7 @@ int cond_read_list(struct policydb *p, void *fp)
452 return 0; 474 return 0;
453err: 475err:
454 cond_list_destroy(p->cond_list); 476 cond_list_destroy(p->cond_list);
477 p->cond_list = NULL;
455 return -1; 478 return -1;
456} 479}
457 480
@@ -465,22 +488,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi
465 if(!ctab || !key || !avd) 488 if(!ctab || !key || !avd)
466 return; 489 return;
467 490
468 for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL; 491 for(node = avtab_search_node(ctab, key); node != NULL;
469 node = avtab_search_node_next(node, AVTAB_AV)) { 492 node = avtab_search_node_next(node, key->specified)) {
470 if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) == 493 if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) ==
471 (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) 494 (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED)))
472 avd->allowed |= avtab_allowed(&node->datum); 495 avd->allowed |= node->datum.data;
473 if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) == 496 if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) ==
474 (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) 497 (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED)))
475 /* Since a '0' in an auditdeny mask represents a 498 /* Since a '0' in an auditdeny mask represents a
476 * permission we do NOT want to audit (dontaudit), we use 499 * permission we do NOT want to audit (dontaudit), we use
477 * the '&' operand to ensure that all '0's in the mask 500 * the '&' operand to ensure that all '0's in the mask
478 * are retained (much unlike the allow and auditallow cases). 501 * are retained (much unlike the allow and auditallow cases).
479 */ 502 */
480 avd->auditdeny &= avtab_auditdeny(&node->datum); 503 avd->auditdeny &= node->datum.data;
481 if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == 504 if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) ==
482 (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) 505 (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED)))
483 avd->auditallow |= avtab_auditallow(&node->datum); 506 avd->auditallow |= node->datum.data;
484 } 507 }
485 return; 508 return;
486} 509}
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index 471370233fd9..8bf41055a6cb 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -32,11 +32,41 @@ struct ebitmap {
32#define ebitmap_length(e) ((e)->highbit) 32#define ebitmap_length(e) ((e)->highbit)
33#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0) 33#define ebitmap_startbit(e) ((e)->node ? (e)->node->startbit : 0)
34 34
35static inline unsigned int ebitmap_start(struct ebitmap *e,
36 struct ebitmap_node **n)
37{
38 *n = e->node;
39 return ebitmap_startbit(e);
40}
41
35static inline void ebitmap_init(struct ebitmap *e) 42static inline void ebitmap_init(struct ebitmap *e)
36{ 43{
37 memset(e, 0, sizeof(*e)); 44 memset(e, 0, sizeof(*e));
38} 45}
39 46
47static inline unsigned int ebitmap_next(struct ebitmap_node **n,
48 unsigned int bit)
49{
50 if ((bit == ((*n)->startbit + MAPSIZE - 1)) &&
51 (*n)->next) {
52 *n = (*n)->next;
53 return (*n)->startbit;
54 }
55
56 return (bit+1);
57}
58
59static inline int ebitmap_node_get_bit(struct ebitmap_node * n,
60 unsigned int bit)
61{
62 if (n->map & (MAPBIT << (bit - n->startbit)))
63 return 1;
64 return 0;
65}
66
67#define ebitmap_for_each_bit(e, n, bit) \
68 for (bit = ebitmap_start(e, &n); bit < ebitmap_length(e); bit = ebitmap_next(&n, bit)) \
69
40int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); 70int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2);
41int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); 71int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src);
42int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); 72int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2);
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index d4c32c39ccc9..aaefac2921f1 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -27,6 +27,7 @@
27int mls_compute_context_len(struct context * context) 27int mls_compute_context_len(struct context * context)
28{ 28{
29 int i, l, len, range; 29 int i, l, len, range;
30 struct ebitmap_node *node;
30 31
31 if (!selinux_mls_enabled) 32 if (!selinux_mls_enabled)
32 return 0; 33 return 0;
@@ -36,24 +37,24 @@ int mls_compute_context_len(struct context * context)
36 range = 0; 37 range = 0;
37 len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); 38 len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
38 39
39 for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { 40 ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
40 if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { 41 if (ebitmap_node_get_bit(node, i)) {
41 if (range) { 42 if (range) {
42 range++; 43 range++;
43 continue; 44 continue;
44 } 45 }
45 46
46 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1; 47 len += strlen(policydb.p_cat_val_to_name[i]) + 1;
47 range++; 48 range++;
48 } else { 49 } else {
49 if (range > 1) 50 if (range > 1)
50 len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; 51 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
51 range = 0; 52 range = 0;
52 } 53 }
53 } 54 }
54 /* Handle case where last category is the end of range */ 55 /* Handle case where last category is the end of range */
55 if (range > 1) 56 if (range > 1)
56 len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1; 57 len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
57 58
58 if (l == 0) { 59 if (l == 0) {
59 if (mls_level_eq(&context->range.level[0], 60 if (mls_level_eq(&context->range.level[0],
@@ -77,6 +78,7 @@ void mls_sid_to_context(struct context *context,
77{ 78{
78 char *scontextp; 79 char *scontextp;
79 int i, l, range, wrote_sep; 80 int i, l, range, wrote_sep;
81 struct ebitmap_node *node;
80 82
81 if (!selinux_mls_enabled) 83 if (!selinux_mls_enabled)
82 return; 84 return;
@@ -94,8 +96,8 @@ void mls_sid_to_context(struct context *context,
94 scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]); 96 scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
95 97
96 /* categories */ 98 /* categories */
97 for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) { 99 ebitmap_for_each_bit(&context->range.level[l].cat, node, i) {
98 if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) { 100 if (ebitmap_node_get_bit(node, i)) {
99 if (range) { 101 if (range) {
100 range++; 102 range++;
101 continue; 103 continue;
@@ -106,8 +108,8 @@ void mls_sid_to_context(struct context *context,
106 wrote_sep = 1; 108 wrote_sep = 1;
107 } else 109 } else
108 *scontextp++ = ','; 110 *scontextp++ = ',';
109 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]); 111 strcpy(scontextp, policydb.p_cat_val_to_name[i]);
110 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]); 112 scontextp += strlen(policydb.p_cat_val_to_name[i]);
111 range++; 113 range++;
112 } else { 114 } else {
113 if (range > 1) { 115 if (range > 1) {
@@ -116,8 +118,8 @@ void mls_sid_to_context(struct context *context,
116 else 118 else
117 *scontextp++ = ','; 119 *scontextp++ = ',';
118 120
119 strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); 121 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
120 scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); 122 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
121 } 123 }
122 range = 0; 124 range = 0;
123 } 125 }
@@ -130,8 +132,8 @@ void mls_sid_to_context(struct context *context,
130 else 132 else
131 *scontextp++ = ','; 133 *scontextp++ = ',';
132 134
133 strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]); 135 strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
134 scontextp += strlen(policydb.p_cat_val_to_name[i - 2]); 136 scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
135 } 137 }
136 138
137 if (l == 0) { 139 if (l == 0) {
@@ -157,6 +159,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
157{ 159{
158 struct level_datum *levdatum; 160 struct level_datum *levdatum;
159 struct user_datum *usrdatum; 161 struct user_datum *usrdatum;
162 struct ebitmap_node *node;
160 int i, l; 163 int i, l;
161 164
162 if (!selinux_mls_enabled) 165 if (!selinux_mls_enabled)
@@ -179,11 +182,11 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
179 if (!levdatum) 182 if (!levdatum)
180 return 0; 183 return 0;
181 184
182 for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { 185 ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
183 if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { 186 if (ebitmap_node_get_bit(node, i)) {
184 if (i > p->p_cats.nprim) 187 if (i > p->p_cats.nprim)
185 return 0; 188 return 0;
186 if (!ebitmap_get_bit(&levdatum->level->cat, i - 1)) 189 if (!ebitmap_get_bit(&levdatum->level->cat, i))
187 /* 190 /*
188 * Category may not be associated with 191 * Category may not be associated with
189 * sensitivity in low level. 192 * sensitivity in low level.
@@ -468,6 +471,7 @@ int mls_convert_context(struct policydb *oldp,
468 struct level_datum *levdatum; 471 struct level_datum *levdatum;
469 struct cat_datum *catdatum; 472 struct cat_datum *catdatum;
470 struct ebitmap bitmap; 473 struct ebitmap bitmap;
474 struct ebitmap_node *node;
471 int l, i; 475 int l, i;
472 476
473 if (!selinux_mls_enabled) 477 if (!selinux_mls_enabled)
@@ -482,12 +486,12 @@ int mls_convert_context(struct policydb *oldp,
482 c->range.level[l].sens = levdatum->level->sens; 486 c->range.level[l].sens = levdatum->level->sens;
483 487
484 ebitmap_init(&bitmap); 488 ebitmap_init(&bitmap);
485 for (i = 1; i <= ebitmap_length(&c->range.level[l].cat); i++) { 489 ebitmap_for_each_bit(&c->range.level[l].cat, node, i) {
486 if (ebitmap_get_bit(&c->range.level[l].cat, i - 1)) { 490 if (ebitmap_node_get_bit(node, i)) {
487 int rc; 491 int rc;
488 492
489 catdatum = hashtab_search(newp->p_cats.table, 493 catdatum = hashtab_search(newp->p_cats.table,
490 oldp->p_cat_val_to_name[i - 1]); 494 oldp->p_cat_val_to_name[i]);
491 if (!catdatum) 495 if (!catdatum)
492 return -EINVAL; 496 return -EINVAL;
493 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1); 497 rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 785c33cf4864..7b03fa0f92b0 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -91,6 +91,11 @@ static struct policydb_compat_info policydb_compat[] = {
91 .sym_num = SYM_NUM, 91 .sym_num = SYM_NUM,
92 .ocon_num = OCON_NUM, 92 .ocon_num = OCON_NUM,
93 }, 93 },
94 {
95 .version = POLICYDB_VERSION_AVTAB,
96 .sym_num = SYM_NUM,
97 .ocon_num = OCON_NUM,
98 },
94}; 99};
95 100
96static struct policydb_compat_info *policydb_lookup_compat(int version) 101static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -584,6 +589,9 @@ void policydb_destroy(struct policydb *p)
584 struct ocontext *c, *ctmp; 589 struct ocontext *c, *ctmp;
585 struct genfs *g, *gtmp; 590 struct genfs *g, *gtmp;
586 int i; 591 int i;
592 struct role_allow *ra, *lra = NULL;
593 struct role_trans *tr, *ltr = NULL;
594 struct range_trans *rt, *lrt = NULL;
587 595
588 for (i = 0; i < SYM_NUM; i++) { 596 for (i = 0; i < SYM_NUM; i++) {
589 hashtab_map(p->symtab[i].table, destroy_f[i], NULL); 597 hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
@@ -624,6 +632,28 @@ void policydb_destroy(struct policydb *p)
624 632
625 cond_policydb_destroy(p); 633 cond_policydb_destroy(p);
626 634
635 for (tr = p->role_tr; tr; tr = tr->next) {
636 if (ltr) kfree(ltr);
637 ltr = tr;
638 }
639 if (ltr) kfree(ltr);
640
641 for (ra = p->role_allow; ra; ra = ra -> next) {
642 if (lra) kfree(lra);
643 lra = ra;
644 }
645 if (lra) kfree(lra);
646
647 for (rt = p->range_tr; rt; rt = rt -> next) {
648 if (lrt) kfree(lrt);
649 lrt = rt;
650 }
651 if (lrt) kfree(lrt);
652
653 for (i = 0; i < p->p_types.nprim; i++)
654 ebitmap_destroy(&p->type_attr_map[i]);
655 kfree(p->type_attr_map);
656
627 return; 657 return;
628} 658}
629 659
@@ -1511,7 +1541,7 @@ int policydb_read(struct policydb *p, void *fp)
1511 p->symtab[i].nprim = nprim; 1541 p->symtab[i].nprim = nprim;
1512 } 1542 }
1513 1543
1514 rc = avtab_read(&p->te_avtab, fp, config); 1544 rc = avtab_read(&p->te_avtab, fp, p->policyvers);
1515 if (rc) 1545 if (rc)
1516 goto bad; 1546 goto bad;
1517 1547
@@ -1825,6 +1855,21 @@ int policydb_read(struct policydb *p, void *fp)
1825 } 1855 }
1826 } 1856 }
1827 1857
1858 p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL);
1859 if (!p->type_attr_map)
1860 goto bad;
1861
1862 for (i = 0; i < p->p_types.nprim; i++) {
1863 ebitmap_init(&p->type_attr_map[i]);
1864 if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
1865 if (ebitmap_read(&p->type_attr_map[i], fp))
1866 goto bad;
1867 }
1868 /* add the type itself as the degenerate case */
1869 if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
1870 goto bad;
1871 }
1872
1828 rc = 0; 1873 rc = 0;
1829out: 1874out:
1830 return rc; 1875 return rc;
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
index 2470e2a1a1c3..b1340711f721 100644
--- a/security/selinux/ss/policydb.h
+++ b/security/selinux/ss/policydb.h
@@ -237,6 +237,9 @@ struct policydb {
237 /* range transitions */ 237 /* range transitions */
238 struct range_trans *range_tr; 238 struct range_trans *range_tr;
239 239
240 /* type -> attribute reverse mapping */
241 struct ebitmap *type_attr_map;
242
240 unsigned int policyvers; 243 unsigned int policyvers;
241}; 244};
242 245
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 014120474e69..92b89dc99bcd 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -266,8 +266,11 @@ static int context_struct_compute_av(struct context *scontext,
266 struct constraint_node *constraint; 266 struct constraint_node *constraint;
267 struct role_allow *ra; 267 struct role_allow *ra;
268 struct avtab_key avkey; 268 struct avtab_key avkey;
269 struct avtab_datum *avdatum; 269 struct avtab_node *node;
270 struct class_datum *tclass_datum; 270 struct class_datum *tclass_datum;
271 struct ebitmap *sattr, *tattr;
272 struct ebitmap_node *snode, *tnode;
273 unsigned int i, j;
271 274
272 /* 275 /*
273 * Remap extended Netlink classes for old policy versions. 276 * Remap extended Netlink classes for old policy versions.
@@ -300,21 +303,34 @@ static int context_struct_compute_av(struct context *scontext,
300 * If a specific type enforcement rule was defined for 303 * If a specific type enforcement rule was defined for
301 * this permission check, then use it. 304 * this permission check, then use it.
302 */ 305 */
303 avkey.source_type = scontext->type;
304 avkey.target_type = tcontext->type;
305 avkey.target_class = tclass; 306 avkey.target_class = tclass;
306 avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV); 307 avkey.specified = AVTAB_AV;
307 if (avdatum) { 308 sattr = &policydb.type_attr_map[scontext->type - 1];
308 if (avdatum->specified & AVTAB_ALLOWED) 309 tattr = &policydb.type_attr_map[tcontext->type - 1];
309 avd->allowed = avtab_allowed(avdatum); 310 ebitmap_for_each_bit(sattr, snode, i) {
310 if (avdatum->specified & AVTAB_AUDITDENY) 311 if (!ebitmap_node_get_bit(snode, i))
311 avd->auditdeny = avtab_auditdeny(avdatum); 312 continue;
312 if (avdatum->specified & AVTAB_AUDITALLOW) 313 ebitmap_for_each_bit(tattr, tnode, j) {
313 avd->auditallow = avtab_auditallow(avdatum); 314 if (!ebitmap_node_get_bit(tnode, j))
314 } 315 continue;
316 avkey.source_type = i + 1;
317 avkey.target_type = j + 1;
318 for (node = avtab_search_node(&policydb.te_avtab, &avkey);
319 node != NULL;
320 node = avtab_search_node_next(node, avkey.specified)) {
321 if (node->key.specified == AVTAB_ALLOWED)
322 avd->allowed |= node->datum.data;
323 else if (node->key.specified == AVTAB_AUDITALLOW)
324 avd->auditallow |= node->datum.data;
325 else if (node->key.specified == AVTAB_AUDITDENY)
326 avd->auditdeny &= node->datum.data;
327 }
315 328
316 /* Check conditional av table for additional permissions */ 329 /* Check conditional av table for additional permissions */
317 cond_compute_av(&policydb.te_cond_avtab, &avkey, avd); 330 cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
331
332 }
333 }
318 334
319 /* 335 /*
320 * Remove any permissions prohibited by a constraint (this includes 336 * Remove any permissions prohibited by a constraint (this includes
@@ -797,7 +813,6 @@ static int security_compute_sid(u32 ssid,
797 struct avtab_key avkey; 813 struct avtab_key avkey;
798 struct avtab_datum *avdatum; 814 struct avtab_datum *avdatum;
799 struct avtab_node *node; 815 struct avtab_node *node;
800 unsigned int type_change = 0;
801 int rc = 0; 816 int rc = 0;
802 817
803 if (!ss_initialized) { 818 if (!ss_initialized) {
@@ -862,33 +877,23 @@ static int security_compute_sid(u32 ssid,
862 avkey.source_type = scontext->type; 877 avkey.source_type = scontext->type;
863 avkey.target_type = tcontext->type; 878 avkey.target_type = tcontext->type;
864 avkey.target_class = tclass; 879 avkey.target_class = tclass;
865 avdatum = avtab_search(&policydb.te_avtab, &avkey, AVTAB_TYPE); 880 avkey.specified = specified;
881 avdatum = avtab_search(&policydb.te_avtab, &avkey);
866 882
867 /* If no permanent rule, also check for enabled conditional rules */ 883 /* If no permanent rule, also check for enabled conditional rules */
868 if(!avdatum) { 884 if(!avdatum) {
869 node = avtab_search_node(&policydb.te_cond_avtab, &avkey, specified); 885 node = avtab_search_node(&policydb.te_cond_avtab, &avkey);
870 for (; node != NULL; node = avtab_search_node_next(node, specified)) { 886 for (; node != NULL; node = avtab_search_node_next(node, specified)) {
871 if (node->datum.specified & AVTAB_ENABLED) { 887 if (node->key.specified & AVTAB_ENABLED) {
872 avdatum = &node->datum; 888 avdatum = &node->datum;
873 break; 889 break;
874 } 890 }
875 } 891 }
876 } 892 }
877 893
878 type_change = (avdatum && (avdatum->specified & specified)); 894 if (avdatum) {
879 if (type_change) {
880 /* Use the type from the type transition/member/change rule. */ 895 /* Use the type from the type transition/member/change rule. */
881 switch (specified) { 896 newcontext.type = avdatum->data;
882 case AVTAB_TRANSITION:
883 newcontext.type = avtab_transition(avdatum);
884 break;
885 case AVTAB_MEMBER:
886 newcontext.type = avtab_member(avdatum);
887 break;
888 case AVTAB_CHANGE:
889 newcontext.type = avtab_change(avdatum);
890 break;
891 }
892 } 897 }
893 898
894 /* Check for class-specific changes. */ 899 /* Check for class-specific changes. */
@@ -1502,6 +1507,7 @@ int security_get_user_sids(u32 fromsid,
1502 struct user_datum *user; 1507 struct user_datum *user;
1503 struct role_datum *role; 1508 struct role_datum *role;
1504 struct av_decision avd; 1509 struct av_decision avd;
1510 struct ebitmap_node *rnode, *tnode;
1505 int rc = 0, i, j; 1511 int rc = 0, i, j;
1506 1512
1507 if (!ss_initialized) { 1513 if (!ss_initialized) {
@@ -1532,13 +1538,13 @@ int security_get_user_sids(u32 fromsid,
1532 } 1538 }
1533 memset(mysids, 0, maxnel*sizeof(*mysids)); 1539 memset(mysids, 0, maxnel*sizeof(*mysids));
1534 1540
1535 for (i = ebitmap_startbit(&user->roles); i < ebitmap_length(&user->roles); i++) { 1541 ebitmap_for_each_bit(&user->roles, rnode, i) {
1536 if (!ebitmap_get_bit(&user->roles, i)) 1542 if (!ebitmap_node_get_bit(rnode, i))
1537 continue; 1543 continue;
1538 role = policydb.role_val_to_struct[i]; 1544 role = policydb.role_val_to_struct[i];
1539 usercon.role = i+1; 1545 usercon.role = i+1;
1540 for (j = ebitmap_startbit(&role->types); j < ebitmap_length(&role->types); j++) { 1546 ebitmap_for_each_bit(&role->types, tnode, j) {
1541 if (!ebitmap_get_bit(&role->types, j)) 1547 if (!ebitmap_node_get_bit(tnode, j))
1542 continue; 1548 continue;
1543 usercon.type = j+1; 1549 usercon.type = j+1;
1544 1550