Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1fd2a25b authored by Paul Moore's avatar Paul Moore Committed by David S. Miller
Browse files

NetLabel: perform input validation earlier on CIPSOv4 DOI add ops



There are a couple of cases where the user input for a CIPSOv4 DOI add
operation was not being done soon enough; the result was unexpected behavior
which was resulting in oops/panics/lockups on some platforms.  This patch moves
the existing input validation code earlier in the code path to protect against
bogus user input.

Signed-off-by: default avatarPaul Moore <paul.moore@hp.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
parent c2fda5fe
Loading
Loading
Loading
Loading
+17 −11
Original line number Original line Diff line number Diff line
@@ -185,20 +185,31 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
	ret_val = netlbl_cipsov4_add_common(info, doi_def);
	ret_val = netlbl_cipsov4_add_common(info, doi_def);
	if (ret_val != 0)
	if (ret_val != 0)
		goto add_std_failure;
		goto add_std_failure;
	ret_val = -EINVAL;


	nla_for_each_nested(nla_a,
	nla_for_each_nested(nla_a,
			    info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
			    info->attrs[NLBL_CIPSOV4_A_MLSLVLLST],
			    nla_a_rem)
			    nla_a_rem)
		if (nla_a->nla_type == NLBL_CIPSOV4_A_MLSLVL) {
		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)
			nla_for_each_nested(nla_b, nla_a, nla_b_rem)
				switch (nla_b->nla_type) {
				switch (nla_b->nla_type) {
				case NLBL_CIPSOV4_A_MLSLVLLOC:
				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) >=
					if (nla_get_u32(nla_b) >=
					    doi_def->map.std->lvl.local_size)
					    doi_def->map.std->lvl.local_size)
					     doi_def->map.std->lvl.local_size =
					     doi_def->map.std->lvl.local_size =
						     nla_get_u32(nla_b) + 1;
						     nla_get_u32(nla_b) + 1;
					break;
					break;
				case NLBL_CIPSOV4_A_MLSLVLREM:
				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) >=
					if (nla_get_u32(nla_b) >=
					    doi_def->map.std->lvl.cipso_size)
					    doi_def->map.std->lvl.cipso_size)
					     doi_def->map.std->lvl.cipso_size =
					     doi_def->map.std->lvl.cipso_size =
@@ -206,9 +217,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
					break;
					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,
	doi_def->map.std->lvl.local = kcalloc(doi_def->map.std->lvl.local_size,
					      sizeof(u32),
					      sizeof(u32),
					      GFP_KERNEL);
					      GFP_KERNEL);
@@ -230,11 +238,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
			struct nlattr *lvl_loc;
			struct nlattr *lvl_loc;
			struct nlattr *lvl_rem;
			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,
			lvl_loc = nla_find_nested(nla_a,
						  NLBL_CIPSOV4_A_MLSLVLLOC);
						  NLBL_CIPSOV4_A_MLSLVLLOC);
			lvl_rem = nla_find_nested(nla_a,
			lvl_rem = nla_find_nested(nla_a,
@@ -264,12 +267,18 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
				nla_for_each_nested(nla_b, nla_a, nla_b_rem)
				nla_for_each_nested(nla_b, nla_a, nla_b_rem)
					switch (nla_b->nla_type) {
					switch (nla_b->nla_type) {
					case NLBL_CIPSOV4_A_MLSCATLOC:
					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) >=
						if (nla_get_u32(nla_b) >=
					      doi_def->map.std->cat.local_size)
					      doi_def->map.std->cat.local_size)
					     doi_def->map.std->cat.local_size =
					     doi_def->map.std->cat.local_size =
						     nla_get_u32(nla_b) + 1;
						     nla_get_u32(nla_b) + 1;
						break;
						break;
					case NLBL_CIPSOV4_A_MLSCATREM:
					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) >=
						if (nla_get_u32(nla_b) >=
					      doi_def->map.std->cat.cipso_size)
					      doi_def->map.std->cat.cipso_size)
					     doi_def->map.std->cat.cipso_size =
					     doi_def->map.std->cat.cipso_size =
@@ -277,9 +286,6 @@ static int netlbl_cipsov4_add_std(struct genl_info *info)
						break;
						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 = kcalloc(
			                      doi_def->map.std->cat.local_size,
			                      doi_def->map.std->cat.local_size,
					      sizeof(u32),
					      sizeof(u32),