From: Stephen Smalley <sds@epoch.ncsc.mil>

This patch fixes a couple of bugs in the SELinux policy loading code.  The
first bug was reported by Magosanyi Arpad; kernel panic upon feeding the
kernel a policy with an empty avtab due to cleanup code trying to free the
avtab twice.  The other bugs were reported by Frank Mayer; failure to
properly validate certain values read from the policy.



---

 25-akpm/security/selinux/ss/avtab.c    |    3 ++-
 25-akpm/security/selinux/ss/policydb.c |   27 +++++++++++++++++++++------
 2 files changed, 23 insertions(+), 7 deletions(-)

diff -puN security/selinux/ss/avtab.c~selinux-policy-loading-fixes security/selinux/ss/avtab.c
--- 25/security/selinux/ss/avtab.c~selinux-policy-loading-fixes	Wed Feb 11 14:22:22 2004
+++ 25-akpm/security/selinux/ss/avtab.c	Wed Feb 11 14:22:22 2004
@@ -98,7 +98,7 @@ void avtab_destroy(struct avtab *h)
 	int i;
 	struct avtab_node *cur, *temp;
 
-	if (!h)
+	if (!h || !h->htable)
 		return;
 
 	for (i = 0; i < AVTAB_SIZE; i++) {
@@ -111,6 +111,7 @@ void avtab_destroy(struct avtab *h)
 		h->htable[i] = NULL;
 	}
 	vfree(h->htable);
+	h->htable = NULL;
 }
 
 
diff -puN security/selinux/ss/policydb.c~selinux-policy-loading-fixes security/selinux/ss/policydb.c
--- 25/security/selinux/ss/policydb.c~selinux-policy-loading-fixes	Wed Feb 11 14:22:22 2004
+++ 25-akpm/security/selinux/ss/policydb.c	Wed Feb 11 14:22:22 2004
@@ -124,6 +124,8 @@ static int common_index(void *key, void 
 
 	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;
 	return 0;
 }
@@ -135,6 +137,8 @@ static int class_index(void *key, void *
 
 	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;
 	p->class_val_to_struct[cladatum->value - 1] = cladatum;
 	return 0;
@@ -147,6 +151,8 @@ static int role_index(void *key, void *d
 
 	role = datum;
 	p = datap;
+	if (!role->value || role->value > p->p_roles.nprim)
+		return -EINVAL;
 	p->p_role_val_to_name[role->value - 1] = key;
 	p->role_val_to_struct[role->value - 1] = role;
 	return 0;
@@ -160,8 +166,11 @@ static int type_index(void *key, void *d
 	typdatum = datum;
 	p = datap;
 
-	if (typdatum->primary)
+	if (typdatum->primary) {
+		if (!typdatum->value || typdatum->value > p->p_types.nprim)
+			return -EINVAL;
 		p->p_type_val_to_name[typdatum->value - 1] = key;
+	}
 
 	return 0;
 }
@@ -173,6 +182,8 @@ static int user_index(void *key, void *d
 
 	usrdatum = datum;
 	p = datap;
+	if (!usrdatum->value || usrdatum->value > p->p_users.nprim)
+		return -EINVAL;
 	p->p_user_val_to_name[usrdatum->value - 1] = key;
 	p->user_val_to_struct[usrdatum->value - 1] = usrdatum;
 	return 0;
@@ -502,13 +513,19 @@ int policydb_context_isvalid(struct poli
 	struct role_datum *role;
 	struct user_datum *usrdatum;
 
-	/*
-	 * Role must be authorized for the type.
-	 */
 	if (!c->role || c->role > p->p_roles.nprim)
 		return 0;
 
+	if (!c->user || c->user > p->p_users.nprim)
+		return 0;
+
+	if (!c->type || c->type > p->p_types.nprim)
+		return 0;
+
 	if (c->role != OBJECT_R_VAL) {
+		/*
+		 * Role must be authorized for the type.
+		 */
 		role = p->role_val_to_struct[c->role - 1];
 		if (!ebitmap_get_bit(&role->types,
 				     c->type - 1))
@@ -518,8 +535,6 @@ int policydb_context_isvalid(struct poli
 		/*
 		 * User must be authorized for the role.
 		 */
-		if (!c->user || c->user > p->p_users.nprim)
-			return 0;
 		usrdatum = p->user_val_to_struct[c->user - 1];
 		if (!usrdatum)
 			return 0;

_