Skip to content

Commit

Permalink
selinux: convert part of the sym_val_to_name array to use flex_array
Browse files Browse the repository at this point in the history
The sym_val_to_name type array can be quite large as it grows linearly with
the number of types.  With known policies having over 5k types these
allocations are growing large enough that they are likely to fail.  Convert
those to flex_array so no allocation is larger than PAGE_SIZE

Signed-off-by: Eric Paris <eparis@redhat.com>
  • Loading branch information
Eric Paris committed Nov 30, 2010
1 parent 23bdecb commit ac76c05
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 68 deletions.
6 changes: 5 additions & 1 deletion security/selinux/ss/conditional.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,18 @@ int cond_index_bool(void *key, void *datum, void *datap)
{
struct policydb *p;
struct cond_bool_datum *booldatum;
struct flex_array *fa;

booldatum = datum;
p = datap;

if (!booldatum->value || booldatum->value > p->p_bools.nprim)
return -EINVAL;

p->p_bool_val_to_name[booldatum->value - 1] = key;
fa = p->sym_val_to_name[SYM_BOOLS];
if (flex_array_put_ptr(fa, booldatum->value - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();
p->bool_val_to_struct[booldatum->value - 1] = booldatum;

return 0;
Expand Down
25 changes: 13 additions & 12 deletions security/selinux/ss/mls.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ int mls_compute_context_len(struct context *context)
len = 1; /* for the beginning ":" */
for (l = 0; l < 2; l++) {
int index_sens = context->range.level[l].sens;
len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));

/* categories */
head = -2;
Expand All @@ -55,17 +55,17 @@ int mls_compute_context_len(struct context *context)
if (i - prev > 1) {
/* one or more negative bits are skipped */
if (head != prev) {
nm = policydb.p_cat_val_to_name[prev];
nm = sym_name(&policydb, SYM_CATS, prev);
len += strlen(nm) + 1;
}
nm = policydb.p_cat_val_to_name[i];
nm = sym_name(&policydb, SYM_CATS, i);
len += strlen(nm) + 1;
head = i;
}
prev = i;
}
if (prev != head) {
nm = policydb.p_cat_val_to_name[prev];
nm = sym_name(&policydb, SYM_CATS, prev);
len += strlen(nm) + 1;
}
if (l == 0) {
Expand Down Expand Up @@ -102,8 +102,8 @@ void mls_sid_to_context(struct context *context,
scontextp++;

for (l = 0; l < 2; l++) {
strcpy(scontextp,
policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
context->range.level[l].sens - 1));
scontextp += strlen(scontextp);

/* categories */
Expand All @@ -118,15 +118,15 @@ void mls_sid_to_context(struct context *context,
*scontextp++ = '.';
else
*scontextp++ = ',';
nm = policydb.p_cat_val_to_name[prev];
nm = sym_name(&policydb, SYM_CATS, prev);
strcpy(scontextp, nm);
scontextp += strlen(nm);
}
if (prev < 0)
*scontextp++ = ':';
else
*scontextp++ = ',';
nm = policydb.p_cat_val_to_name[i];
nm = sym_name(&policydb, SYM_CATS, i);
strcpy(scontextp, nm);
scontextp += strlen(nm);
head = i;
Expand All @@ -139,7 +139,7 @@ void mls_sid_to_context(struct context *context,
*scontextp++ = '.';
else
*scontextp++ = ',';
nm = policydb.p_cat_val_to_name[prev];
nm = sym_name(&policydb, SYM_CATS, prev);
strcpy(scontextp, nm);
scontextp += strlen(nm);
}
Expand All @@ -166,7 +166,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
if (!l->sens || l->sens > p->p_levels.nprim)
return 0;
levdatum = hashtab_search(p->p_levels.table,
p->p_sens_val_to_name[l->sens - 1]);
sym_name(p, SYM_LEVELS, l->sens - 1));
if (!levdatum)
return 0;

Expand Down Expand Up @@ -482,7 +482,8 @@ int mls_convert_context(struct policydb *oldp,

for (l = 0; l < 2; l++) {
levdatum = hashtab_search(newp->p_levels.table,
oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
sym_name(oldp, SYM_LEVELS,
c->range.level[l].sens - 1));

if (!levdatum)
return -EINVAL;
Expand All @@ -493,7 +494,7 @@ int mls_convert_context(struct policydb *oldp,
int rc;

catdatum = hashtab_search(newp->p_cats.table,
oldp->p_cat_val_to_name[i]);
sym_name(oldp, SYM_CATS, i));
if (!catdatum)
return -EINVAL;
rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
Expand Down
109 changes: 82 additions & 27 deletions security/selinux/ss/policydb.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,25 +254,34 @@ static int common_index(void *key, void *datum, void *datap)
{
struct policydb *p;
struct common_datum *comdatum;
struct flex_array *fa;

comdatum = datum;
p = datap;
if (!comdatum->value || comdatum->value > p->p_commons.nprim)
return -EINVAL;
p->p_common_val_to_name[comdatum->value - 1] = key;

fa = p->sym_val_to_name[SYM_COMMONS];
if (flex_array_put_ptr(fa, comdatum->value - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();
return 0;
}

static int class_index(void *key, void *datum, void *datap)
{
struct policydb *p;
struct class_datum *cladatum;
struct flex_array *fa;

cladatum = datum;
p = datap;
if (!cladatum->value || cladatum->value > p->p_classes.nprim)
return -EINVAL;
p->p_class_val_to_name[cladatum->value - 1] = key;
fa = p->sym_val_to_name[SYM_CLASSES];
if (flex_array_put_ptr(fa, cladatum->value - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();
p->class_val_to_struct[cladatum->value - 1] = cladatum;
return 0;
}
Expand All @@ -281,14 +290,19 @@ static int role_index(void *key, void *datum, void *datap)
{
struct policydb *p;
struct role_datum *role;
struct flex_array *fa;

role = datum;
p = datap;
if (!role->value
|| role->value > p->p_roles.nprim
|| role->bounds > p->p_roles.nprim)
return -EINVAL;
p->p_role_val_to_name[role->value - 1] = key;

fa = p->sym_val_to_name[SYM_ROLES];
if (flex_array_put_ptr(fa, role->value - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();
p->role_val_to_struct[role->value - 1] = role;
return 0;
}
Expand All @@ -297,6 +311,7 @@ static int type_index(void *key, void *datum, void *datap)
{
struct policydb *p;
struct type_datum *typdatum;
struct flex_array *fa;

typdatum = datum;
p = datap;
Expand All @@ -306,10 +321,13 @@ static int type_index(void *key, void *datum, void *datap)
|| typdatum->value > p->p_types.nprim
|| typdatum->bounds > p->p_types.nprim)
return -EINVAL;
p->p_type_val_to_name[typdatum->value - 1] = key;
/* this flex array was all preallocated, this cannot fail */
if (flex_array_put_ptr(p->type_val_to_struct_array,
typdatum->value - 1, typdatum,
fa = p->sym_val_to_name[SYM_TYPES];
if (flex_array_put_ptr(fa, typdatum->value - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();

fa = p->type_val_to_struct_array;
if (flex_array_put_ptr(fa, typdatum->value - 1, typdatum,
GFP_KERNEL | __GFP_ZERO))
BUG();
}
Expand All @@ -321,14 +339,19 @@ static int user_index(void *key, void *datum, void *datap)
{
struct policydb *p;
struct user_datum *usrdatum;
struct flex_array *fa;

usrdatum = datum;
p = datap;
if (!usrdatum->value
|| usrdatum->value > p->p_users.nprim
|| usrdatum->bounds > p->p_users.nprim)
return -EINVAL;
p->p_user_val_to_name[usrdatum->value - 1] = key;

fa = p->sym_val_to_name[SYM_USERS];
if (flex_array_put_ptr(fa, usrdatum->value - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();
p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
return 0;
}
Expand All @@ -337,6 +360,7 @@ static int sens_index(void *key, void *datum, void *datap)
{
struct policydb *p;
struct level_datum *levdatum;
struct flex_array *fa;

levdatum = datum;
p = datap;
Expand All @@ -345,7 +369,10 @@ static int sens_index(void *key, void *datum, void *datap)
if (!levdatum->level->sens ||
levdatum->level->sens > p->p_levels.nprim)
return -EINVAL;
p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
fa = p->sym_val_to_name[SYM_LEVELS];
if (flex_array_put_ptr(fa, levdatum->level->sens - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();
}

return 0;
Expand All @@ -355,14 +382,18 @@ static int cat_index(void *key, void *datum, void *datap)
{
struct policydb *p;
struct cat_datum *catdatum;
struct flex_array *fa;

catdatum = datum;
p = datap;

if (!catdatum->isalias) {
if (!catdatum->value || catdatum->value > p->p_cats.nprim)
return -EINVAL;
p->p_cat_val_to_name[catdatum->value - 1] = key;
fa = p->sym_val_to_name[SYM_CATS];
if (flex_array_put_ptr(fa, catdatum->value - 1, key,
GFP_KERNEL | __GFP_ZERO))
BUG();
}

return 0;
Expand Down Expand Up @@ -392,9 +423,16 @@ static int policydb_index_classes(struct policydb *p)
int rc;

rc = -ENOMEM;
p->p_common_val_to_name =
kmalloc(p->p_commons.nprim * sizeof(char *), GFP_KERNEL);
if (!p->p_common_val_to_name)
p->sym_val_to_name[SYM_COMMONS] = flex_array_alloc(sizeof(char *),
p->p_commons.nprim,
GFP_KERNEL | __GFP_ZERO);
if (!p->sym_val_to_name[SYM_COMMONS])
goto out;

rc = flex_array_prealloc(p->sym_val_to_name[SYM_COMMONS],
0, p->p_commons.nprim - 1,
GFP_KERNEL | __GFP_ZERO);
if (rc)
goto out;

rc = hashtab_map(p->p_commons.table, common_index, p);
Expand All @@ -408,9 +446,16 @@ static int policydb_index_classes(struct policydb *p)
goto out;

rc = -ENOMEM;
p->p_class_val_to_name =
kmalloc(p->p_classes.nprim * sizeof(char *), GFP_KERNEL);
if (!p->p_class_val_to_name)
p->sym_val_to_name[SYM_CLASSES] = flex_array_alloc(sizeof(char *),
p->p_classes.nprim,
GFP_KERNEL | __GFP_ZERO);
if (!p->sym_val_to_name[SYM_CLASSES])
goto out;

rc = flex_array_prealloc(p->sym_val_to_name[SYM_CLASSES],
0, p->p_classes.nprim - 1,
GFP_KERNEL | __GFP_ZERO);
if (rc)
goto out;

rc = hashtab_map(p->p_classes.table, class_index, p);
Expand Down Expand Up @@ -507,10 +552,18 @@ static int policydb_index_others(struct policydb *p)

for (i = SYM_ROLES; i < SYM_NUM; i++) {
rc = -ENOMEM;
p->sym_val_to_name[i] =
kmalloc(p->symtab[i].nprim * sizeof(char *), GFP_KERNEL);
p->sym_val_to_name[i] = flex_array_alloc(sizeof(char *),
p->symtab[i].nprim,
GFP_KERNEL | __GFP_ZERO);
if (!p->sym_val_to_name[i])
goto out;

rc = flex_array_prealloc(p->sym_val_to_name[i],
0, p->symtab[i].nprim - 1,
GFP_KERNEL | __GFP_ZERO);
if (rc)
goto out;

rc = hashtab_map(p->symtab[i].table, index_f[i], p);
if (rc)
goto out;
Expand Down Expand Up @@ -703,8 +756,10 @@ void policydb_destroy(struct policydb *p)
hashtab_destroy(p->symtab[i].table);
}

for (i = 0; i < SYM_NUM; i++)
kfree(p->sym_val_to_name[i]);
for (i = 0; i < SYM_NUM; i++) {
if (p->sym_val_to_name[i])
flex_array_free(p->sym_val_to_name[i]);
}

kfree(p->class_val_to_struct);
kfree(p->role_val_to_struct);
Expand Down Expand Up @@ -1566,9 +1621,9 @@ static int user_bounds_sanity_check(void *key, void *datum, void *datap)
printk(KERN_ERR
"SELinux: boundary violated policy: "
"user=%s role=%s bounds=%s\n",
p->p_user_val_to_name[user->value - 1],
p->p_role_val_to_name[bit],
p->p_user_val_to_name[upper->value - 1]);
sym_name(p, SYM_USERS, user->value - 1),
sym_name(p, SYM_ROLES, bit),
sym_name(p, SYM_USERS, upper->value - 1));

return -EINVAL;
}
Expand Down Expand Up @@ -1603,9 +1658,9 @@ static int role_bounds_sanity_check(void *key, void *datum, void *datap)
printk(KERN_ERR
"SELinux: boundary violated policy: "
"role=%s type=%s bounds=%s\n",
p->p_role_val_to_name[role->value - 1],
p->p_type_val_to_name[bit],
p->p_role_val_to_name[upper->value - 1]);
sym_name(p, SYM_ROLES, role->value - 1),
sym_name(p, SYM_TYPES, bit),
sym_name(p, SYM_ROLES, upper->value - 1));

return -EINVAL;
}
Expand Down Expand Up @@ -1637,7 +1692,7 @@ static int type_bounds_sanity_check(void *key, void *datum, void *datap)
printk(KERN_ERR "SELinux: type %s: "
"bounded by attribute %s",
(char *) key,
p->p_type_val_to_name[upper->value - 1]);
sym_name(p, SYM_TYPES, upper->value - 1));
return -EINVAL;
}
}
Expand Down
Loading

0 comments on commit ac76c05

Please sign in to comment.