summaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/policydb.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-07-29 23:02:34 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 15:38:39 +1000
commit6371dcd36f649d9d07823f31400618155a20dde1 (patch)
treea08c4ed2ec77225abbfcc099e78ae8d643429787 /security/selinux/ss/policydb.c
parent016d825fe02cd20fd8803ca37a1e6d428fe878f6 (diff)
selinux: convert the policy type_attr_map to flex_array
Current selinux policy can have over 3000 types. The type_attr_map in policy is an array sized by the number of types times sizeof(struct ebitmap) (12 on x86_64). Basic math tells us the array is going to be of length 3000 x 12 = 36,000 bytes. The largest 'safe' allocation on a long running system is 16k. Most of the time a 32k allocation will work. But on long running systems a 64k allocation (what we need) can fail quite regularly. In order to deal with this I am converting the type_attr_map to use flex_arrays. Let the library code deal with breaking this into PAGE_SIZE pieces. -v2 rework some of the if(!obj) BUG() to be BUG_ON(!obj) drop flex_array_put() calls and just use a _get() object directly -v3 make apply to James' tree (drop the policydb_write changes) Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Stephen D. Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/ss/policydb.c')
-rw-r--r--security/selinux/ss/policydb.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
index 674ddfe0ba0..3a29704be8c 100644
--- a/security/selinux/ss/policydb.c
+++ b/security/selinux/ss/policydb.c
@@ -31,6 +31,7 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/audit.h>
+#include <linux/flex_array.h>
#include "security.h"
#include "policydb.h"
@@ -739,11 +740,17 @@ void policydb_destroy(struct policydb *p)
hashtab_map(p->range_tr, range_tr_destroy, NULL);
hashtab_destroy(p->range_tr);
- if (p->type_attr_map) {
- for (i = 0; i < p->p_types.nprim; i++)
- ebitmap_destroy(&p->type_attr_map[i]);
+ if (p->type_attr_map_array) {
+ for (i = 0; i < p->p_types.nprim; i++) {
+ struct ebitmap *e;
+
+ e = flex_array_get(p->type_attr_map_array, i);
+ if (!e)
+ continue;
+ ebitmap_destroy(e);
+ }
+ flex_array_free(p->type_attr_map_array);
}
- kfree(p->type_attr_map);
ebitmap_destroy(&p->policycaps);
ebitmap_destroy(&p->permissive_map);
@@ -2257,19 +2264,33 @@ int policydb_read(struct policydb *p, void *fp)
if (rc)
goto bad;
- p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL);
- if (!p->type_attr_map)
+ rc = -ENOMEM;
+ p->type_attr_map_array = flex_array_alloc(sizeof(struct ebitmap),
+ p->p_types.nprim,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!p->type_attr_map_array)
+ goto bad;
+
+ /* preallocate so we don't have to worry about the put ever failing */
+ rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1,
+ GFP_KERNEL | __GFP_ZERO);
+ if (rc)
goto bad;
for (i = 0; i < p->p_types.nprim; i++) {
- ebitmap_init(&p->type_attr_map[i]);
+ struct ebitmap *e = flex_array_get(p->type_attr_map_array, i);
+
+ BUG_ON(!e);
+ ebitmap_init(e);
if (p->policyvers >= POLICYDB_VERSION_AVTAB) {
- if (ebitmap_read(&p->type_attr_map[i], fp))
+ rc = ebitmap_read(e, fp);
+ if (rc)
goto bad;
}
/* add the type itself as the degenerate case */
- if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
- goto bad;
+ rc = ebitmap_set_bit(e, i, 1);
+ if (rc)
+ goto bad;
}
rc = policydb_bounds_sanity_check(p);