diff mbox series

[nf-next,v3,1/3] netfilter: bitwise: keep track of bit-length of expressions

Message ID 20220409135213.1450058-2-jeremy@azazel.net
State Superseded, archived
Delegated to: Pablo Neira
Headers show
Series netfilter: bitwise: support boolean operations with variable RHS operands | expand

Commit Message

Jeremy Sowden April 9, 2022, 1:52 p.m. UTC
Some bitwise operations are generated in user space when munging paylod
expressions.  During delinearization, user space attempts to eliminate
these operations.  However, it does this before deducing the byte-order
or the correct length in bits of the operands, which means that it
doesn't always handle multi-byte host-endian operations correctly.
Therefore, add support for storing the bit-length of the expression,
even though the kernel doesn't use it, in order to be able to pass it
back to user space.

Signed-off-by: Jeremy Sowden <jeremy@azazel.net>
---
 include/uapi/linux/netfilter/nf_tables.h |  2 ++
 net/netfilter/nft_bitwise.c              | 14 ++++++++++++++
 2 files changed, 16 insertions(+)
diff mbox series

Patch

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 466fd3f4447c..f3dcc4a34ff1 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -561,6 +561,7 @@  enum nft_bitwise_ops {
  * @NFTA_BITWISE_OP: type of operation (NLA_U32: nft_bitwise_ops)
  * @NFTA_BITWISE_DATA: argument for non-boolean operations
  *                     (NLA_NESTED: nft_data_attributes)
+ * @NFTA_BITWISE_NBITS: length of operation in bits (NLA_U32)
  *
  * The bitwise expression supports boolean and shift operations.  It implements
  * the boolean operations by performing the following operation:
@@ -584,6 +585,7 @@  enum nft_bitwise_attributes {
 	NFTA_BITWISE_XOR,
 	NFTA_BITWISE_OP,
 	NFTA_BITWISE_DATA,
+	NFTA_BITWISE_NBITS,
 	__NFTA_BITWISE_MAX
 };
 #define NFTA_BITWISE_MAX	(__NFTA_BITWISE_MAX - 1)
diff --git a/net/netfilter/nft_bitwise.c b/net/netfilter/nft_bitwise.c
index 83590afe3768..a120eaadb3e7 100644
--- a/net/netfilter/nft_bitwise.c
+++ b/net/netfilter/nft_bitwise.c
@@ -23,6 +23,7 @@  struct nft_bitwise {
 	struct nft_data		mask;
 	struct nft_data		xor;
 	struct nft_data		data;
+	u16                     nbits;
 };
 
 static void nft_bitwise_eval_bool(u32 *dst, const u32 *src,
@@ -88,6 +89,7 @@  static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = {
 	[NFTA_BITWISE_XOR]	= { .type = NLA_NESTED },
 	[NFTA_BITWISE_OP]	= { .type = NLA_U32 },
 	[NFTA_BITWISE_DATA]	= { .type = NLA_NESTED },
+	[NFTA_BITWISE_NBITS]	= { .type = NLA_U32 },
 };
 
 static int nft_bitwise_init_bool(struct nft_bitwise *priv,
@@ -194,6 +196,16 @@  static int nft_bitwise_init(const struct nft_ctx *ctx,
 	} else {
 		priv->op = NFT_BITWISE_BOOL;
 	}
+	if (tb[NFTA_BITWISE_NBITS]) {
+		u32 nbits;
+
+		err = nft_parse_u32_check(tb[NFTA_BITWISE_NBITS],
+					  U8_MAX * BITS_PER_BYTE, &nbits);
+		if (err < 0)
+			return err;
+
+		priv->nbits = nbits;
+	}
 
 	switch(priv->op) {
 	case NFT_BITWISE_BOOL:
@@ -244,6 +256,8 @@  static int nft_bitwise_dump(struct sk_buff *skb, const struct nft_expr *expr)
 		return -1;
 	if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(priv->op)))
 		return -1;
+	if (nla_put_be32(skb, NFTA_BITWISE_NBITS, htonl(priv->nbits)))
+		return -1;
 
 	switch (priv->op) {
 	case NFT_BITWISE_BOOL: