diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/include/security.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/avtab.c | 192 | ||||
-rw-r--r-- | security/selinux/ss/avtab.h | 37 | ||||
-rw-r--r-- | security/selinux/ss/conditional.c | 205 | ||||
-rw-r--r-- | security/selinux/ss/ebitmap.h | 30 | ||||
-rw-r--r-- | security/selinux/ss/mls.c | 42 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 47 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 3 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 76 |
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 |
32 | extern int selinux_enabled; | 33 | extern 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 | ||
128 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key, int specified) | 130 | struct 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 | */ |
161 | struct avtab_node* | 164 | struct avtab_node* |
162 | avtab_search_node(struct avtab *h, struct avtab_key *key, int specified) | 165 | avtab_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 | ||
281 | int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) | 286 | static uint16_t spec_order[] = { |
287 | AVTAB_ALLOWED, | ||
288 | AVTAB_AUDITDENY, | ||
289 | AVTAB_AUDITALLOW, | ||
290 | AVTAB_TRANSITION, | ||
291 | AVTAB_CHANGE, | ||
292 | AVTAB_MEMBER | ||
293 | }; | ||
294 | |||
295 | int 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; | 397 | static int avtab_insertf(struct avtab *a, struct avtab_key *k, |
341 | bad: | 398 | struct avtab_datum *d, void *p) |
342 | return -1; | 399 | { |
400 | return avtab_insert(a, k, d); | ||
343 | } | 401 | } |
344 | 402 | ||
345 | int avtab_read(struct avtab *a, void *fp, u32 config) | 403 | int 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 | ||
23 | struct avtab_key { | 23 | struct 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 | |||
29 | struct 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] | 40 | struct 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 | ||
49 | struct avtab_node { | 44 | struct avtab_node { |
@@ -58,17 +53,21 @@ struct avtab { | |||
58 | }; | 53 | }; |
59 | 54 | ||
60 | int avtab_init(struct avtab *); | 55 | int avtab_init(struct avtab *); |
61 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k, int specified); | 56 | struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k); |
62 | void avtab_destroy(struct avtab *h); | 57 | void avtab_destroy(struct avtab *h); |
63 | void avtab_hash_eval(struct avtab *h, char *tag); | 58 | void avtab_hash_eval(struct avtab *h, char *tag); |
64 | 59 | ||
65 | int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey); | 60 | int avtab_read_item(void *fp, uint32_t vers, struct avtab *a, |
66 | int 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 | |||
65 | int avtab_read(struct avtab *a, void *fp, u32 vers); | ||
67 | 66 | ||
68 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, | 67 | struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, |
69 | struct avtab_datum *datum); | 68 | struct avtab_datum *datum); |
70 | 69 | ||
71 | struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key, int specified); | 70 | struct avtab_node *avtab_search_node(struct avtab *h, struct avtab_key *key); |
72 | 71 | ||
73 | struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified); | 72 | struct 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 | ||
255 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, | 255 | struct 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 | |||
263 | static 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 | |||
347 | err: | 336 | err: |
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 | ||
342 | static 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 | |||
353 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | 375 | static 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; |
453 | err: | 475 | err: |
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 | ||
35 | static 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 | |||
35 | static inline void ebitmap_init(struct ebitmap *e) | 42 | static 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 | ||
47 | static 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 | |||
59 | static 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 | |||
40 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); | 70 | int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2); |
41 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); | 71 | int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src); |
42 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2); | 72 | int 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 @@ | |||
27 | int mls_compute_context_len(struct context * context) | 27 | int 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 | ||
96 | static struct policydb_compat_info *policydb_lookup_compat(int version) | 101 | static 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; |
1829 | out: | 1874 | out: |
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 | ||