Skip to content

Commit

Permalink
netfilter: nftables: add nft_parse_register_store() and use it
Browse files Browse the repository at this point in the history
[ Upstream commit 345023b ]

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

This update requires to replace:

        enum nft_registers      dreg:8;

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

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

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 ec9b0a8 commit 95f80c8
Show file tree
Hide file tree
Showing 22 changed files with 100 additions and 92 deletions.
8 changes: 4 additions & 4 deletions include/net/netfilter/nf_tables.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,10 +204,10 @@ 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_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,
enum nft_data_types type, unsigned int len);
int nft_parse_register_store(const struct nft_ctx *ctx,
const struct nlattr *attr, u8 *dreg,
const struct nft_data *data,
enum nft_data_types type, unsigned int len);

/**
* struct nft_userdata - user defined data associated with an object
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 @@ -27,7 +27,7 @@ struct nft_bitwise_fast_expr {
u32 mask;
u32 xor;
u8 sreg;
enum nft_registers dreg:8;
u8 dreg;
};

struct nft_cmp_fast_expr {
Expand All @@ -40,7 +40,7 @@ struct nft_cmp_fast_expr {

struct nft_immediate_expr {
struct nft_data data;
enum nft_registers dreg:8;
u8 dreg;
u8 dlen;
};

Expand All @@ -60,7 +60,7 @@ struct nft_payload {
enum nft_payload_bases base:8;
u8 offset;
u8 len;
enum nft_registers dreg:8;
u8 dreg;
};

struct nft_payload_set {
Expand Down
2 changes: 1 addition & 1 deletion include/net/netfilter/nft_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <net/netfilter/nf_tables.h>

struct nft_fib {
enum nft_registers dreg:8;
u8 dreg;
u8 result;
u32 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 @@ -7,7 +7,7 @@
struct nft_meta {
enum nft_meta_keys key:8;
union {
enum nft_registers dreg:8;
u8 dreg;
u8 sreg;
};
};
Expand Down
5 changes: 2 additions & 3 deletions net/bridge/netfilter/nft_meta_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,8 @@ static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
return nft_meta_get_init(ctx, expr, tb);
}

priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
}

static struct nft_expr_type nft_meta_bridge_type;
Expand Down
34 changes: 29 additions & 5 deletions net/netfilter/nf_tables_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -4414,6 +4414,12 @@ static int nf_tables_delset(struct net *net, struct sock *nlsk,
return nft_delset(&ctx, set);
}

static int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
enum nft_data_types type,
unsigned int len);

static int nf_tables_bind_check_setelem(const struct nft_ctx *ctx,
struct nft_set *set,
const struct nft_set_iter *iter,
Expand Down Expand Up @@ -8555,10 +8561,11 @@ EXPORT_SYMBOL_GPL(nft_parse_register_load);
* A value of NULL for the data means that its runtime gathered
* data.
*/
int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
enum nft_data_types type, unsigned int len)
static int nft_validate_register_store(const struct nft_ctx *ctx,
enum nft_registers reg,
const struct nft_data *data,
enum nft_data_types type,
unsigned int len)
{
int err;

Expand Down Expand Up @@ -8590,7 +8597,24 @@ int nft_validate_register_store(const struct nft_ctx *ctx,
return 0;
}
}
EXPORT_SYMBOL_GPL(nft_validate_register_store);

int nft_parse_register_store(const struct nft_ctx *ctx,
const struct nlattr *attr, u8 *dreg,
const struct nft_data *data,
enum nft_data_types type, unsigned int len)
{
int err;
u32 reg;

reg = nft_parse_register(attr);
err = nft_validate_register_store(ctx, reg, data, type, len);
if (err < 0)
return err;

*dreg = reg;
return 0;
}
EXPORT_SYMBOL_GPL(nft_parse_register_store);

static const struct nla_policy nft_verdict_policy[NFTA_VERDICT_MAX + 1] = {
[NFTA_VERDICT_CODE] = { .type = NLA_U32 },
Expand Down
13 changes: 6 additions & 7 deletions net/netfilter/nft_bitwise.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

struct nft_bitwise {
u8 sreg;
enum nft_registers dreg:8;
u8 dreg;
enum nft_bitwise_ops op:8;
u8 len;
struct nft_data mask;
Expand Down Expand Up @@ -174,9 +174,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
if (err < 0)
return err;

priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, priv->len);
err = nft_parse_register_store(ctx, tb[NFTA_BITWISE_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
priv->len);
if (err < 0)
return err;

Expand Down Expand Up @@ -320,9 +320,8 @@ static int nft_bitwise_fast_init(const struct nft_ctx *ctx,
if (err < 0)
return err;

priv->dreg = nft_parse_register(tb[NFTA_BITWISE_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
err = nft_parse_register_store(ctx, tb[NFTA_BITWISE_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, sizeof(u32));
if (err < 0)
return err;

Expand Down
8 changes: 4 additions & 4 deletions net/netfilter/nft_byteorder.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

struct nft_byteorder {
u8 sreg;
enum nft_registers dreg:8;
u8 dreg;
enum nft_byteorder_ops op:8;
u8 len;
u8 size;
Expand Down Expand Up @@ -142,9 +142,9 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
if (err < 0)
return err;

priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, priv->len);
return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
priv->len);
}

static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr)
Expand Down
7 changes: 3 additions & 4 deletions net/netfilter/nft_ct.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct nft_ct {
enum nft_ct_keys key:8;
enum ip_conntrack_dir dir:8;
union {
enum nft_registers dreg:8;
u8 dreg;
u8 sreg;
};
};
Expand Down Expand Up @@ -499,9 +499,8 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
}
}

priv->dreg = nft_parse_register(tb[NFTA_CT_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL,
NFT_DATA_VALUE, len);
if (err < 0)
return err;

Expand Down
8 changes: 4 additions & 4 deletions net/netfilter/nft_exthdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct nft_exthdr {
u8 offset;
u8 len;
u8 op;
enum nft_registers dreg:8;
u8 dreg;
u8 sreg;
u8 flags;
};
Expand Down Expand Up @@ -353,12 +353,12 @@ static int nft_exthdr_init(const struct nft_ctx *ctx,
priv->type = nla_get_u8(tb[NFTA_EXTHDR_TYPE]);
priv->offset = offset;
priv->len = len;
priv->dreg = nft_parse_register(tb[NFTA_EXTHDR_DREG]);
priv->flags = flags;
priv->op = op;

return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, priv->len);
return nft_parse_register_store(ctx, tb[NFTA_EXTHDR_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
priv->len);
}

static int nft_exthdr_tcp_set_init(const struct nft_ctx *ctx,
Expand Down
5 changes: 2 additions & 3 deletions net/netfilter/nft_fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
return -EINVAL;

priv->result = ntohl(nla_get_be32(tb[NFTA_FIB_RESULT]));
priv->dreg = nft_parse_register(tb[NFTA_FIB_DREG]);

switch (priv->result) {
case NFT_FIB_RESULT_OIF:
Expand All @@ -106,8 +105,8 @@ int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
return -EINVAL;
}

err = nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
err = nft_parse_register_store(ctx, tb[NFTA_FIB_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
if (err < 0)
return err;

Expand Down
17 changes: 7 additions & 10 deletions net/netfilter/nft_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

struct nft_jhash {
u8 sreg;
enum nft_registers dreg:8;
u8 dreg;
u8 len;
bool autogen_seed:1;
u32 modulus;
Expand All @@ -38,7 +38,7 @@ static void nft_jhash_eval(const struct nft_expr *expr,
}

struct nft_symhash {
enum nft_registers dreg:8;
u8 dreg;
u32 modulus;
u32 offset;
};
Expand Down Expand Up @@ -83,8 +83,6 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
if (tb[NFTA_HASH_OFFSET])
priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));

priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);

err = nft_parse_u32_check(tb[NFTA_HASH_LEN], U8_MAX, &len);
if (err < 0)
return err;
Expand All @@ -111,8 +109,8 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
get_random_bytes(&priv->seed, sizeof(priv->seed));
}

return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, sizeof(u32));
}

static int nft_symhash_init(const struct nft_ctx *ctx,
Expand All @@ -128,17 +126,16 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
if (tb[NFTA_HASH_OFFSET])
priv->offset = ntohl(nla_get_be32(tb[NFTA_HASH_OFFSET]));

priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);

priv->modulus = ntohl(nla_get_be32(tb[NFTA_HASH_MODULUS]));
if (priv->modulus < 1)
return -ERANGE;

if (priv->offset + priv->modulus - 1 < priv->offset)
return -EOVERFLOW;

return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_HASH_DREG],
&priv->dreg, NULL, NFT_DATA_VALUE,
sizeof(u32));
}

static int nft_jhash_dump(struct sk_buff *skb,
Expand Down
6 changes: 3 additions & 3 deletions net/netfilter/nft_immediate.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ static int nft_immediate_init(const struct nft_ctx *ctx,

priv->dlen = desc.len;

priv->dreg = nft_parse_register(tb[NFTA_IMMEDIATE_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, &priv->data,
desc.type, desc.len);
err = nft_parse_register_store(ctx, tb[NFTA_IMMEDIATE_DREG],
&priv->dreg, &priv->data, desc.type,
desc.len);
if (err < 0)
goto err1;

Expand Down
8 changes: 4 additions & 4 deletions net/netfilter/nft_lookup.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
struct nft_lookup {
struct nft_set *set;
u8 sreg;
enum nft_registers dreg:8;
u8 dreg;
bool invert;
struct nft_set_binding binding;
};
Expand Down Expand Up @@ -100,9 +100,9 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
if (!(set->flags & NFT_SET_MAP))
return -EINVAL;

priv->dreg = nft_parse_register(tb[NFTA_LOOKUP_DREG]);
err = nft_validate_register_store(ctx, priv->dreg, NULL,
set->dtype, set->dlen);
err = nft_parse_register_store(ctx, tb[NFTA_LOOKUP_DREG],
&priv->dreg, NULL, set->dtype,
set->dlen);
if (err < 0)
return err;
} else if (set->flags & NFT_SET_MAP)
Expand Down
5 changes: 2 additions & 3 deletions net/netfilter/nft_meta.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,8 @@ int nft_meta_get_init(const struct nft_ctx *ctx,
return -EOPNOTSUPP;
}

priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, len);
return nft_parse_register_store(ctx, tb[NFTA_META_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, len);
}
EXPORT_SYMBOL_GPL(nft_meta_get_init);

Expand Down
15 changes: 6 additions & 9 deletions net/netfilter/nft_numgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
static DEFINE_PER_CPU(struct rnd_state, nft_numgen_prandom_state);

struct nft_ng_inc {
enum nft_registers dreg:8;
u8 dreg;
u32 modulus;
atomic_t counter;
u32 offset;
Expand Down Expand Up @@ -66,11 +66,10 @@ static int nft_ng_inc_init(const struct nft_ctx *ctx,
if (priv->offset + priv->modulus - 1 < priv->offset)
return -EOVERFLOW;

priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]);
atomic_set(&priv->counter, priv->modulus - 1);

return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, sizeof(u32));
}

static int nft_ng_dump(struct sk_buff *skb, enum nft_registers dreg,
Expand Down Expand Up @@ -100,7 +99,7 @@ static int nft_ng_inc_dump(struct sk_buff *skb, const struct nft_expr *expr)
}

struct nft_ng_random {
enum nft_registers dreg:8;
u8 dreg;
u32 modulus;
u32 offset;
};
Expand Down Expand Up @@ -140,10 +139,8 @@ static int nft_ng_random_init(const struct nft_ctx *ctx,

prandom_init_once(&nft_numgen_prandom_state);

priv->dreg = nft_parse_register(tb[NFTA_NG_DREG]);

return nft_validate_register_store(ctx, priv->dreg, NULL,
NFT_DATA_VALUE, sizeof(u32));
return nft_parse_register_store(ctx, tb[NFTA_NG_DREG], &priv->dreg,
NULL, NFT_DATA_VALUE, sizeof(u32));
}

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

0 comments on commit 95f80c8

Please sign in to comment.