diff options
author | Andrew Morton <akpm@osdl.org> | 2003-09-23 09:44:55 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-23 09:44:55 -0700 |
commit | 07c9e4a45de71087bada97e746e0b7be07609181 (patch) | |
tree | 94611c81b6606fd79283f5c6fd73d10d5bd8d659 /security | |
parent | b5ec6deaf4c9db989c3fc163485f5a2194215b63 (diff) | |
download | history-07c9e4a45de71087bada97e746e0b7be07609181.tar.gz |
[PATCH] SELinux leak fixes
From: Stephen Smalley <sds@epoch.ncsc.mil>
I believe that the patch below fixes the legitimate leaks in the SELinux
code. In some cases, it rearranges the code (moving the allocation later
to reduce the need for further cleanup or linking the object into a
containing structure earlier so that the policydb_destroy will handle it
upon any subsequent errors).
Diffstat (limited to 'security')
-rw-r--r-- | security/selinux/ss/mls.c | 13 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 112 |
2 files changed, 68 insertions, 57 deletions
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index ecaae65d95c45e..26fa6691b07623 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -548,8 +548,10 @@ int mls_read_user(struct user_datum *usrdatum, void *fp) memset(r, 0, sizeof(*r)); rc = mls_read_range_helper(&r->range, fp); - if (rc) + if (rc) { + kfree(r); goto out; + } if (l) l->next = r; @@ -581,10 +583,17 @@ int mls_read_trusted(struct policydb *p, void *fp) goto out; rc = ebitmap_read(&p->trustedwriters, fp); if (rc) - goto out; + goto bad; rc = ebitmap_read(&p->trustedobjects, fp); + if (rc) + goto bad2; out: return rc; +bad2: + ebitmap_destroy(&p->trustedwriters); +bad: + ebitmap_destroy(&p->trustedreaders); + goto out; } int sens_index(void *key, void *datum, void *datap) diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index f4a38f435a16ea..9bbd7b50655d2f 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c @@ -390,6 +390,16 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = mls_destroy_f }; +void ocontext_destroy(struct ocontext *c, int i) +{ + context_destroy(&c->context[0]); + context_destroy(&c->context[1]); + if (i == OCON_ISID || i == OCON_FS || + i == OCON_NETIF || i == OCON_FSUSE) + kfree(c->u.name); + kfree(c); +} + /* * Free any memory allocated by a policy database structure. */ @@ -423,12 +433,7 @@ void policydb_destroy(struct policydb *p) while (c) { ctmp = c; c = c->next; - context_destroy(&ctmp->context[0]); - context_destroy(&ctmp->context[1]); - if (i == OCON_ISID || i == OCON_FS || - i == OCON_NETIF || i == OCON_FSUSE) - kfree(ctmp->u.name); - kfree(ctmp); + ocontext_destroy(ctmp,i); } } @@ -439,9 +444,7 @@ void policydb_destroy(struct policydb *p) while (c) { ctmp = c; c = c->next; - context_destroy(&ctmp->context[0]); - kfree(ctmp->u.name); - kfree(ctmp); + ocontext_destroy(ctmp,OCON_FSUSE); } gtmp = g; g = g->next; @@ -762,6 +765,13 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) goto bad; } memset(c, 0, sizeof(*c)); + + if (lc) { + lc->next = c; + } else { + cladatum->constraints = c; + } + buf = next_entry(fp, sizeof(u32)*2); if (!buf) goto bad; @@ -776,67 +786,50 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp) goto bad; } memset(e, 0, sizeof(*e)); + + if (le) { + le->next = e; + } else { + c->expr = e; + } + buf = next_entry(fp, sizeof(u32)*3); - if (!buf) { - kfree(e); + if (!buf) goto bad; - } e->expr_type = le32_to_cpu(buf[0]); e->attr = le32_to_cpu(buf[1]); e->op = le32_to_cpu(buf[2]); switch (e->expr_type) { case CEXPR_NOT: - if (depth < 0) { - kfree(e); + if (depth < 0) goto bad; - } break; case CEXPR_AND: case CEXPR_OR: - if (depth < 1) { - kfree(e); + if (depth < 1) goto bad; - } depth--; break; case CEXPR_ATTR: - if (depth == (CEXPR_MAXDEPTH-1)) { - kfree(e); + if (depth == (CEXPR_MAXDEPTH-1)) goto bad; - } depth++; break; case CEXPR_NAMES: - if (depth == (CEXPR_MAXDEPTH-1)) { - kfree(e); + if (depth == (CEXPR_MAXDEPTH-1)) goto bad; - } depth++; - if (ebitmap_read(&e->names, fp)) { - kfree(e); + if (ebitmap_read(&e->names, fp)) goto bad; - } break; default: - kfree(e); goto bad; - break; - } - if (le) { - le->next = e; - } else { - c->expr = e; } le = e; } if (depth != 0) goto bad; - if (lc) { - lc->next = c; - } else { - cladatum->constraints = c; - } lc = c; } @@ -1331,12 +1324,6 @@ int policydb_read(struct policydb *p, void *fp) genfs_p = NULL; rc = -EINVAL; for (i = 0; i < nel; i++) { - newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL); - if (!newgenfs) { - rc = -ENOMEM; - goto bad; - } - memset(newgenfs, 0, sizeof(*newgenfs)); buf = next_entry(fp, sizeof(u32)); if (!buf) goto bad; @@ -1344,9 +1331,17 @@ int policydb_read(struct policydb *p, void *fp) buf = next_entry(fp, len); if (!buf) goto bad; + newgenfs = kmalloc(sizeof(*newgenfs), GFP_KERNEL); + if (!newgenfs) { + rc = -ENOMEM; + goto bad; + } + memset(newgenfs, 0, sizeof(*newgenfs)); + newgenfs->fstype = kmalloc(len + 1,GFP_KERNEL); if (!newgenfs->fstype) { rc = -ENOMEM; + kfree(newgenfs); goto bad; } memcpy(newgenfs->fstype, buf, len); @@ -1356,6 +1351,8 @@ int policydb_read(struct policydb *p, void *fp) if (strcmp(newgenfs->fstype, genfs->fstype) == 0) { printk(KERN_ERR "security: dup genfs " "fstype %s\n", newgenfs->fstype); + kfree(newgenfs->fstype); + kfree(newgenfs); goto bad; } if (strcmp(newgenfs->fstype, genfs->fstype) < 0) @@ -1371,12 +1368,6 @@ int policydb_read(struct policydb *p, void *fp) goto bad; nel2 = le32_to_cpu(buf[0]); for (j = 0; j < nel2; j++) { - newc = kmalloc(sizeof(*newc), GFP_KERNEL); - if (!newc) { - rc = -ENOMEM; - goto bad; - } - memset(newc, 0, sizeof(*newc)); buf = next_entry(fp, sizeof(u32)); if (!buf) goto bad; @@ -1384,19 +1375,27 @@ int policydb_read(struct policydb *p, void *fp) buf = next_entry(fp, len); if (!buf) goto bad; + + newc = kmalloc(sizeof(*newc), GFP_KERNEL); + if (!newc) { + rc = -ENOMEM; + goto bad; + } + memset(newc, 0, sizeof(*newc)); + newc->u.name = kmalloc(len + 1,GFP_KERNEL); if (!newc->u.name) { rc = -ENOMEM; - goto bad; + goto bad_newc; } memcpy(newc->u.name, buf, len); newc->u.name[len] = 0; buf = next_entry(fp, sizeof(u32)); if (!buf) - goto bad; + goto bad_newc; newc->v.sclass = le32_to_cpu(buf[0]); if (context_read_and_validate(&newc->context[0], p, fp)) - goto bad; + goto bad_newc; for (l = NULL, c = newgenfs->head; c; l = c, c = c->next) { if (!strcmp(newc->u.name, c->u.name) && @@ -1405,13 +1404,14 @@ int policydb_read(struct policydb *p, void *fp) printk(KERN_ERR "security: dup genfs " "entry (%s,%s)\n", newgenfs->fstype, c->u.name); - goto bad; + goto bad_newc; } len = strlen(newc->u.name); len2 = strlen(c->u.name); if (len > len2) break; } + newc->next = c; if (l) l->next = newc; @@ -1425,6 +1425,8 @@ int policydb_read(struct policydb *p, void *fp) goto bad; out: return rc; +bad_newc: + ocontext_destroy(newc,OCON_FSUSE); bad: policydb_destroy(p); goto out; |