Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jmorris/selinux-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6:
  SELinux: add more validity checks on policy load
  SELinux: fix bug in new ebitmap code.
  SELinux: suppress a warning for 64k pages.
  • Loading branch information
Linus Torvalds committed Nov 9, 2007
2 parents e4fc5a1 + 45e5421 commit 98d74e0
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 45 deletions.
32 changes: 28 additions & 4 deletions security/selinux/ss/avtab.c
Original file line number Diff line number Diff line change
Expand Up @@ -325,18 +325,19 @@ static uint16_t spec_order[] = {
AVTAB_MEMBER
};

int avtab_read_item(void *fp, u32 vers, struct avtab *a,
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
int (*insertf)(struct avtab *a, struct avtab_key *k,
struct avtab_datum *d, void *p),
void *p)
{
__le16 buf16[4];
u16 enabled;
__le32 buf32[7];
u32 items, items2, val;
u32 items, items2, val, vers = pol->policyvers;
struct avtab_key key;
struct avtab_datum datum;
int i, rc;
unsigned set;

memset(&key, 0, sizeof(struct avtab_key));
memset(&datum, 0, sizeof(struct avtab_datum));
Expand Down Expand Up @@ -420,12 +421,35 @@ int avtab_read_item(void *fp, u32 vers, struct avtab *a,
key.target_class = le16_to_cpu(buf16[items++]);
key.specified = le16_to_cpu(buf16[items++]);

if (!policydb_type_isvalid(pol, key.source_type) ||
!policydb_type_isvalid(pol, key.target_type) ||
!policydb_class_isvalid(pol, key.target_class)) {
printk(KERN_WARNING "security: avtab: invalid type or class\n");
return -1;
}

set = 0;
for (i = 0; i < ARRAY_SIZE(spec_order); i++) {
if (key.specified & spec_order[i])
set++;
}
if (!set || set > 1) {
printk(KERN_WARNING
"security: avtab: more than one specifier\n");
return -1;
}

rc = next_entry(buf32, fp, sizeof(u32));
if (rc < 0) {
printk("security: avtab: truncated entry\n");
return -1;
}
datum.data = le32_to_cpu(*buf32);
if ((key.specified & AVTAB_TYPE) &&
!policydb_type_isvalid(pol, datum.data)) {
printk(KERN_WARNING "security: avtab: invalid type\n");
return -1;
}
return insertf(a, &key, &datum, p);
}

Expand All @@ -435,7 +459,7 @@ static int avtab_insertf(struct avtab *a, struct avtab_key *k,
return avtab_insert(a, k, d);
}

int avtab_read(struct avtab *a, void *fp, u32 vers)
int avtab_read(struct avtab *a, void *fp, struct policydb *pol)
{
int rc;
__le32 buf[1];
Expand All @@ -459,7 +483,7 @@ int avtab_read(struct avtab *a, void *fp, u32 vers)
goto bad;

for (i = 0; i < nel; i++) {
rc = avtab_read_item(fp,vers, a, avtab_insertf, NULL);
rc = avtab_read_item(a, fp, pol, avtab_insertf, NULL);
if (rc) {
if (rc == -ENOMEM)
printk(KERN_ERR "security: avtab: out of memory\n");
Expand Down
5 changes: 3 additions & 2 deletions security/selinux/ss/avtab.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,13 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k);
void avtab_destroy(struct avtab *h);
void avtab_hash_eval(struct avtab *h, char *tag);

int avtab_read_item(void *fp, uint32_t vers, struct avtab *a,
struct policydb;
int avtab_read_item(struct avtab *a, void *fp, struct policydb *pol,
int (*insert)(struct avtab *a, struct avtab_key *k,
struct avtab_datum *d, void *p),
void *p);

int avtab_read(struct avtab *a, void *fp, u32 vers);
int avtab_read(struct avtab *a, void *fp, struct policydb *pol);

struct avtab_node *avtab_insert_nonunique(struct avtab *h, struct avtab_key *key,
struct avtab_datum *datum);
Expand Down
3 changes: 2 additions & 1 deletion security/selinux/ss/conditional.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
data.head = NULL;
data.tail = NULL;
for (i = 0; i < len; i++) {
rc = avtab_read_item(fp, p->policyvers, &p->te_cond_avtab, cond_insertf, &data);
rc = avtab_read_item(&p->te_cond_avtab, fp, p, cond_insertf,
&data);
if (rc)
return rc;

Expand Down
2 changes: 1 addition & 1 deletion security/selinux/ss/ebitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap,
cmap_sft = delta % NETLBL_CATMAP_MAPSIZE;
c_iter->bitmap[cmap_idx]
|= e_iter->maps[cmap_idx] << cmap_sft;
e_iter = e_iter->next;
}
e_iter = e_iter->next;
}

return 0;
Expand Down
66 changes: 36 additions & 30 deletions security/selinux/ss/mls.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,49 +157,55 @@ void mls_sid_to_context(struct context *context,
return;
}

int mls_level_isvalid(struct policydb *p, struct mls_level *l)
{
struct level_datum *levdatum;
struct ebitmap_node *node;
int i;

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]);
if (!levdatum)
return 0;

ebitmap_for_each_positive_bit(&l->cat, node, i) {
if (i > p->p_cats.nprim)
return 0;
if (!ebitmap_get_bit(&levdatum->level->cat, i)) {
/*
* Category may not be associated with
* sensitivity.
*/
return 0;
}
}

return 1;
}

int mls_range_isvalid(struct policydb *p, struct mls_range *r)
{
return (mls_level_isvalid(p, &r->level[0]) &&
mls_level_isvalid(p, &r->level[1]) &&
mls_level_dom(&r->level[1], &r->level[0]));
}

/*
* Return 1 if the MLS fields in the security context
* structure `c' are valid. Return 0 otherwise.
*/
int mls_context_isvalid(struct policydb *p, struct context *c)
{
struct level_datum *levdatum;
struct user_datum *usrdatum;
struct ebitmap_node *node;
int i, l;

if (!selinux_mls_enabled)
return 1;

/*
* MLS range validity checks: high must dominate low, low level must
* be valid (category set <-> sensitivity check), and high level must
* be valid (category set <-> sensitivity check)
*/
if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
/* High does not dominate low. */
if (!mls_range_isvalid(p, &c->range))
return 0;

for (l = 0; l < 2; l++) {
if (!c->range.level[l].sens || c->range.level[l].sens > p->p_levels.nprim)
return 0;
levdatum = hashtab_search(p->p_levels.table,
p->p_sens_val_to_name[c->range.level[l].sens - 1]);
if (!levdatum)
return 0;

ebitmap_for_each_positive_bit(&c->range.level[l].cat, node, i) {
if (i > p->p_cats.nprim)
return 0;
if (!ebitmap_get_bit(&levdatum->level->cat, i))
/*
* Category may not be associated with
* sensitivity in low level.
*/
return 0;
}
}

if (c->role == OBJECT_R_VAL)
return 1;

Expand Down
2 changes: 2 additions & 0 deletions security/selinux/ss/mls.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
int mls_compute_context_len(struct context *context);
void mls_sid_to_context(struct context *context, char **scontext);
int mls_context_isvalid(struct policydb *p, struct context *c);
int mls_range_isvalid(struct policydb *p, struct mls_range *r);
int mls_level_isvalid(struct policydb *p, struct mls_level *l);

int mls_context_to_sid(char oldc,
char **scontext,
Expand Down
45 changes: 44 additions & 1 deletion security/selinux/ss/policydb.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,27 @@ int policydb_load_isids(struct policydb *p, struct sidtab *s)
return rc;
}

int policydb_class_isvalid(struct policydb *p, unsigned int class)
{
if (!class || class > p->p_classes.nprim)
return 0;
return 1;
}

int policydb_role_isvalid(struct policydb *p, unsigned int role)
{
if (!role || role > p->p_roles.nprim)
return 0;
return 1;
}

int policydb_type_isvalid(struct policydb *p, unsigned int type)
{
if (!type || type > p->p_types.nprim)
return 0;
return 1;
}

/*
* Return 1 if the fields in the security context
* structure `c' are valid. Return 0 otherwise.
Expand Down Expand Up @@ -1260,6 +1281,7 @@ static int mls_read_level(struct mls_level *lp, void *fp)
"categories\n");
goto bad;
}

return 0;

bad:
Expand Down Expand Up @@ -1563,7 +1585,7 @@ int policydb_read(struct policydb *p, void *fp)
p->symtab[i].nprim = nprim;
}

rc = avtab_read(&p->te_avtab, fp, p->policyvers);
rc = avtab_read(&p->te_avtab, fp, p);
if (rc)
goto bad;

Expand Down Expand Up @@ -1595,6 +1617,12 @@ int policydb_read(struct policydb *p, void *fp)
tr->role = le32_to_cpu(buf[0]);
tr->type = le32_to_cpu(buf[1]);
tr->new_role = le32_to_cpu(buf[2]);
if (!policydb_role_isvalid(p, tr->role) ||
!policydb_type_isvalid(p, tr->type) ||
!policydb_role_isvalid(p, tr->new_role)) {
rc = -EINVAL;
goto bad;
}
ltr = tr;
}

Expand All @@ -1619,6 +1647,11 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
ra->role = le32_to_cpu(buf[0]);
ra->new_role = le32_to_cpu(buf[1]);
if (!policydb_role_isvalid(p, ra->role) ||
!policydb_role_isvalid(p, ra->new_role)) {
rc = -EINVAL;
goto bad;
}
lra = ra;
}

Expand Down Expand Up @@ -1872,9 +1905,19 @@ int policydb_read(struct policydb *p, void *fp)
rt->target_class = le32_to_cpu(buf[0]);
} else
rt->target_class = SECCLASS_PROCESS;
if (!policydb_type_isvalid(p, rt->source_type) ||
!policydb_type_isvalid(p, rt->target_type) ||
!policydb_class_isvalid(p, rt->target_class)) {
rc = -EINVAL;
goto bad;
}
rc = mls_read_range_helper(&rt->target_range, fp);
if (rc)
goto bad;
if (!mls_range_isvalid(p, &rt->target_range)) {
printk(KERN_WARNING "security: rangetrans: invalid range\n");
goto bad;
}
lrt = rt;
}
}
Expand Down
3 changes: 3 additions & 0 deletions security/selinux/ss/policydb.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,9 @@ struct policydb {
extern void policydb_destroy(struct policydb *p);
extern int policydb_load_isids(struct policydb *p, struct sidtab *s);
extern int policydb_context_isvalid(struct policydb *p, struct context *c);
extern int policydb_class_isvalid(struct policydb *p, unsigned int class);
extern int policydb_type_isvalid(struct policydb *p, unsigned int type);
extern int policydb_role_isvalid(struct policydb *p, unsigned int role);
extern int policydb_read(struct policydb *p, void *fp);

#define PERM_SYMTAB_SIZE 32
Expand Down
13 changes: 7 additions & 6 deletions security/selinux/xfrm.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,26 +211,27 @@ static int selinux_xfrm_sec_ctx_alloc(struct xfrm_sec_ctx **ctxp,
if (uctx->ctx_doi != XFRM_SC_ALG_SELINUX)
return -EINVAL;

if (uctx->ctx_len >= PAGE_SIZE)
str_len = uctx->ctx_len;
if (str_len >= PAGE_SIZE)
return -ENOMEM;

*ctxp = ctx = kmalloc(sizeof(*ctx) +
uctx->ctx_len + 1,
str_len + 1,
GFP_KERNEL);

if (!ctx)
return -ENOMEM;

ctx->ctx_doi = uctx->ctx_doi;
ctx->ctx_len = uctx->ctx_len;
ctx->ctx_len = str_len;
ctx->ctx_alg = uctx->ctx_alg;

memcpy(ctx->ctx_str,
uctx+1,
ctx->ctx_len);
ctx->ctx_str[ctx->ctx_len] = 0;
str_len);
ctx->ctx_str[str_len] = 0;
rc = security_context_to_sid(ctx->ctx_str,
ctx->ctx_len,
str_len,
&ctx->ctx_sid);

if (rc)
Expand Down

0 comments on commit 98d74e0

Please sign in to comment.