diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:39:55 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-09-08 05:39:55 -0400 |
| commit | c324b44c34050cf2a9b58830e11c974806bd85d8 (patch) | |
| tree | 3ac45a783221283925cd698334a8f5e7dd4c1df8 /security/selinux | |
| parent | 2fcf522509cceea524b6e7ece8fd6759b682175a (diff) | |
| parent | caf39e87cc1182f7dae84eefc43ca14d54c78ef9 (diff) | |
Merge /spare/repo/linux-2.6/
Diffstat (limited to 'security/selinux')
| -rw-r--r-- | security/selinux/avc.c | 4 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 3 | ||||
| -rw-r--r-- | security/selinux/ss/avtab.c | 196 | ||||
| -rw-r--r-- | security/selinux/ss/avtab.h | 37 | ||||
| -rw-r--r-- | security/selinux/ss/conditional.c | 215 | ||||
| -rw-r--r-- | security/selinux/ss/ebitmap.c | 5 | ||||
| -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 | 107 | ||||
| -rw-r--r-- | security/selinux/ss/policydb.h | 3 | ||||
| -rw-r--r-- | security/selinux/ss/services.c | 76 |
11 files changed, 449 insertions, 269 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 451502467a9b..cf6020f85403 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
| @@ -490,7 +490,7 @@ out: | |||
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 492 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, |
| 493 | struct in6_addr *addr, u16 port, | 493 | struct in6_addr *addr, __be16 port, |
| 494 | char *name1, char *name2) | 494 | char *name1, char *name2) |
| 495 | { | 495 | { |
| 496 | if (!ipv6_addr_any(addr)) | 496 | if (!ipv6_addr_any(addr)) |
| @@ -501,7 +501,7 @@ static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | |||
| 501 | } | 501 | } |
| 502 | 502 | ||
| 503 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, | 503 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, u32 addr, |
| 504 | u16 port, char *name1, char *name2) | 504 | __be16 port, char *name1, char *name2) |
| 505 | { | 505 | { |
| 506 | if (addr) | 506 | if (addr) |
| 507 | audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); | 507 | audit_log_format(ab, " %s=%d.%d.%d.%d", name1, NIPQUAD(addr)); |
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..dde094feb20d 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,76 +283,129 @@ 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 | __le16 buf16[4]; |
| 284 | u32 items, items2; | 301 | u16 enabled; |
| 285 | int rc; | 302 | __le32 buf32[7]; |
| 303 | u32 items, items2, val; | ||
| 304 | struct avtab_key key; | ||
| 305 | struct avtab_datum datum; | ||
| 306 | int i, rc; | ||
| 307 | |||
| 308 | memset(&key, 0, sizeof(struct avtab_key)); | ||
| 309 | memset(&datum, 0, sizeof(struct avtab_datum)); | ||
| 310 | |||
| 311 | if (vers < POLICYDB_VERSION_AVTAB) { | ||
| 312 | rc = next_entry(buf32, fp, sizeof(u32)); | ||
| 313 | if (rc < 0) { | ||
| 314 | printk(KERN_ERR "security: avtab: truncated entry\n"); | ||
| 315 | return -1; | ||
| 316 | } | ||
| 317 | items2 = le32_to_cpu(buf32[0]); | ||
| 318 | if (items2 > ARRAY_SIZE(buf32)) { | ||
| 319 | printk(KERN_ERR "security: avtab: entry overflow\n"); | ||
| 320 | return -1; | ||
| 286 | 321 | ||
| 287 | memset(avkey, 0, sizeof(struct avtab_key)); | 322 | } |
| 288 | memset(avdatum, 0, sizeof(struct avtab_datum)); | 323 | rc = next_entry(buf32, fp, sizeof(u32)*items2); |
| 324 | if (rc < 0) { | ||
| 325 | printk(KERN_ERR "security: avtab: truncated entry\n"); | ||
| 326 | return -1; | ||
| 327 | } | ||
| 328 | items = 0; | ||
| 289 | 329 | ||
| 290 | rc = next_entry(buf, fp, sizeof(u32)); | 330 | val = le32_to_cpu(buf32[items++]); |
| 291 | if (rc < 0) { | 331 | key.source_type = (u16)val; |
| 292 | printk(KERN_ERR "security: avtab: truncated entry\n"); | 332 | if (key.source_type != val) { |
| 293 | goto bad; | 333 | printk("security: avtab: truncated source type\n"); |
| 294 | } | 334 | return -1; |
| 295 | items2 = le32_to_cpu(buf[0]); | 335 | } |
| 296 | if (items2 > ARRAY_SIZE(buf)) { | 336 | val = le32_to_cpu(buf32[items++]); |
| 297 | printk(KERN_ERR "security: avtab: entry overflow\n"); | 337 | key.target_type = (u16)val; |
| 298 | goto bad; | 338 | if (key.target_type != val) { |
| 339 | printk("security: avtab: truncated target type\n"); | ||
| 340 | return -1; | ||
| 341 | } | ||
| 342 | val = le32_to_cpu(buf32[items++]); | ||
| 343 | key.target_class = (u16)val; | ||
| 344 | if (key.target_class != val) { | ||
| 345 | printk("security: avtab: truncated target class\n"); | ||
| 346 | return -1; | ||
| 347 | } | ||
| 348 | |||
| 349 | val = le32_to_cpu(buf32[items++]); | ||
| 350 | enabled = (val & AVTAB_ENABLED_OLD) ? AVTAB_ENABLED : 0; | ||
| 351 | |||
| 352 | if (!(val & (AVTAB_AV | AVTAB_TYPE))) { | ||
| 353 | printk("security: avtab: null entry\n"); | ||
| 354 | return -1; | ||
| 355 | } | ||
| 356 | if ((val & AVTAB_AV) && | ||
| 357 | (val & AVTAB_TYPE)) { | ||
| 358 | printk("security: avtab: entry has both access vectors and types\n"); | ||
| 359 | return -1; | ||
| 360 | } | ||
| 361 | |||
| 362 | for (i = 0; i < sizeof(spec_order)/sizeof(u16); i++) { | ||
| 363 | if (val & spec_order[i]) { | ||
| 364 | key.specified = spec_order[i] | enabled; | ||
| 365 | datum.data = le32_to_cpu(buf32[items++]); | ||
| 366 | rc = insertf(a, &key, &datum, p); | ||
| 367 | if (rc) return rc; | ||
| 368 | } | ||
| 369 | } | ||
| 370 | |||
| 371 | if (items != items2) { | ||
| 372 | printk("security: avtab: entry only had %d items, expected %d\n", items2, items); | ||
| 373 | return -1; | ||
| 374 | } | ||
| 375 | return 0; | ||
| 299 | } | 376 | } |
| 300 | rc = next_entry(buf, fp, sizeof(u32)*items2); | 377 | |
| 378 | rc = next_entry(buf16, fp, sizeof(u16)*4); | ||
| 301 | if (rc < 0) { | 379 | if (rc < 0) { |
| 302 | printk(KERN_ERR "security: avtab: truncated entry\n"); | 380 | printk("security: avtab: truncated entry\n"); |
| 303 | goto bad; | 381 | return -1; |
| 304 | } | 382 | } |
| 383 | |||
| 305 | items = 0; | 384 | items = 0; |
| 306 | avkey->source_type = le32_to_cpu(buf[items++]); | 385 | key.source_type = le16_to_cpu(buf16[items++]); |
| 307 | avkey->target_type = le32_to_cpu(buf[items++]); | 386 | key.target_type = le16_to_cpu(buf16[items++]); |
| 308 | avkey->target_class = le32_to_cpu(buf[items++]); | 387 | key.target_class = le16_to_cpu(buf16[items++]); |
| 309 | avdatum->specified = le32_to_cpu(buf[items++]); | 388 | key.specified = le16_to_cpu(buf16[items++]); |
| 310 | if (!(avdatum->specified & (AVTAB_AV | AVTAB_TYPE))) { | 389 | |
| 311 | printk(KERN_ERR "security: avtab: null entry\n"); | 390 | rc = next_entry(buf32, fp, sizeof(u32)); |
| 312 | goto bad; | 391 | if (rc < 0) { |
| 313 | } | 392 | printk("security: avtab: truncated entry\n"); |
| 314 | if ((avdatum->specified & AVTAB_AV) && | 393 | 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 | } | 394 | } |
| 395 | datum.data = le32_to_cpu(*buf32); | ||
| 396 | return insertf(a, &key, &datum, p); | ||
| 397 | } | ||
| 339 | 398 | ||
| 340 | return 0; | 399 | static int avtab_insertf(struct avtab *a, struct avtab_key *k, |
| 341 | bad: | 400 | struct avtab_datum *d, void *p) |
| 342 | return -1; | 401 | { |
| 402 | return avtab_insert(a, k, d); | ||
| 343 | } | 403 | } |
| 344 | 404 | ||
| 345 | int avtab_read(struct avtab *a, void *fp, u32 config) | 405 | int avtab_read(struct avtab *a, void *fp, u32 vers) |
| 346 | { | 406 | { |
| 347 | int rc; | 407 | int rc; |
| 348 | struct avtab_key avkey; | 408 | __le32 buf[1]; |
| 349 | struct avtab_datum avdatum; | ||
| 350 | u32 buf[1]; | ||
| 351 | u32 nel, i; | 409 | u32 nel, i; |
| 352 | 410 | ||
| 353 | 411 | ||
| @@ -363,16 +421,14 @@ int avtab_read(struct avtab *a, void *fp, u32 config) | |||
| 363 | goto bad; | 421 | goto bad; |
| 364 | } | 422 | } |
| 365 | for (i = 0; i < nel; i++) { | 423 | for (i = 0; i < nel; i++) { |
| 366 | if (avtab_read_item(fp, &avdatum, &avkey)) { | 424 | 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) { | 425 | if (rc) { |
| 372 | if (rc == -ENOMEM) | 426 | if (rc == -ENOMEM) |
| 373 | printk(KERN_ERR "security: avtab: out of memory\n"); | 427 | printk(KERN_ERR "security: avtab: out of memory\n"); |
| 374 | if (rc == -EEXIST) | 428 | else if (rc == -EEXIST) |
| 375 | printk(KERN_ERR "security: avtab: duplicate entry\n"); | 429 | printk(KERN_ERR "security: avtab: duplicate entry\n"); |
| 430 | else | ||
| 431 | rc = -EINVAL; | ||
| 376 | goto bad; | 432 | goto bad; |
| 377 | } | 433 | } |
| 378 | } | 434 | } |
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..daf288007460 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 | } |
| @@ -216,7 +216,8 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) | |||
| 216 | { | 216 | { |
| 217 | char *key = NULL; | 217 | char *key = NULL; |
| 218 | struct cond_bool_datum *booldatum; | 218 | struct cond_bool_datum *booldatum; |
| 219 | u32 buf[3], len; | 219 | __le32 buf[3]; |
| 220 | u32 len; | ||
| 220 | int rc; | 221 | int rc; |
| 221 | 222 | ||
| 222 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); | 223 | booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); |
| @@ -252,104 +253,127 @@ err: | |||
| 252 | return -1; | 253 | return -1; |
| 253 | } | 254 | } |
| 254 | 255 | ||
| 255 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, | 256 | struct cond_insertf_data |
| 256 | struct cond_av_list *other) | ||
| 257 | { | 257 | { |
| 258 | struct cond_av_list *list, *last = NULL, *cur; | 258 | struct policydb *p; |
| 259 | struct avtab_key key; | 259 | struct cond_av_list *other; |
| 260 | struct avtab_datum datum; | 260 | struct cond_av_list *head; |
| 261 | struct cond_av_list *tail; | ||
| 262 | }; | ||
| 263 | |||
| 264 | static int cond_insertf(struct avtab *a, struct avtab_key *k, struct avtab_datum *d, void *ptr) | ||
| 265 | { | ||
| 266 | struct cond_insertf_data *data = ptr; | ||
| 267 | struct policydb *p = data->p; | ||
| 268 | struct cond_av_list *other = data->other, *list, *cur; | ||
| 261 | struct avtab_node *node_ptr; | 269 | struct avtab_node *node_ptr; |
| 262 | int rc; | ||
| 263 | u32 buf[1], i, len; | ||
| 264 | u8 found; | 270 | u8 found; |
| 265 | 271 | ||
| 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 | 272 | ||
| 278 | for (i = 0; i < len; i++) { | 273 | /* |
| 279 | if (avtab_read_item(fp, &datum, &key)) | 274 | * For type rules we have to make certain there aren't any |
| 275 | * conflicting rules by searching the te_avtab and the | ||
| 276 | * cond_te_avtab. | ||
| 277 | */ | ||
| 278 | if (k->specified & AVTAB_TYPE) { | ||
| 279 | if (avtab_search(&p->te_avtab, k)) { | ||
| 280 | printk("security: type rule already exists outside of a conditional."); | ||
| 280 | goto err; | 281 | goto err; |
| 281 | 282 | } | |
| 282 | /* | 283 | /* |
| 283 | * For type rules we have to make certain there aren't any | 284 | * If we are reading the false list other will be a pointer to |
| 284 | * conflicting rules by searching the te_avtab and the | 285 | * the true list. We can have duplicate entries if there is only |
| 285 | * cond_te_avtab. | 286 | * 1 other entry and it is in our true list. |
| 287 | * | ||
| 288 | * If we are reading the true list (other == NULL) there shouldn't | ||
| 289 | * be any other entries. | ||
| 286 | */ | 290 | */ |
| 287 | if (datum.specified & AVTAB_TYPE) { | 291 | if (other) { |
| 288 | if (avtab_search(&p->te_avtab, &key, AVTAB_TYPE)) { | 292 | node_ptr = avtab_search_node(&p->te_cond_avtab, k); |
| 289 | printk("security: type rule already exists outside of a conditional."); | 293 | if (node_ptr) { |
| 290 | goto err; | 294 | if (avtab_search_node_next(node_ptr, k->specified)) { |
| 291 | } | 295 | printk("security: too many conflicting type rules."); |
| 292 | /* | 296 | goto err; |
| 293 | * If we are reading the false list other will be a pointer to | 297 | } |
| 294 | * the true list. We can have duplicate entries if there is only | 298 | found = 0; |
| 295 | * 1 other entry and it is in our true list. | 299 | for (cur = other; cur != NULL; cur = cur->next) { |
| 296 | * | 300 | if (cur->node == node_ptr) { |
| 297 | * If we are reading the true list (other == NULL) there shouldn't | 301 | found = 1; |
| 298 | * be any other entries. | 302 | 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 | } | 303 | } |
| 318 | } | 304 | } |
| 319 | } else { | 305 | if (!found) { |
| 320 | if (avtab_search(&p->te_cond_avtab, &key, AVTAB_TYPE)) { | 306 | printk("security: conflicting type rules.\n"); |
| 321 | printk("security: conflicting type rules when adding type rule for true."); | ||
| 322 | goto err; | 307 | goto err; |
| 323 | } | 308 | } |
| 324 | } | 309 | } |
| 310 | } else { | ||
| 311 | if (avtab_search(&p->te_cond_avtab, k)) { | ||
| 312 | printk("security: conflicting type rules when adding type rule for true.\n"); | ||
| 313 | goto err; | ||
| 314 | } | ||
| 325 | } | 315 | } |
| 326 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, &key, &datum); | 316 | } |
| 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 | 317 | ||
| 318 | node_ptr = avtab_insert_nonunique(&p->te_cond_avtab, k, d); | ||
| 319 | if (!node_ptr) { | ||
| 320 | printk("security: could not insert rule."); | ||
| 321 | goto err; | ||
| 344 | } | 322 | } |
| 345 | 323 | ||
| 324 | list = kmalloc(sizeof(struct cond_av_list), GFP_KERNEL); | ||
| 325 | if (!list) | ||
| 326 | goto err; | ||
| 327 | memset(list, 0, sizeof(*list)); | ||
| 328 | |||
| 329 | list->node = node_ptr; | ||
| 330 | if (!data->head) | ||
| 331 | data->head = list; | ||
| 332 | else | ||
| 333 | data->tail->next = list; | ||
| 334 | data->tail = list; | ||
| 346 | return 0; | 335 | return 0; |
| 336 | |||
| 347 | err: | 337 | err: |
| 348 | cond_av_list_destroy(*ret_list); | 338 | cond_av_list_destroy(data->head); |
| 349 | *ret_list = NULL; | 339 | data->head = NULL; |
| 350 | return -1; | 340 | return -1; |
| 351 | } | 341 | } |
| 352 | 342 | ||
| 343 | static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list **ret_list, struct cond_av_list *other) | ||
| 344 | { | ||
| 345 | int i, rc; | ||
| 346 | __le32 buf[1]; | ||
| 347 | u32 len; | ||
| 348 | struct cond_insertf_data data; | ||
| 349 | |||
| 350 | *ret_list = NULL; | ||
| 351 | |||
| 352 | len = 0; | ||
| 353 | rc = next_entry(buf, fp, sizeof(u32)); | ||
| 354 | if (rc < 0) | ||
| 355 | return -1; | ||
| 356 | |||
| 357 | len = le32_to_cpu(buf[0]); | ||
| 358 | if (len == 0) { | ||
| 359 | return 0; | ||
| 360 | } | ||
| 361 | |||
| 362 | data.p = p; | ||
| 363 | data.other = other; | ||
| 364 | data.head = NULL; | ||
| 365 | data.tail = NULL; | ||
| 366 | for (i = 0; i < len; i++) { | ||
| 367 | rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data); | ||
| 368 | if (rc) | ||
| 369 | return rc; | ||
| 370 | |||
| 371 | } | ||
| 372 | |||
| 373 | *ret_list = data.head; | ||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | |||
| 353 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | 377 | static int expr_isvalid(struct policydb *p, struct cond_expr *expr) |
| 354 | { | 378 | { |
| 355 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { | 379 | if (expr->expr_type <= 0 || expr->expr_type > COND_LAST) { |
| @@ -366,7 +390,8 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr) | |||
| 366 | 390 | ||
| 367 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) | 391 | static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) |
| 368 | { | 392 | { |
| 369 | u32 buf[2], len, i; | 393 | __le32 buf[2]; |
| 394 | u32 len, i; | ||
| 370 | int rc; | 395 | int rc; |
| 371 | struct cond_expr *expr = NULL, *last = NULL; | 396 | struct cond_expr *expr = NULL, *last = NULL; |
| 372 | 397 | ||
| @@ -424,7 +449,8 @@ err: | |||
| 424 | int cond_read_list(struct policydb *p, void *fp) | 449 | int cond_read_list(struct policydb *p, void *fp) |
| 425 | { | 450 | { |
| 426 | struct cond_node *node, *last = NULL; | 451 | struct cond_node *node, *last = NULL; |
| 427 | u32 buf[1], i, len; | 452 | __le32 buf[1]; |
| 453 | u32 i, len; | ||
| 428 | int rc; | 454 | int rc; |
| 429 | 455 | ||
| 430 | rc = next_entry(buf, fp, sizeof buf); | 456 | rc = next_entry(buf, fp, sizeof buf); |
| @@ -452,6 +478,7 @@ int cond_read_list(struct policydb *p, void *fp) | |||
| 452 | return 0; | 478 | return 0; |
| 453 | err: | 479 | err: |
| 454 | cond_list_destroy(p->cond_list); | 480 | cond_list_destroy(p->cond_list); |
| 481 | p->cond_list = NULL; | ||
| 455 | return -1; | 482 | return -1; |
| 456 | } | 483 | } |
| 457 | 484 | ||
| @@ -465,22 +492,22 @@ void cond_compute_av(struct avtab *ctab, struct avtab_key *key, struct av_decisi | |||
| 465 | if(!ctab || !key || !avd) | 492 | if(!ctab || !key || !avd) |
| 466 | return; | 493 | return; |
| 467 | 494 | ||
| 468 | for(node = avtab_search_node(ctab, key, AVTAB_AV); node != NULL; | 495 | for(node = avtab_search_node(ctab, key); node != NULL; |
| 469 | node = avtab_search_node_next(node, AVTAB_AV)) { | 496 | node = avtab_search_node_next(node, key->specified)) { |
| 470 | if ( (__u32) (AVTAB_ALLOWED|AVTAB_ENABLED) == | 497 | if ( (u16) (AVTAB_ALLOWED|AVTAB_ENABLED) == |
| 471 | (node->datum.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) | 498 | (node->key.specified & (AVTAB_ALLOWED|AVTAB_ENABLED))) |
| 472 | avd->allowed |= avtab_allowed(&node->datum); | 499 | avd->allowed |= node->datum.data; |
| 473 | if ( (__u32) (AVTAB_AUDITDENY|AVTAB_ENABLED) == | 500 | if ( (u16) (AVTAB_AUDITDENY|AVTAB_ENABLED) == |
| 474 | (node->datum.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) | 501 | (node->key.specified & (AVTAB_AUDITDENY|AVTAB_ENABLED))) |
| 475 | /* Since a '0' in an auditdeny mask represents a | 502 | /* Since a '0' in an auditdeny mask represents a |
| 476 | * permission we do NOT want to audit (dontaudit), we use | 503 | * permission we do NOT want to audit (dontaudit), we use |
| 477 | * the '&' operand to ensure that all '0's in the mask | 504 | * the '&' operand to ensure that all '0's in the mask |
| 478 | * are retained (much unlike the allow and auditallow cases). | 505 | * are retained (much unlike the allow and auditallow cases). |
| 479 | */ | 506 | */ |
| 480 | avd->auditdeny &= avtab_auditdeny(&node->datum); | 507 | avd->auditdeny &= node->datum.data; |
| 481 | if ( (__u32) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == | 508 | if ( (u16) (AVTAB_AUDITALLOW|AVTAB_ENABLED) == |
| 482 | (node->datum.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) | 509 | (node->key.specified & (AVTAB_AUDITALLOW|AVTAB_ENABLED))) |
| 483 | avd->auditallow |= avtab_auditallow(&node->datum); | 510 | avd->auditallow |= node->datum.data; |
| 484 | } | 511 | } |
| 485 | return; | 512 | return; |
| 486 | } | 513 | } |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d8ce9cc0b9f1..d515154128cc 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
| @@ -196,8 +196,9 @@ int ebitmap_read(struct ebitmap *e, void *fp) | |||
| 196 | { | 196 | { |
| 197 | int rc; | 197 | int rc; |
| 198 | struct ebitmap_node *n, *l; | 198 | struct ebitmap_node *n, *l; |
| 199 | u32 buf[3], mapsize, count, i; | 199 | __le32 buf[3]; |
| 200 | u64 map; | 200 | u32 mapsize, count, i; |
| 201 | __le64 map; | ||
| 201 | 202 | ||
| 202 | ebitmap_init(e); | 203 | ebitmap_init(e); |
| 203 | 204 | ||
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..0a758323a9cf 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 | ||
| @@ -714,7 +744,8 @@ int policydb_context_isvalid(struct policydb *p, struct context *c) | |||
| 714 | */ | 744 | */ |
| 715 | static int mls_read_range_helper(struct mls_range *r, void *fp) | 745 | static int mls_read_range_helper(struct mls_range *r, void *fp) |
| 716 | { | 746 | { |
| 717 | u32 buf[2], items; | 747 | __le32 buf[2]; |
| 748 | u32 items; | ||
| 718 | int rc; | 749 | int rc; |
| 719 | 750 | ||
| 720 | rc = next_entry(buf, fp, sizeof(u32)); | 751 | rc = next_entry(buf, fp, sizeof(u32)); |
| @@ -775,7 +806,7 @@ static int context_read_and_validate(struct context *c, | |||
| 775 | struct policydb *p, | 806 | struct policydb *p, |
| 776 | void *fp) | 807 | void *fp) |
| 777 | { | 808 | { |
| 778 | u32 buf[3]; | 809 | __le32 buf[3]; |
| 779 | int rc; | 810 | int rc; |
| 780 | 811 | ||
| 781 | rc = next_entry(buf, fp, sizeof buf); | 812 | rc = next_entry(buf, fp, sizeof buf); |
| @@ -815,7 +846,8 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 815 | char *key = NULL; | 846 | char *key = NULL; |
| 816 | struct perm_datum *perdatum; | 847 | struct perm_datum *perdatum; |
| 817 | int rc; | 848 | int rc; |
| 818 | u32 buf[2], len; | 849 | __le32 buf[2]; |
| 850 | u32 len; | ||
| 819 | 851 | ||
| 820 | perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); | 852 | perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); |
| 821 | if (!perdatum) { | 853 | if (!perdatum) { |
| @@ -855,7 +887,8 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 855 | { | 887 | { |
| 856 | char *key = NULL; | 888 | char *key = NULL; |
| 857 | struct common_datum *comdatum; | 889 | struct common_datum *comdatum; |
| 858 | u32 buf[4], len, nel; | 890 | __le32 buf[4]; |
| 891 | u32 len, nel; | ||
| 859 | int i, rc; | 892 | int i, rc; |
| 860 | 893 | ||
| 861 | comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); | 894 | comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); |
| @@ -909,7 +942,8 @@ static int read_cons_helper(struct constraint_node **nodep, int ncons, | |||
| 909 | { | 942 | { |
| 910 | struct constraint_node *c, *lc; | 943 | struct constraint_node *c, *lc; |
| 911 | struct constraint_expr *e, *le; | 944 | struct constraint_expr *e, *le; |
| 912 | u32 buf[3], nexpr; | 945 | __le32 buf[3]; |
| 946 | u32 nexpr; | ||
| 913 | int rc, i, j, depth; | 947 | int rc, i, j, depth; |
| 914 | 948 | ||
| 915 | lc = NULL; | 949 | lc = NULL; |
| @@ -993,7 +1027,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 993 | { | 1027 | { |
| 994 | char *key = NULL; | 1028 | char *key = NULL; |
| 995 | struct class_datum *cladatum; | 1029 | struct class_datum *cladatum; |
| 996 | u32 buf[6], len, len2, ncons, nel; | 1030 | __le32 buf[6]; |
| 1031 | u32 len, len2, ncons, nel; | ||
| 997 | int i, rc; | 1032 | int i, rc; |
| 998 | 1033 | ||
| 999 | cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); | 1034 | cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); |
| @@ -1087,7 +1122,8 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1087 | char *key = NULL; | 1122 | char *key = NULL; |
| 1088 | struct role_datum *role; | 1123 | struct role_datum *role; |
| 1089 | int rc; | 1124 | int rc; |
| 1090 | u32 buf[2], len; | 1125 | __le32 buf[2]; |
| 1126 | u32 len; | ||
| 1091 | 1127 | ||
| 1092 | role = kmalloc(sizeof(*role), GFP_KERNEL); | 1128 | role = kmalloc(sizeof(*role), GFP_KERNEL); |
| 1093 | if (!role) { | 1129 | if (!role) { |
| @@ -1147,7 +1183,8 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1147 | char *key = NULL; | 1183 | char *key = NULL; |
| 1148 | struct type_datum *typdatum; | 1184 | struct type_datum *typdatum; |
| 1149 | int rc; | 1185 | int rc; |
| 1150 | u32 buf[3], len; | 1186 | __le32 buf[3]; |
| 1187 | u32 len; | ||
| 1151 | 1188 | ||
| 1152 | typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); | 1189 | typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); |
| 1153 | if (!typdatum) { | 1190 | if (!typdatum) { |
| @@ -1191,7 +1228,7 @@ bad: | |||
| 1191 | */ | 1228 | */ |
| 1192 | static int mls_read_level(struct mls_level *lp, void *fp) | 1229 | static int mls_read_level(struct mls_level *lp, void *fp) |
| 1193 | { | 1230 | { |
| 1194 | u32 buf[1]; | 1231 | __le32 buf[1]; |
| 1195 | int rc; | 1232 | int rc; |
| 1196 | 1233 | ||
| 1197 | memset(lp, 0, sizeof(*lp)); | 1234 | memset(lp, 0, sizeof(*lp)); |
| @@ -1219,7 +1256,8 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1219 | char *key = NULL; | 1256 | char *key = NULL; |
| 1220 | struct user_datum *usrdatum; | 1257 | struct user_datum *usrdatum; |
| 1221 | int rc; | 1258 | int rc; |
| 1222 | u32 buf[2], len; | 1259 | __le32 buf[2]; |
| 1260 | u32 len; | ||
| 1223 | 1261 | ||
| 1224 | usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); | 1262 | usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); |
| 1225 | if (!usrdatum) { | 1263 | if (!usrdatum) { |
| @@ -1273,7 +1311,8 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1273 | char *key = NULL; | 1311 | char *key = NULL; |
| 1274 | struct level_datum *levdatum; | 1312 | struct level_datum *levdatum; |
| 1275 | int rc; | 1313 | int rc; |
| 1276 | u32 buf[2], len; | 1314 | __le32 buf[2]; |
| 1315 | u32 len; | ||
| 1277 | 1316 | ||
| 1278 | levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); | 1317 | levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); |
| 1279 | if (!levdatum) { | 1318 | if (!levdatum) { |
| @@ -1324,7 +1363,8 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp) | |||
| 1324 | char *key = NULL; | 1363 | char *key = NULL; |
| 1325 | struct cat_datum *catdatum; | 1364 | struct cat_datum *catdatum; |
| 1326 | int rc; | 1365 | int rc; |
| 1327 | u32 buf[3], len; | 1366 | __le32 buf[3]; |
| 1367 | u32 len; | ||
| 1328 | 1368 | ||
| 1329 | catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); | 1369 | catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); |
| 1330 | if (!catdatum) { | 1370 | if (!catdatum) { |
| @@ -1387,7 +1427,8 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1387 | struct ocontext *l, *c, *newc; | 1427 | struct ocontext *l, *c, *newc; |
| 1388 | struct genfs *genfs_p, *genfs, *newgenfs; | 1428 | struct genfs *genfs_p, *genfs, *newgenfs; |
| 1389 | int i, j, rc; | 1429 | int i, j, rc; |
| 1390 | u32 buf[8], len, len2, config, nprim, nel, nel2; | 1430 | __le32 buf[8]; |
| 1431 | u32 len, len2, config, nprim, nel, nel2; | ||
| 1391 | char *policydb_str; | 1432 | char *policydb_str; |
| 1392 | struct policydb_compat_info *info; | 1433 | struct policydb_compat_info *info; |
| 1393 | struct range_trans *rt, *lrt; | 1434 | struct range_trans *rt, *lrt; |
| @@ -1403,17 +1444,14 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1403 | if (rc < 0) | 1444 | if (rc < 0) |
| 1404 | goto bad; | 1445 | goto bad; |
| 1405 | 1446 | ||
| 1406 | for (i = 0; i < 2; i++) | 1447 | if (le32_to_cpu(buf[0]) != POLICYDB_MAGIC) { |
| 1407 | buf[i] = le32_to_cpu(buf[i]); | ||
| 1408 | |||
| 1409 | if (buf[0] != POLICYDB_MAGIC) { | ||
| 1410 | printk(KERN_ERR "security: policydb magic number 0x%x does " | 1448 | printk(KERN_ERR "security: policydb magic number 0x%x does " |
| 1411 | "not match expected magic number 0x%x\n", | 1449 | "not match expected magic number 0x%x\n", |
| 1412 | buf[0], POLICYDB_MAGIC); | 1450 | le32_to_cpu(buf[0]), POLICYDB_MAGIC); |
| 1413 | goto bad; | 1451 | goto bad; |
| 1414 | } | 1452 | } |
| 1415 | 1453 | ||
| 1416 | len = buf[1]; | 1454 | len = le32_to_cpu(buf[1]); |
| 1417 | if (len != strlen(POLICYDB_STRING)) { | 1455 | if (len != strlen(POLICYDB_STRING)) { |
| 1418 | printk(KERN_ERR "security: policydb string length %d does not " | 1456 | printk(KERN_ERR "security: policydb string length %d does not " |
| 1419 | "match expected length %Zu\n", | 1457 | "match expected length %Zu\n", |
| @@ -1448,19 +1486,17 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1448 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1486 | rc = next_entry(buf, fp, sizeof(u32)*4); |
| 1449 | if (rc < 0) | 1487 | if (rc < 0) |
| 1450 | goto bad; | 1488 | goto bad; |
| 1451 | for (i = 0; i < 4; i++) | ||
| 1452 | buf[i] = le32_to_cpu(buf[i]); | ||
| 1453 | 1489 | ||
| 1454 | p->policyvers = buf[0]; | 1490 | p->policyvers = le32_to_cpu(buf[0]); |
| 1455 | if (p->policyvers < POLICYDB_VERSION_MIN || | 1491 | if (p->policyvers < POLICYDB_VERSION_MIN || |
| 1456 | p->policyvers > POLICYDB_VERSION_MAX) { | 1492 | p->policyvers > POLICYDB_VERSION_MAX) { |
| 1457 | printk(KERN_ERR "security: policydb version %d does not match " | 1493 | printk(KERN_ERR "security: policydb version %d does not match " |
| 1458 | "my version range %d-%d\n", | 1494 | "my version range %d-%d\n", |
| 1459 | buf[0], POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); | 1495 | le32_to_cpu(buf[0]), POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); |
| 1460 | goto bad; | 1496 | goto bad; |
| 1461 | } | 1497 | } |
| 1462 | 1498 | ||
| 1463 | if ((buf[1] & POLICYDB_CONFIG_MLS)) { | 1499 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
| 1464 | if (ss_initialized && !selinux_mls_enabled) { | 1500 | if (ss_initialized && !selinux_mls_enabled) { |
| 1465 | printk(KERN_ERR "Cannot switch between non-MLS and MLS " | 1501 | printk(KERN_ERR "Cannot switch between non-MLS and MLS " |
| 1466 | "policies\n"); | 1502 | "policies\n"); |
| @@ -1489,9 +1525,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1489 | goto bad; | 1525 | goto bad; |
| 1490 | } | 1526 | } |
| 1491 | 1527 | ||
| 1492 | if (buf[2] != info->sym_num || buf[3] != info->ocon_num) { | 1528 | if (le32_to_cpu(buf[2]) != info->sym_num || |
| 1529 | le32_to_cpu(buf[3]) != info->ocon_num) { | ||
| 1493 | printk(KERN_ERR "security: policydb table sizes (%d,%d) do " | 1530 | printk(KERN_ERR "security: policydb table sizes (%d,%d) do " |
| 1494 | "not match mine (%d,%d)\n", buf[2], buf[3], | 1531 | "not match mine (%d,%d)\n", le32_to_cpu(buf[2]), |
| 1532 | le32_to_cpu(buf[3]), | ||
| 1495 | info->sym_num, info->ocon_num); | 1533 | info->sym_num, info->ocon_num); |
| 1496 | goto bad; | 1534 | goto bad; |
| 1497 | } | 1535 | } |
| @@ -1511,7 +1549,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1511 | p->symtab[i].nprim = nprim; | 1549 | p->symtab[i].nprim = nprim; |
| 1512 | } | 1550 | } |
| 1513 | 1551 | ||
| 1514 | rc = avtab_read(&p->te_avtab, fp, config); | 1552 | rc = avtab_read(&p->te_avtab, fp, p->policyvers); |
| 1515 | if (rc) | 1553 | if (rc) |
| 1516 | goto bad; | 1554 | goto bad; |
| 1517 | 1555 | ||
| @@ -1825,6 +1863,21 @@ int policydb_read(struct policydb *p, void *fp) | |||
| 1825 | } | 1863 | } |
| 1826 | } | 1864 | } |
| 1827 | 1865 | ||
| 1866 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | ||
| 1867 | if (!p->type_attr_map) | ||
| 1868 | goto bad; | ||
| 1869 | |||
| 1870 | for (i = 0; i < p->p_types.nprim; i++) { | ||
| 1871 | ebitmap_init(&p->type_attr_map[i]); | ||
| 1872 | if (p->policyvers >= POLICYDB_VERSION_AVTAB) { | ||
| 1873 | if (ebitmap_read(&p->type_attr_map[i], fp)) | ||
| 1874 | goto bad; | ||
| 1875 | } | ||
| 1876 | /* add the type itself as the degenerate case */ | ||
| 1877 | if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) | ||
| 1878 | goto bad; | ||
| 1879 | } | ||
| 1880 | |||
| 1828 | rc = 0; | 1881 | rc = 0; |
| 1829 | out: | 1882 | out: |
| 1830 | return rc; | 1883 | 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 | ||
