Commit 6371dcd3 authored by Eric Paris's avatar Eric Paris Committed by James Morris

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: default avatarEric Paris <eparis@redhat.com>
Acked-by: default avatarStephen D. Smalley <sds@tycho.nsa.gov>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent 016d825f
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/flex_array.h>
#include "security.h" #include "security.h"
#include "policydb.h" #include "policydb.h"
...@@ -739,11 +740,17 @@ void policydb_destroy(struct policydb *p) ...@@ -739,11 +740,17 @@ void policydb_destroy(struct policydb *p)
hashtab_map(p->range_tr, range_tr_destroy, NULL); hashtab_map(p->range_tr, range_tr_destroy, NULL);
hashtab_destroy(p->range_tr); hashtab_destroy(p->range_tr);
if (p->type_attr_map) { if (p->type_attr_map_array) {
for (i = 0; i < p->p_types.nprim; i++) for (i = 0; i < p->p_types.nprim; i++) {
ebitmap_destroy(&p->type_attr_map[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->policycaps);
ebitmap_destroy(&p->permissive_map); ebitmap_destroy(&p->permissive_map);
...@@ -2257,19 +2264,33 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -2257,19 +2264,33 @@ int policydb_read(struct policydb *p, void *fp)
if (rc) if (rc)
goto bad; goto bad;
p->type_attr_map = kmalloc(p->p_types.nprim * sizeof(struct ebitmap), GFP_KERNEL); rc = -ENOMEM;
if (!p->type_attr_map) 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; goto bad;
for (i = 0; i < p->p_types.nprim; i++) { 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 (p->policyvers >= POLICYDB_VERSION_AVTAB) {
if (ebitmap_read(&p->type_attr_map[i], fp)) rc = ebitmap_read(e, fp);
if (rc)
goto bad; goto bad;
} }
/* add the type itself as the degenerate case */ /* add the type itself as the degenerate case */
if (ebitmap_set_bit(&p->type_attr_map[i], i, 1)) rc = ebitmap_set_bit(e, i, 1);
goto bad; if (rc)
goto bad;
} }
rc = policydb_bounds_sanity_check(p); rc = policydb_bounds_sanity_check(p);
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#ifndef _SS_POLICYDB_H_ #ifndef _SS_POLICYDB_H_
#define _SS_POLICYDB_H_ #define _SS_POLICYDB_H_
#include <linux/flex_array.h>
#include "symtab.h" #include "symtab.h"
#include "avtab.h" #include "avtab.h"
#include "sidtab.h" #include "sidtab.h"
...@@ -246,7 +248,7 @@ struct policydb { ...@@ -246,7 +248,7 @@ struct policydb {
struct hashtab *range_tr; struct hashtab *range_tr;
/* type -> attribute reverse mapping */ /* type -> attribute reverse mapping */
struct ebitmap *type_attr_map; struct flex_array *type_attr_map_array;
struct ebitmap policycaps; struct ebitmap policycaps;
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/audit.h> #include <linux/audit.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/selinux.h> #include <linux/selinux.h>
#include <linux/flex_array.h>
#include <net/netlabel.h> #include <net/netlabel.h>
#include "flask.h" #include "flask.h"
...@@ -626,8 +627,10 @@ static void context_struct_compute_av(struct context *scontext, ...@@ -626,8 +627,10 @@ static void context_struct_compute_av(struct context *scontext,
*/ */
avkey.target_class = tclass; avkey.target_class = tclass;
avkey.specified = AVTAB_AV; avkey.specified = AVTAB_AV;
sattr = &policydb.type_attr_map[scontext->type - 1]; sattr = flex_array_get(policydb.type_attr_map_array, scontext->type - 1);
tattr = &policydb.type_attr_map[tcontext->type - 1]; BUG_ON(!sattr);
tattr = flex_array_get(policydb.type_attr_map_array, tcontext->type - 1);
BUG_ON(!tattr);
ebitmap_for_each_positive_bit(sattr, snode, i) { ebitmap_for_each_positive_bit(sattr, snode, i) {
ebitmap_for_each_positive_bit(tattr, tnode, j) { ebitmap_for_each_positive_bit(tattr, tnode, j) {
avkey.source_type = i + 1; avkey.source_type = i + 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment