Commit 066752a3 authored by Stephen D. Smalley's avatar Stephen D. Smalley Committed by Linus Torvalds

[PATCH] SELinux: eliminate unaligned accesses by policy loading code

This patch rewrites the SELinux next_entry() function and all callers to
copy entry data from the binary policy into properly aligned buffers,
eliminating unaligned accesses.  This patch is in response to a bug report
from Prarit Bhargava for SELinux and ia64, and he has confirmed that this
patch eliminates the unaligned access warnings.
Signed-off-by: default avatarStephen Smalley <sds@epoch.ncsc.mil>
Signed-off-by: default avatarJames Morris <jmorris@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 263891c2
...@@ -303,20 +303,25 @@ void avtab_hash_eval(struct avtab *h, char *tag) ...@@ -303,20 +303,25 @@ void avtab_hash_eval(struct avtab *h, char *tag)
int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey) int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avkey)
{ {
__u32 *buf; u32 buf[7];
__u32 items, items2; u32 items, items2;
int rc;
memset(avkey, 0, sizeof(struct avtab_key)); memset(avkey, 0, sizeof(struct avtab_key));
memset(avdatum, 0, sizeof(struct avtab_datum)); memset(avdatum, 0, sizeof(struct avtab_datum));
buf = next_entry(fp, sizeof(__u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) { if (rc < 0) {
printk(KERN_ERR "security: avtab: truncated entry\n"); printk(KERN_ERR "security: avtab: truncated entry\n");
goto bad; goto bad;
} }
items2 = le32_to_cpu(buf[0]); items2 = le32_to_cpu(buf[0]);
buf = next_entry(fp, sizeof(__u32)*items2); if (items2 > ARRAY_SIZE(buf)) {
if (!buf) { printk(KERN_ERR "security: avtab: entry overflow\n");
goto bad;
}
rc = next_entry(buf, fp, sizeof(u32)*items2);
if (rc < 0) {
printk(KERN_ERR "security: avtab: truncated entry\n"); printk(KERN_ERR "security: avtab: truncated entry\n");
goto bad; goto bad;
} }
...@@ -362,21 +367,22 @@ int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avk ...@@ -362,21 +367,22 @@ int avtab_read_item(void *fp, struct avtab_datum *avdatum, struct avtab_key *avk
int avtab_read(struct avtab *a, void *fp, u32 config) int avtab_read(struct avtab *a, void *fp, u32 config)
{ {
int i, rc = -EINVAL; int rc;
struct avtab_key avkey; struct avtab_key avkey;
struct avtab_datum avdatum; struct avtab_datum avdatum;
u32 *buf; u32 buf[1];
u32 nel; u32 nel, i;
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) { if (rc < 0) {
printk(KERN_ERR "security: avtab: truncated table\n"); printk(KERN_ERR "security: avtab: truncated table\n");
goto bad; goto bad;
} }
nel = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[0]);
if (!nel) { if (!nel) {
printk(KERN_ERR "security: avtab: table is empty\n"); printk(KERN_ERR "security: avtab: table is empty\n");
rc = -EINVAL;
goto bad; goto bad;
} }
for (i = 0; i < nel; i++) { for (i = 0; i < nel; i++) {
......
...@@ -219,15 +219,16 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) ...@@ -219,15 +219,16 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
{ {
char *key = NULL; char *key = NULL;
struct cond_bool_datum *booldatum; struct cond_bool_datum *booldatum;
__u32 *buf, len; u32 buf[3], len;
int rc;
booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL); booldatum = kmalloc(sizeof(struct cond_bool_datum), GFP_KERNEL);
if (!booldatum) if (!booldatum)
return -1; return -1;
memset(booldatum, 0, sizeof(struct cond_bool_datum)); memset(booldatum, 0, sizeof(struct cond_bool_datum));
buf = next_entry(fp, sizeof(__u32) * 3); rc = next_entry(buf, fp, sizeof buf);
if (!buf) if (rc < 0)
goto err; goto err;
booldatum->value = le32_to_cpu(buf[0]); booldatum->value = le32_to_cpu(buf[0]);
...@@ -238,13 +239,12 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp) ...@@ -238,13 +239,12 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
len = le32_to_cpu(buf[2]); len = le32_to_cpu(buf[2]);
buf = next_entry(fp, len);
if (!buf)
goto err;
key = kmalloc(len + 1, GFP_KERNEL); key = kmalloc(len + 1, GFP_KERNEL);
if (!key) if (!key)
goto err; goto err;
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto err;
key[len] = 0; key[len] = 0;
if (hashtab_insert(h, key, booldatum)) if (hashtab_insert(h, key, booldatum))
goto err; goto err;
...@@ -262,15 +262,15 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list * ...@@ -262,15 +262,15 @@ static int cond_read_av_list(struct policydb *p, void *fp, struct cond_av_list *
struct avtab_key key; struct avtab_key key;
struct avtab_datum datum; struct avtab_datum datum;
struct avtab_node *node_ptr; struct avtab_node *node_ptr;
int len, i; int rc;
__u32 *buf; u32 buf[1], i, len;
__u8 found; u8 found;
*ret_list = NULL; *ret_list = NULL;
len = 0; len = 0;
buf = next_entry(fp, sizeof(__u32)); rc = next_entry(buf, fp, sizeof buf);
if (!buf) if (rc < 0)
return -1; return -1;
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
...@@ -369,27 +369,27 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr) ...@@ -369,27 +369,27 @@ static int expr_isvalid(struct policydb *p, struct cond_expr *expr)
static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
{ {
__u32 *buf; u32 buf[2], len, i;
int len, i; int rc;
struct cond_expr *expr = NULL, *last = NULL; struct cond_expr *expr = NULL, *last = NULL;
buf = next_entry(fp, sizeof(__u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
return -1; return -1;
node->cur_state = le32_to_cpu(buf[0]); node->cur_state = le32_to_cpu(buf[0]);
len = 0; len = 0;
buf = next_entry(fp, sizeof(__u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
return -1; return -1;
/* expr */ /* expr */
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
for (i = 0; i < len; i++ ) { for (i = 0; i < len; i++ ) {
buf = next_entry(fp, sizeof(__u32) * 2); rc = next_entry(buf, fp, sizeof(u32) * 2);
if (!buf) if (rc < 0)
goto err; goto err;
expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL); expr = kmalloc(sizeof(struct cond_expr), GFP_KERNEL);
...@@ -425,11 +425,11 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp) ...@@ -425,11 +425,11 @@ static int cond_read_node(struct policydb *p, struct cond_node *node, void *fp)
int cond_read_list(struct policydb *p, void *fp) int cond_read_list(struct policydb *p, void *fp)
{ {
struct cond_node *node, *last = NULL; struct cond_node *node, *last = NULL;
__u32 *buf; u32 buf[1], i, len;
int i, len; int rc;
buf = next_entry(fp, sizeof(__u32)); rc = next_entry(buf, fp, sizeof buf);
if (!buf) if (rc < 0)
return -1; return -1;
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
......
...@@ -239,13 +239,13 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -239,13 +239,13 @@ int ebitmap_read(struct ebitmap *e, void *fp)
{ {
int rc = -EINVAL; int rc = -EINVAL;
struct ebitmap_node *n, *l; struct ebitmap_node *n, *l;
u32 *buf, mapsize, count, i; u32 buf[3], mapsize, count, i;
u64 map; u64 map;
ebitmap_init(e); ebitmap_init(e);
buf = next_entry(fp, sizeof(u32)*3); rc = next_entry(buf, fp, sizeof buf);
if (!buf) if (rc < 0)
goto out; goto out;
mapsize = le32_to_cpu(buf[0]); mapsize = le32_to_cpu(buf[0]);
...@@ -269,8 +269,8 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -269,8 +269,8 @@ int ebitmap_read(struct ebitmap *e, void *fp)
} }
l = NULL; l = NULL;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) { if (rc < 0) {
printk(KERN_ERR "security: ebitmap: truncated map\n"); printk(KERN_ERR "security: ebitmap: truncated map\n");
goto bad; goto bad;
} }
...@@ -296,12 +296,11 @@ int ebitmap_read(struct ebitmap *e, void *fp) ...@@ -296,12 +296,11 @@ int ebitmap_read(struct ebitmap *e, void *fp)
n->startbit, (e->highbit - MAPSIZE)); n->startbit, (e->highbit - MAPSIZE));
goto bad_free; goto bad_free;
} }
buf = next_entry(fp, sizeof(u64)); rc = next_entry(&map, fp, sizeof(u64));
if (!buf) { if (rc < 0) {
printk(KERN_ERR "security: ebitmap: truncated map\n"); printk(KERN_ERR "security: ebitmap: truncated map\n");
goto bad_free; goto bad_free;
} }
memcpy(&map, buf, sizeof(u64));
n->map = le64_to_cpu(map); n->map = le64_to_cpu(map);
if (!n->map) { if (!n->map) {
......
...@@ -402,10 +402,11 @@ void mls_user_destroy(struct user_datum *usrdatum) ...@@ -402,10 +402,11 @@ void mls_user_destroy(struct user_datum *usrdatum)
int mls_read_perm(struct perm_datum *perdatum, void *fp) int mls_read_perm(struct perm_datum *perdatum, void *fp)
{ {
u32 *buf; u32 buf[1];
int rc;
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof buf);
if (!buf) if (rc < 0)
return -EINVAL; return -EINVAL;
perdatum->base_perms = le32_to_cpu(buf[0]); perdatum->base_perms = le32_to_cpu(buf[0]);
return 0; return 0;
...@@ -418,7 +419,8 @@ int mls_read_perm(struct perm_datum *perdatum, void *fp) ...@@ -418,7 +419,8 @@ int mls_read_perm(struct perm_datum *perdatum, void *fp)
struct mls_level *mls_read_level(void *fp) struct mls_level *mls_read_level(void *fp)
{ {
struct mls_level *l; struct mls_level *l;
u32 *buf; u32 buf[1];
int rc;
l = kmalloc(sizeof(*l), GFP_ATOMIC); l = kmalloc(sizeof(*l), GFP_ATOMIC);
if (!l) { if (!l) {
...@@ -427,8 +429,8 @@ struct mls_level *mls_read_level(void *fp) ...@@ -427,8 +429,8 @@ struct mls_level *mls_read_level(void *fp)
} }
memset(l, 0, sizeof(*l)); memset(l, 0, sizeof(*l));
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0) {
printk(KERN_ERR "security: mls: truncated level\n"); printk(KERN_ERR "security: mls: truncated level\n");
goto bad; goto bad;
} }
...@@ -453,16 +455,21 @@ struct mls_level *mls_read_level(void *fp) ...@@ -453,16 +455,21 @@ struct mls_level *mls_read_level(void *fp)
*/ */
static int mls_read_range_helper(struct mls_range *r, void *fp) static int mls_read_range_helper(struct mls_range *r, void *fp)
{ {
u32 *buf; u32 buf[2], items;
int items, rc = -EINVAL; int rc;
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
goto out; goto out;
items = le32_to_cpu(buf[0]); items = le32_to_cpu(buf[0]);
buf = next_entry(fp, sizeof(u32) * items); if (items > ARRAY_SIZE(buf)) {
if (!buf) { printk(KERN_ERR "security: mls: range overflow\n");
rc = -EINVAL;
goto out;
}
rc = next_entry(buf, fp, sizeof(u32) * items);
if (rc < 0) {
printk(KERN_ERR "security: mls: truncated range\n"); printk(KERN_ERR "security: mls: truncated range\n");
goto out; goto out;
} }
...@@ -515,10 +522,11 @@ int mls_read_range(struct context *c, void *fp) ...@@ -515,10 +522,11 @@ int mls_read_range(struct context *c, void *fp)
int mls_read_class(struct class_datum *cladatum, void *fp) int mls_read_class(struct class_datum *cladatum, void *fp)
{ {
struct mls_perms *p = &cladatum->mlsperms; struct mls_perms *p = &cladatum->mlsperms;
u32 *buf; u32 buf[4];
int rc;
buf = next_entry(fp, sizeof(u32)*4); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0) {
printk(KERN_ERR "security: mls: truncated mls permissions\n"); printk(KERN_ERR "security: mls: truncated mls permissions\n");
return -EINVAL; return -EINVAL;
} }
...@@ -532,15 +540,13 @@ int mls_read_class(struct class_datum *cladatum, void *fp) ...@@ -532,15 +540,13 @@ int mls_read_class(struct class_datum *cladatum, void *fp)
int mls_read_user(struct user_datum *usrdatum, void *fp) int mls_read_user(struct user_datum *usrdatum, void *fp)
{ {
struct mls_range_list *r, *l; struct mls_range_list *r, *l;
int rc = 0; int rc;
u32 nel, i; u32 nel, i;
u32 *buf; u32 buf[1];
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto out; goto out;
}
nel = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[0]);
l = NULL; l = NULL;
for (i = 0; i < nel; i++) { for (i = 0; i < nel; i++) {
...@@ -569,10 +575,11 @@ int mls_read_user(struct user_datum *usrdatum, void *fp) ...@@ -569,10 +575,11 @@ int mls_read_user(struct user_datum *usrdatum, void *fp)
int mls_read_nlevels(struct policydb *p, void *fp) int mls_read_nlevels(struct policydb *p, void *fp)
{ {
u32 *buf; u32 buf[1];
int rc;
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof buf);
if (!buf) if (rc < 0)
return -EINVAL; return -EINVAL;
p->nlevels = le32_to_cpu(buf[0]); p->nlevels = le32_to_cpu(buf[0]);
return 0; return 0;
...@@ -657,7 +664,7 @@ int sens_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -657,7 +664,7 @@ int sens_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL; char *key = NULL;
struct level_datum *levdatum; struct level_datum *levdatum;
int rc; int rc;
u32 *buf, len; u32 buf[2], len;
levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC); levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
if (!levdatum) { if (!levdatum) {
...@@ -666,26 +673,21 @@ int sens_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -666,26 +673,21 @@ int sens_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(levdatum, 0, sizeof(*levdatum)); memset(levdatum, 0, sizeof(*levdatum));
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
levdatum->isalias = le32_to_cpu(buf[1]); levdatum->isalias = le32_to_cpu(buf[1]);
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_ATOMIC); key = kmalloc(len + 1,GFP_ATOMIC);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
levdatum->level = mls_read_level(fp); levdatum->level = mls_read_level(fp);
...@@ -710,7 +712,7 @@ int cat_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -710,7 +712,7 @@ int cat_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL; char *key = NULL;
struct cat_datum *catdatum; struct cat_datum *catdatum;
int rc; int rc;
u32 *buf, len; u32 buf[3], len;
catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC); catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
if (!catdatum) { if (!catdatum) {
...@@ -719,27 +721,22 @@ int cat_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -719,27 +721,22 @@ int cat_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(catdatum, 0, sizeof(*catdatum)); memset(catdatum, 0, sizeof(*catdatum));
buf = next_entry(fp, sizeof(u32)*3); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
catdatum->value = le32_to_cpu(buf[1]); catdatum->value = le32_to_cpu(buf[1]);
catdatum->isalias = le32_to_cpu(buf[2]); catdatum->isalias = le32_to_cpu(buf[2]);
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_ATOMIC); key = kmalloc(len + 1,GFP_ATOMIC);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
rc = hashtab_insert(h, key, catdatum); rc = hashtab_insert(h, key, catdatum);
......
...@@ -633,13 +633,12 @@ static int context_read_and_validate(struct context *c, ...@@ -633,13 +633,12 @@ static int context_read_and_validate(struct context *c,
struct policydb *p, struct policydb *p,
void *fp) void *fp)
{ {
u32 *buf; u32 buf[3];
int rc = 0; int rc;
buf = next_entry(fp, sizeof(u32)*3); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0) {
printk(KERN_ERR "security: context truncated\n"); printk(KERN_ERR "security: context truncated\n");
rc = -EINVAL;
goto out; goto out;
} }
c->user = le32_to_cpu(buf[0]); c->user = le32_to_cpu(buf[0]);
...@@ -672,7 +671,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -672,7 +671,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL; char *key = NULL;
struct perm_datum *perdatum; struct perm_datum *perdatum;
int rc; int rc;
u32 *buf, len; u32 buf[2], len;
perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL); perdatum = kmalloc(sizeof(*perdatum), GFP_KERNEL);
if (!perdatum) { if (!perdatum) {
...@@ -681,11 +680,9 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -681,11 +680,9 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(perdatum, 0, sizeof(*perdatum)); memset(perdatum, 0, sizeof(*perdatum));
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
perdatum->value = le32_to_cpu(buf[1]); perdatum->value = le32_to_cpu(buf[1]);
...@@ -693,17 +690,14 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -693,17 +690,14 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
if (rc) if (rc)
goto bad; goto bad;
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_KERNEL); key = kmalloc(len + 1,GFP_KERNEL);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
rc = hashtab_insert(h, key, perdatum); rc = hashtab_insert(h, key, perdatum);
...@@ -720,7 +714,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -720,7 +714,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
{ {
char *key = NULL; char *key = NULL;
struct common_datum *comdatum; struct common_datum *comdatum;
u32 *buf, len, nel; u32 buf[4], len, nel;
int i, rc; int i, rc;
comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL); comdatum = kmalloc(sizeof(*comdatum), GFP_KERNEL);
...@@ -730,11 +724,9 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -730,11 +724,9 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(comdatum, 0, sizeof(*comdatum)); memset(comdatum, 0, sizeof(*comdatum));
buf = next_entry(fp, sizeof(u32)*4); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
comdatum->value = le32_to_cpu(buf[1]); comdatum->value = le32_to_cpu(buf[1]);
...@@ -745,17 +737,14 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -745,17 +737,14 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
comdatum->permissions.nprim = le32_to_cpu(buf[2]); comdatum->permissions.nprim = le32_to_cpu(buf[2]);
nel = le32_to_cpu(buf[3]); nel = le32_to_cpu(buf[3]);
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_KERNEL); key = kmalloc(len + 1,GFP_KERNEL);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
for (i = 0; i < nel; i++) { for (i = 0; i < nel; i++) {
...@@ -780,7 +769,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -780,7 +769,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
struct class_datum *cladatum; struct class_datum *cladatum;
struct constraint_node *c, *lc; struct constraint_node *c, *lc;
struct constraint_expr *e, *le; struct constraint_expr *e, *le;
u32 *buf, len, len2, ncons, nexpr, nel; u32 buf[6], len, len2, ncons, nexpr, nel;
int i, j, depth, rc; int i, j, depth, rc;
cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL); cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
...@@ -790,11 +779,9 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -790,11 +779,9 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(cladatum, 0, sizeof(*cladatum)); memset(cladatum, 0, sizeof(*cladatum));
buf = next_entry(fp, sizeof(u32)*6); rc = next_entry(buf, fp, sizeof(u32)*6);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
len2 = le32_to_cpu(buf[1]); len2 = le32_to_cpu(buf[1]);
...@@ -808,17 +795,14 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -808,17 +795,14 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
ncons = le32_to_cpu(buf[5]); ncons = le32_to_cpu(buf[5]);
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_KERNEL); key = kmalloc(len + 1,GFP_KERNEL);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
if (len2) { if (len2) {
...@@ -827,12 +811,9 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -827,12 +811,9 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
buf = next_entry(fp, len2); rc = next_entry(cladatum->comkey, fp, len2);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
memcpy(cladatum->comkey, buf, len2);
cladatum->comkey[len2] = 0; cladatum->comkey[len2] = 0;
cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comdatum = hashtab_search(p->p_commons.table,
...@@ -866,8 +847,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -866,8 +847,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
cladatum->constraints = c; cladatum->constraints = c;
} }
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof(u32)*2);
if (!buf) if (rc < 0)
goto bad; goto bad;
c->permissions = le32_to_cpu(buf[0]); c->permissions = le32_to_cpu(buf[0]);
nexpr = le32_to_cpu(buf[1]); nexpr = le32_to_cpu(buf[1]);
...@@ -887,8 +868,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -887,8 +868,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
c->expr = e; c->expr = e;
} }
buf = next_entry(fp, sizeof(u32)*3); rc = next_entry(buf, fp, sizeof(u32)*3);
if (!buf) if (rc < 0)
goto bad; goto bad;
e->expr_type = le32_to_cpu(buf[0]); e->expr_type = le32_to_cpu(buf[0]);
e->attr = le32_to_cpu(buf[1]); e->attr = le32_to_cpu(buf[1]);
...@@ -946,7 +927,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -946,7 +927,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL; char *key = NULL;
struct role_datum *role; struct role_datum *role;
int rc; int rc;
u32 *buf, len; u32 buf[2], len;
role = kmalloc(sizeof(*role), GFP_KERNEL); role = kmalloc(sizeof(*role), GFP_KERNEL);
if (!role) { if (!role) {
...@@ -955,26 +936,21 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -955,26 +936,21 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(role, 0, sizeof(*role)); memset(role, 0, sizeof(*role));
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
role->value = le32_to_cpu(buf[1]); role->value = le32_to_cpu(buf[1]);
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_KERNEL); key = kmalloc(len + 1,GFP_KERNEL);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
rc = ebitmap_read(&role->dominates, fp); rc = ebitmap_read(&role->dominates, fp);
...@@ -1011,7 +987,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -1011,7 +987,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL; char *key = NULL;
struct type_datum *typdatum; struct type_datum *typdatum;
int rc; int rc;
u32 *buf, len; u32 buf[3], len;
typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL); typdatum = kmalloc(sizeof(*typdatum),GFP_KERNEL);
if (!typdatum) { if (!typdatum) {
...@@ -1020,27 +996,22 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -1020,27 +996,22 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(typdatum, 0, sizeof(*typdatum)); memset(typdatum, 0, sizeof(*typdatum));
buf = next_entry(fp, sizeof(u32)*3); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
typdatum->value = le32_to_cpu(buf[1]); typdatum->value = le32_to_cpu(buf[1]);
typdatum->primary = le32_to_cpu(buf[2]); typdatum->primary = le32_to_cpu(buf[2]);
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_KERNEL); key = kmalloc(len + 1,GFP_KERNEL);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
rc = hashtab_insert(h, key, typdatum); rc = hashtab_insert(h, key, typdatum);
...@@ -1058,7 +1029,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -1058,7 +1029,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
char *key = NULL; char *key = NULL;
struct user_datum *usrdatum; struct user_datum *usrdatum;
int rc; int rc;
u32 *buf, len; u32 buf[2], len;
usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL); usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
...@@ -1068,26 +1039,21 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp) ...@@ -1068,26 +1039,21 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
} }
memset(usrdatum, 0, sizeof(*usrdatum)); memset(usrdatum, 0, sizeof(*usrdatum));
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof buf);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
usrdatum->value = le32_to_cpu(buf[1]); usrdatum->value = le32_to_cpu(buf[1]);
buf = next_entry(fp, len);
if (!buf) {
rc = -EINVAL;
goto bad;
}
key = kmalloc(len + 1,GFP_KERNEL); key = kmalloc(len + 1,GFP_KERNEL);
if (!key) { if (!key) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(key, buf, len); rc = next_entry(key, fp, len);
if (rc < 0)
goto bad;
key[len] = 0; key[len] = 0;
rc = ebitmap_read(&usrdatum->roles, fp); rc = ebitmap_read(&usrdatum->roles, fp);
...@@ -1133,7 +1099,7 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1133,7 +1099,7 @@ int policydb_read(struct policydb *p, void *fp)
struct ocontext *l, *c, *newc; struct ocontext *l, *c, *newc;
struct genfs *genfs_p, *genfs, *newgenfs; struct genfs *genfs_p, *genfs, *newgenfs;
int i, j, rc, r_policyvers = 0; int i, j, rc, r_policyvers = 0;
u32 *buf, len, len2, config, nprim, nel, nel2; u32 buf[8], len, len2, config, nprim, nel, nel2;
char *policydb_str; char *policydb_str;
struct policydb_compat_info *info; struct policydb_compat_info *info;
...@@ -1146,8 +1112,8 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1146,8 +1112,8 @@ int policydb_read(struct policydb *p, void *fp)
rc = -EINVAL; rc = -EINVAL;
/* Read the magic number and string length. */ /* Read the magic number and string length. */
buf = next_entry(fp, sizeof(u32)* 2); rc = next_entry(buf, fp, sizeof(u32)* 2);
if (!buf) if (rc < 0)
goto bad; goto bad;
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
...@@ -1167,11 +1133,6 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1167,11 +1133,6 @@ int policydb_read(struct policydb *p, void *fp)
len, strlen(POLICYDB_STRING)); len, strlen(POLICYDB_STRING));
goto bad; goto bad;
} }
buf = next_entry(fp, len);
if (!buf) {
printk(KERN_ERR "security: truncated policydb string identifier\n");
goto bad;
}
policydb_str = kmalloc(len + 1,GFP_KERNEL); policydb_str = kmalloc(len + 1,GFP_KERNEL);
if (!policydb_str) { if (!policydb_str) {
printk(KERN_ERR "security: unable to allocate memory for policydb " printk(KERN_ERR "security: unable to allocate memory for policydb "
...@@ -1179,7 +1140,12 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1179,7 +1140,12 @@ int policydb_read(struct policydb *p, void *fp)
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(policydb_str, buf, len); rc = next_entry(policydb_str, fp, len);
if (rc < 0) {
printk(KERN_ERR "security: truncated policydb string identifier\n");
kfree(policydb_str);
goto bad;
}
policydb_str[len] = 0; policydb_str[len] = 0;
if (strcmp(policydb_str, POLICYDB_STRING)) { if (strcmp(policydb_str, POLICYDB_STRING)) {
printk(KERN_ERR "security: policydb string %s does not match " printk(KERN_ERR "security: policydb string %s does not match "
...@@ -1192,8 +1158,8 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1192,8 +1158,8 @@ int policydb_read(struct policydb *p, void *fp)
policydb_str = NULL; policydb_str = NULL;
/* Read the version, config, and table sizes. */ /* Read the version, config, and table sizes. */
buf = next_entry(fp, sizeof(u32)*4); rc = next_entry(buf, fp, sizeof(u32)*4);
if (!buf) if (rc < 0)
goto bad; goto bad;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
buf[i] = le32_to_cpu(buf[i]); buf[i] = le32_to_cpu(buf[i]);
...@@ -1235,11 +1201,9 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1235,11 +1201,9 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
for (i = 0; i < info->sym_num; i++) { for (i = 0; i < info->sym_num; i++) {
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof(u32)*2);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
nprim = le32_to_cpu(buf[0]); nprim = le32_to_cpu(buf[0]);
nel = le32_to_cpu(buf[1]); nel = le32_to_cpu(buf[1]);
for (j = 0; j < nel; j++) { for (j = 0; j < nel; j++) {
...@@ -1261,11 +1225,9 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1261,11 +1225,9 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
} }
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
nel = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[0]);
ltr = NULL; ltr = NULL;
for (i = 0; i < nel; i++) { for (i = 0; i < nel; i++) {
...@@ -1280,22 +1242,18 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1280,22 +1242,18 @@ int policydb_read(struct policydb *p, void *fp)
} else { } else {
p->role_tr = tr; p->role_tr = tr;
} }
buf = next_entry(fp, sizeof(u32)*3); rc = next_entry(buf, fp, sizeof(u32)*3);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
tr->role = le32_to_cpu(buf[0]); tr->role = le32_to_cpu(buf[0]);
tr->type = le32_to_cpu(buf[1]); tr->type = le32_to_cpu(buf[1]);
tr->new_role = le32_to_cpu(buf[2]); tr->new_role = le32_to_cpu(buf[2]);
ltr = tr; ltr = tr;
} }
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
nel = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[0]);
lra = NULL; lra = NULL;
for (i = 0; i < nel; i++) { for (i = 0; i < nel; i++) {
...@@ -1310,11 +1268,9 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1310,11 +1268,9 @@ int policydb_read(struct policydb *p, void *fp)
} else { } else {
p->role_allow = ra; p->role_allow = ra;
} }
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof(u32)*2);
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
ra->role = le32_to_cpu(buf[0]); ra->role = le32_to_cpu(buf[0]);
ra->new_role = le32_to_cpu(buf[1]); ra->new_role = le32_to_cpu(buf[1]);
lra = ra; lra = ra;
...@@ -1329,11 +1285,9 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1329,11 +1285,9 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
for (i = 0; i < info->ocon_num; i++) { for (i = 0; i < info->ocon_num; i++) {
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
nel = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[0]);
l = NULL; l = NULL;
for (j = 0; j < nel; j++) { for (j = 0; j < nel; j++) {
...@@ -1352,8 +1306,8 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1352,8 +1306,8 @@ int policydb_read(struct policydb *p, void *fp)
rc = -EINVAL; rc = -EINVAL;
switch (i) { switch (i) {
case OCON_ISID: case OCON_ISID:
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
goto bad; goto bad;
c->sid[0] = le32_to_cpu(buf[0]); c->sid[0] = le32_to_cpu(buf[0]);
rc = context_read_and_validate(&c->context[0], p, fp); rc = context_read_and_validate(&c->context[0], p, fp);
...@@ -1362,19 +1316,18 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1362,19 +1316,18 @@ int policydb_read(struct policydb *p, void *fp)
break; break;
case OCON_FS: case OCON_FS:
case OCON_NETIF: case OCON_NETIF:
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
goto bad; goto bad;
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
buf = next_entry(fp, len);
if (!buf)
goto bad;
c->u.name = kmalloc(len + 1,GFP_KERNEL); c->u.name = kmalloc(len + 1,GFP_KERNEL);
if (!c->u.name) { if (!c->u.name) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(c->u.name, buf, len); rc = next_entry(c->u.name, fp, len);
if (rc < 0)
goto bad;
c->u.name[len] = 0; c->u.name[len] = 0;
rc = context_read_and_validate(&c->context[0], p, fp); rc = context_read_and_validate(&c->context[0], p, fp);
if (rc) if (rc)
...@@ -1384,8 +1337,8 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1384,8 +1337,8 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
break; break;
case OCON_PORT: case OCON_PORT:
buf = next_entry(fp, sizeof(u32)*3); rc = next_entry(buf, fp, sizeof(u32)*3);
if (!buf) if (rc < 0)
goto bad; goto bad;
c->u.port.protocol = le32_to_cpu(buf[0]); c->u.port.protocol = le32_to_cpu(buf[0]);
c->u.port.low_port = le32_to_cpu(buf[1]); c->u.port.low_port = le32_to_cpu(buf[1]);
...@@ -1395,8 +1348,8 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1395,8 +1348,8 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
break; break;
case OCON_NODE: case OCON_NODE:
buf = next_entry(fp, sizeof(u32)* 2); rc = next_entry(buf, fp, sizeof(u32)* 2);
if (!buf) if (rc < 0)
goto bad; goto bad;
c->u.node.addr = le32_to_cpu(buf[0]); c->u.node.addr = le32_to_cpu(buf[0]);
c->u.node.mask = le32_to_cpu(buf[1]); c->u.node.mask = le32_to_cpu(buf[1]);
...@@ -1405,22 +1358,21 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1405,22 +1358,21 @@ int policydb_read(struct policydb *p, void *fp)
goto bad; goto bad;
break; break;
case OCON_FSUSE: case OCON_FSUSE:
buf = next_entry(fp, sizeof(u32)*2); rc = next_entry(buf, fp, sizeof(u32)*2);
if (!buf) if (rc < 0)
goto bad; goto bad;
c->v.behavior = le32_to_cpu(buf[0]); c->v.behavior = le32_to_cpu(buf[0]);
if (c->v.behavior > SECURITY_FS_USE_NONE) if (c->v.behavior > SECURITY_FS_USE_NONE)
goto bad; goto bad;
len = le32_to_cpu(buf[1]); len = le32_to_cpu(buf[1]);
buf = next_entry(fp, len);
if (!buf)
goto bad;
c->u.name = kmalloc(len + 1,GFP_KERNEL); c->u.name = kmalloc(len + 1,GFP_KERNEL);
if (!c->u.name) { if (!c->u.name) {
rc = -ENOMEM; rc = -ENOMEM;
goto bad; goto bad;
} }
memcpy(c->u.name, buf, len); rc = next_entry(c->u.name, fp, len);
if (rc < 0)
goto bad;
c->u.name[len] = 0; c->u.name[len] = 0;
rc = context_read_and_validate(&c->context[0], p, fp); rc = context_read_and_validate(&c->context[0], p, fp);
if (rc) if (rc)
...@@ -1429,8 +1381,8 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1429,8 +1381,8 @@ int policydb_read(struct policydb *p, void *fp)
case OCON_NODE6: { case OCON_NODE6: {
int k; int k;
buf = next_entry(fp, sizeof(u32) * 8); rc = next_entry(buf, fp, sizeof(u32) * 8);
if (!buf) if (rc < 0)
goto bad; goto bad;
for (k = 0; k < 4; k++) for (k = 0; k < 4; k++)
c->u.node6.addr[k] = le32_to_cpu(buf[k]); c->u.node6.addr[k] = le32_to_cpu(buf[k]);
...@@ -1444,22 +1396,17 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1444,22 +1396,17 @@ int policydb_read(struct policydb *p, void *fp)
} }
} }
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) { if (rc < 0)
rc = -EINVAL;
goto bad; goto bad;
}
nel = le32_to_cpu(buf[0]); nel = le32_to_cpu(buf[0]);
genfs_p = NULL; genfs_p = NULL;
rc = -EINVAL; rc = -EINVAL;
for (i = 0; i < nel; i++) { for (i = 0; i < nel; i++) {
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
goto bad; goto bad;
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
buf = next_entry(fp, len);
if (!buf)
goto bad;
newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL); newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL);
if (!newgenfs) { if (!newgenfs) {
rc = -ENOMEM; rc = -ENOMEM;
...@@ -1473,7 +1420,12 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1473,7 +1420,12 @@ int policydb_read(struct policydb *p, void *fp)
kfree(newgenfs); kfree(newgenfs);
goto bad; goto bad;
} }
memcpy(newgenfs->fstype, buf, len); rc = next_entry(newgenfs->fstype, fp, len);
if (rc < 0) {
kfree(newgenfs->fstype);
kfree(newgenfs);
goto bad;
}
newgenfs->fstype[len] = 0; newgenfs->fstype[len] = 0;
for (genfs_p = NULL, genfs = p->genfs; genfs; for (genfs_p = NULL, genfs = p->genfs; genfs;
genfs_p = genfs, genfs = genfs->next) { genfs_p = genfs, genfs = genfs->next) {
...@@ -1492,18 +1444,15 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1492,18 +1444,15 @@ int policydb_read(struct policydb *p, void *fp)
genfs_p->next = newgenfs; genfs_p->next = newgenfs;
else else
p->genfs = newgenfs; p->genfs = newgenfs;
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
goto bad; goto bad;
nel2 = le32_to_cpu(buf[0]); nel2 = le32_to_cpu(buf[0]);
for (j = 0; j < nel2; j++) { for (j = 0; j < nel2; j++) {
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
goto bad; goto bad;
len = le32_to_cpu(buf[0]); len = le32_to_cpu(buf[0]);
buf = next_entry(fp, len);
if (!buf)
goto bad;
newc = kmalloc(sizeof(*newc), GFP_KERNEL); newc = kmalloc(sizeof(*newc), GFP_KERNEL);
if (!newc) { if (!newc) {
...@@ -1517,10 +1466,12 @@ int policydb_read(struct policydb *p, void *fp) ...@@ -1517,10 +1466,12 @@ int policydb_read(struct policydb *p, void *fp)
rc = -ENOMEM; rc = -ENOMEM;
goto bad_newc; goto bad_newc;
} }
memcpy(newc->u.name, buf, len); rc = next_entry(newc->u.name, fp, len);
if (rc < 0)
goto bad_newc;
newc->u.name[len] = 0; newc->u.name[len] = 0;
buf = next_entry(fp, sizeof(u32)); rc = next_entry(buf, fp, sizeof(u32));
if (!buf) if (rc < 0)
goto bad_newc; goto bad_newc;
newc->v.sclass = le32_to_cpu(buf[0]); newc->v.sclass = le32_to_cpu(buf[0]);
if (context_read_and_validate(&newc->context[0], p, fp)) if (context_read_and_validate(&newc->context[0], p, fp))
......
...@@ -271,17 +271,15 @@ struct policy_file { ...@@ -271,17 +271,15 @@ struct policy_file {
size_t len; size_t len;
}; };
static inline void *next_entry(struct policy_file *fp, size_t bytes) static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes)
{ {
void *buf;
if (bytes > fp->len) if (bytes > fp->len)
return NULL; return -EINVAL;
buf = fp->data; memcpy(buf, fp->data, bytes);
fp->data += bytes; fp->data += bytes;
fp->len -= bytes; fp->len -= bytes;
return buf; return 0;
} }
#endif /* _SS_POLICYDB_H_ */ #endif /* _SS_POLICYDB_H_ */
......
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