diff options
author | Eric Paris <eparis@redhat.com> | 2010-11-29 15:47:09 -0500 |
---|---|---|
committer | Eric Paris <eparis@redhat.com> | 2010-11-30 17:28:57 -0500 |
commit | 23bdecb000c806cf4ec52764499a600f7200d7a9 (patch) | |
tree | f13a523f6bec22c5e7ec58ea02a4988aefe7c8ac /security/selinux/ss | |
parent | c41ab6a1b9028de33e74101cb0aae13098a56fdb (diff) |
selinux: convert type_val_to_struct to flex_array
In rawhide type_val_to_struct will allocate 26848 bytes, an order 3
allocations. While this hasn't been seen to fail it isn't outside the
realm of possibiliy on systems with severe memory fragmentation. Convert
to flex_array so no allocation will ever be bigger than PAGE_SIZE.
Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'security/selinux/ss')
-rw-r--r-- | security/selinux/ss/policydb.c | 28 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 17 |
3 files changed, 34 insertions, 13 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 6ad73e81da5c..af41fdfe1a71 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -307,7 +307,11 @@ static int type_index(void *key, void *datum, void *datap) | |||
307 | || typdatum->bounds > p->p_types.nprim) | 307 | || typdatum->bounds > p->p_types.nprim) |
308 | return -EINVAL; | 308 | return -EINVAL; |
309 | p->p_type_val_to_name[typdatum->value - 1] = key; | 309 | p->p_type_val_to_name[typdatum->value - 1] = key; |
310 | p->type_val_to_struct[typdatum->value - 1] = typdatum; | 310 | /* this flex array was all preallocated, this cannot fail */ |
311 | if (flex_array_put_ptr(p->type_val_to_struct_array, | ||
312 | typdatum->value - 1, typdatum, | ||
313 | GFP_KERNEL | __GFP_ZERO)) | ||
314 | BUG(); | ||
311 | } | 315 | } |
312 | 316 | ||
313 | return 0; | 317 | return 0; |
@@ -484,11 +488,17 @@ static int policydb_index_others(struct policydb *p) | |||
484 | if (!p->user_val_to_struct) | 488 | if (!p->user_val_to_struct) |
485 | goto out; | 489 | goto out; |
486 | 490 | ||
491 | /* Yes, I want the sizeof the pointer, not the structure */ | ||
487 | rc = -ENOMEM; | 492 | rc = -ENOMEM; |
488 | p->type_val_to_struct = | 493 | p->type_val_to_struct_array = flex_array_alloc(sizeof(struct type_datum *), |
489 | kmalloc(p->p_types.nprim * sizeof(*(p->type_val_to_struct)), | 494 | p->p_types.nprim, |
490 | GFP_KERNEL); | 495 | GFP_KERNEL | __GFP_ZERO); |
491 | if (!p->type_val_to_struct) | 496 | if (!p->type_val_to_struct_array) |
497 | goto out; | ||
498 | |||
499 | rc = flex_array_prealloc(p->type_val_to_struct_array, 0, | ||
500 | p->p_types.nprim - 1, GFP_KERNEL | __GFP_ZERO); | ||
501 | if (rc) | ||
492 | goto out; | 502 | goto out; |
493 | 503 | ||
494 | rc = -ENOMEM; | 504 | rc = -ENOMEM; |
@@ -699,7 +709,8 @@ void policydb_destroy(struct policydb *p) | |||
699 | kfree(p->class_val_to_struct); | 709 | kfree(p->class_val_to_struct); |
700 | kfree(p->role_val_to_struct); | 710 | kfree(p->role_val_to_struct); |
701 | kfree(p->user_val_to_struct); | 711 | kfree(p->user_val_to_struct); |
702 | kfree(p->type_val_to_struct); | 712 | if (p->type_val_to_struct_array) |
713 | flex_array_free(p->type_val_to_struct_array); | ||
703 | 714 | ||
704 | avtab_destroy(&p->te_avtab); | 715 | avtab_destroy(&p->te_avtab); |
705 | 716 | ||
@@ -1618,7 +1629,10 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap) | |||
1618 | return -EINVAL; | 1629 | return -EINVAL; |
1619 | } | 1630 | } |
1620 | 1631 | ||
1621 | upper = p->type_val_to_struct[upper->bounds - 1]; | 1632 | upper = flex_array_get_ptr(p->type_val_to_struct_array, |
1633 | upper->bounds - 1); | ||
1634 | BUG_ON(!upper); | ||
1635 | |||
1622 | if (upper->attribute) { | 1636 | if (upper->attribute) { |
1623 | printk(KERN_ERR "SELinux: type %s: " | 1637 | printk(KERN_ERR "SELinux: type %s: " |
1624 | "bounded by attribute %s", | 1638 | "bounded by attribute %s", |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 95d3d7de361e..9826a92a6b0c 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -217,7 +217,7 @@ struct policydb { | |||
217 | struct class_datum **class_val_to_struct; | 217 | struct class_datum **class_val_to_struct; |
218 | struct role_datum **role_val_to_struct; | 218 | struct role_datum **role_val_to_struct; |
219 | struct user_datum **user_val_to_struct; | 219 | struct user_datum **user_val_to_struct; |
220 | struct type_datum **type_val_to_struct; | 220 | struct flex_array *type_val_to_struct_array; |
221 | 221 | ||
222 | /* type enforcement access vectors and transitions */ | 222 | /* type enforcement access vectors and transitions */ |
223 | struct avtab te_avtab; | 223 | struct avtab te_avtab; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ab6dbce5fd2a..afcbc19817f7 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -530,12 +530,18 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
530 | struct context lo_scontext; | 530 | struct context lo_scontext; |
531 | struct context lo_tcontext; | 531 | struct context lo_tcontext; |
532 | struct av_decision lo_avd; | 532 | struct av_decision lo_avd; |
533 | struct type_datum *source | 533 | struct type_datum *source; |
534 | = policydb.type_val_to_struct[scontext->type - 1]; | 534 | struct type_datum *target; |
535 | struct type_datum *target | ||
536 | = policydb.type_val_to_struct[tcontext->type - 1]; | ||
537 | u32 masked = 0; | 535 | u32 masked = 0; |
538 | 536 | ||
537 | source = flex_array_get_ptr(policydb.type_val_to_struct_array, | ||
538 | scontext->type - 1); | ||
539 | BUG_ON(!source); | ||
540 | |||
541 | target = flex_array_get_ptr(policydb.type_val_to_struct_array, | ||
542 | tcontext->type - 1); | ||
543 | BUG_ON(!target); | ||
544 | |||
539 | if (source->bounds) { | 545 | if (source->bounds) { |
540 | memset(&lo_avd, 0, sizeof(lo_avd)); | 546 | memset(&lo_avd, 0, sizeof(lo_avd)); |
541 | 547 | ||
@@ -828,7 +834,8 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
828 | 834 | ||
829 | index = new_context->type; | 835 | index = new_context->type; |
830 | while (true) { | 836 | while (true) { |
831 | type = policydb.type_val_to_struct[index - 1]; | 837 | type = flex_array_get_ptr(policydb.type_val_to_struct_array, |
838 | index - 1); | ||
832 | BUG_ON(!type); | 839 | BUG_ON(!type); |
833 | 840 | ||
834 | /* not bounded anymore */ | 841 | /* not bounded anymore */ |