Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1605

kernel-2.6.18-128.1.10.el5.src.rpm

From: Eric Paris <eparis@redhat.com>
Subject: [RHEL5 PATCH] NetLabel: 219393: Invalid user input cases kernel 	oops
Date: Fri, 22 Dec 2006 12:00:32 -0500
Bugzilla: 219393
Message-Id: <1166806832.23016.61.camel@localhost.localdomain>
Changelog: NetLabel: stricter configuration checking


BZ 219393

IBM discovered in their testing that an invalid netlabel configuration
from the admin can cause a kernel oops.  This is fixed by checking
validity before using the information.

The second part to this bug is that back when the original NetLabel
patches were being changed to use Netlink attributes correctly some code
was accidentially dropped which set all of the undefined CIPSOv4 level
and category mappings to a sentinel value.  The result is the mappings
data in the kernel contains bogus mappings which always map to zero.
This patch restores the old/correct behavior by initializing the mapping
data to the correct sentinel value.  Which means that when the NetLabel
subsystem is called to resolve the security attributes of a packet it
will, in certain configurations, return security attributes/contexts
which are incorrect.

Part one of this patch I was easy able to reproduce and resolve.  Part 2
was tested by HP as part of the LSPP effort.

These patches were submitted for 2.6.20 but have not yet hit linus's
tree.  They can be found at:

http://www.mail-archive.com/netdev@vger.kernel.org/msg28367.html
http://www.mail-archive.com/netdev@vger.kernel.org/msg28365.html

-Eric

diff -Naupr linux-2.6.18.i686.pre.netlabel/net/netlabel/netlabel_cipso_v4.c linux-2.6.18.i686/net/netlabel/netlabel_cipso_v4.c
--- linux-2.6.18.i686.pre.netlabel/net/netlabel/netlabel_cipso_v4.c
+++ linux-2.6.18.i686/net/netlabel/netlabel_cipso_v4.c
@@ -162,6 +162,7 @@ static int netlbl_cipsov4_add_std(struct
 	struct nlattr *nla_b;
 	int nla_a_rem;
 	int nla_b_rem;
+	u32 iter;
 
 	if (!info->attrs[NLBL_CIPSOV4_A_TAGLST] ||
 	    !info->attrs[NLBL_CIPSOV4_A_MLSLVLLST])
@@ -185,20 +186,31 @@ static int netlbl_cipsov4_add_std(struct
 	ret_val = netlbl_cipsov4_add_common(info, doi_def);
 	if (ret_val != 0)
 		goto add_std_failure;
+	ret_val = -EINVAL;
 
 	nla_for_each_nested(nla_a,
 			    info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
 			    nla_a_rem)
 		if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
+			if (nla_validate_nested(nla_a,
+					    NLBL_CIPSOV4_A_MAX,
+					    netlbl_cipsov4_genl_policy) != 0)
+					goto add_std_failure;
 			nla_for_each_nested(nla_b, nla_a, nla_b_rem)
 				switch (nla_b->nla_type) {
 				case NLBL_CIPSOV4_A_MLSLVLLOC:
+					if (nla_get_u32(nla_b) >
+					    CIPSO_V4_MAX_LOC_LVLS)
+						goto add_std_failure;
 					if (nla_get_u32(nla_b) >=
 					    doi_def->map.std->lvl.local_size)
 					     doi_def->map.std->lvl.local_size =
 						     nla_get_u32(nla_b) + 1;
 					break;
 				case NLBL_CIPSOV4_A_MLSLVLREM:
+					if (nla_get_u32(nla_b) >
+					    CIPSO_V4_MAX_REM_LVLS)
+						goto add_std_failure;
 					if (nla_get_u32(nla_b) >=
 					    doi_def->map.std->lvl.cipso_size)
 					     doi_def->map.std->lvl.cipso_size =
@@ -206,9 +218,6 @@ static int netlbl_cipsov4_add_std(struct
 					break;
 				}
 		}
-	if (doi_def->map.std->lvl.local_size > CIPSO_V4_MAX_LOC_LVLS ||
-	    doi_def->map.std->lvl.cipso_size > CIPSO_V4_MAX_REM_LVLS)
-		goto add_std_failure;
 	doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
 					      sizeof(u32),
 					      GFP_KERNEL);
@@ -223,6 +232,10 @@ static int netlbl_cipsov4_add_std(struct
 		ret_val = -ENOMEM;
 		goto add_std_failure;
 	}
+	for (iter = 0; iter < doi_def->map.std->lvl.local_size; iter++)
+		doi_def->map.std->lvl.local[iter] = CIPSO_V4_INV_LVL;
+	for (iter = 0; iter < doi_def->map.std->lvl.cipso_size; iter++)
+		doi_def->map.std->lvl.cipso[iter] = CIPSO_V4_INV_LVL;
 	nla_for_each_nested(nla_a,
 			    info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
 			    nla_a_rem)
@@ -230,11 +243,6 @@ static int netlbl_cipsov4_add_std(struct
 			struct nlattr *lvl_loc;
 			struct nlattr *lvl_rem;
 
-			if (nla_validate_nested(nla_a,
-					      NLBL_CIPSOV4_A_MAX,
-					      netlbl_cipsov4_genl_policy) != 0)
-				goto add_std_failure;
-
 			lvl_loc = nla_find_nested(nla_a,
 						  NLBL_CIPSOV4_A_MLSLVLLOC);
 			lvl_rem = nla_find_nested(nla_a,
@@ -264,12 +272,18 @@ static int netlbl_cipsov4_add_std(struct
 				nla_for_each_nested(nla_b, nla_a, nla_b_rem)
 					switch (nla_b->nla_type) {
 					case NLBL_CIPSOV4_A_MLSCATLOC:
+						if (nla_get_u32(nla_b) >
+						    CIPSO_V4_MAX_LOC_CATS)
+							goto add_std_failure;
 						if (nla_get_u32(nla_b) >=
 					      doi_def->map.std->cat.local_size)
 					     doi_def->map.std->cat.local_size =
 						     nla_get_u32(nla_b) + 1;
 						break;
 					case NLBL_CIPSOV4_A_MLSCATREM:
+						if (nla_get_u32(nla_b) >
+						    CIPSO_V4_MAX_REM_CATS)
+							goto add_std_failure;
 						if (nla_get_u32(nla_b) >=
 					      doi_def->map.std->cat.cipso_size)
 					     doi_def->map.std->cat.cipso_size =
@@ -277,9 +291,6 @@ static int netlbl_cipsov4_add_std(struct
 						break;
 					}
 			}
-		if (doi_def->map.std->cat.local_size > CIPSO_V4_MAX_LOC_CATS ||
-		    doi_def->map.std->cat.cipso_size > CIPSO_V4_MAX_REM_CATS)
-			goto add_std_failure;
 		doi_def->map.std->cat.local = kcalloc(
 			                      doi_def->map.std->cat.local_size,
 					      sizeof(u32),
@@ -296,6 +307,10 @@ static int netlbl_cipsov4_add_std(struct
 			ret_val = -ENOMEM;
 			goto add_std_failure;
 		}
+		for (iter = 0; iter < doi_def->map.std->cat.local_size; iter++)
+			doi_def->map.std->cat.local[iter] = CIPSO_V4_INV_CAT;
+		for (iter = 0; iter < doi_def->map.std->cat.cipso_size; iter++)
+			doi_def->map.std->cat.cipso[iter] = CIPSO_V4_INV_CAT;
 		nla_for_each_nested(nla_a,
 				    info->attrs[NLBL_CIPSOV4_A_MLSCATLST],
 				    nla_a_rem)