summaryrefslogtreecommitdiff
path: root/security/selinux/ss/mls.c
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2007-11-07 10:08:00 -0500
committerJames Morris <jmorris@namei.org>2007-11-08 08:56:23 +1100
commit45e5421eb5bbcd9efa037d682dd357284e3ef982 (patch)
treeceb24143024fe335d08ac30fb4da9ca25fbeb6e6 /security/selinux/ss/mls.c
parent6d2b685564ba417f4c6d80c3661f0dfee13fff85 (diff)
SELinux: add more validity checks on policy load
Add more validity checks at policy load time to reject malformed policies and prevent subsequent out-of-range indexing when in permissive mode. Resolves the NULL pointer dereference reported in https://bugzilla.redhat.com/show_bug.cgi?id=357541. Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/ss/mls.c')
-rw-r--r--security/selinux/ss/mls.c66
1 files changed, 36 insertions, 30 deletions
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 9a11deaaa9e7..fb5d70a6628d 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -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;