]> git.itanic.dy.fi Git - linux-stable/commitdiff
netfilter: nftables: add nft_parse_register_store() and use it
authorPablo Neira Ayuso <pablo@netfilter.org>
Tue, 16 May 2023 15:06:06 +0000 (17:06 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 30 May 2023 11:42:12 +0000 (12:42 +0100)
345023b0db315648ccc3c1a36aee88304a8b4d91 ]

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>
19 files changed:
include/net/netfilter/nf_tables.h
include/net/netfilter/nf_tables_core.h
include/net/netfilter/nft_fib.h
net/netfilter/nf_tables_api.c
net/netfilter/nft_bitwise.c
net/netfilter/nft_byteorder.c
net/netfilter/nft_ct.c
net/netfilter/nft_exthdr.c
net/netfilter/nft_fib.c
net/netfilter/nft_hash.c
net/netfilter/nft_immediate.c
net/netfilter/nft_lookup.c
net/netfilter/nft_meta.c
net/netfilter/nft_numgen.c
net/netfilter/nft_osf.c
net/netfilter/nft_payload.c
net/netfilter/nft_rt.c
net/netfilter/nft_socket.c
net/netfilter/nft_tunnel.c

index e7b1e241f6f6ed5a0337292655f30a366e73e429..bf957156e9b761626632c879aa4eb1a36c85fe3e 100644 (file)
@@ -195,10 +195,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
index c81c12a825de476a42c8e13d533145e2354e38a4..6a3f76e012be37e330b1b8a083d8afd56f5410a5 100644 (file)
@@ -28,7 +28,7 @@ struct nft_cmp_fast_expr {
 
 struct nft_immediate_expr {
        struct nft_data         data;
-       enum nft_registers      dreg:8;
+       u8                      dreg;
        u8                      dlen;
 };
 
@@ -48,7 +48,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 {
index a88f92737308d18c90fd4111ef3f469222454311..1f8726739529108f680af29718135aac53e7bb6a 100644 (file)
@@ -3,7 +3,7 @@
 #define _NFT_FIB_H_
 
 struct nft_fib {
-       enum nft_registers      dreg:8;
+       u8                      dreg;
        u8                      result;
        u32                     flags;
 };
index 3b4cb6a9e85d58c9493a4812eab1c2608bdf4da8..b86d9c14cbd6994ad7cd0f4038710369a5969d35 100644 (file)
@@ -3687,6 +3687,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,
@@ -7067,10 +7073,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;
 
@@ -7102,7 +7109,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 },
index 23a8a9d119876f744d04c21522f44df6e771da70..c1055251ebdebf0f7414a715e3a0286e53f1069e 100644 (file)
@@ -19,7 +19,7 @@
 
 struct nft_bitwise {
        u8                      sreg;
-       enum nft_registers      dreg:8;
+       u8                      dreg;
        u8                      len;
        struct nft_data         mask;
        struct nft_data         xor;
@@ -73,9 +73,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;
 
index c81d618137ce8b8e2f8c98d451fb5784b560e6cd..5e1fbdd7b2846cd5e409d5f856d58331dcdc9280 100644 (file)
@@ -20,7 +20,7 @@
 
 struct nft_byteorder {
        u8                      sreg;
-       enum nft_registers      dreg:8;
+       u8                      dreg;
        enum nft_byteorder_ops  op:8;
        u8                      len;
        u8                      size;
@@ -144,9 +144,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)
index 045e350ba03ea68f18989dfdc123644e82715a8e..f29f02805bcc0a4709574eb9af2cf59d11dcc6dd 100644 (file)
@@ -29,7 +29,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;
        };
 };
@@ -486,9 +486,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;
 
index 340520f10b686e255e0ed70f35f3b4c632d73486..8d0f14cd7cc3eea12bbacc31b4d907788505dbb1 100644 (file)
@@ -22,7 +22,7 @@ struct nft_exthdr {
        u8                      offset;
        u8                      len;
        u8                      op;
-       enum nft_registers      dreg:8;
+       u8                      dreg;
        u8                      sreg;
        u8                      flags;
 };
@@ -258,12 +258,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,
index 21df8cccea6582e56d7bfbb6fba21f821b7c56d9..ce6891337304d01dd94eb4ed24d103a5ffded4ba 100644 (file)
@@ -88,7 +88,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:
@@ -108,8 +107,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;
 
index d08a14cfe56b7ce83f545efcbeac0aec9d4a32ec..513419aca9c66bc2b5a65939b724e5f30ce88f1e 100644 (file)
@@ -19,7 +19,7 @@
 
 struct nft_jhash {
        u8                      sreg;
-       enum nft_registers      dreg:8;
+       u8                      dreg;
        u8                      len;
        bool                    autogen_seed:1;
        u32                     modulus;
@@ -65,7 +65,7 @@ static void nft_jhash_map_eval(const struct nft_expr *expr,
 }
 
 struct nft_symhash {
-       enum nft_registers      dreg:8;
+       u8                      dreg;
        u32                     modulus;
        u32                     offset;
        struct nft_set          *map;
@@ -136,8 +136,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;
@@ -164,8 +162,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_jhash_map_init(const struct nft_ctx *ctx,
@@ -195,8 +193,6 @@ 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;
@@ -204,8 +200,9 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
        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_symhash_map_init(const struct nft_ctx *ctx,
index 3f6d1d2a628186c964e79727bbb62fb59370b919..af4e2a4bce93ef9aa5132d2633a71c5148236739 100644 (file)
@@ -50,9 +50,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;
 
index 671f124d56b34161c902f986035db0db611299eb..3c380fb32651148f9b4eab338df093f1fd3623d2 100644 (file)
@@ -21,7 +21,7 @@
 struct nft_lookup {
        struct nft_set                  *set;
        u8                              sreg;
-       enum nft_registers              dreg:8;
+       u8                              dreg;
        bool                            invert;
        struct nft_set_binding          binding;
 };
@@ -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)
index 7af90ed22111384661c464b30aacdc73d6149d0f..061a29bd3066194959507226786384b6da540aa3 100644 (file)
@@ -30,7 +30,7 @@
 struct nft_meta {
        enum nft_meta_keys      key:8;
        union {
-               enum nft_registers      dreg:8;
+               u8              dreg;
                u8              sreg;
        };
 };
@@ -358,9 +358,8 @@ static 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);
 }
 
 static int nft_meta_get_validate(const struct nft_ctx *ctx,
index 3cc1b3dc3c3cdb2508cef7825f3bd9c485679fdb..8ff82f17ecba9a849a9ce1b597cb3278c73700d5 100644 (file)
@@ -20,7 +20,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;
@@ -70,11 +70,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,
@@ -104,7 +103,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;
 };
@@ -144,10 +143,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)
index 4fac2d9a4b8858a10e1316d15f851e0d2b18dad2..af2ce7a8c5877d512be08ddc34c4ceceedea8ba2 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/netfilter/nfnetlink_osf.h>
 
 struct nft_osf {
-       enum nft_registers      dreg:8;
+       u8                      dreg;
 };
 
 static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = {
@@ -55,9 +55,9 @@ static int nft_osf_init(const struct nft_ctx *ctx,
        if (!tb[NFTA_OSF_DREG])
                return -EINVAL;
 
-       priv->dreg = nft_parse_register(tb[NFTA_OSF_DREG]);
-       err = nft_validate_register_store(ctx, priv->dreg, NULL,
-                                         NFT_DATA_VALUE, NFT_OSF_MAXGENRELEN);
+       err = nft_parse_register_store(ctx, tb[NFTA_OSF_DREG], &priv->dreg,
+                                      NULL, NFT_DATA_VALUE,
+                                      NFT_OSF_MAXGENRELEN);
        if (err < 0)
                return err;
 
index 6c5312fecac5c5e864f87bbe667a77deb71fb891..77cfd5182784ffb3a2c7fd5afb455e73683bc450 100644 (file)
@@ -135,10 +135,10 @@ static int nft_payload_init(const struct nft_ctx *ctx,
        priv->base   = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
        priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
        priv->len    = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
-       priv->dreg   = nft_parse_register(tb[NFTA_PAYLOAD_DREG]);
 
-       return nft_validate_register_store(ctx, priv->dreg, NULL,
-                                          NFT_DATA_VALUE, priv->len);
+       return nft_parse_register_store(ctx, tb[NFTA_PAYLOAD_DREG],
+                                       &priv->dreg, NULL, NFT_DATA_VALUE,
+                                       priv->len);
 }
 
 static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
index 76dba9f6b6f627de7de1ada08320cc2ed5a12b24..edce109ef4b01ed0589d0609fdad2acd98dadf06 100644 (file)
@@ -18,7 +18,7 @@
 
 struct nft_rt {
        enum nft_rt_keys        key:8;
-       enum nft_registers      dreg:8;
+       u8                      dreg;
 };
 
 static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skbdst)
@@ -134,9 +134,8 @@ static int nft_rt_get_init(const struct nft_ctx *ctx,
                return -EOPNOTSUPP;
        }
 
-       priv->dreg = nft_parse_register(tb[NFTA_RT_DREG]);
-       return nft_validate_register_store(ctx, priv->dreg, NULL,
-                                          NFT_DATA_VALUE, len);
+       return nft_parse_register_store(ctx, tb[NFTA_RT_DREG], &priv->dreg,
+                                       NULL, NFT_DATA_VALUE, len);
 }
 
 static int nft_rt_get_dump(struct sk_buff *skb,
index 4026ec38526f69e4902c6ad3a38e8e6983ce3b42..7e4f7063f4811d83b065cbba34fe5504917db2bf 100644 (file)
@@ -10,7 +10,7 @@
 struct nft_socket {
        enum nft_socket_keys            key:8;
        union {
-               enum nft_registers      dreg:8;
+               u8                      dreg;
        };
 };
 
@@ -119,9 +119,8 @@ static int nft_socket_init(const struct nft_ctx *ctx,
                return -EOPNOTSUPP;
        }
 
-       priv->dreg = nft_parse_register(tb[NFTA_SOCKET_DREG]);
-       return nft_validate_register_store(ctx, priv->dreg, NULL,
-                                          NFT_DATA_VALUE, len);
+       return nft_parse_register_store(ctx, tb[NFTA_SOCKET_DREG], &priv->dreg,
+                                       NULL, NFT_DATA_VALUE, len);
 }
 
 static int nft_socket_dump(struct sk_buff *skb,
index 3fc55c81f16ac8b3be9aa199e8962e73bfc914db..ab69a34210a8dbc1e385e54e3470faa2dfc64834 100644 (file)
@@ -14,7 +14,7 @@
 
 struct nft_tunnel {
        enum nft_tunnel_keys    key:8;
-       enum nft_registers      dreg:8;
+       u8                      dreg;
 };
 
 static void nft_tunnel_get_eval(const struct nft_expr *expr,
@@ -72,10 +72,8 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx,
                return -EOPNOTSUPP;
        }
 
-       priv->dreg = nft_parse_register(tb[NFTA_TUNNEL_DREG]);
-
-       return nft_validate_register_store(ctx, priv->dreg, NULL,
-                                          NFT_DATA_VALUE, len);
+       return nft_parse_register_store(ctx, tb[NFTA_TUNNEL_DREG], &priv->dreg,
+                                       NULL, NFT_DATA_VALUE, len);
 }
 
 static int nft_tunnel_get_dump(struct sk_buff *skb,