Blame SOURCES/0067-src-fix-jumps-on-bigendian-arches.patch

bacbc8
From dddf806059088efd00b90e79456c66774b1976f1 Mon Sep 17 00:00:00 2001
bacbc8
From: Florian Westphal <fw@strlen.de>
bacbc8
Date: Tue, 13 Aug 2019 22:12:44 +0200
bacbc8
Subject: [PATCH] src: fix jumps on bigendian arches
bacbc8
bacbc8
table bla {
bacbc8
  chain foo { }
bacbc8
  chain bar { jump foo }
bacbc8
 }
bacbc8
}
bacbc8
bacbc8
Fails to restore on big-endian platforms:
bacbc8
jump.nft:5:2-9: Error: Could not process rule: No such file or directory
bacbc8
 jump foo
bacbc8
bacbc8
nft passes a 0-length name to the kernel.
bacbc8
bacbc8
This is because when we export the value (the string), we provide
bacbc8
the size of the destination buffer.
bacbc8
bacbc8
In earlier versions, the parser allocated the name with the same
bacbc8
fixed size and all was fine.
bacbc8
bacbc8
After the fix, the export places the name in the wrong location
bacbc8
in the destination buffer.
bacbc8
bacbc8
This makes tests/shell/testcases/chains/0001jumps_0 work on s390x.
bacbc8
bacbc8
v2: convert one error check to a BUG(), it should not happen unless
bacbc8
    kernel abi is broken.
bacbc8
bacbc8
Fixes: 142350f154c78 ("src: invalid read when importing chain name")
bacbc8
Signed-off-by: Florian Westphal <fw@strlen.de>
bacbc8
Acked-by: Pablo Neira Ayuso <pablo@netfilter.org>
bacbc8
(cherry picked from commit fb6d826afb1fa346bdf61c43cd6f7551caee27ba)
bacbc8
bacbc8
Conflicts:
bacbc8
	src/datatype.c
bacbc8
-> Context change due to missing commit 72931553828af
bacbc8
   ("src: expr: add expression etype")
bacbc8
bacbc8
Signed-off-by: Phil Sutter <psutter@redhat.com>
bacbc8
---
bacbc8
 src/datatype.c | 27 ++++++++++++++++++---------
bacbc8
 src/netlink.c  | 16 +++++++++++++---
bacbc8
 2 files changed, 31 insertions(+), 12 deletions(-)
bacbc8
bacbc8
diff --git a/src/datatype.c b/src/datatype.c
bacbc8
index 5791a6a41599e..7bea6062de9c4 100644
bacbc8
--- a/src/datatype.c
bacbc8
+++ b/src/datatype.c
bacbc8
@@ -251,10 +251,25 @@ const struct datatype invalid_type = {
bacbc8
 	.print		= invalid_type_print,
bacbc8
 };
bacbc8
 
bacbc8
-static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
bacbc8
+static void verdict_jump_chain_print(const char *what, const struct expr *e,
bacbc8
+				     struct output_ctx *octx)
bacbc8
 {
bacbc8
 	char chain[NFT_CHAIN_MAXNAMELEN];
bacbc8
+	unsigned int len;
bacbc8
+
bacbc8
+	memset(chain, 0, sizeof(chain));
bacbc8
+
bacbc8
+	len = e->len / BITS_PER_BYTE;
bacbc8
+	if (len >= sizeof(chain))
bacbc8
+		BUG("verdict expression length %u is too large (%lu bits max)",
bacbc8
+		    e->len, (unsigned long)sizeof(chain) * BITS_PER_BYTE);
bacbc8
 
bacbc8
+	mpz_export_data(chain, e->value, BYTEORDER_HOST_ENDIAN, len);
bacbc8
+	nft_print(octx, "%s %s", what, chain);
bacbc8
+}
bacbc8
+
bacbc8
+static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
bacbc8
+{
bacbc8
 	switch (expr->verdict) {
bacbc8
 	case NFT_CONTINUE:
bacbc8
 		nft_print(octx, "continue");
bacbc8
@@ -264,10 +279,7 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
bacbc8
 		break;
bacbc8
 	case NFT_JUMP:
bacbc8
 		if (expr->chain->ops->type == EXPR_VALUE) {
bacbc8
-			mpz_export_data(chain, expr->chain->value,
bacbc8
-					BYTEORDER_HOST_ENDIAN,
bacbc8
-					NFT_CHAIN_MAXNAMELEN);
bacbc8
-			nft_print(octx, "jump %s", chain);
bacbc8
+			verdict_jump_chain_print("jump", expr->chain, octx);
bacbc8
 		} else {
bacbc8
 			nft_print(octx, "jump ");
bacbc8
 			expr_print(expr->chain, octx);
bacbc8
@@ -275,10 +287,7 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
bacbc8
 		break;
bacbc8
 	case NFT_GOTO:
bacbc8
 		if (expr->chain->ops->type == EXPR_VALUE) {
bacbc8
-			mpz_export_data(chain, expr->chain->value,
bacbc8
-					BYTEORDER_HOST_ENDIAN,
bacbc8
-					NFT_CHAIN_MAXNAMELEN);
bacbc8
-			nft_print(octx, "goto %s", chain);
bacbc8
+			verdict_jump_chain_print("goto", expr->chain, octx);
bacbc8
 		} else {
bacbc8
 			nft_print(octx, "goto ");
bacbc8
 			expr_print(expr->chain, octx);
bacbc8
diff --git a/src/netlink.c b/src/netlink.c
bacbc8
index fc310fd293d64..4ad527a02e871 100644
bacbc8
--- a/src/netlink.c
bacbc8
+++ b/src/netlink.c
bacbc8
@@ -392,17 +392,27 @@ static void netlink_gen_verdict(const struct expr *expr,
bacbc8
 				struct nft_data_linearize *data)
bacbc8
 {
bacbc8
 	char chain[NFT_CHAIN_MAXNAMELEN];
bacbc8
+	unsigned int len;
bacbc8
 
bacbc8
 	data->verdict = expr->verdict;
bacbc8
 
bacbc8
 	switch (expr->verdict) {
bacbc8
 	case NFT_JUMP:
bacbc8
 	case NFT_GOTO:
bacbc8
+		len = expr->chain->len / BITS_PER_BYTE;
bacbc8
+
bacbc8
+		if (!len)
bacbc8
+			BUG("chain length is 0");
bacbc8
+
bacbc8
+		if (len > sizeof(chain))
bacbc8
+			BUG("chain is too large (%u, %u max)",
bacbc8
+			    len, (unsigned int)sizeof(chain));
bacbc8
+
bacbc8
+		memset(chain, 0, sizeof(chain));
bacbc8
+
bacbc8
 		mpz_export_data(chain, expr->chain->value,
bacbc8
-				BYTEORDER_HOST_ENDIAN,
bacbc8
-				NFT_CHAIN_MAXNAMELEN);
bacbc8
+				BYTEORDER_HOST_ENDIAN, len);
bacbc8
 		snprintf(data->chain, NFT_CHAIN_MAXNAMELEN, "%s", chain);
bacbc8
-		data->chain[NFT_CHAIN_MAXNAMELEN-1] = '\0';
bacbc8
 		break;
bacbc8
 	}
bacbc8
 }
bacbc8
-- 
bacbc8
2.22.0
bacbc8