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