Skip to content

Commit

Permalink
netfilter: nftables: add nft_parse_register_load() and use it
Browse files Browse the repository at this point in the history
[ Upstream commit 4f16d25 ]

This new function combines the netlink register attribute parser
and the load validation function.

This update requires to replace:

	enum nft_registers      sreg:8;

in many of the expression private areas otherwise compiler complains
with:

	error: cannot take address of bit-field ‘sreg’

when passing the register field as reference.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
ummakynes authored and gregkh committed Jun 29, 2022
1 parent 8adedb4 commit ec9b0a8
Show file tree
Hide file tree
Showing 25 changed files with 132 additions and 135 deletions.
2 changes: 1 addition & 1 deletion include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest);
unsigned int nft_parse_register(const struct nlattr *attr);
int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg);

int nft_validate_register_load(enum nft_registers reg, unsigned int len);
int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len);
int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
Expand Down
6 changes: 3 additions & 3 deletions include/net/netfilter/nf_tables_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ void nf_tables_core_module_exit(void);
struct nft_bitwise_fast_expr {
u32 mask;
u32 xor;
enum nft_registers sreg:8;
u8 sreg;
enum nft_registers dreg:8;
};

struct nft_cmp_fast_expr {
u32 data;
u32 mask;
enum nft_registers sreg:8;
u8 sreg;
u8 len;
bool inv;
};
Expand Down Expand Up @@ -67,7 +67,7 @@ struct nft_payload_set {
enum nft_payload_bases base:8;
u8 offset;
u8 len;
enum nft_registers sreg:8;
u8 sreg;
u8 csum_type;
u8 csum_offset;
u8 csum_flags;
Expand Down
2 changes: 1 addition & 1 deletion include/net/netfilter/nft_meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ struct nft_meta {
enum nft_meta_keys key:8;
union {
enum nft_registers dreg:8;
enum nft_registers sreg:8;
u8 sreg;
};
};

Expand Down
18 changes: 9 additions & 9 deletions net/ipv4/netfilter/nft_dup_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
#include <net/netfilter/ipv4/nf_dup_ipv4.h>

struct nft_dup_ipv4 {
enum nft_registers sreg_addr:8;
enum nft_registers sreg_dev:8;
u8 sreg_addr;
u8 sreg_dev;
};

static void nft_dup_ipv4_eval(const struct nft_expr *expr,
Expand All @@ -40,16 +40,16 @@ static int nft_dup_ipv4_init(const struct nft_ctx *ctx,
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
return -EINVAL;

priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]);
err = nft_validate_register_load(priv->sreg_addr, sizeof(struct in_addr));
err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
sizeof(struct in_addr));
if (err < 0)
return err;

if (tb[NFTA_DUP_SREG_DEV] != NULL) {
priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
}
return 0;
if (tb[NFTA_DUP_SREG_DEV])
err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
&priv->sreg_dev, sizeof(int));

return err;
}

static int nft_dup_ipv4_dump(struct sk_buff *skb, const struct nft_expr *expr)
Expand Down
18 changes: 9 additions & 9 deletions net/ipv6/netfilter/nft_dup_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
#include <net/netfilter/ipv6/nf_dup_ipv6.h>

struct nft_dup_ipv6 {
enum nft_registers sreg_addr:8;
enum nft_registers sreg_dev:8;
u8 sreg_addr;
u8 sreg_dev;
};

static void nft_dup_ipv6_eval(const struct nft_expr *expr,
Expand All @@ -38,16 +38,16 @@ static int nft_dup_ipv6_init(const struct nft_ctx *ctx,
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
return -EINVAL;

priv->sreg_addr = nft_parse_register(tb[NFTA_DUP_SREG_ADDR]);
err = nft_validate_register_load(priv->sreg_addr, sizeof(struct in6_addr));
err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr,
sizeof(struct in6_addr));
if (err < 0)
return err;

if (tb[NFTA_DUP_SREG_DEV] != NULL) {
priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
}
return 0;
if (tb[NFTA_DUP_SREG_DEV])
err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV],
&priv->sreg_dev, sizeof(int));

return err;
}

static int nft_dup_ipv6_dump(struct sk_buff *skb, const struct nft_expr *expr)
Expand Down
18 changes: 16 additions & 2 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -8514,7 +8514,7 @@ EXPORT_SYMBOL_GPL(nft_dump_register);
* Validate that the input register is one of the general purpose
* registers and that the length of the load is within the bounds.
*/
int nft_validate_register_load(enum nft_registers reg, unsigned int len)
static int nft_validate_register_load(enum nft_registers reg, unsigned int len)
{
if (reg < NFT_REG_1 * NFT_REG_SIZE / NFT_REG32_SIZE)
return -EINVAL;
Expand All @@ -8525,7 +8525,21 @@ int nft_validate_register_load(enum nft_registers reg, unsigned int len)

return 0;
}
EXPORT_SYMBOL_GPL(nft_validate_register_load);

int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
{
u32 reg;
int err;

reg = nft_parse_register(attr);
err = nft_validate_register_load(reg, len);
if (err < 0)
return err;

*sreg = reg;
return 0;
}
EXPORT_SYMBOL_GPL(nft_parse_register_load);

/**
* nft_validate_register_store - validate an expressions' register store
Expand Down
10 changes: 5 additions & 5 deletions net/netfilter/nft_bitwise.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <net/netfilter/nf_tables_offload.h>

struct nft_bitwise {
enum nft_registers sreg:8;
u8 sreg;
enum nft_registers dreg:8;
enum nft_bitwise_ops op:8;
u8 len;
Expand Down Expand Up @@ -169,8 +169,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,

priv->len = len;

priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]);
err = nft_validate_register_load(priv->sreg, priv->len);
err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg,
priv->len);
if (err < 0)
return err;

Expand Down Expand Up @@ -315,8 +315,8 @@ static int nft_bitwise_fast_init(const struct nft_ctx *ctx,
struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr);
int err;

priv->sreg = nft_parse_register(tb[NFTA_BITWISE_SREG]);
err = nft_validate_register_load(priv->sreg, sizeof(u32));
err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg,
sizeof(u32));
if (err < 0)
return err;

Expand Down
6 changes: 3 additions & 3 deletions net/netfilter/nft_byteorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <net/netfilter/nf_tables.h>

struct nft_byteorder {
enum nft_registers sreg:8;
u8 sreg;
enum nft_registers dreg:8;
enum nft_byteorder_ops op:8;
u8 len;
Expand Down Expand Up @@ -131,14 +131,14 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
return -EINVAL;
}

priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]);
err = nft_parse_u32_check(tb[NFTA_BYTEORDER_LEN], U8_MAX, &len);
if (err < 0)
return err;

priv->len = len;

err = nft_validate_register_load(priv->sreg, priv->len);
err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg,
priv->len);
if (err < 0)
return err;

Expand Down
8 changes: 3 additions & 5 deletions net/netfilter/nft_cmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

struct nft_cmp_expr {
struct nft_data data;
enum nft_registers sreg:8;
u8 sreg;
u8 len;
enum nft_cmp_ops op:8;
};
Expand Down Expand Up @@ -87,8 +87,7 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
return err;
}

priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
err = nft_validate_register_load(priv->sreg, desc.len);
err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
if (err < 0)
return err;

Expand Down Expand Up @@ -211,8 +210,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx,
if (err < 0)
return err;

priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
err = nft_validate_register_load(priv->sreg, desc.len);
err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len);
if (err < 0)
return err;

Expand Down
5 changes: 2 additions & 3 deletions net/netfilter/nft_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ struct nft_ct {
enum ip_conntrack_dir dir:8;
union {
enum nft_registers dreg:8;
enum nft_registers sreg:8;
u8 sreg;
};
};

Expand Down Expand Up @@ -608,8 +608,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
}
}

priv->sreg = nft_parse_register(tb[NFTA_CT_SREG]);
err = nft_validate_register_load(priv->sreg, len);
err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len);
if (err < 0)
goto err1;

Expand Down
6 changes: 3 additions & 3 deletions net/netfilter/nft_dup_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include <net/netfilter/nf_dup_netdev.h>

struct nft_dup_netdev {
enum nft_registers sreg_dev:8;
u8 sreg_dev;
};

static void nft_dup_netdev_eval(const struct nft_expr *expr,
Expand All @@ -40,8 +40,8 @@ static int nft_dup_netdev_init(const struct nft_ctx *ctx,
if (tb[NFTA_DUP_SREG_DEV] == NULL)
return -EINVAL;

priv->sreg_dev = nft_parse_register(tb[NFTA_DUP_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
return nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev,
sizeof(int));
}

static int nft_dup_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr)
Expand Down
12 changes: 6 additions & 6 deletions net/netfilter/nft_dynset.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ struct nft_dynset {
struct nft_set *set;
struct nft_set_ext_tmpl tmpl;
enum nft_dynset_ops op:8;
enum nft_registers sreg_key:8;
enum nft_registers sreg_data:8;
u8 sreg_key;
u8 sreg_data;
bool invert;
u64 timeout;
struct nft_expr *expr;
Expand Down Expand Up @@ -154,8 +154,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
return err;
}

priv->sreg_key = nft_parse_register(tb[NFTA_DYNSET_SREG_KEY]);
err = nft_validate_register_load(priv->sreg_key, set->klen);
err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key,
set->klen);
if (err < 0)
return err;

Expand All @@ -165,8 +165,8 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
if (set->dtype == NFT_DATA_VERDICT)
return -EOPNOTSUPP;

priv->sreg_data = nft_parse_register(tb[NFTA_DYNSET_SREG_DATA]);
err = nft_validate_register_load(priv->sreg_data, set->dlen);
err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_DATA],
&priv->sreg_data, set->dlen);
if (err < 0)
return err;
} else if (set->flags & NFT_SET_MAP)
Expand Down
6 changes: 3 additions & 3 deletions net/netfilter/nft_exthdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ struct nft_exthdr {
u8 len;
u8 op;
enum nft_registers dreg:8;
enum nft_registers sreg:8;
u8 sreg;
u8 flags;
};

Expand Down Expand Up @@ -403,11 +403,11 @@ static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx,
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
priv->offset = offset;
priv->len = len;
priv->sreg = nft_parse_register(tb[NFTA_EXTHDR_SREG]);
priv->flags = flags;
priv->op = op;

return nft_validate_register_load(priv->sreg, priv->len);
return nft_parse_register_load(tb[NFTA_EXTHDR_SREG], &priv->sreg,
priv->len);
}

static int nft_exthdr_ipv4_init(const struct nft_ctx *ctx,
Expand Down
18 changes: 9 additions & 9 deletions net/netfilter/nft_fwd_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include <net/ip.h>

struct nft_fwd_netdev {
enum nft_registers sreg_dev:8;
u8 sreg_dev;
};

static void nft_fwd_netdev_eval(const struct nft_expr *expr,
Expand Down Expand Up @@ -50,8 +50,8 @@ static int nft_fwd_netdev_init(const struct nft_ctx *ctx,
if (tb[NFTA_FWD_SREG_DEV] == NULL)
return -EINVAL;

priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]);
return nft_validate_register_load(priv->sreg_dev, sizeof(int));
return nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
sizeof(int));
}

static int nft_fwd_netdev_dump(struct sk_buff *skb, const struct nft_expr *expr)
Expand Down Expand Up @@ -83,8 +83,8 @@ static bool nft_fwd_netdev_offload_action(const struct nft_expr *expr)
}

struct nft_fwd_neigh {
enum nft_registers sreg_dev:8;
enum nft_registers sreg_addr:8;
u8 sreg_dev;
u8 sreg_addr;
u8 nfproto;
};

Expand Down Expand Up @@ -162,8 +162,6 @@ static int nft_fwd_neigh_init(const struct nft_ctx *ctx,
!tb[NFTA_FWD_NFPROTO])
return -EINVAL;

priv->sreg_dev = nft_parse_register(tb[NFTA_FWD_SREG_DEV]);
priv->sreg_addr = nft_parse_register(tb[NFTA_FWD_SREG_ADDR]);
priv->nfproto = ntohl(nla_get_be32(tb[NFTA_FWD_NFPROTO]));

switch (priv->nfproto) {
Expand All @@ -177,11 +175,13 @@ static int nft_fwd_neigh_init(const struct nft_ctx *ctx,
return -EOPNOTSUPP;
}

err = nft_validate_register_load(priv->sreg_dev, sizeof(int));
err = nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev,
sizeof(int));
if (err < 0)
return err;

return nft_validate_register_load(priv->sreg_addr, addr_len);
return nft_parse_register_load(tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr,
addr_len);
}

static int nft_fwd_neigh_dump(struct sk_buff *skb, const struct nft_expr *expr)
Expand Down

0 comments on commit ec9b0a8

Please sign in to comment.