summaryrefslogtreecommitdiffstats
path: root/src/netlink.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2022-12-08 01:35:05 +0100
committerPablo Neira Ayuso <pablo@netfilter.org>2022-12-08 03:12:32 +0100
commit508f3a27053169970211fc9a3f4ba973288f8d78 (patch)
treee738759bda063887e147313871d59fce712889da /src/netlink.c
parenta8fb933956efbcabd05cc718623bf88a94cf6304 (diff)
netlink: swap byteorder of value component in concatenation of intervals
Commit 1017d323cafa ("src: support for selectors with different byteorder with interval concatenations") was incomplete. Switch byteorder of singleton values in a set that contains concatenation of intervals. This singleton value is actually represented as a range in the kernel. After this patch, if the set represents a concatenation of intervals: - EXPR_F_INTERVAL denotes the lhs of the interval. - EXPR_F_INTERVAL_END denotes the rhs of the interval (this flag was already used in this way before this patch). If none of these flags are set on, then the set contains concatenations of singleton values (no interval flag is set on), in such case, no byteorder swap is required. Update tests/shell and tests/py to cover the use-case breakage reported by Eric. Fixes: 1017d323cafa ("src: support for selectors with different byteorder with interval concatenations") Reported-by: Eric Garver <eric@garver.life> Tested-by: Eric Garver <eric@garver.life> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src/netlink.c')
-rw-r--r--src/netlink.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/src/netlink.c b/src/netlink.c
index db5e79f2..2ede25b9 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -133,16 +133,23 @@ struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
case EXPR_SET_ELEM_CATCHALL:
break;
default:
- __netlink_gen_data(key, &nld, false);
- nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
if (set->set_flags & NFT_SET_INTERVAL &&
key->etype == EXPR_CONCAT && key->field_count > 1) {
+ key->flags |= EXPR_F_INTERVAL;
+ __netlink_gen_data(key, &nld, false);
+ key->flags &= ~EXPR_F_INTERVAL;
+
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
+
key->flags |= EXPR_F_INTERVAL_END;
__netlink_gen_data(key, &nld, false);
key->flags &= ~EXPR_F_INTERVAL_END;
nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY_END,
&nld.value, nld.len);
+ } else {
+ __netlink_gen_data(key, &nld, false);
+ nftnl_set_elem_set(nlse, NFTNL_SET_ELEM_KEY, &nld.value, nld.len);
}
break;
}
@@ -246,14 +253,14 @@ static int netlink_export_pad(unsigned char *data, const mpz_t v,
return netlink_padded_len(i->len) / BITS_PER_BYTE;
}
-static int netlink_gen_concat_data_expr(int end, const struct expr *i,
+static int netlink_gen_concat_data_expr(uint32_t flags, const struct expr *i,
unsigned char *data)
{
struct expr *expr;
switch (i->etype) {
case EXPR_RANGE:
- if (end)
+ if (flags & EXPR_F_INTERVAL_END)
expr = i->right;
else
expr = i->left;
@@ -265,7 +272,7 @@ static int netlink_gen_concat_data_expr(int end, const struct expr *i,
i = expr;
break;
case EXPR_PREFIX:
- if (end) {
+ if (flags & EXPR_F_INTERVAL_END) {
int count;
mpz_t v;
@@ -281,6 +288,16 @@ static int netlink_gen_concat_data_expr(int end, const struct expr *i,
}
return netlink_export_pad(data, i->prefix->value, i);
case EXPR_VALUE:
+ /* Switch byteorder only once for singleton values when the set
+ * contains concatenation of intervals.
+ */
+ if (!(flags & EXPR_F_INTERVAL))
+ break;
+
+ expr = (struct expr *)i;
+ if (expr_basetype(expr)->type == TYPE_INTEGER &&
+ expr->byteorder == BYTEORDER_HOST_ENDIAN)
+ mpz_switch_byteorder(expr->value, expr->len / BITS_PER_BYTE);
break;
default:
BUG("invalid expression type '%s' in set", expr_ops(i)->name);
@@ -293,14 +310,13 @@ static void __netlink_gen_concat(const struct expr *expr,
struct nft_data_linearize *nld)
{
unsigned int len = expr->len / BITS_PER_BYTE, offset = 0;
- int end = expr->flags & EXPR_F_INTERVAL_END;
unsigned char data[len];
const struct expr *i;
memset(data, 0, len);
list_for_each_entry(i, &expr->expressions, list)
- offset += netlink_gen_concat_data_expr(end, i, data + offset);
+ offset += netlink_gen_concat_data_expr(expr->flags, i, data + offset);
memcpy(nld->value, data, len);
nld->len = len;
@@ -316,10 +332,10 @@ static void __netlink_gen_concat_expand(const struct expr *expr,
memset(data, 0, len);
list_for_each_entry(i, &expr->expressions, list)
- offset += netlink_gen_concat_data_expr(false, i, data + offset);
+ offset += netlink_gen_concat_data_expr(0, i, data + offset);
list_for_each_entry(i, &expr->expressions, list)
- offset += netlink_gen_concat_data_expr(true, i, data + offset);
+ offset += netlink_gen_concat_data_expr(EXPR_F_INTERVAL_END, i, data + offset);
memcpy(nld->value, data, len);
nld->len = len;