stable fixes for 5.4
Subsystems (2)
Pablo Neira Ayuso
maintainercover stable fixes for 5.4
Hi,
This is round of -stable backport fixes for 5.4. This batch includes dependency patches which are not currently in the 5.4 branch.
The following list shows the backported patches, I am using original commit IDs for reference:
1) 4f16d25c68ec ("netfilter: nftables: add nft_parse_register_load() and use it")
2) 345023b0db31 ("netfilter: nftables: add nft_parse_register_store() and use it")
3) 08a01c11a5bb ("netfilter: nftables: statify nft_parse_register()")
4) 6e1acfa387b9 ("netfilter: nf_tables: validate registers coming from userspace.")
5) 20a1452c3542 ("netfilter: nf_tables: add nft_setelem_parse_key()")
6) fdb9c405e35b ("netfilter: nf_tables: allow up to 64 bytes in the set element data area")
7) 7e6bc1f6cabc ("netfilter: nf_tables: stricter validation of element data")
8) 5a2f3dc31811 ("netfilter: nf_tables: validate NFTA_SET_ELEM_OBJREF based on NFT_SET_OBJECT flag")
9) 3923b1e44066 ("netfilter: nf_tables: hold mutex on netns pre_exit path")
Patches #1, #2, #3, #5, #6 are backported stable dependencies.
Please, apply.
Thanks.
Pablo Neira Ayuso (9):
netfilter: nftables: add nft_parse_register_load() and use it
netfilter: nftables: add nft_parse_register_store() and use it
netfilter: nftables: statify nft_parse_register()
netfilter: nf_tables: validate registers coming from userspace.
netfilter: nf_tables: add nft_setelem_parse_key()
netfilter: nf_tables: allow up to 64 bytes in the set element data area
netfilter: nf_tables: stricter validation of element data
netfilter: nf_tables: validate NFTA_SET_ELEM_OBJREF based on NFT_SET_OBJECT flag
netfilter: nf_tables: hold mutex on netns pre_exit path
include/net/netfilter/nf_tables.h | 15 +- include/net/netfilter/nf_tables_core.h | 8 +- include/net/netfilter/nft_fib.h | 2 +- include/net/netfilter/nft_meta.h | 4 +- net/bridge/netfilter/nft_meta_bridge.c | 5 +- net/ipv4/netfilter/nft_dup_ipv4.c | 18 +- net/ipv6/netfilter/nft_dup_ipv6.c | 18 +- net/netfilter/nf_tables_api.c | 228 ++++++++++++++++--------- net/netfilter/nft_bitwise.c | 14 +- net/netfilter/nft_byteorder.c | 14 +- net/netfilter/nft_cmp.c | 8 +- net/netfilter/nft_ct.c | 12 +- net/netfilter/nft_dup_netdev.c | 6 +- net/netfilter/nft_dynset.c | 12 +- net/netfilter/nft_exthdr.c | 14 +- net/netfilter/nft_fib.c | 5 +- net/netfilter/nft_fwd_netdev.c | 18 +- net/netfilter/nft_hash.c | 25 ++- net/netfilter/nft_immediate.c | 6 +- net/netfilter/nft_lookup.c | 14 +- net/netfilter/nft_masq.c | 18 +- net/netfilter/nft_meta.c | 8 +- net/netfilter/nft_nat.c | 35 ++-- net/netfilter/nft_numgen.c | 15 +- net/netfilter/nft_objref.c | 6 +- net/netfilter/nft_osf.c | 8 +- net/netfilter/nft_payload.c | 10 +- net/netfilter/nft_queue.c | 12 +- net/netfilter/nft_range.c | 6 +- net/netfilter/nft_redir.c | 18 +- net/netfilter/nft_rt.c | 7 +- net/netfilter/nft_socket.c | 7 +- net/netfilter/nft_tproxy.c | 14 +- net/netfilter/nft_tunnel.c | 8 +- net/netfilter/nft_xfrm.c | 7 +- 35 files changed, 332 insertions(+), 293 deletions(-)
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 1/9 netfilter: nftables: add nft_parse_register_load() and use it
[ 4f16d25c68ec844299a4df6ecbb0234eaf88a935 ]
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.
--- include/net/netfilter/nf_tables.h | 2 +- include/net/netfilter/nf_tables_core.h | 4 +-- include/net/netfilter/nft_meta.h | 2 +- net/ipv4/netfilter/nft_dup_ipv4.c | 18 ++++++------- net/ipv6/netfilter/nft_dup_ipv6.c | 18 ++++++------- net/netfilter/nf_tables_api.c | 18 +++++++++++-- net/netfilter/nft_bitwise.c | 6 ++--- net/netfilter/nft_byteorder.c | 6 ++--- net/netfilter/nft_cmp.c | 8 +++--- net/netfilter/nft_ct.c | 5 ++-- net/netfilter/nft_dup_netdev.c | 6 ++--- net/netfilter/nft_dynset.c | 12 ++++----- net/netfilter/nft_exthdr.c | 6 ++--- net/netfilter/nft_fwd_netdev.c | 18 ++++++------- net/netfilter/nft_hash.c | 10 +++++--- net/netfilter/nft_lookup.c | 6 ++--- net/netfilter/nft_masq.c | 18 ++++++------- net/netfilter/nft_meta.c | 3 +-- net/netfilter/nft_nat.c | 35 +++++++++++--------------- net/netfilter/nft_objref.c | 6 ++--- net/netfilter/nft_payload.c | 4 +-- net/netfilter/nft_queue.c | 12 ++++----- net/netfilter/nft_range.c | 6 ++--- net/netfilter/nft_redir.c | 18 ++++++------- net/netfilter/nft_tproxy.c | 14 +++++------ 25 files changed, 129 insertions(+), 132 deletions(-)
include/net/netfilter/nf_tables.h +1 -1
@@ -208,7 +208,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,
include/net/netfilter/nf_tables_core.h +2 -2
@@ -25,7 +25,7 @@ void nf_tables_core_module_exit(void);struct nft_cmp_fast_expr {u32 data; -enum nft_registers sreg:8 ; +u8 sreg;u8 len; };
@@ -58,7 +58,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;
include/net/netfilter/nft_meta.h +1 -1
@@ -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; }; };
net/ipv4/netfilter/nft_dup_ipv4.c +9 -9
@@ -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,
@@ -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)
net/ipv6/netfilter/nft_dup_ipv6.c +9 -9
@@ -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,
@@ -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)
net/netfilter/nf_tables_api.c +16 -2
@@ -7424,7 +7424,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 ;
@@ -7435,7 +7435,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
net/netfilter/nft_bitwise.c +3 -3
@@ -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 ;u8 len;struct nft_data mask;
@@ -65,8 +65,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;
net/netfilter/nft_byteorder.c +3 -3
@@ -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;
@@ -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;
net/netfilter/nft_cmp.c +3 -5
@@ -17,7 +17,7 @@struct nft_cmp_expr {struct nft_data data; -enum nft_registers sreg:8 ; +u8 sreg;u8 len;enum nft_cmp_ops op:8 ; };
@@ -86,8 +86,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;
@@ -169,8 +168,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;
net/netfilter/nft_ct.c +2 -3
@@ -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; }; };
@@ -600,8 +600,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;
net/netfilter/nft_dup_netdev.c +3 -3
@@ -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,
@@ -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)
net/netfilter/nft_dynset.c +6 -6
@@ -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;
@@ -177,8 +177,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;
@@ -188,8 +188,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 )
net/netfilter/nft_exthdr.c +3 -3
@@ -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; };
@@ -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,
net/netfilter/nft_fwd_netdev.c +9 -9
@@ -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,
@@ -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)
@@ -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; };
@@ -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) {
@@ -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)
net/netfilter/nft_hash.c +6 -4
@@ -14,7 +14,7 @@#include <linux/jhash.h> struct nft_jhash { -enum nft_registers sreg:8 ; +u8 sreg;enum nft_registers dreg:8 ;u8 len;bool autogen_seed:1 ;
@@ -83,7 +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->sreg =nft_parse_register (tb[NFTA_HASH_SREG ]); priv->dreg =nft_parse_register (tb[NFTA_HASH_DREG ]); err =nft_parse_u32_check (tb[NFTA_HASH_LEN ],U8_MAX , &len);
@@ -94,6 +93,10 @@ static int nft_jhash_init(const struct nft_ctx *ctx, priv->len = len; + err =nft_parse_register_load (tb[NFTA_HASH_SREG ], &priv->sreg, len); +if (err <0 ) +return err; + priv->modulus =ntohl (nla_get_be32 (tb[NFTA_HASH_MODULUS ]));if (priv->modulus <1 )return -ERANGE ;
@@ -108,8 +111,7 @@ static int nft_jhash_init(const struct nft_ctx *ctx,get_random_bytes (&priv->seed,sizeof (priv->seed)); } -return nft_validate_register_load (priv->sreg, len) && -nft_validate_register_store (ctx, priv->dreg,NULL , +return nft_validate_register_store (ctx, priv->dreg,NULL ,NFT_DATA_VALUE ,sizeof (u32)); }
net/netfilter/nft_lookup.c +3 -3
@@ -17,7 +17,7 @@struct nft_lookup {struct nft_set *set; -enum nft_registers sreg:8 ; +u8 sreg;enum nft_registers dreg:8 ;bool invert;struct nft_set_binding binding;
@@ -73,8 +73,8 @@ static int nft_lookup_init(const struct nft_ctx *ctx,if (IS_ERR (set))return PTR_ERR (set); - priv->sreg =nft_parse_register (tb[NFTA_LOOKUP_SREG ]); - err =nft_validate_register_load (priv->sreg, set->klen); + err =nft_parse_register_load (tb[NFTA_LOOKUP_SREG ], &priv->sreg, + set->klen);if (err <0 )return err;
net/netfilter/nft_masq.c +7 -11
@@ -15,8 +15,8 @@struct nft_masq {u32 flags; -enum nft_registers sreg_proto_min:8 ; -enum nft_registers sreg_proto_max:8 ; +u8 sreg_proto_min; +u8 sreg_proto_max; };static const struct nla_policy nft_masq_policy[NFTA_MASQ_MAX +1 ] = {
@@ -54,19 +54,15 @@ static int nft_masq_init(const struct nft_ctx *ctx, }if (tb[NFTA_MASQ_REG_PROTO_MIN ]) { - priv->sreg_proto_min = -nft_parse_register (tb[NFTA_MASQ_REG_PROTO_MIN ]); - - err =nft_validate_register_load (priv->sreg_proto_min, plen); + err =nft_parse_register_load (tb[NFTA_MASQ_REG_PROTO_MIN ], + &priv->sreg_proto_min, plen);if (err <0 )return err;if (tb[NFTA_MASQ_REG_PROTO_MAX ]) { - priv->sreg_proto_max = -nft_parse_register (tb[NFTA_MASQ_REG_PROTO_MAX ]); - - err =nft_validate_register_load (priv->sreg_proto_max, - plen); + err =nft_parse_register_load (tb[NFTA_MASQ_REG_PROTO_MAX ], + &priv->sreg_proto_max, + plen);if (err <0 )return err; }else {
net/netfilter/nft_meta.c +1 -2
@@ -475,8 +475,7 @@ int nft_meta_set_init(const struct nft_ctx *ctx,return -EOPNOTSUPP ; } - priv->sreg =nft_parse_register (tb[NFTA_META_SREG ]); - err =nft_validate_register_load (priv->sreg, len); + err =nft_parse_register_load (tb[NFTA_META_SREG ], &priv->sreg, len);if (err <0 )return err;
net/netfilter/nft_nat.c +14 -21
@@ -21,10 +21,10 @@#include <net/ip.h> struct nft_nat { -enum nft_registers sreg_addr_min:8 ; -enum nft_registers sreg_addr_max:8 ; -enum nft_registers sreg_proto_min:8 ; -enum nft_registers sreg_proto_max:8 ; +u8 sreg_addr_min; +u8 sreg_addr_max; +u8 sreg_proto_min; +u8 sreg_proto_max;enum nf_nat_manip_type type:8 ;u8 family;u16 flags;
@@ -154,18 +154,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, priv->family = family;if (tb[NFTA_NAT_REG_ADDR_MIN ]) { - priv->sreg_addr_min = -nft_parse_register (tb[NFTA_NAT_REG_ADDR_MIN ]); - err =nft_validate_register_load (priv->sreg_addr_min, alen); + err =nft_parse_register_load (tb[NFTA_NAT_REG_ADDR_MIN ], + &priv->sreg_addr_min, alen);if (err <0 )return err;if (tb[NFTA_NAT_REG_ADDR_MAX ]) { - priv->sreg_addr_max = -nft_parse_register (tb[NFTA_NAT_REG_ADDR_MAX ]); - - err =nft_validate_register_load (priv->sreg_addr_max, - alen); + err =nft_parse_register_load (tb[NFTA_NAT_REG_ADDR_MAX ], + &priv->sreg_addr_max, + alen);if (err <0 )return err; }else {
@@ -175,19 +172,15 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);if (tb[NFTA_NAT_REG_PROTO_MIN ]) { - priv->sreg_proto_min = -nft_parse_register (tb[NFTA_NAT_REG_PROTO_MIN ]); - - err =nft_validate_register_load (priv->sreg_proto_min, plen); + err =nft_parse_register_load (tb[NFTA_NAT_REG_PROTO_MIN ], + &priv->sreg_proto_min, plen);if (err <0 )return err;if (tb[NFTA_NAT_REG_PROTO_MAX ]) { - priv->sreg_proto_max = -nft_parse_register (tb[NFTA_NAT_REG_PROTO_MAX ]); - - err =nft_validate_register_load (priv->sreg_proto_max, - plen); + err =nft_parse_register_load (tb[NFTA_NAT_REG_PROTO_MAX ], + &priv->sreg_proto_max, + plen);if (err <0 )return err; }else {
net/netfilter/nft_objref.c +3 -3
@@ -95,7 +95,7 @@ static const struct nft_expr_ops nft_objref_ops = {struct nft_objref_map {struct nft_set *set; -enum nft_registers sreg:8 ; +u8 sreg;struct nft_set_binding binding; };
@@ -137,8 +137,8 @@ static int nft_objref_map_init(const struct nft_ctx *ctx,if (!(set->flags &NFT_SET_OBJECT ))return -EINVAL ; - priv->sreg =nft_parse_register (tb[NFTA_OBJREF_SET_SREG ]); - err =nft_validate_register_load (priv->sreg, set->klen); + err =nft_parse_register_load (tb[NFTA_OBJREF_SET_SREG ], &priv->sreg, + set->klen);if (err <0 )return err;
net/netfilter/nft_payload.c +2 -2
@@ -564,7 +564,6 @@ static int nft_payload_set_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->sreg =nft_parse_register (tb[NFTA_PAYLOAD_SREG ]);if (tb[NFTA_PAYLOAD_CSUM_TYPE ]) csum_type =ntohl (nla_get_be32 (tb[NFTA_PAYLOAD_CSUM_TYPE ]));
@@ -595,7 +594,8 @@ static int nft_payload_set_init(const struct nft_ctx *ctx, } priv->csum_type = csum_type; -return nft_validate_register_load (priv->sreg, priv->len); +return nft_parse_register_load (tb[NFTA_PAYLOAD_SREG ], &priv->sreg, + priv->len); }static int nft_payload_set_dump (struct sk_buff *skb,const struct nft_expr *expr)
net/netfilter/nft_queue.c +6 -6
@@ -19,10 +19,10 @@static u32 jhash_initval__read_mostly ;struct nft_queue { -enum nft_registers sreg_qnum:8 ; -u16 queuenum; -u16 queues_total; -u16 flags; +u8 sreg_qnum; +u16 queuenum; +u16 queues_total; +u16 flags; }; static void nft_queue_eval(const struct nft_expr *expr,
@@ -111,8 +111,8 @@ static int nft_queue_sreg_init(const struct nft_ctx *ctx,struct nft_queue *priv =nft_expr_priv (expr);int err; - priv->sreg_qnum =nft_parse_register (tb[NFTA_QUEUE_SREG_QNUM ]); - err =nft_validate_register_load (priv->sreg_qnum,sizeof (u32)); + err =nft_parse_register_load (tb[NFTA_QUEUE_SREG_QNUM ], + &priv->sreg_qnum,sizeof (u32));if (err <0 )return err;
net/netfilter/nft_range.c +3 -3
@@ -15,7 +15,7 @@struct nft_range_expr {struct nft_data data_from;struct nft_data data_to; -enum nft_registers sreg:8 ; +u8 sreg;u8 len;enum nft_range_ops op:8 ; };
@@ -86,8 +86,8 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr goto err2; } - priv->sreg =nft_parse_register (tb[NFTA_RANGE_SREG ]); - err =nft_validate_register_load (priv->sreg, desc_from.len); + err =nft_parse_register_load (tb[NFTA_RANGE_SREG ], &priv->sreg, + desc_from.len);if (err <0 ) goto err2;
net/netfilter/nft_redir.c +7 -11
@@ -14,8 +14,8 @@#include <net/netfilter/nf_tables.h> struct nft_redir { -enum nft_registers sreg_proto_min:8 ; -enum nft_registers sreg_proto_max:8 ; +u8 sreg_proto_min; +u8 sreg_proto_max;u16 flags; };
@@ -50,19 +50,15 @@ static int nft_redir_init(const struct nft_ctx *ctx, plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);if (tb[NFTA_REDIR_REG_PROTO_MIN ]) { - priv->sreg_proto_min = -nft_parse_register (tb[NFTA_REDIR_REG_PROTO_MIN ]); - - err =nft_validate_register_load (priv->sreg_proto_min, plen); + err =nft_parse_register_load (tb[NFTA_REDIR_REG_PROTO_MIN ], + &priv->sreg_proto_min, plen);if (err <0 )return err;if (tb[NFTA_REDIR_REG_PROTO_MAX ]) { - priv->sreg_proto_max = -nft_parse_register (tb[NFTA_REDIR_REG_PROTO_MAX ]); - - err =nft_validate_register_load (priv->sreg_proto_max, - plen); + err =nft_parse_register_load (tb[NFTA_REDIR_REG_PROTO_MAX ], + &priv->sreg_proto_max, + plen);if (err <0 )return err; }else {
net/netfilter/nft_tproxy.c +7 -7
@@ -13,9 +13,9 @@#endif struct nft_tproxy { -enum nft_registers sreg_addr:8 ; -enum nft_registers sreg_port:8 ; -u8 family; +u8 sreg_addr; +u8 sreg_port; +u8 family; }; static void nft_tproxy_eval_v4(const struct nft_expr *expr,
@@ -254,15 +254,15 @@ static int nft_tproxy_init(const struct nft_ctx *ctx, }if (tb[NFTA_TPROXY_REG_ADDR ]) { - priv->sreg_addr =nft_parse_register (tb[NFTA_TPROXY_REG_ADDR ]); - err =nft_validate_register_load (priv->sreg_addr, alen); + err =nft_parse_register_load (tb[NFTA_TPROXY_REG_ADDR ], + &priv->sreg_addr, alen);if (err <0 )return err; }if (tb[NFTA_TPROXY_REG_PORT ]) { - priv->sreg_port =nft_parse_register (tb[NFTA_TPROXY_REG_PORT ]); - err =nft_validate_register_load (priv->sreg_port,sizeof (u16)); + err =nft_parse_register_load (tb[NFTA_TPROXY_REG_PORT ], + &priv->sreg_port,sizeof (u16));if (err <0 )return err; }
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 2/9 netfilter: nftables: add nft_parse_register_store() and use it
In reply to Pablo Neira Ayuso[ 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.
--- include/net/netfilter/nf_tables.h | 8 +++--- include/net/netfilter/nf_tables_core.h | 4 +-- include/net/netfilter/nft_fib.h | 2 +- include/net/netfilter/nft_meta.h | 2 +- net/bridge/netfilter/nft_meta_bridge.c | 5 ++-- net/netfilter/nf_tables_api.c | 34 ++++++++++++++++++++++---- net/netfilter/nft_bitwise.c | 8 +++--- net/netfilter/nft_byteorder.c | 8 +++--- net/netfilter/nft_ct.c | 7 +++--- net/netfilter/nft_exthdr.c | 8 +++--- net/netfilter/nft_fib.c | 5 ++-- net/netfilter/nft_hash.c | 17 ++++++------- net/netfilter/nft_immediate.c | 6 ++--- net/netfilter/nft_lookup.c | 8 +++--- net/netfilter/nft_meta.c | 5 ++-- net/netfilter/nft_numgen.c | 15 +++++------- net/netfilter/nft_osf.c | 8 +++--- net/netfilter/nft_payload.c | 6 ++--- net/netfilter/nft_rt.c | 7 +++--- net/netfilter/nft_socket.c | 7 +++--- net/netfilter/nft_tunnel.c | 8 +++--- net/netfilter/nft_xfrm.c | 7 +++--- 22 files changed, 97 insertions(+), 88 deletions(-)
include/net/netfilter/nf_tables.h +4 -4
@@ -209,10 +209,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
include/net/netfilter/nf_tables_core.h +2 -2
@@ -31,7 +31,7 @@ struct nft_cmp_fast_expr {struct nft_immediate_expr {struct nft_data data; -enum nft_registers dreg:8 ; +u8 dreg;u8 dlen; };
@@ -51,7 +51,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 {
include/net/netfilter/nft_fib.h +1 -1
@@ -5,7 +5,7 @@#include <net/netfilter/nf_tables.h> struct nft_fib { -enum nft_registers dreg:8 ; +u8 dreg;u8 result;u32 flags; };
include/net/netfilter/nft_meta.h +1 -1
@@ -7,7 +7,7 @@struct nft_meta {enum nft_meta_keys key:8 ;union { -enum nft_registers dreg:8 ; +u8 dreg;u8 sreg; }; };
net/bridge/netfilter/nft_meta_bridge.c +2 -3
@@ -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;
net/netfilter/nf_tables_api.c +29 -5
@@ -3839,6 +3839,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,
@@ -7465,10 +7471,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;
@@ -7500,7 +7507,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 },
net/netfilter/nft_bitwise.c +4 -4
@@ -17,7 +17,7 @@struct nft_bitwise {u8 sreg; -enum nft_registers dreg:8 ; +u8 dreg;u8 len;struct nft_data mask;struct nft_data xor;
@@ -70,9 +70,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;
net/netfilter/nft_byteorder.c +4 -4
@@ -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;
@@ -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)
net/netfilter/nft_ct.c +3 -4
@@ -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; }; };
@@ -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;
net/netfilter/nft_exthdr.c +4 -4
@@ -19,7 +19,7 @@ struct nft_exthdr {u8 offset;u8 len;u8 op; - enum nft_registers dreg:8; +u8 dreg;u8 sreg;u8 flags; };
@@ -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,
net/netfilter/nft_fib.c +2 -3
@@ -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 :
@@ -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;
net/netfilter/nft_hash.c +7 -10
@@ -15,7 +15,7 @@struct nft_jhash {u8 sreg; -enum nft_registers dreg:8 ; +u8 dreg;u8 len;bool autogen_seed:1 ;u32 modulus;
@@ -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; };
@@ -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;
@@ -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,
@@ -128,8 +126,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 ;
@@ -137,8 +133,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_jhash_dump(struct sk_buff *skb,
net/netfilter/nft_immediate.c +3 -3
@@ -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;
net/netfilter/nft_lookup.c +4 -4
@@ -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; };
@@ -97,9 +97,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 )
net/netfilter/nft_meta.c +2 -3
@@ -380,9 +380,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);
net/netfilter/nft_numgen.c +6 -9
@@ -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;
@@ -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,
@@ -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; };
@@ -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)
net/netfilter/nft_osf.c +4 -4
@@ -6,7 +6,7 @@#include <linux/netfilter/nfnetlink_osf.h> struct nft_osf { -enum nft_registers dreg:8 ; +u8 dreg;u8 ttl;u32 flags; };
@@ -83,9 +83,9 @@ static int nft_osf_init(const struct nft_ctx *ctx, priv->flags = flags; } - 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;
net/netfilter/nft_payload.c +3 -3
@@ -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)
net/netfilter/nft_rt.c +3 -4
@@ -15,7 +15,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)
@@ -141,9 +141,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,
net/netfilter/nft_socket.c +3 -4
@@ -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,
net/netfilter/nft_tunnel.c +3 -5
@@ -14,7 +14,7 @@struct nft_tunnel {enum nft_tunnel_keys key:8 ; -enum nft_registers dreg:8 ; +u8 dreg;enum nft_tunnel_mode mode:8 ; };
@@ -92,8 +92,6 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx,return -EOPNOTSUPP ; } - priv->dreg =nft_parse_register (tb[NFTA_TUNNEL_DREG ]); -if (tb[NFTA_TUNNEL_MODE ]) { priv->mode =ntohl (nla_get_be32 (tb[NFTA_TUNNEL_MODE ]));if (priv->mode >NFT_TUNNEL_MODE_MAX )
@@ -102,8 +100,8 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx, priv->mode =NFT_TUNNEL_MODE_NONE ; } -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,
net/netfilter/nft_xfrm.c +3 -4
@@ -24,7 +24,7 @@ static const struct nla_policy nft_xfrm_policy[NFTA_XFRM_MAX + 1] = {struct nft_xfrm {enum nft_xfrm_keys key:8 ; -enum nft_registers dreg:8 ; +u8 dreg;u8 dir;u8 spnum; };
@@ -86,9 +86,8 @@ static int nft_xfrm_get_init(const struct nft_ctx *ctx, priv->spnum = spnum; - priv->dreg =nft_parse_register (tb[NFTA_XFRM_DREG ]); -return nft_validate_register_store (ctx, priv->dreg,NULL , -NFT_DATA_VALUE , len); +return nft_parse_register_store (ctx, tb[NFTA_XFRM_DREG ], &priv->dreg, +NULL ,NFT_DATA_VALUE , len); }/* Return true if key asks for daddr/saddr and current
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 3/9 netfilter: nftables: statify nft_parse_register()
In reply to Pablo Neira Ayuso[ 08a01c11a5bb3de9b0a9c9b2685867e50eda9910 ]
This function is not used anymore by any extension, statify it.
--- include/net/netfilter/nf_tables.h | 1 - net/netfilter/nf_tables_api.c | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-)
include/net/netfilter/nf_tables.h +0 -1
@@ -205,7 +205,6 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type) }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_parse_register_load (const struct nlattr *attr,u8 *sreg,u32 len);
net/netfilter/nf_tables_api.c +1 -2
@@ -7385,7 +7385,7 @@ EXPORT_SYMBOL_GPL(nft_parse_u32_check);* Registers used to be 128 bit wide, these register numbers will be * mapped to the corresponding 32 bit register numbers. */ -unsigned int nft_parse_register (const struct nlattr *attr) +static unsigned int nft_parse_register (const struct nlattr *attr) {unsigned int reg;
@@ -7397,7 +7397,6 @@ unsigned int nft_parse_register(const struct nlattr *attr)return reg +NFT_REG_SIZE /NFT_REG32_SIZE -NFT_REG32_00 ; } } -EXPORT_SYMBOL_GPL (nft_parse_register);/** * nft_dump_register - dump a register value to a netlink attribute
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 4/9 netfilter: nf_tables: validate registers coming from userspace.
In reply to Pablo Neira Ayuso[ 6e1acfa387b9ff82cfc7db8cc3b6959221a95851 ]
Bail out in case userspace uses unsupported registers.
--- net/netfilter/nf_tables_api.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-)
net/netfilter/nf_tables_api.c +17 -14
@@ -7376,26 +7376,23 @@ int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest) }EXPORT_SYMBOL_GPL (nft_parse_u32_check); -/** -* nft_parse_register - parse a register value from a netlink attribute -* -* @attr: netlink attribute -* -* Parse and translate a register value from a netlink attribute. -* Registers used to be 128 bit wide, these register numbers will be -* mapped to the corresponding 32 bit register numbers. -*/ -static unsigned int nft_parse_register (const struct nlattr *attr) +static int nft_parse_register (const struct nlattr *attr,u32 *preg) {unsigned int reg; reg =ntohl (nla_get_be32 (attr));switch (reg) { case NFT_REG_VERDICT...NFT_REG_4: -return reg *NFT_REG_SIZE /NFT_REG32_SIZE ; + *preg = reg *NFT_REG_SIZE /NFT_REG32_SIZE ; +break ; + case NFT_REG32_00...NFT_REG32_15: + *preg = reg +NFT_REG_SIZE /NFT_REG32_SIZE -NFT_REG32_00 ; +break ;default : -return reg +NFT_REG_SIZE /NFT_REG32_SIZE -NFT_REG32_00 ; +return -ERANGE ; } + +return 0 ; }/**
@@ -7446,7 +7443,10 @@ int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)u32 reg;int err; - reg =nft_parse_register (attr); + err =nft_parse_register (attr, ®); +if (err <0 ) +return err; + err =nft_validate_register_load (reg, len);if (err <0 )return err;
@@ -7515,7 +7515,10 @@ int nft_parse_register_store(const struct nft_ctx *ctx,int err;u32 reg; - reg =nft_parse_register (attr); + err =nft_parse_register (attr, ®); +if (err <0 ) +return err; + err =nft_validate_register_store (ctx, reg, data, type, len);if (err <0 )return err;
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 5/9 netfilter: nf_tables: add nft_setelem_parse_key()
In reply to Pablo Neira Ayuso[ 20a1452c35425b2cef76f21f8395ef069dfddfa9 ]
Add helper function to parse the set element key netlink attribute.
v4: No changes
v3: New patch
[sbrivio: refactor error paths and labels; use NFT_DATA_VALUE_MAXLEN
instead of sizeof(*key) in helper, value can be longer than that; rebase]
--- net/netfilter/nf_tables_api.c | 91 +++++++++++++++++------------------ 1 file changed, 45 insertions(+), 46 deletions(-)
net/netfilter/nf_tables_api.c +45 -46
@@ -4280,11 +4280,28 @@ static int nft_setelem_parse_flags(const struct nft_set *set,return 0 ; } +static int nft_setelem_parse_key (struct nft_ctx *ctx,struct nft_set *set, +struct nft_data *key,struct nlattr *attr) +{ +struct nft_data_desc desc; +int err; + + err =nft_data_init (ctx, key,NFT_DATA_VALUE_MAXLEN , &desc, attr); +if (err <0 ) +return err; + +if (desc.type !=NFT_DATA_VALUE || desc.len != set->klen) { +nft_data_release (key, desc.type); +return -EINVAL ; + } + +return 0 ; +} +static int nft_get_set_elem (struct nft_ctx *ctx,struct nft_set *set,const struct nlattr *attr) {struct nlattr *nla[NFTA_SET_ELEM_MAX +1 ]; -struct nft_data_desc desc;struct nft_set_elem elem;struct sk_buff *skb;uint32_t flags =0 ;
@@ -4303,17 +4320,11 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,if (err <0 )return err; - err =nft_data_init (ctx, &elem.key.val,sizeof (elem.key), &desc, - nla[NFTA_SET_ELEM_KEY ]); + err =nft_setelem_parse_key (ctx, set, &elem.key.val, + nla[NFTA_SET_ELEM_KEY ]);if (err <0 )return err; - err = -EINVAL ; -if (desc.type !=NFT_DATA_VALUE || desc.len != set->klen) { -nft_data_release (&elem.key.val, desc.type); -return err; - } - priv = set->ops->get (ctx->net, set, &elem, flags);if (IS_ERR (priv))return PTR_ERR (priv);
@@ -4506,13 +4517,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, {struct nlattr *nla[NFTA_SET_ELEM_MAX +1 ];u8 genmask =nft_genmask_next (ctx->net); -struct nft_data_desc d1, d2;struct nft_set_ext_tmpl tmpl;struct nft_set_ext *ext, *ext2;struct nft_set_elem elem;struct nft_set_binding *binding;struct nft_object *obj =NULL ;struct nft_userdata *udata; +struct nft_data_desc desc;struct nft_data data;enum nft_registers dreg;struct nft_trans *trans;
@@ -4578,15 +4589,12 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,return err; } - err =nft_data_init (ctx, &elem.key.val,sizeof (elem.key), &d1, - nla[NFTA_SET_ELEM_KEY ]); + err =nft_setelem_parse_key (ctx, set, &elem.key.val, + nla[NFTA_SET_ELEM_KEY ]);if (err <0 ) goto err1; - err = -EINVAL ; -if (d1.type !=NFT_DATA_VALUE || d1.len != set->klen) - goto err2; -nft_set_ext_add_length (&tmpl,NFT_SET_EXT_KEY , d1.len); +nft_set_ext_add_length (&tmpl,NFT_SET_EXT_KEY , set->klen);if (timeout >0 ) {nft_set_ext_add (&tmpl,NFT_SET_EXT_EXPIRATION );if (timeout != set->timeout)
@@ -4609,13 +4617,13 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, }if (nla[NFTA_SET_ELEM_DATA ] !=NULL ) { - err =nft_data_init (ctx, &data,sizeof (data), &d2, + err =nft_data_init (ctx, &data,sizeof (data), &desc, nla[NFTA_SET_ELEM_DATA ]);if (err <0 ) goto err2; err = -EINVAL ; -if (set->dtype !=NFT_DATA_VERDICT && d2.len != set->dlen) +if (set->dtype !=NFT_DATA_VERDICT && desc.len != set->dlen) goto err3; dreg =nft_type_to_reg (set->dtype);
@@ -4632,18 +4640,18 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, err =nft_validate_register_store (&bind_ctx, dreg, &data, - d2.type, d2.len); + desc.type, desc.len);if (err <0 ) goto err3; -if (d2.type ==NFT_DATA_VERDICT && +if (desc.type ==NFT_DATA_VERDICT && (data.verdict.code ==NFT_GOTO || data.verdict.code ==NFT_JUMP ))nft_validate_state_update (ctx->net,NFT_VALIDATE_NEED ); } -nft_set_ext_add_length (&tmpl,NFT_SET_EXT_DATA , d2.len); +nft_set_ext_add_length (&tmpl,NFT_SET_EXT_DATA , desc.len); }/* The full maximum length of userdata can exceed the maximum
@@ -4726,9 +4734,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,kfree (elem.priv); err3:if (nla[NFTA_SET_ELEM_DATA ] !=NULL ) -nft_data_release (&data, d2.type); +nft_data_release (&data, desc.type); err2: -nft_data_release (&elem.key.val, d1.type); +nft_data_release (&elem.key.val,NFT_DATA_VALUE ); err1:return err; }
@@ -4824,7 +4832,6 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, {struct nlattr *nla[NFTA_SET_ELEM_MAX +1 ];struct nft_set_ext_tmpl tmpl; -struct nft_data_desc desc;struct nft_set_elem elem;struct nft_set_ext *ext;struct nft_trans *trans;
@@ -4835,11 +4842,10 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, err =nla_parse_nested_deprecated (nla,NFTA_SET_ELEM_MAX , attr, nft_set_elem_policy,NULL );if (err <0 ) - goto err1; +return err; - err = -EINVAL ;if (nla[NFTA_SET_ELEM_KEY ] ==NULL ) - goto err1; +return -EINVAL ;nft_set_ext_prepare (&tmpl);
@@ -4849,37 +4855,31 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,if (flags !=0 )nft_set_ext_add (&tmpl,NFT_SET_EXT_FLAGS ); - err =nft_data_init (ctx, &elem.key.val,sizeof (elem.key), &desc, - nla[NFTA_SET_ELEM_KEY ]); + err =nft_setelem_parse_key (ctx, set, &elem.key.val, + nla[NFTA_SET_ELEM_KEY ]);if (err <0 ) - goto err1; - - err = -EINVAL ; -if (desc.type !=NFT_DATA_VALUE || desc.len != set->klen) - goto err2; +return err; -nft_set_ext_add_length (&tmpl,NFT_SET_EXT_KEY , desc.len); +nft_set_ext_add_length (&tmpl,NFT_SET_EXT_KEY , set->klen); err = -ENOMEM ; elem.priv =nft_set_elem_init (set, &tmpl, elem.key.val.data,NULL ,0 ,0 ,GFP_KERNEL );if (elem.priv ==NULL ) - goto err2; + goto fail_elem; ext =nft_set_elem_ext (set, elem.priv);if (flags) *nft_set_ext_flags (ext) = flags; trans =nft_trans_elem_alloc (ctx,NFT_MSG_DELSETELEM , set); -if (trans ==NULL ) { - err = -ENOMEM ; - goto err3; - } +if (trans ==NULL ) + goto fail_trans; priv = set->ops->deactivate (ctx->net, set, &elem);if (priv ==NULL ) { err = -ENOENT ; - goto err4; + goto fail_ops; }kfree (elem.priv); elem.priv = priv;
@@ -4890,13 +4890,12 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,list_add_tail (&trans->list, &ctx->net->nft.commit_list);return 0 ; -err4: +fail_ops:kfree (trans); -err3: +fail_trans:kfree (elem.priv); -err2: -nft_data_release (&elem.key.val, desc.type); -err1: +fail_elem: +nft_data_release (&elem.key.val,NFT_DATA_VALUE );return err; }
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 6/9 netfilter: nf_tables: allow up to 64 bytes in the set element data area
In reply to Pablo Neira Ayuso[ fdb9c405e35bdc6e305b9b4e20ebc141ed14fc81 ]
So far, the set elements could store up to 128-bits in the data area.
--- include/net/netfilter/nf_tables.h | 4 +++ net/netfilter/nf_tables_api.c | 41 +++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 13 deletions(-)
include/net/netfilter/nf_tables.h +4 -0
@@ -239,6 +239,10 @@ struct nft_set_elem {u32 buf[NFT_DATA_VALUE_MAXLEN /sizeof (u32)];struct nft_data val; } key; +union { +u32 buf[NFT_DATA_VALUE_MAXLEN /sizeof (u32)]; +struct nft_data val; + } data;void *priv; };
net/netfilter/nf_tables_api.c +28 -13
85 lines not on this page · raw message
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 7/9 netfilter: nf_tables: stricter validation of element data
In reply to Pablo Neira Ayuso[ 7e6bc1f6cabcd30aba0b11219d8e01b952eacbb6 ]
Make sure element data type and length do not mismatch the one specified by the set declaration.
--- net/netfilter/nf_tables_api.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
net/netfilter/nf_tables_api.c +8 -1
@@ -4303,13 +4303,20 @@ static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set,struct nft_data *data, struct nlattr *attr) { + u32 dtype;int err; err =nft_data_init (ctx, data,NFT_DATA_VALUE_MAXLEN , desc, attr);if (err <0 )return err; -if (desc->type !=NFT_DATA_VERDICT && desc->len != set->dlen) { +if (set->dtype ==NFT_DATA_VERDICT ) + dtype =NFT_DATA_VERDICT ; +else + dtype =NFT_DATA_VALUE ; + +if (dtype != desc->type || + set->dlen != desc->len) {nft_data_release (data, desc->type);return -EINVAL ; }
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 8/9 netfilter: nf_tables: validate NFTA_SET_ELEM_OBJREF based on NFT_SET_OBJECT flag
In reply to Pablo Neira Ayuso[ 5a2f3dc31811e93be15522d9eb13ed61460b76c8 ]
If the NFTA_SET_ELEM_OBJREF netlink attribute is present and NFT_SET_OBJECT flag is set on, report EINVAL.
Move existing sanity check earlier to validate that NFT_SET_OBJECT requires NFTA_SET_ELEM_OBJREF.
--- net/netfilter/nf_tables_api.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
net/netfilter/nf_tables_api.c +9 -4
@@ -4583,6 +4583,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,return -EINVAL ; } +if (set->flags &NFT_SET_OBJECT ) { +if (!nla[NFTA_SET_ELEM_OBJREF ] && + !(flags &NFT_SET_ELEM_INTERVAL_END )) +return -EINVAL ; + }else { +if (nla[NFTA_SET_ELEM_OBJREF ]) +return -EINVAL ; + } + if ((flags & NFT_SET_ELEM_INTERVAL_END) && (nla[NFTA_SET_ELEM_DATA] || nla[NFTA_SET_ELEM_OBJREF] ||
@@ -4627,10 +4636,6 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, }if (nla[NFTA_SET_ELEM_OBJREF ] !=NULL ) { -if (!(set->flags &NFT_SET_OBJECT )) { - err = -EINVAL ; - goto err2; - } obj =nft_obj_lookup (ctx->net, ctx->table, nla[NFTA_SET_ELEM_OBJREF ], set->objtype, genmask);
Signature · 1 line
2.30.2
Pablo Neira Ayuso
maintainerPATCH 9/9 netfilter: nf_tables: hold mutex on netns pre_exit path
In reply to Pablo Neira Ayuso[ 3923b1e4406680d57da7e873da77b1683035d83f ]
clean_net() runs in workqueue while walking over the lists, grab mutex.
--- net/netfilter/nf_tables_api.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/nf_tables_api.c +2 -0
@@ -7858,7 +7858,9 @@ static int __net_init nf_tables_init_net(struct net *net) static void __net_exit nf_tables_pre_exit_net(struct net *net) { +mutex_lock (&net->nft.commit_mutex);__nft_release_hooks (net); +mutex_unlock (&net->nft.commit_mutex); } static void __net_exit nf_tables_exit_net(struct net *net)
Signature · 1 line
2.30.2