Blame SOURCES/0023-parser_json-Fix-for-ineffective-family-value-checks.patch

34625f
From c40b8c22beef6011d79c60742bc4043d681198c1 Mon Sep 17 00:00:00 2001
34625f
From: Phil Sutter <phil@nwl.cc>
34625f
Date: Fri, 12 Oct 2018 17:23:24 +0200
34625f
Subject: [PATCH] parser_json: Fix for ineffective family value checks
34625f
34625f
Since handle->family is unsigned, checking for value < 0 never yields
34625f
true. Overcome this by changing parse_family() to return an error code
34625f
and write the parsed family value into a pointer passed as parameter.
34625f
34625f
The above change required a bit more cleanup to avoid passing pointers
34625f
to signed variables to the function. Also leverage json_parse_family() a
34625f
bit more to reduce code side.
34625f
34625f
Signed-off-by: Phil Sutter <phil@nwl.cc>
34625f
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
34625f
(cherry picked from commit c7a5401943df8b6b96f6b5eedd9a1e0013e01d86)
34625f
34625f
Conflicts:
34625f
	src/parser_json.c
34625f
-> Missing ct timeout support
34625f
-> missing tproxy support in JSON
34625f
-> Missing ipsec expression
34625f
34625f
Signed-off-by: Phil Sutter <psutter@redhat.com>
34625f
---
34625f
 src/parser_json.c | 130 ++++++++++++++++++++++------------------------
34625f
 1 file changed, 62 insertions(+), 68 deletions(-)
34625f
34625f
diff --git a/src/parser_json.c b/src/parser_json.c
34625f
index af57b3025a104..30de17f8a1e26 100644
34625f
--- a/src/parser_json.c
34625f
+++ b/src/parser_json.c
34625f
@@ -173,7 +173,7 @@ static int json_unpack_stmt(struct json_ctx *ctx, json_t *root,
34625f
 	return 1;
34625f
 }
34625f
 
34625f
-static int parse_family(const char *name)
34625f
+static int parse_family(const char *name, uint32_t *family)
34625f
 {
34625f
 	unsigned int i;
34625f
 	struct {
34625f
@@ -188,13 +188,37 @@ static int parse_family(const char *name)
34625f
 		{ "netdev", NFPROTO_NETDEV }
34625f
 	};
34625f
 
34625f
+	assert(family);
34625f
+
34625f
 	for (i = 0; i < array_size(family_tbl); i++) {
34625f
-		if (!strcmp(name, family_tbl[i].name))
34625f
-			return family_tbl[i].val;
34625f
+		if (strcmp(name, family_tbl[i].name))
34625f
+			continue;
34625f
+
34625f
+		*family = family_tbl[i].val;
34625f
+		return 0;
34625f
 	}
34625f
 	return -1;
34625f
 }
34625f
 
34625f
+static int json_parse_family(struct json_ctx *ctx, json_t *root)
34625f
+{
34625f
+	const char *family;
34625f
+
34625f
+	if (!json_unpack(root, "{s:s}", "family", &family)) {
34625f
+		uint32_t familyval;
34625f
+
34625f
+		if (parse_family(family, &familyval) ||
34625f
+		    (familyval != NFPROTO_IPV6 &&
34625f
+		     familyval != NFPROTO_IPV4)) {
34625f
+			json_error(ctx, "Invalid family '%s'.", family);
34625f
+			return -1;
34625f
+		}
34625f
+		return familyval;
34625f
+	}
34625f
+
34625f
+	return NFPROTO_UNSPEC;
34625f
+}
34625f
+
34625f
 static bool is_keyword(const char *keyword)
34625f
 {
34625f
 	const char *keywords[] = {
34625f
@@ -594,19 +618,15 @@ static struct expr *json_parse_rt_expr(struct json_ctx *ctx,
34625f
 		{ "nexthop", NFT_RT_NEXTHOP4 },
34625f
 		{ "mtu", NFT_RT_TCPMSS },
34625f
 	};
34625f
-	unsigned int i, familyval = NFPROTO_UNSPEC;
34625f
-	const char *key, *family = NULL;
34625f
+	const char *key;
34625f
+	unsigned int i;
34625f
+	int familyval;
34625f
 
34625f
 	if (json_unpack_err(ctx, root, "{s:s}", "key", &key))
34625f
 		return NULL;
34625f
-	if (!json_unpack(root, "{s:s}", "family", &family)) {
34625f
-		familyval = parse_family(family);
34625f
-		if (familyval != NFPROTO_IPV4 &&
34625f
-		    familyval != NFPROTO_IPV6) {
34625f
-			json_error(ctx, "Invalid RT family '%s'.", family);
34625f
-			return NULL;
34625f
-		}
34625f
-	}
34625f
+	familyval = json_parse_family(ctx, root);
34625f
+	if (familyval < 0)
34625f
+		return NULL;
34625f
 
34625f
 	for (i = 0; i < array_size(rt_key_tbl); i++) {
34625f
 		int val = rt_key_tbl[i].val;
34625f
@@ -653,9 +673,9 @@ static bool ct_key_is_dir(enum nft_ct_keys key)
34625f
 static struct expr *json_parse_ct_expr(struct json_ctx *ctx,
34625f
 				       const char *type, json_t *root)
34625f
 {
34625f
-	const char *key, *dir, *family;
34625f
+	const char *key, *dir;
34625f
 	unsigned int i;
34625f
-	int dirval = -1, familyval = NFPROTO_UNSPEC, keyval = -1;
34625f
+	int dirval = -1, familyval, keyval = -1;
34625f
 
34625f
 	if (json_unpack_err(ctx, root, "{s:s}", "key", &key))
34625f
 		return NULL;
34625f
@@ -672,14 +692,9 @@ static struct expr *json_parse_ct_expr(struct json_ctx *ctx,
34625f
 		return NULL;
34625f
 	}
34625f
 
34625f
-	if (!json_unpack(root, "{s:s}", "family", &family)) {
34625f
-		familyval = parse_family(family);
34625f
-		if (familyval != NFPROTO_IPV4 &&
34625f
-		    familyval != NFPROTO_IPV6) {
34625f
-			json_error(ctx, "Invalid CT family '%s'.", family);
34625f
-			return NULL;
34625f
-		}
34625f
-	}
34625f
+	familyval = json_parse_family(ctx, root);
34625f
+	if (familyval < 0)
34625f
+		return NULL;
34625f
 
34625f
 	if (!json_unpack(root, "{s:s}", "dir", &dir)) {
34625f
 		if (!strcmp(dir, "original")) {
34625f
@@ -1562,7 +1577,6 @@ static struct stmt *json_parse_fwd_stmt(struct json_ctx *ctx,
34625f
 					const char *key, json_t *value)
34625f
 {
34625f
 	json_t *jaddr, *jdev;
34625f
-	const char *family;
34625f
 	struct stmt *stmt;
34625f
 	int familyval;
34625f
 
34625f
@@ -1577,21 +1591,15 @@ static struct stmt *json_parse_fwd_stmt(struct json_ctx *ctx,
34625f
 		goto out_err;
34625f
 	}
34625f
 
34625f
-	if (json_unpack(value, "{s:s, s:o}",
34625f
-			"family", &family, "addr", &jaddr))
34625f
-		return stmt;
34625f
-
34625f
-	familyval = parse_family(family);
34625f
-	switch (familyval) {
34625f
-	case NFPROTO_IPV4:
34625f
-	case NFPROTO_IPV6:
34625f
-		stmt->fwd.family = familyval;
34625f
-		break;
34625f
-	default:
34625f
-		json_error(ctx, "Invalid fwd family value '%s'.", family);
34625f
+	familyval = json_parse_family(ctx, value);
34625f
+	if (familyval < 0)
34625f
 		goto out_err;
34625f
-	}
34625f
 
34625f
+	if (familyval == NFPROTO_UNSPEC ||
34625f
+	    json_unpack(value, "{s:o}", "addr", &jaddr))
34625f
+		return stmt;
34625f
+
34625f
+	stmt->fwd.family = familyval;
34625f
 	stmt->fwd.addr = json_parse_stmt_expr(ctx, jaddr);
34625f
 	if (!stmt->fwd.addr) {
34625f
 		json_error(ctx, "Invalid fwd addr value.");
34625f
@@ -2137,8 +2145,7 @@ static struct cmd *json_parse_cmd_add_table(struct json_ctx *ctx, json_t *root,
34625f
 		json_error(ctx, "Either name or handle required to delete a table.");
34625f
 		return NULL;
34625f
 	}
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2178,8 +2185,7 @@ static struct cmd *json_parse_cmd_add_chain(struct json_ctx *ctx, json_t *root,
34625f
 		json_error(ctx, "Either name or handle required to delete a chain.");
34625f
 		return NULL;
34625f
 	}
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2240,8 +2246,7 @@ static struct cmd *json_parse_cmd_add_rule(struct json_ctx *ctx, json_t *root,
34625f
 		 json_unpack_err(ctx, root, "{s:I}", "handle", &h.handle.id))
34625f
 		return NULL;
34625f
 
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2347,8 +2352,7 @@ static struct cmd *json_parse_cmd_add_set(struct json_ctx *ctx, json_t *root,
34625f
 		return NULL;
34625f
 	}
34625f
 
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2459,8 +2463,7 @@ static struct cmd *json_parse_cmd_add_element(struct json_ctx *ctx,
34625f
 			    "elem", &tmp))
34625f
 		return NULL;
34625f
 
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2523,8 +2526,7 @@ static struct cmd *json_parse_cmd_add_flowtable(struct json_ctx *ctx,
34625f
 			    "name", &h.flowtable))
34625f
 		return NULL;
34625f
 
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2568,6 +2570,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
34625f
 					     enum cmd_obj cmd_obj)
34625f
 {
34625f
 	const char *family, *tmp, *rate_unit = "packets", *burst_unit = "bytes";
34625f
+	uint32_t l3proto = NFPROTO_IPV4;
34625f
 	struct handle h = { 0 };
34625f
 	struct obj *obj;
34625f
 	int inv = 0;
34625f
@@ -2588,8 +2591,7 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
34625f
 		return NULL;
34625f
 	}
34625f
 
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2647,18 +2649,13 @@ static struct cmd *json_parse_cmd_add_object(struct json_ctx *ctx,
34625f
 				return NULL;
34625f
 			}
34625f
 		}
34625f
-		if (!json_unpack(root, "{s:s}", "l3proto", &tmp)) {
34625f
-			int family = parse_family(tmp);
34625f
-
34625f
-			if (family < 0) {
34625f
-				json_error(ctx, "Invalid ct helper l3proto '%s'.", tmp);
34625f
-				obj_free(obj);
34625f
-				return NULL;
34625f
-			}
34625f
-			obj->ct_helper.l3proto = family;
34625f
-		} else {
34625f
-			obj->ct_helper.l3proto = NFPROTO_IPV4;
34625f
+		if (!json_unpack(root, "{s:s}", "l3proto", &tmp) &&
34625f
+		    parse_family(tmp, &l3proto)) {
34625f
+			json_error(ctx, "Invalid ct helper l3proto '%s'.", tmp);
34625f
+			obj_free(obj);
34625f
+			return NULL;
34625f
 		}
34625f
+		obj->ct_helper.l3proto = l3proto;
34625f
 		break;
34625f
 	case CMD_OBJ_LIMIT:
34625f
 		obj->type = NFT_OBJECT_LIMIT;
34625f
@@ -2770,8 +2767,7 @@ static struct cmd *json_parse_cmd_replace(struct json_ctx *ctx,
34625f
 		h.handle.id = 0;
34625f
 	}
34625f
 
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
@@ -2825,8 +2821,7 @@ static struct cmd *json_parse_cmd_list_multiple(struct json_ctx *ctx,
34625f
 	const char *tmp;
34625f
 
34625f
 	if (!json_unpack(root, "{s:s}", "family", &tmp)) {
34625f
-		h.family = parse_family(tmp);
34625f
-		if (h.family < 0) {
34625f
+		if (parse_family(tmp, &h.family)) {
34625f
 			json_error(ctx, "Unknown family '%s'.", tmp);
34625f
 			return NULL;
34625f
 		}
34625f
@@ -2981,8 +2976,7 @@ static struct cmd *json_parse_cmd_rename(struct json_ctx *ctx,
34625f
 			    "name", &h.chain.name,
34625f
 			    "newname", &newname))
34625f
 		return NULL;
34625f
-	h.family = parse_family(family);
34625f
-	if (h.family < 0) {
34625f
+	if (parse_family(family, &h.family)) {
34625f
 		json_error(ctx, "Unknown family '%s'.", family);
34625f
 		return NULL;
34625f
 	}
34625f
-- 
34625f
2.19.0
34625f