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
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 <[email protected]>
  • Loading branch information
ummakynes committed Jan 27, 2021
1 parent 4f16d25 commit 345023b
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 @@ -4438,6 +4438,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 @@ -8675,10 +8681,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 @@ -8710,7 +8717,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 @@ -498,9 +498,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 @@ -350,12 +350,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
Loading

0 comments on commit 345023b

Please sign in to comment.