Netfilter updates for net-next
Subsystems (5)
Pablo Neira Ayuso
maintainercover Netfilter updates for net-next
Hi David,
The following patchset contains Netfilter updates for your net-next tree:
1) Support for matching on ipsec policy already set in the route, from Florian Westphal.
2) Split set destruction into deactivate and destroy phase to make it fit better into the transaction infrastructure, also from Florian. This includes a patch to warn on imbalance when setting the new activate and deactivate interfaces.
3) Release transaction list from the workqueue to remove expensive synchronize_rcu() from configuration plane path. This speeds up configuration plane quite a bit. From Florian Westphal.
4) Add new xfrm/ipsec extension, this new extension allows you to match for ipsec tunnel keys such as source and destination address, spi and reqid. From Máté Eckl and Florian Westphal.
5) Add secmark support, this includes connsecmark too, patches from Christian Gottsche.
6) Allow to specify remaining bytes in xt_quota, from Chenbo Feng. One follow up patch to calm a clang warning for this one, from Nathan Chancellor.
7) Flush conntrack entries based on layer 3 family, from Kristian Evensen.
8) New revision for cgroups2 to shrink the path field.
9) Get rid of obsolete need_conntrack(), as a result from recent demodularization works.
10) Use WARN_ON instead of BUG_ON, from Florian Westphal.
11) Unused exported symbol in nf_nat_ipv4_fn(), from Florian.
12) Remove superfluous check for timeout netlink parser and dump functions in layer 4 conntrack helpers.
13) Unnecessary redundant rcu read side locks in NAT redirect, from Taehee Yoo.
14) Pass nf_hook_state structure to error handlers, patch from Florian Westphal.
15) Remove ->new() interface from layer 4 protocol trackers. Place
them in the ->packet() interface. From Florian.
16) Place conntrack ->error() handling in the ->packet() interface. Patches from Florian Westphal.
17) Remove unused parameter in the pernet initialization path, also from Florian.
18) Remove additional parameter to specify layer 3 protocol when looking up for protocol tracker. From Florian.
19) Shrink array of layer 4 protocol trackers, from Florian.
20) Check for linear skb only once from the ALG NAT mangling codebase, from Taehee Yoo.
21) Use rhashtable_walk_enter() instead of deprecated rhashtable_walk_init(), also from Taehee.
22) No need to flush all conntracks when only one single address is gone, from Tan Hu.
23) Remove redundant check for NAT flags in flowtable code, from Taehee Yoo.
24) Use rhashtable_lookup() instead of rhashtable_lookup_fast() from netfilter codebase, since rcu read lock side is already assumed in this path.
You can pull these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git
Thanks.
----------------------------------------------------------------
The following changes since commit a82738adff167593bbb9df90b4201ce4b3407d21:
ip6_gre: simplify gre header parsing in ip6gre_err (2018-09-16 15:32:59 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git HEAD
for you to fetch changes up to ffa0a9a5903e9fcfde71a0200af30692ac223ef7:
netfilter: xt_quota: Don't use aligned attribute in sizeof (2018-10-09 00:19:25 +0200)
----------------------------------------------------------------
Chenbo Feng (1):
netfilter: xt_quota: fix the behavior of xt_quota module
Christian Göttsche (2):
netfilter: nf_tables: add SECMARK support
netfilter: nf_tables: add requirements for connsecmark support
Florian Westphal (18):
netfilter: nf_tables: rt: allow checking if dst has xfrm attached
netfilter: nf_tables: split set destruction in deactivate and destroy phase
netfilter: nf_tables: warn when expr implements only one of activate/deactivate
netfilter: nf_tables: asynchronous release
netfilter: remove obsolete need_conntrack stub
netfilter: nf_tables: add xfrm expression
netfilter: nf_tables: avoid BUG_ON usage
netfilter: xtables: avoid BUG_ON
netfilter: nf_nat_ipv4: remove obsolete EXPORT_SYMBOL
netfilter: conntrack: pass nf_hook_state to packet and error handlers
netfilter: conntrack: remove the l4proto->new() function
netfilter: conntrack: deconstify packet callback skb pointer
netfilter: conntrack: avoid using ->error callback if possible
netfilter: conntrack: remove error callback and handle icmp from core
netfilter: conntrack: remove unused proto arg from netns init functions
netfilter: conntrack: remove l3->l4 mapping information
netfilter: conntrack: clamp l4proto array size at largers supported protocol
netfilter: ctnetlink: must check mark attributes vs NULL
Kristian Evensen (1):
netfilter: ctnetlink: Support L3 protocol-filter on flush
Nathan Chancellor (1):
netfilter: xt_quota: Don't use aligned attribute in sizeof
Pablo Neira Ayuso (2):
netfilter: xt_cgroup: shrink size of v2 path
netfilter: cttimeout: remove superfluous check on layer 4 netlink functions
Taehee Yoo (5):
netfilter: nat: remove unnecessary rcu_read_lock in nf_nat_redirect_ipv{4/6}
netfilter: nat: remove duplicate skb_is_nonlinear() in __nf_nat_mangle_tcp_packet()
netfilter: nf_tables: use rhashtable_walk_enter instead of rhashtable_walk_init
netfilter: nf_flow_table: remove unnecessary nat flag check code
netfilter: nf_tables: use rhashtable_lookup() instead of rhashtable_lookup_fast()
Tan Hu (1):
netfilter: masquerade: don't flush all conntracks if only one address deleted on device
include/linux/netfilter/nf_conntrack_common.h | 3 - include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 13 +- include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 13 -- include/net/netfilter/nf_conntrack_core.h | 3 +- include/net/netfilter/nf_conntrack_l4proto.h | 36 ++- include/net/netfilter/nf_tables.h | 9 +- include/net/netfilter/nf_tables_core.h | 4 + include/uapi/linux/netfilter/nf_tables.h | 49 ++++- include/uapi/linux/netfilter/xt_cgroup.h | 16 ++ include/uapi/linux/netfilter/xt_quota.h | 8 +- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 1 - net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 22 +- net/ipv6/netfilter/ip6t_ipv6header.c | 5 +- net/ipv6/netfilter/ip6t_rt.c | 10 +- net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 19 +- net/netfilter/Kconfig | 7 + net/netfilter/Makefile | 1 + net/netfilter/nf_conntrack_core.c | 105 +++++---- net/netfilter/nf_conntrack_expect.c | 3 +- net/netfilter/nf_conntrack_netlink.c | 73 +++--- net/netfilter/nf_conntrack_proto.c | 117 +++------- net/netfilter/nf_conntrack_proto_dccp.c | 155 +++++-------- net/netfilter/nf_conntrack_proto_generic.c | 28 +-- net/netfilter/nf_conntrack_proto_gre.c | 44 ++-- net/netfilter/nf_conntrack_proto_icmp.c | 78 +++---- net/netfilter/nf_conntrack_proto_icmpv6.c | 80 +++---- net/netfilter/nf_conntrack_proto_sctp.c | 253 +++++++++------------ net/netfilter/nf_conntrack_proto_tcp.c | 251 +++++++++------------ net/netfilter/nf_conntrack_proto_udp.c | 236 +++++++++----------- net/netfilter/nf_conntrack_standalone.c | 9 +- net/netfilter/nf_flow_table_core.c | 41 ++-- net/netfilter/nf_flow_table_ip.c | 6 +- net/netfilter/nf_nat_helper.c | 4 +- net/netfilter/nf_nat_redirect.c | 4 - net/netfilter/nf_tables_api.c | 120 ++++++++-- net/netfilter/nf_tables_core.c | 28 ++- net/netfilter/nfnetlink_cttimeout.c | 59 ++--- net/netfilter/nft_cmp.c | 6 +- net/netfilter/nft_ct.c | 22 +- net/netfilter/nft_dynset.c | 21 +- net/netfilter/nft_lookup.c | 20 +- net/netfilter/nft_meta.c | 116 ++++++++++ net/netfilter/nft_objref.c | 20 +- net/netfilter/nft_reject.c | 6 +- net/netfilter/nft_rt.c | 11 + net/netfilter/nft_set_hash.c | 38 +--- net/netfilter/nft_xfrm.c | 293 +++++++++++++++++++++++++ net/netfilter/xt_CT.c | 2 +- net/netfilter/xt_IDLETIMER.c | 4 - net/netfilter/xt_SECMARK.c | 2 - net/netfilter/xt_cgroup.c | 72 ++++++ net/netfilter/xt_quota.c | 55 ++--- net/openvswitch/conntrack.c | 8 +- 53 files changed, 1555 insertions(+), 1054 deletions(-) create mode 100644 net/netfilter/nft_xfrm.c
Pablo Neira Ayuso
maintainerPATCH 1/31 netfilter: nf_tables: rt: allow checking if dst has xfrm attached
From: Florian Westphal <[email protected]>
Useful e.g. to avoid NATting inner headers of to-be-encrypted packets.
--- include/uapi/linux/netfilter/nf_tables.h | 2 ++ net/netfilter/nft_rt.c | 11 +++++++++++ 2 files changed, 13 insertions(+)
include/uapi/linux/netfilter/nf_tables.h +2 -0
@@ -826,12 +826,14 @@ enum nft_meta_keys {* @NFT_RT_NEXTHOP4: routing nexthop for IPv4 * @NFT_RT_NEXTHOP6: routing nexthop for IPv6 * @NFT_RT_TCPMSS: fetch current path tcp mss +* @NFT_RT_XFRM: boolean, skb->dst->xfrm != NULL */ enum nft_rt_keys {NFT_RT_CLASSID ,NFT_RT_NEXTHOP4 ,NFT_RT_NEXTHOP6 ,NFT_RT_TCPMSS , +NFT_RT_XFRM , __NFT_RT_MAX };#define NFT_RT_MAX (__NFT_RT_MAX - 1)
net/netfilter/nft_rt.c +11 -0
@@ -90,6 +90,11 @@ static void nft_rt_get_eval(const struct nft_expr *expr,case NFT_RT_TCPMSS :nft_reg_store16 (dest,get_tcpmss (pkt, dst));break ; +#ifdef CONFIG_XFRM +case NFT_RT_XFRM : +nft_reg_store8 (dest, !!dst->xfrm); +break ; +#endif default :WARN_ON (1 ); goto err;
@@ -130,6 +135,11 @@ static int nft_rt_get_init(const struct nft_ctx *ctx,case NFT_RT_TCPMSS : len =sizeof (u16);break ; +#ifdef CONFIG_XFRM +case NFT_RT_XFRM : + len =sizeof (u8); +break ; +#endif default :return -EOPNOTSUPP ; }
@@ -164,6 +174,7 @@ static int nft_rt_validate(const struct nft_ctx *ctx, const struct nft_expr *expcase NFT_RT_NEXTHOP4 :case NFT_RT_NEXTHOP6 :case NFT_RT_CLASSID : +case NFT_RT_XFRM :return 0 ;case NFT_RT_TCPMSS : hooks = (1 << NF_INET_FORWARD) |
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 2/31 netfilter: nf_tables: split set destruction in deactivate and destroy phase
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Splits unbind_set into destroy_set and unbinding operation.
Unbinding removes set from lists (so new transaction would not find it anymore) but keeps memory allocated (so packet path continues to work).
Rebind function is added to allow unrolling in case transaction that wants to remove set is aborted.
Destroy function is added to free the memory, but this could occur outside of transaction in the future.
--- include/net/netfilter/nf_tables.h | 7 ++++++- net/netfilter/nf_tables_api.c | 36 +++++++++++++++++++++++++----------- net/netfilter/nft_dynset.c | 21 ++++++++++++++++++++- net/netfilter/nft_lookup.c | 20 +++++++++++++++++++- net/netfilter/nft_objref.c | 20 +++++++++++++++++++- 5 files changed, 89 insertions(+), 15 deletions(-)
include/net/netfilter/nf_tables.h +6 -1
@@ -470,6 +470,9 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, struct nft_set_binding *binding);void nf_tables_unbind_set (const struct nft_ctx *ctx,struct nft_set *set,struct nft_set_binding *binding); +void nf_tables_rebind_set (const struct nft_ctx *ctx,struct nft_set *set, +struct nft_set_binding *binding); +void nf_tables_destroy_set (const struct nft_ctx *ctx,struct nft_set *set);/** * enum nft_set_extensions - set extension type IDs
@@ -724,7 +727,9 @@ struct nft_expr_type {* @eval: Expression evaluation function * @size: full expression size, including private data size * @init: initialization function -* @destroy: destruction function +* @activate: activate expression in the next generation +* @deactivate: deactivate expression in next generation +* @destroy: destruction function, called after synchronize_rcu * @dump: function to dump parameters * @type: expression type * @validate: validate expression, called during loop detection
net/netfilter/nf_tables_api.c +25 -11
@@ -298,7 +298,7 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)return 0 ; } -static int nft_trans_set_add (struct nft_ctx *ctx,int msg_type, +static int nft_trans_set_add (const struct nft_ctx *ctx,int msg_type,struct nft_set *set) {struct nft_trans *trans;
@@ -318,7 +318,7 @@ static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,return 0 ; } -static int nft_delset (struct nft_ctx *ctx,struct nft_set *set) +static int nft_delset (const struct nft_ctx *ctx,struct nft_set *set) {int err;
@@ -3567,13 +3567,6 @@ static void nft_set_destroy(struct nft_set *set)kvfree (set); } -static void nf_tables_set_destroy (const struct nft_ctx *ctx,struct nft_set *set) -{ -list_del_rcu (&set->list); -nf_tables_set_notify (ctx, set,NFT_MSG_DELSET ,GFP_ATOMIC ); -nft_set_destroy (set); -} - static int nf_tables_delset(struct net *net, struct sock *nlsk, struct sk_buff *skb, const struct nlmsghdr *nlh, const struct nlattr * const nla[],
@@ -3668,17 +3661,38 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set, }EXPORT_SYMBOL_GPL (nf_tables_bind_set); -void nf_tables_unbind_set (const struct nft_ctx *ctx,struct nft_set *set, +void nf_tables_rebind_set (const struct nft_ctx *ctx,struct nft_set *set,struct nft_set_binding *binding) { +if (list_empty (&set->bindings) &&nft_set_is_anonymous (set) && +nft_is_active (ctx->net, set)) +list_add_tail_rcu (&set->list, &ctx->table->sets); + +list_add_tail_rcu (&binding->list, &set->bindings); +} +EXPORT_SYMBOL_GPL (nf_tables_rebind_set); + +void nf_tables_unbind_set (const struct nft_ctx *ctx,struct nft_set *set, +struct nft_set_binding *binding) +{list_del_rcu (&binding->list);if (list_empty (&set->bindings) &&nft_set_is_anonymous (set) &&nft_is_active (ctx->net, set)) -nf_tables_set_destroy (ctx, set); +list_del_rcu (&set->list); }EXPORT_SYMBOL_GPL (nf_tables_unbind_set); +void nf_tables_destroy_set (const struct nft_ctx *ctx,struct nft_set *set) +{ +if (list_empty (&set->bindings) &&nft_set_is_anonymous (set) && +nft_is_active (ctx->net, set)) { +nf_tables_set_notify (ctx, set,NFT_MSG_DELSET ,GFP_ATOMIC ); +nft_set_destroy (set); + } +} +EXPORT_SYMBOL_GPL (nf_tables_destroy_set); +const struct nft_set_ext_type nft_set_ext_types[] = { [NFT_SET_EXT_KEY ] = { .align = __alignof__(u32 ),
net/netfilter/nft_dynset.c +20 -1
@@ -235,14 +235,31 @@ static int nft_dynset_init(const struct nft_ctx *ctx,return err; } +static void nft_dynset_activate (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_dynset *priv =nft_expr_priv (expr); + +nf_tables_rebind_set (ctx, priv->set, &priv->binding); +} + +static void nft_dynset_deactivate (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_dynset *priv =nft_expr_priv (expr); + +nf_tables_unbind_set (ctx, priv->set, &priv->binding); +} +static void nft_dynset_destroy (const struct nft_ctx *ctx,const struct nft_expr *expr) {struct nft_dynset *priv =nft_expr_priv (expr); -nf_tables_unbind_set (ctx, priv->set, &priv->binding);if (priv->expr !=NULL )nft_expr_destroy (ctx, priv->expr); + +nf_tables_destroy_set (ctx, priv->set); }static int nft_dynset_dump (struct sk_buff *skb,const struct nft_expr *expr)
@@ -279,6 +296,8 @@ static const struct nft_expr_ops nft_dynset_ops = { .eval = nft_dynset_eval, .init = nft_dynset_init, .destroy = nft_dynset_destroy, + .activate = nft_dynset_activate, + .deactivate = nft_dynset_deactivate, .dump = nft_dynset_dump, };
net/netfilter/nft_lookup.c +19 -1
@@ -121,12 +121,28 @@ static int nft_lookup_init(const struct nft_ctx *ctx,return 0 ; } +static void nft_lookup_activate (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_lookup *priv =nft_expr_priv (expr); + +nf_tables_rebind_set (ctx, priv->set, &priv->binding); +} + +static void nft_lookup_deactivate (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_lookup *priv =nft_expr_priv (expr); + +nf_tables_unbind_set (ctx, priv->set, &priv->binding); +} +static void nft_lookup_destroy (const struct nft_ctx *ctx,const struct nft_expr *expr) {struct nft_lookup *priv =nft_expr_priv (expr); -nf_tables_unbind_set (ctx, priv->set, &priv->binding); +nf_tables_destroy_set (ctx, priv->set); }static int nft_lookup_dump (struct sk_buff *skb,const struct nft_expr *expr)
@@ -209,6 +225,8 @@ static const struct nft_expr_ops nft_lookup_ops = { .size = NFT_EXPR_SIZE(sizeof(struct nft_lookup)), .eval = nft_lookup_eval, .init = nft_lookup_init, + .activate = nft_lookup_activate, + .deactivate = nft_lookup_deactivate, .destroy = nft_lookup_destroy, .dump = nft_lookup_dump, .validate = nft_lookup_validate,
net/netfilter/nft_objref.c +19 -1
@@ -155,12 +155,28 @@ static int nft_objref_map_dump(struct sk_buff *skb, const struct nft_expr *expr)return -1 ; } +static void nft_objref_map_activate (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_objref_map *priv =nft_expr_priv (expr); + +nf_tables_rebind_set (ctx, priv->set, &priv->binding); +} + +static void nft_objref_map_deactivate (const struct nft_ctx *ctx, +const struct nft_expr *expr) +{ +struct nft_objref_map *priv =nft_expr_priv (expr); + +nf_tables_unbind_set (ctx, priv->set, &priv->binding); +} +static void nft_objref_map_destroy (const struct nft_ctx *ctx,const struct nft_expr *expr) {struct nft_objref_map *priv =nft_expr_priv (expr); -nf_tables_unbind_set (ctx, priv->set, &priv->binding); +nf_tables_destroy_set (ctx, priv->set); }static struct nft_expr_type nft_objref_type;
@@ -169,6 +185,8 @@ static const struct nft_expr_ops nft_objref_map_ops = { .size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)), .eval = nft_objref_map_eval, .init = nft_objref_map_init, + .activate = nft_objref_map_activate, + .deactivate = nft_objref_map_deactivate, .destroy = nft_objref_map_destroy, .dump = nft_objref_map_dump, };
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 3/31 netfilter: nf_tables: warn when expr implements only one of activate/deactivate
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
->destroy is only allowed to free data, or do other cleanups that do not have side effects on other state, such as visibility to other netlink requests.
Such things need to be done in ->deactivate.
As a transaction can fail, we need to make sure we can undo such operations, therefore ->activate() has to be provided too.
So print a warning and refuse registration if expr->ops provides only one of the two operations.
v2: fix nft_expr_check_ops to not repeat same check twice (Jones Desougi)
--- net/netfilter/nf_tables_api.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
net/netfilter/nf_tables_api.c +19 -0
@@ -207,6 +207,18 @@ static int nft_delchain(struct nft_ctx *ctx)return err; } +/* either expr ops provide both activate/deactivate, or neither */ +static bool nft_expr_check_ops (const struct nft_expr_ops *ops) +{ +if (!ops) +return true; + +if (WARN_ON_ONCE ((!ops->activate ^ !ops->deactivate))) +return false; + +return true; +} +static void nft_rule_expr_activate (const struct nft_ctx *ctx,struct nft_rule *rule) {
@@ -1907,6 +1919,9 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,*/ int nft_register_expr (struct nft_expr_type *type) { +if (!nft_expr_check_ops (type->ops)) +return -EINVAL ; +nfnl_lock (NFNL_SUBSYS_NFTABLES );if (type->family ==NFPROTO_UNSPEC )list_add_tail_rcu (&type->list, &nf_tables_expressions);
@@ -2054,6 +2069,10 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx, err =PTR_ERR (ops); goto err1; } +if (!nft_expr_check_ops (ops)) { + err = -EINVAL ; + goto err1; + } }else ops = type->ops;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 4/31 netfilter: nf_tables: asynchronous release
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Release the committed transaction log from a work queue, moving expensive synchronize_rcu out of the locked section and providing opportunity to batch this.
On my test machine this cuts runtime of nft-test.py in half. Based on earlier patch from Pablo Neira Ayuso.
--- include/net/netfilter/nf_tables.h | 2 ++ net/netfilter/nf_tables_api.c | 56 ++++++++++++++++++++++++++++++++++----- 2 files changed, 52 insertions(+), 6 deletions(-)
include/net/netfilter/nf_tables.h +2 -0
@@ -1298,12 +1298,14 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)* * @list: used internally * @msg_type: message type +* @put_net: ctx->net needs to be put * @ctx: transaction context * @data: internal information related to the transaction */ struct nft_trans {struct list_head list;int msg_type; +bool put_net;struct nft_ctx ctx;char data[0 ]; };
net/netfilter/nf_tables_api.c +50 -6
115 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 5/31 netfilter: remove obsolete need_conntrack stub
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
as of a0ae2562c6c4b27 ("netfilter: conntrack: remove l3proto abstraction") there are no users anymore.
--- include/linux/netfilter/nf_conntrack_common.h | 3 --- net/netfilter/nf_conntrack_standalone.c | 7 ------- 2 files changed, 10 deletions(-)
include/linux/netfilter/nf_conntrack_common.h +0 -3
@@ -19,7 +19,4 @@ struct ip_conntrack_stat { unsigned int search_restart; }; -/* call to create an explicit dependency on nf_conntrack. */ -void need_conntrack (void ); -#endif /* _NF_CONNTRACK_COMMON_H */
net/netfilter/nf_conntrack_standalone.c +0 -7
@@ -720,10 +720,3 @@ static void __exit nf_conntrack_standalone_fini(void)module_init (nf_conntrack_standalone_init);module_exit (nf_conntrack_standalone_fini); - -/* Some modules need us, but don't depend directly on any symbol. -They should call this. */ -void need_conntrack (void ) -{ -} -EXPORT_SYMBOL_GPL (need_conntrack);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 6/31 netfilter: nf_tables: add xfrm expression
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
supports fetching saddr/daddr of tunnel mode states, request id and spi. If direction is 'in', use inbound skb secpath, else dst->xfrm.
Joint work with Máté Eckl.
--- include/uapi/linux/netfilter/nf_tables.h | 29 +++ net/netfilter/Kconfig | 7 + net/netfilter/Makefile | 1 + net/netfilter/nft_xfrm.c | 293 +++++++++++++++++++++++++++++++ 4 files changed, 330 insertions(+) create mode 100644 net/netfilter/nft_xfrm.c
include/uapi/linux/netfilter/nf_tables.h +29 -0
@@ -1514,6 +1514,35 @@ enum nft_devices_attributes { };#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1) +/* +* enum nft_xfrm_attributes - nf_tables xfrm expr netlink attributes +* +* @NFTA_XFRM_DREG: destination register (NLA_U32) +* @NFTA_XFRM_KEY: enum nft_xfrm_keys (NLA_U32) +* @NFTA_XFRM_DIR: direction (NLA_U8) +* @NFTA_XFRM_SPNUM: index in secpath array (NLA_U32) +*/ +enum nft_xfrm_attributes { +NFTA_XFRM_UNSPEC , +NFTA_XFRM_DREG , +NFTA_XFRM_KEY , +NFTA_XFRM_DIR , +NFTA_XFRM_SPNUM , + __NFTA_XFRM_MAX +}; +#define NFTA_XFRM_MAX (__NFTA_XFRM_MAX - 1) + +enum nft_xfrm_keys { +NFT_XFRM_KEY_UNSPEC , +NFT_XFRM_KEY_DADDR_IP4 , +NFT_XFRM_KEY_DADDR_IP6 , +NFT_XFRM_KEY_SADDR_IP4 , +NFT_XFRM_KEY_SADDR_IP6 , +NFT_XFRM_KEY_REQID , +NFT_XFRM_KEY_SPI , + __NFT_XFRM_KEY_MAX, +}; +#define NFT_XFRM_KEY_MAX (__NFT_XFRM_KEY_MAX - 1)/** * enum nft_trace_attributes - nf_tables trace netlink attributes
net/netfilter/Kconfig +7 -0
@@ -625,6 +625,13 @@ config NFT_FIB_INET The lookup will be delegated to the IPv4 or IPv6 FIB depending on the protocol of the packet. +config NFT_XFRM + tristate "Netfilter nf_tables xfrm/IPSec security association matching" + depends on XFRM + help + This option adds an expression that you can use to extract properties + of a packets security association. + config NFT_SOCKET tristate "Netfilter nf_tables socket match support" depends on IPV6 || IPV6=n
net/netfilter/Makefile +1 -0
@@ -113,6 +113,7 @@ obj-$(CONFIG_NFT_FIB_NETDEV) += nft_fib_netdev.o obj-$(CONFIG_NFT_SOCKET) += nft_socket.o obj-$(CONFIG_NFT_OSF) += nft_osf.o obj-$(CONFIG_NFT_TPROXY) += nft_tproxy.o +obj-$(CONFIG_NFT_XFRM) += nft_xfrm.o # nf_tables netdev obj-$(CONFIG_NFT_DUP_NETDEV) += nft_dup_netdev.o
net/netfilter/nft_xfrm.c new file +293 -0
293 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [PATCH 06/31] netfilter: nf_tables: add xfrm expression
Hi Florian,
Quoted 10 lines · On Tue, 9 Oct 2018 01:01:00 +0200 Pablo Neira Ayuso <[email protected]>…
From: Florian Westphal <[email protected]>
supports fetching saddr/daddr of tunnel mode states, request id and spi. If direction is 'in', use inbound skb secpath, else
dst->xfrm.Joint work with Máté Eckl.
Signed-off-by Florian Westphal <[email protected]>Signed-off-by Pablo Neira Ayuso <[email protected]>---
<snip>
Quoted 71 lines
net/netfilter/nft_xfrm.c new file +5
-0+ +/* Return true if key asks for daddr/saddr and current +* state does have a valid address (BEET, TUNNEL). +*/ +static bool xfrm_state_addr_ok(enum nft_xfrm_keys k, u8 family, u8mode) +{
net/netfilter/nft_xfrm.c new file +26
-0+switch (k) { +case NFT_XFRM_KEY_DADDR_IP4 : +case NFT_XFRM_KEY_SADDR_IP4 : +if (family ==NFPROTO_IPV4 ) +break ; +return false; +case NFT_XFRM_KEY_DADDR_IP6 : +case NFT_XFRM_KEY_SADDR_IP6 : +if (family ==NFPROTO_IPV6 ) +break ; +return false; +default : +return true; + } + +return mode ==XFRM_MODE_BEET || mode ==XFRM_MODE_TUNNEL ; +} + +static void nft_xfrm_state_get_key(const struct nft_xfrm *priv, + struct nft_regs *regs, + const struct xfrm_state *state, + u8 family) +{ + u32 *dest = ®s->data[priv->dreg]; + + if (!xfrm_state_addr_ok(priv->key, family,
state->props.mode)) {net/netfilter/nft_xfrm.c new file +14
-0+ regs->verdict.code =NFT_BREAK ; +return ; + } + +switch (priv->key) { +case NFT_XFRM_KEY_UNSPEC : +case __NFT_XFRM_KEY_MAX: +WARN_ON_ONCE (1 ); +break ; +case NFT_XFRM_KEY_DADDR_IP4 : + *dest = state->id.daddr.a4; +return ; +case NFT_XFRM_KEY_DADDR_IP6 : + memcpy(dest, &state->id.daddr.in6, sizeof(struct
in6_addr));net/netfilter/nft_xfrm.c new file +6
-0+return ; +case NFT_XFRM_KEY_SADDR_IP4 : + *dest = state->props.saddr.a4; +return ; +case NFT_XFRM_KEY_SADDR_IP6 : + memcpy(dest, &state->props.saddr.in6, sizeof(struct
in6_addr));net/netfilter/nft_xfrm.c new file +16
-0+return ; +case NFT_XFRM_KEY_REQID : + *dest = state->props.reqid; +return ; +case NFT_XFRM_KEY_SPI : + *dest = state->id.spi; +return ; + } + + regs->verdict.code =NFT_BREAK ; +} + +static void nft_xfrm_get_eval_in (const struct nft_xfrm *priv, +struct nft_regs *regs, +const struct nft_pktinfo *pkt) +{
net/netfilter/nft_xfrm.c line 172
Quoted 10 lines
net/netfilter/nft_xfrm.c new file +10
-0+const struct sec_path *sp = pkt->skb->sp; +const struct xfrm_state *state; + +if (sp ==NULL || sp->len <= priv->spnum) { + regs->verdict.code =NFT_BREAK ; +return ; + } + + state = sp->xvec[priv->spnum]; +nft_xfrm_state_get_key (priv, regs, state,nft_pf (pkt));
I'm not familiar enough with nftables to be sure, but doesn't the use of nft_pf(pkt) in this context limit the matching of encapsulated packets to the same family?
IIUC when an e.g. IPv6-in-IPv4 packet is matched, the nft_pf(pkt) will be the decapsulated packet family - IPv6 - whereas the state may be IPv4. So this check would not allow matching the 'underlay' address in such cases.
I know this was a limitation in xt_policy. but is this intentional in this matcher? or is it possible to use state->props.family when validating the match instead of nft_pf(pkt)?
Eyal.
Florian Westphal
maintainerRe: [PATCH 06/31] netfilter: nf_tables: add xfrm expression
Quoted 6 lines · Eyal Birger
Review
Quoted 2 lines
(quoted diff) +2
-0+ state = sp->xvec[priv->spnum]; + nft_xfrm_state_get_key(priv, regs, state, nft_pf(pkt));I'm not familiar enough with nftables to be sure, but doesn't the use of
nft_pf(pkt)in this context limit the matching of encapsulated packets to the same family?
Good point. I'll test this fix:
net/netfilter/nft_xfrm.c +6 -5
@@ -118,12 +118,13 @@ static bool xfrm_state_addr_ok(enum nft_xfrm_keys k, u8 family, u8 mode)static void nft_xfrm_state_get_key (const struct nft_xfrm *priv,struct nft_regs *regs, -const struct xfrm_state *state, -u8 family) +const struct xfrm_state *state) {u32 *dest = ®s->data[priv->dreg]; -if (!xfrm_state_addr_ok (priv->key, family, state->props.mode)) { +if (!xfrm_state_addr_ok (priv->key, + state->props.family, + state->props.mode)) { regs->verdict.code =NFT_BREAK ;return ; }
@@ -169,7 +170,7 @@ static void nft_xfrm_get_eval_in(const struct nft_xfrm *priv, } state = sp->xvec[priv->spnum]; -nft_xfrm_state_get_key (priv, regs, state,nft_pf (pkt)); +nft_xfrm_state_get_key (priv, regs, state); } static void nft_xfrm_get_eval_out(const struct nft_xfrm *priv,
@@ -184,7 +185,7 @@ static void nft_xfrm_get_eval_out(const struct nft_xfrm *priv,if (i < priv->spnum)continue ; -nft_xfrm_state_get_key (priv, regs, dst->xfrm,nft_pf (pkt)); +nft_xfrm_state_get_key (priv, regs, dst->xfrm);return ; }
Pablo Neira Ayuso
maintainerPATCH 7/31 netfilter: ctnetlink: Support L3 protocol-filter on flush
In reply to Pablo Neira AyusoFrom: Kristian Evensen <[email protected]>
The same connection mark can be set on flows belonging to different address families. This commit adds support for filtering on the L3 protocol when flushing connection track entries. If no protocol is specified, then all L3 protocols match.
In order to avoid code duplication and a redundant check, the protocol comparison in ctnetlink_dump_table() has been removed. Instead, a filter is created if the GET-message triggering the dump contains an address family. ctnetlink_filter_match() is then used to compare the L3 protocols.
--- net/netfilter/nf_conntrack_netlink.c | 50 ++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 22 deletions(-)
net/netfilter/nf_conntrack_netlink.c +28 -22
@@ -821,6 +821,7 @@ static int ctnetlink_done(struct netlink_callback *cb) }struct ctnetlink_filter { +u8 family;struct {u_int32_t val;u_int32_t mask;
@@ -828,31 +829,32 @@ struct ctnetlink_filter { };static struct ctnetlink_filter * -ctnetlink_alloc_filter (const struct nlattr *const cda[]) +ctnetlink_alloc_filter (const struct nlattr *const cda[],u8 family) { -#ifdef CONFIG_NF_CONNTRACK_MARK struct ctnetlink_filter *filter; filter =kzalloc (sizeof (*filter),GFP_KERNEL );if (filter ==NULL )return ERR_PTR (-ENOMEM ); + filter->family = family; + +#ifdef CONFIG_NF_CONNTRACK_MARK filter->mark.val =ntohl (nla_get_be32 (cda[CTA_MARK ])); filter->mark.mask =ntohl (nla_get_be32 (cda[CTA_MARK_MASK ])); - -return filter; -#else -return ERR_PTR (-EOPNOTSUPP );#endif +return filter; }static int ctnetlink_start (struct netlink_callback *cb) {const struct nlattr *const *cda = cb->data;struct ctnetlink_filter *filter =NULL ; +struct nfgenmsg *nfmsg =nlmsg_data (cb->nlh); +u8 family = nfmsg->nfgen_family; -if (cda[CTA_MARK ] && cda[CTA_MARK_MASK ]) { - filter =ctnetlink_alloc_filter (cda); +if (family || (cda[CTA_MARK ] && cda[CTA_MARK_MASK ])) { + filter =ctnetlink_alloc_filter (cda, family);if (IS_ERR (filter))return PTR_ERR (filter); }
@@ -866,13 +868,24 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)struct ctnetlink_filter *filter = data;if (filter ==NULL ) -return 1 ; + goto out; + +/* Match entries of a given L3 protocol number. +* If it is not specified, ie. l3proto == 0, +* then match everything. +*/ +if (filter->family &&nf_ct_l3num (ct) != filter->family) + goto ignore_entry;#ifdef CONFIG_NF_CONNTRACK_MARK -if ((ct->mark & filter->mark.mask) == filter->mark.val) -return 1 ; +if ((ct->mark & filter->mark.mask) != filter->mark.val) + goto ignore_entry;#endif +out: +return 1 ; + +ignore_entry:return 0 ; }
@@ -883,8 +896,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)struct nf_conn *ct, *last;struct nf_conntrack_tuple_hash *h;struct hlist_nulls_node *n; -struct nfgenmsg *nfmsg =nlmsg_data (cb->nlh); -u_int8_t l3proto = nfmsg->nfgen_family;struct nf_conn *nf_ct_evict[8 ];int res, i;spinlock_t *lockp;
@@ -923,11 +934,6 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)if (!net_eq (net,nf_ct_net (ct)))continue ; -/* Dump entries of a given L3 protocol number. -* If it is not specified, ie. l3proto == 0, -* then dump everything. */ -if (l3proto &&nf_ct_l3num (ct) != l3proto) -continue ;if (cb->args[1 ]) {if (ct != last)continue ;
@@ -1213,12 +1219,12 @@ static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)static int ctnetlink_flush_conntrack (struct net *net,const struct nlattr *const cda[], -u32 portid,int report) +u32 portid,int report,u8 family) {struct ctnetlink_filter *filter =NULL ; -if (cda[CTA_MARK ] && cda[CTA_MARK_MASK ]) { - filter =ctnetlink_alloc_filter (cda); +if (family || (cda[CTA_MARK ] && cda[CTA_MARK_MASK ])) { + filter =ctnetlink_alloc_filter (cda, family);if (IS_ERR (filter))return PTR_ERR (filter); }
@@ -1257,7 +1263,7 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,else {return ctnetlink_flush_conntrack (net, cda,NETLINK_CB (skb).portid, -nlmsg_report (nlh)); +nlmsg_report (nlh), u3); }if (err <0 )
Signature · 1 line
2.11.0
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Le 09/10/2018 à 01:01, Pablo Neira Ayuso a écrit :
Quoted 13 lines
From: Kristian Evensen <[email protected]>
The same connection mark can be set on flows belonging to different address families. This commit adds support for filtering on the L3 protocol when flushing connection track entries. If no protocol is specified, then all L3 protocols match.
In order to avoid code duplication and a redundant check, the protocol comparison in
ctnetlink_dump_table()has been removed. Instead, a filter is created if the GET-message triggering the dump contains an address family.ctnetlink_filter_match()is then used to compare the L3 protocols.
Quoted 3 lines
Signed-off-by Kristian Evensen <[email protected]>Signed-off-by Pablo Neira Ayuso <[email protected]>---
[snip] continue;
net/netfilter/nf_conntrack_netlink.c static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data) · line 1226
Quoted 12 lines
net/netfilter/nf_conntrack_netlink.c +2
-3@@ -1213,12 +1219,12 @@ static int ctnetlink_flush_iterate(struct nf_conn *ct, void *data)static int ctnetlink_flush_conntrack (struct net *net,const struct nlattr *const cda[], -u32 portid,int report) +u32 portid,int report,u8 family) {struct ctnetlink_filter *filter =NULL ; -if (cda[CTA_MARK ] && cda[CTA_MARK_MASK ]) { - filter =ctnetlink_alloc_filter (cda); +if (family || (cda[CTA_MARK ] && cda[CTA_MARK_MASK ])) {
Since this patch, there is a regression with 'conntrack -F', it does not flush anymore ipv6 conntrack entries.
In fact, the conntrack tool set by default the family to AF_INET and forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').
Any idea to fix this (without changing the conntrack tool) is welcomed.
Regards,
Nicolas
Quoted 14 lines
net/netfilter/nf_conntrack_netlink.c +2
-1+ filter =ctnetlink_alloc_filter (cda, family);if (IS_ERR (filter))return PTR_ERR (filter); }@@ -1257,7 +1263,7 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,else {return ctnetlink_flush_conntrack (net, cda,NETLINK_CB (skb).portid, -nlmsg_report (nlh)); +nlmsg_report (nlh), u3); }if (err <0 )
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Le 25/04/2019 à 12:07, Nicolas Dichtel a écrit :
[snip]
Quoted 3 lines
In fact, the conntrack tool set by default the family to
AF_INETand forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').
'conntrack -D -f ipv6' will do the job, but this is still a regression.
Regards,
Nicolas
Pablo Neira Ayuso
maintainerRe: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Quoted 7 lines · Nicolas Dichtel
Le 25/04/2019 à 12:07, Nicolas Dichtel a écrit :
[snip]Quoted 3 lines
In fact, the conntrack tool set by default the family to
AF_INETand forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').'conntrack -D -f ipv6' will do the job, but this is still a regression.
You mean, before this patch, flush was ignoring the family, and after Kristian's patch, it forces you to use NFPROTO_UNSPEC to achieve the same thing, right?
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Le 26/04/2019 à 21:25, Pablo Neira Ayuso a écrit :
Quoted 7 lines · Nicolas Dichtel
Quoted 6 lines
Le 25/04/2019 à 12:07, Nicolas Dichtel a écrit :
[snip]Quoted 3 lines
In fact, the conntrack tool set by default the family to
AF_INETand forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').
Quoted 6 lines
Quoted 1 line
'conntrack -D -f ipv6' will do the job, but this is still a regression.
You mean, before this patch, flush was ignoring the family, and after Kristian's patch, it forces you to use
NFPROTO_UNSPECto achieve the same thing, right?
Before the patch, flush was ignoring the family, and after the patch, the flush takes care of the family.
The conntrack tool has always set the family to AF_INET by default, thus, since this patch, only ipv4 conntracks are flushed with 'conntrack -F':
https://git.netfilter.org/conntrack-tools/tree/src/conntrack.c#n2565
https://git.netfilter.org/conntrack-tools/tree/src/conntrack.c#n2796
Regards,
Nicolas
Pablo Neira Ayuso
maintainerRe: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Quoted 14 lines · Nicolas Dichtel
Le 26/04/2019 à 21:25, Pablo Neira Ayuso a écrit :
Quoted 7 lines · Nicolas Dichtel
Quoted 6 lines
Le 25/04/2019 à 12:07, Nicolas Dichtel a écrit :
[snip]Quoted 3 lines
In fact, the conntrack tool set by default the family to
AF_INETand forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').Quoted 6 lines
Quoted 1 line
'conntrack -D -f ipv6' will do the job, but this is still a regression.
You mean, before this patch, flush was ignoring the family, and after Kristian's patch, it forces you to use
NFPROTO_UNSPECto achieve the same thing, right?
Quoted 6 lines
Before the patch, flush was ignoring the family, and after the patch, the flush takes care of the family.
The conntrack tool has always set the family toAF_INETby default, thus, since this patch, only ipv4 conntracks are flushed with 'conntrack -F':
https://git.netfilter.org/conntrack-tools/tree/src/conntrack.c#n2565
https://git.netfilter.org/conntrack-tools/tree/src/conntrack.c#n2796
Thanks for explaining, what fix would you propose for this?
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Le 29/04/2019 à 17:23, Pablo Neira Ayuso a écrit :
Quoted 15 lines · Nicolas Dichtel
Quoted 14 lines
Le 26/04/2019 à 21:25, Pablo Neira Ayuso a écrit :
Quoted 13 lines · Nicolas Dichtel
Quoted 7 lines
Le 25/04/2019 à 12:07, Nicolas Dichtel a écrit :
[snip]Quoted 3 lines
In fact, the conntrack tool set by default the family to
AF_INETand forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').'conntrack -D -f ipv6' will do the job, but this is still a regression.
You mean, before this patch, flush was ignoring the family, and after Kristian's patch, it forces you to use
NFPROTO_UNSPECto achieve the same thing, right?
Quoted 9 lines
Quoted 6 lines
Before the patch, flush was ignoring the family, and after the patch, the flush takes care of the family.
The conntrack tool has always set the family toAF_INETby default, thus, since this patch, only ipv4 conntracks are flushed with 'conntrack -F':
https://git.netfilter.org/conntrack-tools/tree/src/conntrack.c#n2565
https://git.netfilter.org/conntrack-tools/tree/src/conntrack.c#n2796Thanks for explaining, what fix would you propose for this?
The least bad fix I see is adding a new attribute, something like CTA_FLUSH_FAMILY, to be used by the flush filter (and ignoring struct nfgenmsg->nfgen_family in this flush filter).
The drawback is that it will break the (relatively new) users of this feature (the patch has been pushed in v4.20).
Regards,
Nicolas
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
In reply to Nicolas DichtelHello,
Quoted 5 lines · Nicolas Dichtel
Since this patch, there is a regression with 'conntrack -F', it does not flush anymore ipv6 conntrack entries.
In fact, the conntrack tool set by default the family toAF_INETand forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').
I am very sorry for my late reply and for the trouble my change has caused. However, I am not sure if I agree that it triggers a regression. Had conntrack for example not set any family and my change caused only IPv4 entries to be flushed, then I agree it would have been a regression. If you ask me, what my change has exposed is incorrect API usage in conntrack. One could argue that since conntrack explicitly sets the family to AF_INET, the fact that IPv6 entries also has been flushed has been incorrect. However, if the general consensus is that this is a regression, I am more than willing to help in finding a solution (if I have anything to contribute :)).
BR,
Kristian
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Le 01/05/2019 à 10:47, Kristian Evensen a écrit :
Quoted 10 lines
Hello,
Quoted 5 lines · Nicolas Dichtel
Since this patch, there is a regression with 'conntrack -F', it does not flush anymore ipv6 conntrack entries.
In fact, the conntrack tool set by default the family toAF_INETand forbid to set the family to something else (the '-f' option is not allowed for the command 'flush').
Quoted 10 lines
I am very sorry for my late reply and for the trouble my change has caused. However, I am not sure if I agree that it triggers a regression. Had conntrack for example not set any family and my change caused only IPv4 entries to be flushed, then I agree it would have been a regression. If you ask me, what my change has exposed is incorrect API usage in conntrack. One could argue that since conntrack explicitly sets the family to
AF_INET, the fact that IPv6 entries also has been flushed has been incorrect. However, if the general consensus is that this is a regression, I am more than willing to help in finding a solution (if I have anything to contribute :)).
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
Regards,
Nicolas
Florian Westphal
maintainerRe: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Quoted 5 lines · Nicolas Dichtel
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
FWIW I agree with Nicolas, we should restore old behaviour and flush everything when AF_INET is given. We can add new netlink attr to restrict this.
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Hi,
Quoted 11 lines · Florian Westphal
Quoted 5 lines · Nicolas Dichtel
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
FWIW I agree with Nicolas, we should restore old behaviour and flush everything when
AF_INETis given. We can add new netlink attr to restrict this.
I agree with both of you. Unless anyone beats me to it, I will try to have a fix ready during the weekend.
BR,
Kristian
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
In reply to Florian WestphalLe 02/05/2019 à 09:46, Florian Westphal a écrit :
Quoted 9 lines
Quoted 5 lines · Nicolas Dichtel
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
FWIW I agree with Nicolas, we should restore old behaviour and flush everything when
AF_INETis given. We can add new netlink attr to
To avoid regression, we sould ignore it, AF_INET or not.
Quoted 1 line
restrict this.
Yes.
Pablo Neira Ayuso
maintainerRe: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
In reply to Florian WestphalQuoted 10 lines · Florian Westphal
Quoted 5 lines · Nicolas Dichtel
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
FWIW I agree with Nicolas, we should restore old behaviour and flush everything when
AF_INETis given. We can add new netlink attr to restrict this.
Let's use nfgenmsg->version for this. This is so far set to zero. We can just update userspace to set it to 1, so family is used.
The version field in the kernel size is ignored so far, so this should be enough. So we avoid that extract netlink attribute.
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Le 02/05/2019 à 13:31, Pablo Neira Ayuso a écrit :
Quoted 12 lines · Florian Westphal
Quoted 10 lines
Quoted 5 lines · Nicolas Dichtel
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
FWIW I agree with Nicolas, we should restore old behaviour and flush everything when
AF_INETis given. We can add new netlink attr to restrict this.
Quoted 5 lines
Let's use
nfgenmsg->versionfor this. This is so far set to zero. We can just update userspace to set it to 1, so family is used.The version field in the kernel size is ignored so far, so this should be enough. So we avoid that extract netlink attribute.
Why making such a hack? If any userspace app set this field (simply because it's not initialized), it will show up a new regression.
What is the problem of adding another attribute?
Pablo Neira Ayuso
maintainerRe: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Quoted 16 lines · Nicolas Dichtel
Le 02/05/2019 à 13:31, Pablo Neira Ayuso a écrit :
Quoted 15 lines · Florian Westphal
Quoted 10 lines
Quoted 5 lines · Nicolas Dichtel
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
FWIW I agree with Nicolas, we should restore old behaviour and flush everything when
AF_INETis given. We can add new netlink attr to restrict this.Let's use
nfgenmsg->versionfor this. This is so far set to zero. We can just update userspace to set it to 1, so family is used.
Quoted 6 lines
Quoted 2 lines
The version field in the kernel size is ignored so far, so this should be enough. So we avoid that extract netlink attribute.
Why making such a hack? If any userspace app set this field (simply because it's not initialized), it will show up a new regression.
What is the problem of adding another attribute?
The version field was meant to deal with this case.
It has been not unused so far because we had no good reason.
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Le 02/05/2019 à 17:06, Pablo Neira Ayuso a écrit :
Quoted 20 lines · Nicolas Dichtel
Quoted 19 lines
Le 02/05/2019 à 13:31, Pablo Neira Ayuso a écrit :
Quoted 17 lines · Florian Westphal
Quoted 10 lines
Quoted 5 lines · Nicolas Dichtel
I understand your point, but this is a regression. Ignoring a field/attribute of a netlink message is part of the uAPI. This field exists for more than a decade (probably two), so you cannot just use it because nobody was using it. Just see all discussions about strict validation of netlink messages. Moreover, the conntrack tool exists also for ages and is an official tool.
FWIW I agree with Nicolas, we should restore old behaviour and flush everything when
AF_INETis given. We can add new netlink attr to restrict this.Let's use
nfgenmsg->versionfor this. This is so far set to zero. We can just update userspace to set it to 1, so family is used.The version field in the kernel size is ignored so far, so this should be enough. So we avoid that extract netlink attribute.
Quoted 8 lines
Quoted 3 lines
Why making such a hack? If any userspace app set this field (simply because it's not initialized), it will show up a new regression.
What is the problem of adding another attribute?The version field was meant to deal with this case.
It has been not unused so far because we had no good reason.
Fair point, agreed.
Thank you,
Nicolas
Re: [PATCH 07/31] netfilter: ctnetlink: Support L3 protocol-filter on flush
Hi,
Quoted 10 lines · Nicolas Dichtel
Quoted 10 lines
Quoted 9 lines
Quoted 5 lines
Let's use
nfgenmsg->versionfor this. This is so far set to zero. We can just update userspace to set it to 1, so family is used.The version field in the kernel size is ignored so far, so this should be enough. So we avoid that extract netlink attribute.
Why making such a hack? If any userspace app set this field (simply because it's not initialized), it will show up a new regression.
What is the problem of adding another attribute?
Quoted 5 lines
Quoted 4 lines
The version field was meant to deal with this case.
It has been not unused so far because we had no good reason.
Fair point, agreed.
Great that the discussion has reached a conclusion. I will prepare a fix based on the version-filed and submit it either later today or during the weekend. Sorry again for the problems my change caused.
BR,
Kristian
Pablo Neira Ayuso
maintainerPATCH 8/31 netfilter: xt_cgroup: shrink size of v2 path
In reply to Pablo Neira Ayusocgroup v2 path field is PATH_MAX which is too large, this is placing too much pressure on memory allocation for people with many rules doing cgroup v1 classid matching, side effects of this are bug reports like:
https://bugzilla.kernel.org/show_bug.cgi?id=200639
This patch registers a new revision that shrinks the cgroup path to 512 bytes, which is the same approach we follow in similar extensions that have a path field.
--- include/uapi/linux/netfilter/xt_cgroup.h | 16 +++++++ net/netfilter/xt_cgroup.c | 72 ++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+)
include/uapi/linux/netfilter/xt_cgroup.h +16 -0
@@ -22,4 +22,20 @@ struct xt_cgroup_info_v1 { void *priv __attribute__((aligned(8))); }; +#define XT_CGROUP_PATH_MAX 512 + +struct xt_cgroup_info_v2 { +__u8 has_path; +__u8 has_classid; +__u8 invert_path; +__u8 invert_classid; +union { +char path[XT_CGROUP_PATH_MAX ]; +__u32 classid; + }; + +/* kernel internal data */ +void *priv __attribute__((aligned (8 ))); +}; +#endif /* _UAPI_XT_CGROUP_H */
net/netfilter/xt_cgroup.c +72 -0
96 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 9/31 netfilter: nf_tables: avoid BUG_ON usage
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
None of these spots really needs to crash the kernel.
In one two cases we can jsut report error to userspace, in the other cases we can just use WARN_ON (and leak memory instead).
--- net/netfilter/nf_tables_api.c | 9 ++++++--- net/netfilter/nft_cmp.c | 6 ++++-- net/netfilter/nft_reject.c | 6 ++++-- 3 files changed, 14 insertions(+), 7 deletions(-)
net/netfilter/nf_tables_api.c +6 -3
@@ -1021,7 +1021,8 @@ static int nf_tables_deltable(struct net *net, struct sock *nlsk,static void nf_tables_table_destroy (struct nft_ctx *ctx) { -BUG_ON (ctx->table->use >0 ); +if (WARN_ON (ctx->table->use >0 )) +return ;rhltable_destroy (&ctx->table->chains_ht);kfree (ctx->table->name);
@@ -1428,7 +1429,8 @@ static void nf_tables_chain_destroy(struct nft_ctx *ctx) {struct nft_chain *chain = ctx->chain; -BUG_ON (chain->use >0 ); +if (WARN_ON (chain->use >0 )) +return ;/* no concurrent access possible anymore */ nf_tables_chain_free_chain_rules (chain);
@@ -7243,7 +7245,8 @@ int __nft_release_basechain(struct nft_ctx *ctx) {struct nft_rule *rule, *nr; -BUG_ON (!nft_is_base_chain (ctx->chain)); +if (WARN_ON (!nft_is_base_chain (ctx->chain))) +return 0 ;nf_tables_unregister_hook (ctx->net, ctx->chain->table, ctx->chain);list_for_each_entry_safe (rule, nr, &ctx->chain->rules, list) {
net/netfilter/nft_cmp.c +4 -2
@@ -79,7 +79,8 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr, err =nft_data_init (NULL , &priv->data,sizeof (priv->data), &desc, tb[NFTA_CMP_DATA ]); -BUG_ON (err <0 ); +if (err <0 ) +return err; priv->sreg =nft_parse_register (tb[NFTA_CMP_SREG ]); err =nft_validate_register_load (priv->sreg, desc.len);
@@ -129,7 +130,8 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx, err =nft_data_init (NULL , &data,sizeof (data), &desc, tb[NFTA_CMP_DATA ]); -BUG_ON (err <0 ); +if (err <0 ) +return err; priv->sreg =nft_parse_register (tb[NFTA_CMP_SREG ]); err =nft_validate_register_load (priv->sreg, desc.len);
net/netfilter/nft_reject.c +4 -2
@@ -94,7 +94,8 @@ static u8 icmp_code_v4[NFT_REJECT_ICMPX_MAX + 1] = {int nft_reject_icmp_code (u8 code) { -BUG_ON (code >NFT_REJECT_ICMPX_MAX ); +if (WARN_ON_ONCE (code >NFT_REJECT_ICMPX_MAX )) +return ICMP_NET_UNREACH ;return icmp_code_v4[code]; }
@@ -111,7 +112,8 @@ static u8 icmp_code_v6[NFT_REJECT_ICMPX_MAX + 1] = {int nft_reject_icmpv6_code (u8 code) { -BUG_ON (code >NFT_REJECT_ICMPX_MAX ); +if (WARN_ON_ONCE (code >NFT_REJECT_ICMPX_MAX )) +return ICMPV6_NOROUTE ;return icmp_code_v6[code]; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 10/31 netfilter: xtables: avoid BUG_ON
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
I see no reason for them, label or timer cannot be NULL, and if they were, we'll crash with null deref anyway.
For skb_header_pointer failure, just set hotdrop to true and toss such packet.
--- net/ipv6/netfilter/ip6t_ipv6header.c | 5 ++++- net/ipv6/netfilter/ip6t_rt.c | 10 ++++++++-- net/netfilter/xt_IDLETIMER.c | 4 ---- net/netfilter/xt_SECMARK.c | 2 -- 4 files changed, 12 insertions(+), 9 deletions(-)
net/ipv6/netfilter/ip6t_ipv6header.c +4 -1
@@ -65,7 +65,10 @@ ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par) } hp =skb_header_pointer (skb, ptr,sizeof (_hdr), &_hdr); -BUG_ON (hp ==NULL ); +if (!hp) { + par->hotdrop = true; +return false; + }/* Calculate the header length */ if (nexthdr ==NEXTHDR_FRAGMENT )
net/ipv6/netfilter/ip6t_rt.c +8 -2
@@ -137,7 +137,10 @@ static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par)sizeof (_addr), &_addr); -BUG_ON (ap ==NULL ); +if (ap ==NULL ) { + par->hotdrop = true; +return false; + }if (ipv6_addr_equal (ap, &rtinfo->addrs[i])) {pr_debug ("i=%d temp=%d;\n" , i, temp);
@@ -166,7 +169,10 @@ static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par) + temp *sizeof (_addr),sizeof (_addr), &_addr); -BUG_ON (ap ==NULL ); +if (ap ==NULL ) { + par->hotdrop = true; +return false; + }if (!ipv6_addr_equal (ap, &rtinfo->addrs[temp]))break ;
net/netfilter/xt_IDLETIMER.c +0 -4
@@ -68,8 +68,6 @@ struct idletimer_tg *__idletimer_tg_find_by_label(const char *label) {struct idletimer_tg *entry; -BUG_ON (!label); -list_for_each_entry (entry, &idletimer_tg_list, entry) {if (!strcmp (label, entry->attr.attr.name))return entry;
@@ -172,8 +170,6 @@ static unsigned int idletimer_tg_target(struct sk_buff *skb,pr_debug ("resetting timer %s, timeout period %u\n" , info->label, info->timeout); -BUG_ON (!info->timer); -mod_timer (&info->timer->timer,msecs_to_jiffies (info->timeout *1000 ) + jiffies);
net/netfilter/xt_SECMARK.c +0 -2
@@ -35,8 +35,6 @@ secmark_tg(struct sk_buff *skb, const struct xt_action_param *par)u32 secmark =0 ;const struct xt_secmark_target_info *info = par->targinfo; -BUG_ON (info->mode != mode); -switch (mode) {case SECMARK_MODE_SEL : secmark = info->secid;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 11/31 netfilter: nf_nat_ipv4: remove obsolete EXPORT_SYMBOL
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
There are no external callers anymore, previous change just forgot to also remove the EXPORT_SYMBOL().
--- net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | 1 - 1 file changed, 1 deletion(-)
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +0 -1
@@ -264,7 +264,6 @@ nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,return nf_nat_inet_fn (priv, skb, state); } -EXPORT_SYMBOL_GPL (nf_nat_ipv4_fn); static unsigned int nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 12/31 netfilter: cttimeout: remove superfluous check on layer 4 netlink functions
In reply to Pablo Neira AyusoWe assume they are always set accordingly since a874752a10da ("netfilter: conntrack: timeout interface depend on CONFIG_NF_CONNTRACK_TIMEOUT"), so we can get rid of this checks.
--- net/netfilter/nfnetlink_cttimeout.c | 48 ++++++++++++++----------------------- net/netfilter/nft_ct.c | 3 --- 2 files changed, 18 insertions(+), 33 deletions(-)
net/netfilter/nfnetlink_cttimeout.c +18 -30
@@ -53,9 +53,6 @@ ctnl_timeout_parse_policy(void *timeout,struct nlattr **tb;int ret =0 ; -if (!l4proto->ctnl_timeout.nlattr_to_obj) -return 0 ; - tb =kcalloc (l4proto->ctnl_timeout.nlattr_max +1 ,sizeof (*tb),GFP_KERNEL );
@@ -167,6 +164,8 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,struct nfgenmsg *nfmsg;unsigned int flags = portid ?NLM_F_MULTI :0 ;const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto; +struct nlattr *nest_parms; +int ret; event =nfnl_msg_type (NFNL_SUBSYS_CTNETLINK_TIMEOUT , event); nlh =nlmsg_put (skb, portid, seq, event,sizeof (*nfmsg), flags);
@@ -186,22 +185,15 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, htonl(refcount_read(&timeout->refcnt)))) goto nla_put_failure; -if (likely (l4proto->ctnl_timeout.obj_to_nlattr)) { -struct nlattr *nest_parms; -int ret; - - nest_parms =nla_nest_start (skb, -CTA_TIMEOUT_DATA |NLA_F_NESTED ); -if (!nest_parms) - goto nla_put_failure; + nest_parms =nla_nest_start (skb,CTA_TIMEOUT_DATA |NLA_F_NESTED ); +if (!nest_parms) + goto nla_put_failure; - ret = l4proto->ctnl_timeout.obj_to_nlattr (skb, - &timeout->timeout.data); -if (ret <0 ) - goto nla_put_failure; + ret = l4proto->ctnl_timeout.obj_to_nlattr (skb, &timeout->timeout.data); +if (ret <0 ) + goto nla_put_failure; -nla_nest_end (skb, nest_parms); - } +nla_nest_end (skb, nest_parms);nlmsg_end (skb, nlh);return skb->len;
@@ -397,6 +389,8 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,struct nlmsghdr *nlh;struct nfgenmsg *nfmsg;unsigned int flags = portid ?NLM_F_MULTI :0 ; +struct nlattr *nest_parms; +int ret; event =nfnl_msg_type (NFNL_SUBSYS_CTNETLINK_TIMEOUT , event); nlh =nlmsg_put (skb, portid, seq, event,sizeof (*nfmsg), flags);
@@ -412,21 +406,15 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto)) goto nla_put_failure; -if (likely (l4proto->ctnl_timeout.obj_to_nlattr)) { -struct nlattr *nest_parms; -int ret; - - nest_parms =nla_nest_start (skb, -CTA_TIMEOUT_DATA |NLA_F_NESTED ); -if (!nest_parms) - goto nla_put_failure; + nest_parms =nla_nest_start (skb,CTA_TIMEOUT_DATA |NLA_F_NESTED ); +if (!nest_parms) + goto nla_put_failure; - ret = l4proto->ctnl_timeout.obj_to_nlattr (skb,NULL ); -if (ret <0 ) - goto nla_put_failure; + ret = l4proto->ctnl_timeout.obj_to_nlattr (skb,NULL ); +if (ret <0 ) + goto nla_put_failure; -nla_nest_end (skb, nest_parms); - } +nla_nest_end (skb, nest_parms);nlmsg_end (skb, nlh);return skb->len;
net/netfilter/nft_ct.c +0 -3
@@ -776,9 +776,6 @@ nft_ct_timeout_parse_policy(void *timeouts,struct nlattr **tb;int ret =0 ; -if (!l4proto->ctnl_timeout.nlattr_to_obj) -return 0 ; - tb =kcalloc (l4proto->ctnl_timeout.nlattr_max +1 ,sizeof (*tb),GFP_KERNEL );
Signature · 1 line
2.11.0
Re: [PATCH 12/31] netfilter: cttimeout: remove superfluous check on layer 4 netlink functions
Quoted 82 lines · Pablo Neira Ayuso
We assume they are always set accordingly since
a874752a10da("netfilter: conntrack: timeout interface depend onCONFIG_NF_CONNTRACK_TIMEOUT"), so we can get rid of this checks.Signed-off-by Pablo Neira Ayuso <[email protected]>--- net/netfilter/nfnetlink_cttimeout.c | 48 ++++++++++++++----------------------- net/netfilter/nft_ct.c | 3 --- 2 files changed, 18 insertions(+), 33 deletions(-)net/netfilter/nfnetlink_cttimeout.c +11
-23@@ -53,9 +53,6 @@ ctnl_timeout_parse_policy(void *timeout,struct nlattr **tb;int ret =0 ; -if (!l4proto->ctnl_timeout.nlattr_to_obj) -return 0 ; - tb =kcalloc (l4proto->ctnl_timeout.nlattr_max +1 ,sizeof (*tb),GFP_KERNEL );@@ -167,6 +164,8 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,struct nfgenmsg *nfmsg;unsigned int flags = portid ?NLM_F_MULTI :0 ;const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto; +struct nlattr *nest_parms; +int ret; event =nfnl_msg_type (NFNL_SUBSYS_CTNETLINK_TIMEOUT , event); nlh =nlmsg_put (skb, portid, seq, event,sizeof (*nfmsg), flags);@@ -186,22 +185,15 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, htonl(refcount_read(&timeout->refcnt)))) goto nla_put_failure; -if (likely (l4proto->ctnl_timeout.obj_to_nlattr)) { -struct nlattr *nest_parms; -int ret; - - nest_parms =nla_nest_start (skb, -CTA_TIMEOUT_DATA |NLA_F_NESTED ); -if (!nest_parms) - goto nla_put_failure; + nest_parms =nla_nest_start (skb,CTA_TIMEOUT_DATA |NLA_F_NESTED ); +if (!nest_parms) + goto nla_put_failure; - ret = l4proto->ctnl_timeout.obj_to_nlattr (skb, - &timeout->timeout.data); -if (ret <0 ) - goto nla_put_failure; + ret = l4proto->ctnl_timeout.obj_to_nlattr (skb, &timeout->timeout.data); +if (ret <0 ) + goto nla_put_failure; -nla_nest_end (skb, nest_parms); - } +nla_nest_end (skb, nest_parms);nlmsg_end (skb, nlh);return skb->len;@@ -397,6 +389,8 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,struct nlmsghdr *nlh;struct nfgenmsg *nfmsg;unsigned int flags = portid ?NLM_F_MULTI :0 ; +struct nlattr *nest_parms; +int ret; event =nfnl_msg_type (NFNL_SUBSYS_CTNETLINK_TIMEOUT , event); nlh =nlmsg_put (skb, portid, seq, event,sizeof (*nfmsg), flags);@@ -412,21 +406,15 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto)) goto nla_put_failure; -if (likely (l4proto->ctnl_timeout.obj_to_nlattr)) { -struct nlattr *nest_parms; -int ret; - - nest_parms =nla_nest_start (skb, -CTA_TIMEOUT_DATA |NLA_F_NESTED );
net/netfilter/nfnetlink_cttimeout.c cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, · line 413
Quoted 10 lines
net/netfilter/nfnetlink_cttimeout.c +4
-5-if (!nest_parms) - goto nla_put_failure; + nest_parms =nla_nest_start (skb,CTA_TIMEOUT_DATA |NLA_F_NESTED ); +if (!nest_parms) + goto nla_put_failure; - ret = l4proto->ctnl_timeout.obj_to_nlattr (skb,NULL ); -if (ret <0 ) - goto nla_put_failure; + ret = l4proto->ctnl_timeout.obj_to_nlattr (skb,NULL );
Hi Pablo
None of the obj_to_nlattr handlers can handle a NULL pointer. What is the intent here ?
netlink: 24 bytes leftover after parsing attributes in process `syz-executor2'.
kasan: CONFIG_KASAN_INLINE enabled
kasan: GPF could be caused by NULL-ptr deref or user memory access
general protection fault: 0000 [#1] PREEMPT SMP KASAN CPU: 0 PID: 9575 Comm: syz-executor1 Not tainted 4.19.0+ #312 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:icmp_timeout_obj_to_nlattr+0x77/0x170 net/netfilter/nf_conntrack_proto_icmp.c:297 kobject: 'loop5' (00000000d8ff612b): kobject_uevent_env Code: b5 41 c7 00 f1 f1 f1 f1 c7 40 04 04 f2 f2 f2 65 48 8b 04 25 28 00 00 00 48 89 45 d0 31 c0 e8 c0 06 26 fb 4c 89 e8 48 c1 e8 03 <42> 0f b6 14 38 4c 89 e8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 kobject: 'loop5' (00000000d8ff612b): fill_kobj_path: path = '/devices/virtual/block/loop5' RSP: 0018:ffff88017def7220 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 1ffff1002fbdee45 RCX: ffffc90004561000 RDX: 000000000000064f RSI: ffffffff865970c0 RDI: ffff8801ba602bc0 RBP: ffff88017def72b0 R08: ffff8801879e2400 R09: ffff880188d264a8 R10: ffffed00311a4c94 R11: ffff880188d264a0 R12: ffff8801ba602bc0 R13: 0000000000000000 R14: ffff88017def7288 R15: dffffc0000000000 FS: 00007fb495a6f700(0000) GS:ffff8801dae00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 kobject: 'loop3' (00000000bc48af2d): kobject_uevent_env CR2: 00007f4879a55000 CR3: 00000001b7b96000 CR4: 00000000001406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: kobject: 'loop3' (00000000bc48af2d): fill_kobj_path: path = '/devices/virtual/block/loop3' cttimeout_default_fill_info net/netfilter/nfnetlink_cttimeout.c:411 [inline] cttimeout_default_get+0x644/0x9e0 net/netfilter/nfnetlink_cttimeout.c:457 nfnetlink_rcv_msg+0xdd3/0x10c0 net/netfilter/nfnetlink.c:228 kobject: 'loop3' (00000000bc48af2d): kobject_uevent_env kobject: 'loop3' (00000000bc48af2d): fill_kobj_path: path = '/devices/virtual/block/loop3' netlink_rcv_skb+0x172/0x440 net/netlink/af_netlink.c:2477 nfnetlink_rcv+0x1c0/0x4d0 net/netfilter/nfnetlink.c:560 netlink_unicast_kernel net/netlink/af_netlink.c:1310 [inline] netlink_unicast+0x5a5/0x760 net/netlink/af_netlink.c:1336 netlink_sendmsg+0xa18/0xfc0 net/netlink/af_netlink.c:1917 sock_sendmsg_nosec net/socket.c:621 [inline] sock_sendmsg+0xd5/0x120 net/socket.c:631 ___sys_sendmsg+0x7fd/0x930 net/socket.c:2116 __sys_sendmsg+0x11d/0x280 net/socket.c:2154 __do_sys_sendmsg net/socket.c:2163 [inline] __se_sys_sendmsg net/socket.c:2161 [inline] __x64_sys_sendmsg+0x78/0xb0 net/socket.c:2161 do_syscall_64+0x1b9/0x820 arch/x86/entry/common.c:290
Quoted 24 lines
net/netfilter/nfnetlink_cttimeout.c +3
-2+if (ret <0 ) + goto nla_put_failure; -nla_nest_end (skb, nest_parms); - } +nla_nest_end (skb, nest_parms);nlmsg_end (skb, nlh);return skb->len;net/netfilter/nft_ct.c +0
-3@@ -776,9 +776,6 @@ nft_ct_timeout_parse_policy(void *timeouts,struct nlattr **tb;int ret =0 ; -if (!l4proto->ctnl_timeout.nlattr_to_obj) -return 0 ; - tb =kcalloc (l4proto->ctnl_timeout.nlattr_max +1 ,sizeof (*tb),GFP_KERNEL );
Pablo Neira Ayuso
maintainerRe: [PATCH 12/31] netfilter: cttimeout: remove superfluous check on layer 4 netlink functions
Hi Eric,
Quoted 1 line · Eric Dumazet
On 10/08/2018 04:01 PM, Pablo Neira Ayuso wrote:
[...]
Quoted 23 lines
Quoted 10 lines
net/netfilter/nfnetlink_cttimeout.c +0
-6@@ -412,21 +406,15 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto)) goto nla_put_failure; -if (likely (l4proto->ctnl_timeout.obj_to_nlattr)) { -struct nlattr *nest_parms; -int ret; - - nest_parms =nla_nest_start (skb, -CTA_TIMEOUT_DATA |NLA_F_NESTED );net/netfilter/nfnetlink_cttimeout.c cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, · line 413
Quoted 10 lines
net/netfilter/nfnetlink_cttimeout.c +4
-5-if (!nest_parms) - goto nla_put_failure; + nest_parms =nla_nest_start (skb,CTA_TIMEOUT_DATA |NLA_F_NESTED ); +if (!nest_parms) + goto nla_put_failure; - ret = l4proto->ctnl_timeout.obj_to_nlattr (skb,NULL ); -if (ret <0 ) - goto nla_put_failure; + ret = l4proto->ctnl_timeout.obj_to_nlattr (skb,NULL );Hi Pablo
Quoted 2 lines
None of the
obj_to_nlattrhandlers can handle a NULL pointer. What is the intent here ?
It seems this was accidentally set to NULL here.
commit c779e849608a875448f6ffc2a5c2a15523bdcd00
Author: Florian Westphal <[email protected]> Date: Fri Jun 29 07:46:50 2018 +0200
netfilter: conntrack: remove get_timeout() indirection
Just sent patches to fix this to nf-devel ML.
Thanks for reporting !
Pablo Neira Ayuso
maintainerPATCH 13/31 netfilter: nat: remove unnecessary rcu_read_lock in nf_nat_redirect_ipv{4/6}
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
nf_nat_redirect_ipv4() and nf_nat_redirect_ipv6() are only called by netfilter hook point. so that rcu_read_lock and rcu_read_unlock() are unnecessary.
--- net/netfilter/nf_nat_redirect.c | 4 ---- 1 file changed, 4 deletions(-)
net/netfilter/nf_nat_redirect.c +0 -4
@@ -52,13 +52,11 @@ nf_nat_redirect_ipv4(struct sk_buff *skb, newdst =0 ; -rcu_read_lock (); indev =__in_dev_get_rcu (skb->dev);if (indev && indev->ifa_list) { ifa = indev->ifa_list; newdst = ifa->ifa_local; } -rcu_read_unlock ();if (!newdst)return NF_DROP ;
@@ -97,7 +95,6 @@ nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,struct inet6_ifaddr *ifa;bool addr = false; -rcu_read_lock (); idev =__in6_dev_get (skb->dev);if (idev !=NULL ) {read_lock_bh (&idev->lock);
@@ -108,7 +105,6 @@ nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range, }read_unlock_bh (&idev->lock); } -rcu_read_unlock ();if (!addr)return NF_DROP ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 14/31 netfilter: conntrack: pass nf_hook_state to packet and error handlers
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
nf_hook_state contains all the hook meta-information: netns, protocol family, hook location, and so on.
Instead of only passing selected information, pass a pointer to entire structure.
This will allow to merge the error and the packet handlers and remove the ->new() function in followup patches.
--- include/net/netfilter/nf_conntrack_core.h | 3 +- include/net/netfilter/nf_conntrack_l4proto.h | 7 ++-- net/netfilter/nf_conntrack_core.c | 49 ++++++++++++------------- net/netfilter/nf_conntrack_proto.c | 8 ++--- net/netfilter/nf_conntrack_proto_dccp.c | 17 +++++---- net/netfilter/nf_conntrack_proto_generic.c | 3 +- net/netfilter/nf_conntrack_proto_gre.c | 3 +- net/netfilter/nf_conntrack_proto_icmp.c | 36 ++++++++++--------- net/netfilter/nf_conntrack_proto_icmpv6.c | 29 ++++++++------- net/netfilter/nf_conntrack_proto_sctp.c | 12 ++++--- net/netfilter/nf_conntrack_proto_tcp.c | 28 ++++++++------- net/netfilter/nf_conntrack_proto_udp.c | 54 +++++++++++++++------------- net/openvswitch/conntrack.c | 8 +++-- 13 files changed, 142 insertions(+), 115 deletions(-)
include/net/netfilter/nf_conntrack_core.h +1 -2
@@ -20,8 +20,7 @@/* This header is used to share core functionality between the standalone connection tracking module, and the compatibility layer's use of connection tracking. */ -unsigned int nf_conntrack_in (struct net *net,u_int8_t pf,unsigned int hooknum, -struct sk_buff *skb); +unsigned int nf_conntrack_in (struct sk_buff *skb,const struct nf_hook_state *state);int nf_conntrack_init_net (struct net *net);void nf_conntrack_cleanup_net (struct net *net);
include/net/netfilter/nf_conntrack_l4proto.h +4 -3
@@ -45,7 +45,8 @@ struct nf_conntrack_l4proto {int (*packet)(struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo); +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state);/* Called when a new connection for this protocol found; * returns TRUE if it's OK. If so, packet() called next. */
@@ -55,9 +56,9 @@ struct nf_conntrack_l4proto {/* Called when a conntrack entry is destroyed */ void (*destroy)(struct nf_conn *ct); -int (*error)(struct net *net,struct nf_conn *tmpl,struct sk_buff *skb, +int (*error)(struct nf_conn *tmpl,struct sk_buff *skb,unsigned int dataoff, -u_int8_t pf,unsigned int hooknum); +const struct nf_hook_state *state);/* called by gc worker if table is full */ bool (*can_early_drop)(const struct nf_conn *ct);
net/netfilter/nf_conntrack_core.c +25 -24
129 lines not on this page · raw message
net/netfilter/nf_conntrack_proto.c +4 -4
@@ -455,7 +455,7 @@ static unsigned int ipv4_conntrack_in(void *priv,struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_conntrack_in(state->net, PF_INET, state->hook, skb); + return nf_conntrack_in(skb, state); } static unsigned int ipv4_conntrack_local(void *priv,
@@ -477,7 +477,7 @@ static unsigned int ipv4_conntrack_local(void *priv,return NF_ACCEPT ; } -return nf_conntrack_in (state->net,PF_INET , state->hook, skb); +return nf_conntrack_in (skb, state); }/* Connection tracking may drop packets, but never alters them, so
@@ -690,14 +690,14 @@ static unsigned int ipv6_conntrack_in(void *priv,struct sk_buff *skb, const struct nf_hook_state *state) { - return nf_conntrack_in(state->net, PF_INET6, state->hook, skb); + return nf_conntrack_in(skb, state); }static unsigned int ipv6_conntrack_local (void *priv,struct sk_buff *skb,const struct nf_hook_state *state) { -return nf_conntrack_in (state->net,PF_INET6 , state->hook, skb); +return nf_conntrack_in (skb, state); } static unsigned int ipv6_helper(void *priv,
net/netfilter/nf_conntrack_proto_dccp.c +10 -7
@@ -439,7 +439,8 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh) }static int dccp_packet (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff,enum ip_conntrack_info ctinfo) +unsigned int dataoff,enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {enum ip_conntrack_dir dir =CTINFO2DIR (ctinfo);struct dccp_hdr _dh, *dh;
@@ -527,9 +528,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,return NF_ACCEPT ; } -static int dccp_error (struct net *net,struct nf_conn *tmpl, +static int dccp_error (struct nf_conn *tmpl,struct sk_buff *skb,unsigned int dataoff, -u_int8_t pf,unsigned int hooknum) +const struct nf_hook_state *state) {struct dccp_hdr _dh, *dh;unsigned int dccp_len = skb->len - dataoff;
@@ -557,9 +558,10 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, } } -if (net->ct.sysctl_checksum && hooknum ==NF_INET_PRE_ROUTING && -nf_checksum_partial (skb, hooknum, dataoff, cscov,IPPROTO_DCCP , - pf)) { +if (state->hook ==NF_INET_PRE_ROUTING && + state->net->ct.sysctl_checksum && +nf_checksum_partial (skb, state->hook, dataoff, cscov, +IPPROTO_DCCP , state->pf)) { msg ="nf_ct_dccp: bad checksum " ; goto out_invalid; }
@@ -572,7 +574,8 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,return NF_ACCEPT ; out_invalid: -nf_l4proto_log_invalid (skb, net, pf,IPPROTO_DCCP ,"%s" , msg); +nf_l4proto_log_invalid (skb, state->net, state->pf, +IPPROTO_DCCP ,"%s" , msg);return -NF_ACCEPT ; }
net/netfilter/nf_conntrack_proto_generic.c +2 -1
@@ -46,7 +46,8 @@ static bool generic_pkt_to_tuple(const struct sk_buff *skb,static int generic_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo) +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {const unsigned int *timeout =nf_ct_timeout_lookup (ct);
net/netfilter/nf_conntrack_proto_gre.c +2 -1
@@ -235,7 +235,8 @@ static unsigned int *gre_get_timeouts(struct net *net)static int gre_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo) +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {/* If we've seen traffic both ways, this is a GRE connection. * Extend timeout. */
net/netfilter/nf_conntrack_proto_icmp.c +20 -16
@@ -81,7 +81,8 @@ static unsigned int *icmp_get_timeouts(struct net *net)static int icmp_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo) +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {/* Do not immediately delete the connection after the first successful reply to avoid excessive conntrackd traffic
@@ -120,8 +121,8 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,/* Returns conntrack if it dealt with ICMP, and filled in skb fields */ static int -icmp_error_message (struct net *net,struct nf_conn *tmpl,struct sk_buff *skb, -unsigned int hooknum) +icmp_error_message (struct nf_conn *tmpl,struct sk_buff *skb, +const struct nf_hook_state *state) {struct nf_conntrack_tuple innertuple, origtuple;const struct nf_conntrack_l4proto *innerproto;
@@ -137,7 +138,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,if (!nf_ct_get_tuplepr (skb,skb_network_offset (skb) +ip_hdrlen (skb) +sizeof (struct icmphdr ), -PF_INET , net, &origtuple)) { +PF_INET , state->net, &origtuple)) {pr_debug ("icmp_error_message: failed to get tuple\n" );return -NF_ACCEPT ; }
@@ -154,7 +155,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, ctinfo =IP_CT_RELATED ; - h =nf_conntrack_find_get (net, zone, &innertuple); + h =nf_conntrack_find_get (state->net, zone, &innertuple);if (!h) {pr_debug ("icmp_error_message: no match\n" );return -NF_ACCEPT ;
@@ -168,17 +169,19 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,return NF_ACCEPT ; } -static void icmp_error_log (const struct sk_buff *skb,struct net *net, -u8 pf,const char *msg) +static void icmp_error_log (const struct sk_buff *skb, +const struct nf_hook_state *state, +const char *msg) { -nf_l4proto_log_invalid (skb, net, pf,IPPROTO_ICMP ,"%s" , msg); +nf_l4proto_log_invalid (skb, state->net, state->pf, +IPPROTO_ICMP ,"%s" , msg); }/* Small and modified version of icmp_rcv */ static int -icmp_error (struct net *net,struct nf_conn *tmpl, +icmp_error (struct nf_conn *tmpl,struct sk_buff *skb,unsigned int dataoff, -u8 pf,unsigned int hooknum) +const struct nf_hook_state *state) {const struct icmphdr *icmph;struct icmphdr _ih;
@@ -186,14 +189,15 @@ icmp_error(struct net *net, struct nf_conn *tmpl,/* Not enough header? */ icmph =skb_header_pointer (skb,ip_hdrlen (skb),sizeof (_ih), &_ih);if (icmph ==NULL ) { -icmp_error_log (skb, net, pf,"short packet" ); +icmp_error_log (skb, state,"short packet" );return -NF_ACCEPT ; }/* See ip_conntrack_proto_tcp.c */ -if (net->ct.sysctl_checksum && hooknum ==NF_INET_PRE_ROUTING && -nf_ip_checksum (skb, hooknum, dataoff,0 )) { -icmp_error_log (skb, net, pf,"bad hw icmp checksum" ); +if (state->net->ct.sysctl_checksum && + state->hook ==NF_INET_PRE_ROUTING && +nf_ip_checksum (skb, state->hook, dataoff,0 )) { +icmp_error_log (skb, state,"bad hw icmp checksum" );return -NF_ACCEPT ; }
@@ -204,7 +208,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl,* discarded. */ if (icmph->type >NR_ICMP_TYPES ) { -icmp_error_log (skb, net, pf,"invalid icmp type" ); +icmp_error_log (skb, state,"invalid icmp type" );return -NF_ACCEPT ; }
@@ -216,7 +220,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, icmph->type != ICMP_REDIRECT)return NF_ACCEPT ; -return icmp_error_message (net, tmpl, skb, hooknum); +return icmp_error_message (tmpl, skb, state); }#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
net/netfilter/nf_conntrack_proto_icmpv6.c +17 -12
@@ -94,7 +94,8 @@ static unsigned int *icmpv6_get_timeouts(struct net *net)static int icmpv6_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo) +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {unsigned int *timeout =nf_ct_timeout_lookup (ct);
@@ -179,16 +180,19 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,return NF_ACCEPT ; } -static void icmpv6_error_log (const struct sk_buff *skb,struct net *net, -u8 pf,const char *msg) +static void icmpv6_error_log (const struct sk_buff *skb, +const struct nf_hook_state *state, +const char *msg) { -nf_l4proto_log_invalid (skb, net, pf,IPPROTO_ICMPV6 ,"%s" , msg); +nf_l4proto_log_invalid (skb, state->net, state->pf, +IPPROTO_ICMPV6 ,"%s" , msg); }static int -icmpv6_error (struct net *net,struct nf_conn *tmpl, -struct sk_buff *skb,unsigned int dataoff, -u8 pf,unsigned int hooknum) +icmpv6_error (struct nf_conn *tmpl, +struct sk_buff *skb, +unsigned int dataoff, +const struct nf_hook_state *state) {const struct icmp6hdr *icmp6h;struct icmp6hdr _ih;
@@ -196,13 +200,14 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl, icmp6h =skb_header_pointer (skb, dataoff,sizeof (_ih), &_ih);if (icmp6h ==NULL ) { -icmpv6_error_log (skb, net, pf,"short packet" ); +icmpv6_error_log (skb, state,"short packet" );return -NF_ACCEPT ; } -if (net->ct.sysctl_checksum && hooknum ==NF_INET_PRE_ROUTING && -nf_ip6_checksum (skb, hooknum, dataoff,IPPROTO_ICMPV6 )) { -icmpv6_error_log (skb, net, pf,"ICMPv6 checksum failed" ); +if (state->hook ==NF_INET_PRE_ROUTING && + state->net->ct.sysctl_checksum && +nf_ip6_checksum (skb, state->hook, dataoff,IPPROTO_ICMPV6 )) { +icmpv6_error_log (skb, state,"ICMPv6 checksum failed" );return -NF_ACCEPT ; }
@@ -217,7 +222,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,if (icmp6h->icmp6_type >=128 )return NF_ACCEPT ; -return icmpv6_error_message (net, tmpl, skb, dataoff); +return icmpv6_error_message (state->net, tmpl, skb, dataoff); }#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
net/netfilter/nf_conntrack_proto_sctp.c +7 -5
@@ -277,7 +277,8 @@ static int sctp_new_state(enum ip_conntrack_dir dir,static int sctp_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo) +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {enum sctp_conntrack new_state, old_state;enum ip_conntrack_dir dir =CTINFO2DIR (ctinfo);
@@ -471,9 +472,9 @@ static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,return true; } -static int sctp_error (struct net *net,struct nf_conn *tpl,struct sk_buff *skb, +static int sctp_error (struct nf_conn *tpl,struct sk_buff *skb,unsigned int dataoff, -u8 pf,unsigned int hooknum) +const struct nf_hook_state *state) {const struct sctphdr *sh;const char *logmsg;
@@ -482,7 +483,8 @@ static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb, logmsg ="nf_ct_sctp: short packet " ; goto out_invalid; } -if (net->ct.sysctl_checksum && hooknum ==NF_INET_PRE_ROUTING && +if (state->hook ==NF_INET_PRE_ROUTING && + state->net->ct.sysctl_checksum && skb->ip_summed ==CHECKSUM_NONE ) {if (!skb_make_writable (skb, dataoff +sizeof (struct sctphdr ))) { logmsg ="nf_ct_sctp: failed to read header " ;
@@ -497,7 +499,7 @@ static int sctp_error(struct net *net, struct nf_conn *tpl, struct sk_buff *skb, }return NF_ACCEPT ; out_invalid: -nf_l4proto_log_invalid (skb, net, pf,IPPROTO_SCTP ,"%s" , logmsg); +nf_l4proto_log_invalid (skb, state->net, state->pf,IPPROTO_SCTP ,"%s" , logmsg);return -NF_ACCEPT ; }
net/netfilter/nf_conntrack_proto_tcp.c +15 -13
@@ -717,18 +717,18 @@ static const u8 tcp_valid_flags[(TCPHDR_FIN|TCPHDR_SYN|TCPHDR_RST|TCPHDR_ACK| [TCPHDR_ACK|TCPHDR_URG] = 1, }; -static void tcp_error_log (const struct sk_buff *skb,struct net *net, -u8 pf,const char *msg) +static void tcp_error_log (const struct sk_buff *skb, +const struct nf_hook_state *state, +const char *msg) { -nf_l4proto_log_invalid (skb, net, pf,IPPROTO_TCP ,"%s" , msg); +nf_l4proto_log_invalid (skb, state->net, state->pf,IPPROTO_TCP ,"%s" , msg); }/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */ -static int tcp_error (struct net *net,struct nf_conn *tmpl, +static int tcp_error (struct nf_conn *tmpl,struct sk_buff *skb,unsigned int dataoff, -u_int8_t pf, -unsigned int hooknum) +const struct nf_hook_state *state) {const struct tcphdr *th;struct tcphdr _tcph;
@@ -738,13 +738,13 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,/* Smaller that minimal TCP header? */ th =skb_header_pointer (skb, dataoff,sizeof (_tcph), &_tcph);if (th ==NULL ) { -tcp_error_log (skb, net, pf,"short packet" ); +tcp_error_log (skb, state,"short packet" );return -NF_ACCEPT ; }/* Not whole TCP header or malformed packet */ if (th->doff*4 <sizeof (struct tcphdr ) || tcplen < th->doff*4 ) { -tcp_error_log (skb, net, pf,"truncated packet" ); +tcp_error_log (skb, state,"truncated packet" );return -NF_ACCEPT ; }
@@ -753,16 +753,17 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,* because the checksum is assumed to be correct. */ /* FIXME: Source route IP option packets --RR */ -if (net->ct.sysctl_checksum && hooknum ==NF_INET_PRE_ROUTING && -nf_checksum (skb, hooknum, dataoff,IPPROTO_TCP , pf)) { -tcp_error_log (skb, net, pf,"bad checksum" ); +if (state->net->ct.sysctl_checksum && + state->hook ==NF_INET_PRE_ROUTING && +nf_checksum (skb, state->hook, dataoff,IPPROTO_TCP , state->pf)) { +tcp_error_log (skb, state,"bad checksum" );return -NF_ACCEPT ; }/* Check TCP flags. */ tcpflags = (tcp_flag_byte (th) & ~(TCPHDR_ECE |TCPHDR_CWR |TCPHDR_PSH ));if (!tcp_valid_flags[tcpflags]) { -tcp_error_log (skb, net, pf,"invalid tcp flag combination" ); +tcp_error_log (skb, state,"invalid tcp flag combination" );return -NF_ACCEPT ; }
@@ -773,7 +774,8 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,static int tcp_packet (struct nf_conn *ct,const struct sk_buff *skb,unsigned int dataoff, -enum ip_conntrack_info ctinfo) +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {struct net *net =nf_ct_net (ct);struct nf_tcp_net *tn =tcp_pernet (net);
net/netfilter/nf_conntrack_proto_udp.c +29 -25
118 lines not on this page · raw message
net/openvswitch/conntrack.c +6 -2
@@ -933,6 +933,11 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,struct nf_conn *ct;if (!cached) { +struct nf_hook_state state = { + .hook =NF_INET_PRE_ROUTING , + .pf = info->family, + .net = net, + };struct nf_conn *tmpl = info->ct;int err;
@@ -944,8 +949,7 @@ static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key,nf_ct_set (skb, tmpl,IP_CT_NEW ); } - err =nf_conntrack_in (net, info->family, -NF_INET_PRE_ROUTING , skb); + err =nf_conntrack_in (skb, &state);if (err !=NF_ACCEPT )return -ENOENT ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 15/31 netfilter: conntrack: remove the l4proto->new() function
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
->new() gets invoked after ->error() and before ->packet() if a conntrack lookup has found no result for the tuple.
We can fold it into ->packet() -- the packet() implementations can check if the conntrack is confirmed (new) or not (already in hash).
If its unconfirmed, the conntrack isn't in the hash yet so current skb created a new conntrack entry.
Only relevant side effect -- if packet() doesn't return NF_ACCEPT but -NF_ACCEPT (or drop), while the conntrack was just created, then the newly allocated conntrack is freed right away, rather than not created in the first place.
--- include/net/netfilter/nf_conntrack_l4proto.h | 5 - net/netfilter/nf_conntrack_core.c | 6 -- net/netfilter/nf_conntrack_proto_dccp.c | 17 ++- net/netfilter/nf_conntrack_proto_generic.c | 20 ++-- net/netfilter/nf_conntrack_proto_gre.c | 33 +++--- net/netfilter/nf_conntrack_proto_icmp.c | 28 ++--- net/netfilter/nf_conntrack_proto_icmpv6.c | 37 +++---- net/netfilter/nf_conntrack_proto_sctp.c | 144 ++++++++++++------------- net/netfilter/nf_conntrack_proto_tcp.c | 156 +++++++++++++-------------- net/netfilter/nf_conntrack_proto_udp.c | 11 -- 10 files changed, 194 insertions(+), 263 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +0 -5
@@ -48,11 +48,6 @@ struct nf_conntrack_l4proto {enum ip_conntrack_info ctinfo, const struct nf_hook_state *state); -/* Called when a new connection for this protocol found; -* returns TRUE if it's OK. If so, packet() called next. */ -bool (*new)(struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff); -/* Called when a conntrack entry is destroyed */ void (*destroy)(struct nf_conn *ct);
net/netfilter/nf_conntrack_core.c +0 -6
@@ -1370,12 +1370,6 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, timeout_ext = tmpl ?nf_ct_timeout_find (tmpl) :NULL ; -if (!l4proto->new (ct, skb, dataoff)) { -nf_conntrack_free (ct); -pr_debug ("can't track with proto module\n" ); -return NULL ; - } -if (timeout_ext)nf_ct_timeout_ext_add (ct,rcu_dereference (timeout_ext->timeout),GFP_ATOMIC );
net/netfilter/nf_conntrack_proto_dccp.c +8 -9
@@ -389,18 +389,15 @@ static inline struct nf_dccp_net *dccp_pernet(struct net *net)return &net->ct.nf_ct_proto.dccp; } -static bool dccp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff) +static noinline bool +dccp_new (struct nf_conn *ct,const struct sk_buff *skb, +const struct dccp_hdr *dh) {struct net *net =nf_ct_net (ct);struct nf_dccp_net *dn; -struct dccp_hdr _dh, *dh;const char *msg;u_int8_t state; - dh =skb_header_pointer (skb, dataoff,sizeof (_dh), &_dh); -BUG_ON (dh ==NULL ); - state = dccp_state_table[CT_DCCP_ROLE_CLIENT ][dh->dccph_type][CT_DCCP_NONE ];switch (state) {default :
@@ -449,8 +446,12 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,unsigned int *timeouts; dh =skb_header_pointer (skb, dataoff,sizeof (_dh), &_dh); -BUG_ON (dh ==NULL ); +if (!dh) +return NF_DROP ; + type = dh->dccph_type; +if (!nf_ct_is_confirmed (ct) && !dccp_new (ct, skb, dh)) +return -NF_ACCEPT ;if (type ==DCCP_PKT_RESET && !test_bit (IPS_SEEN_REPLY_BIT , &ct->status)) {
@@ -850,7 +851,6 @@ static struct nf_proto_net *dccp_get_net_proto(struct net *net)const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { .l3proto =AF_INET , .l4proto =IPPROTO_DCCP , - .new = dccp_new, .packet = dccp_packet, .error = dccp_error, .can_early_drop = dccp_can_early_drop,
@@ -883,7 +883,6 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4);const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { .l3proto =AF_INET6 , .l4proto =IPPROTO_DCCP , - .new = dccp_new, .packet = dccp_packet, .error = dccp_error, .can_early_drop = dccp_can_early_drop,
net/netfilter/nf_conntrack_proto_generic.c +6 -14
@@ -51,6 +51,12 @@ static int generic_packet(struct nf_conn *ct, {const unsigned int *timeout =nf_ct_timeout_lookup (ct); +if (!nf_generic_should_process (nf_ct_protonum (ct))) { +pr_warn_once ("conntrack: generic helper won't handle protocol %d. Please consider loading the specific helper module.\n" , +nf_ct_protonum (ct)); +return -NF_ACCEPT ; + } +if (!timeout) timeout = &generic_pernet (nf_ct_net (ct))->timeout;
@@ -58,19 +64,6 @@ static int generic_packet(struct nf_conn *ct,return NF_ACCEPT ; } -/* Called when a new connection for this protocol found. */ -static bool generic_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff) -{ -bool ret; - - ret =nf_generic_should_process (nf_ct_protonum (ct)); -if (!ret) -pr_warn_once ("conntrack: generic helper won't handle protocol %d. Please consider loading the specific helper module.\n" , -nf_ct_protonum (ct)); -return ret; -} -#ifdef CONFIG_NF_CONNTRACK_TIMEOUT #include <linux/netfilter/nfnetlink.h>
@@ -164,7 +157,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = .l4proto = 255, .pkt_to_tuple = generic_pkt_to_tuple, .packet = generic_packet, - .new = generic_new, #ifdef CONFIG_NF_CONNTRACK_TIMEOUT .ctnl_timeout = { .nlattr_to_obj = generic_timeout_nlattr_to_obj,
net/netfilter/nf_conntrack_proto_gre.c +12 -21
@@ -238,6 +238,18 @@ static int gre_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, const struct nf_hook_state *state) { +if (!nf_ct_is_confirmed (ct)) { +unsigned int *timeouts =nf_ct_timeout_lookup (ct); + +if (!timeouts) + timeouts =gre_get_timeouts (nf_ct_net (ct)); + +/* initialize to sane value. Ideally a conntrack helper +* (e.g. in case of pptp) is increasing them */ + ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED ]; + ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED ]; + } +/* If we've seen traffic both ways, this is a GRE connection. * Extend timeout. */ if (ct->status &IPS_SEEN_REPLY ) {
@@ -253,26 +265,6 @@ static int gre_packet(struct nf_conn *ct,return NF_ACCEPT ; } -/* Called when a new connection for this protocol found. */ -static bool gre_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff) -{ -unsigned int *timeouts =nf_ct_timeout_lookup (ct); - -if (!timeouts) - timeouts =gre_get_timeouts (nf_ct_net (ct)); - -pr_debug (": " ); -nf_ct_dump_tuple (&ct->tuplehash[IP_CT_DIR_ORIGINAL ].tuple); - -/* initialize to sane value. Ideally a conntrack helper -* (e.g. in case of pptp) is increasing them */ - ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED ]; - ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED ]; - -return true; -} -/* Called when a conntrack entry has already been removed from the hashes * and is about to be deleted from memory */ static void gre_destroy (struct nf_conn *ct)
@@ -359,7 +351,6 @@ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { .print_conntrack = gre_print_conntrack, #endif .packet = gre_packet, - .new = gre_new, .destroy = gre_destroy, .me = THIS_MODULE,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
net/netfilter/nf_conntrack_proto_icmp.c +7 -21
@@ -72,11 +72,6 @@ static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple,return true; } -static unsigned int *icmp_get_timeouts (struct net *net) -{ -return &icmp_pernet (net)->timeout; -} -/* Returns verdict for packet, or -1 for invalid. */ static int icmp_packet(struct nf_conn *ct, const struct sk_buff *skb,
@@ -88,19 +83,6 @@ static int icmp_packet(struct nf_conn *ct,successful reply to avoid excessive conntrackd traffic and also to handle correctly ICMP echo reply duplicates. */ unsigned int *timeout =nf_ct_timeout_lookup (ct); - -if (!timeout) - timeout =icmp_get_timeouts (nf_ct_net (ct)); - -nf_ct_refresh_acct (ct, ctinfo, skb, *timeout); - -return NF_ACCEPT ; -} - -/* Called when a new connection for this protocol found. */ -static bool icmp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff) -{static const u_int8_t valid_new[] = { [ICMP_ECHO ] =1 , [ICMP_TIMESTAMP ] =1 ,
@@ -114,9 +96,14 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,pr_debug ("icmp: can't create new conn with type %u\n" , ct->tuplehash[0 ].tuple.dst.u.icmp.type);nf_ct_dump_tuple_ip (&ct->tuplehash[0 ].tuple); -return false; +return -NF_ACCEPT ; } -return true; + +if (!timeout) + timeout = &icmp_pernet (nf_ct_net (ct))->timeout; + +nf_ct_refresh_acct (ct, ctinfo, skb, *timeout); +return NF_ACCEPT ; }/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
@@ -368,7 +355,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = .pkt_to_tuple = icmp_pkt_to_tuple, .invert_tuple = icmp_invert_tuple, .packet = icmp_packet, - .new = icmp_new, .error = icmp_error, .destroy = NULL, .me = NULL,
net/netfilter/nf_conntrack_proto_icmpv6.c +16 -21
@@ -98,6 +98,22 @@ static int icmpv6_packet(struct nf_conn *ct, const struct nf_hook_state *state) {unsigned int *timeout =nf_ct_timeout_lookup (ct); +static const u8 valid_new[] = { + [ICMPV6_ECHO_REQUEST -128 ] =1 , + [ICMPV6_NI_QUERY -128 ] =1 + }; + +if (!nf_ct_is_confirmed (ct)) { +int type = ct->tuplehash[0 ].tuple.dst.u.icmp.type -128 ; + +if (type <0 || type >=sizeof (valid_new) || !valid_new[type]) { +/* Can't create a new ICMPv6 `conn' with this. */ +pr_debug ("icmpv6: can't create new conn with type %u\n" , + type +128 ); +nf_ct_dump_tuple_ipv6 (&ct->tuplehash[0 ].tuple); +return -NF_ACCEPT ; + } + }if (!timeout) timeout =icmpv6_get_timeouts (nf_ct_net (ct));
@@ -110,26 +126,6 @@ static int icmpv6_packet(struct nf_conn *ct,return NF_ACCEPT ; } -/* Called when a new connection for this protocol found. */ -static bool icmpv6_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff) -{ -static const u_int8_t valid_new[] = { - [ICMPV6_ECHO_REQUEST -128 ] =1 , - [ICMPV6_NI_QUERY -128 ] =1 - }; -int type = ct->tuplehash[0 ].tuple.dst.u.icmp.type -128 ; - -if (type <0 || type >=sizeof (valid_new) || !valid_new[type]) { -/* Can't create a new ICMPv6 `conn' with this. */ -pr_debug ("icmpv6: can't create new conn with type %u\n" , - type +128 ); -nf_ct_dump_tuple_ipv6 (&ct->tuplehash[0 ].tuple); -return false; - } -return true; -} - static int icmpv6_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
@@ -370,7 +366,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = .pkt_to_tuple = icmpv6_pkt_to_tuple, .invert_tuple = icmpv6_invert_tuple, .packet = icmpv6_packet, - .new = icmpv6_new, .error = icmpv6_error, #if IS_ENABLED(CONFIG_NF_CT_NETLINK) .tuple_to_nlattr = icmpv6_tuple_to_nlattr,
net/netfilter/nf_conntrack_proto_sctp.c +68 -76
174 lines not on this page · raw message
net/netfilter/nf_conntrack_proto_tcp.c +77 -79
186 lines not on this page · raw message
net/netfilter/nf_conntrack_proto_udp.c +0 -11
@@ -70,13 +70,6 @@ static int udp_packet(struct nf_conn *ct,return NF_ACCEPT ; } -/* Called when a new connection for this protocol found. */ -static bool udp_new (struct nf_conn *ct,const struct sk_buff *skb, -unsigned int dataoff) -{ -return true; -} -#ifdef CONFIG_NF_CT_PROTO_UDPLITE static void udplite_error_log(const struct sk_buff *skb, const struct nf_hook_state *state,
@@ -288,7 +281,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 = .l4proto = IPPROTO_UDP, .allow_clash = true, .packet = udp_packet, - .new = udp_new, .error = udp_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
@@ -317,7 +309,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 = .l4proto = IPPROTO_UDPLITE, .allow_clash = true, .packet = udp_packet, - .new = udp_new, .error = udplite_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
@@ -346,7 +337,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 = .l4proto = IPPROTO_UDP, .allow_clash = true, .packet = udp_packet, - .new = udp_new, .error = udp_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
@@ -375,7 +365,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 = .l4proto = IPPROTO_UDPLITE, .allow_clash = true, .packet = udp_packet, - .new = udp_new, .error = udplite_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 16/31 netfilter: conntrack: deconstify packet callback skb pointer
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Only two protocols need the ->error() function: icmp and icmpv6. This is because icmp error mssages might be RELATED to an existing connection (e.g. PMTUD, port unreachable and the like), and their ->error() handlers do this.
The error callback is already optional, so remove it for udp and call them from ->packet() instead.
As the error() callback can call checksum functions that write to skb->csum*, the const qualifier has to be removed as well.
--- include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/netfilter/nf_conntrack_proto_dccp.c | 2 +- net/netfilter/nf_conntrack_proto_generic.c | 2 +- net/netfilter/nf_conntrack_proto_gre.c | 2 +- net/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/netfilter/nf_conntrack_proto_icmpv6.c | 8 +- net/netfilter/nf_conntrack_proto_sctp.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_proto_udp.c | 137 ++++++++++++++++----------- 9 files changed, 95 insertions(+), 64 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +1 -1
@@ -43,7 +43,7 @@ struct nf_conntrack_l4proto {/* Returns verdict for packet, or -1 for invalid. */ int (*packet)(struct nf_conn *ct, -const struct sk_buff *skb, +struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state);
net/netfilter/nf_conntrack_proto_dccp.c +1 -1
@@ -435,7 +435,7 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh)ntohl (dhack->dccph_ack_nr_low); } -static int dccp_packet (struct nf_conn *ct,const struct sk_buff *skb, +static int dccp_packet (struct nf_conn *ct,struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state) {
net/netfilter/nf_conntrack_proto_generic.c +1 -1
@@ -44,7 +44,7 @@ static bool generic_pkt_to_tuple(const struct sk_buff *skb,/* Returns verdict for packet, or -1 for invalid. */ static int generic_packet (struct nf_conn *ct, -const struct sk_buff *skb, +struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_gre.c +1 -1
@@ -233,7 +233,7 @@ static unsigned int *gre_get_timeouts(struct net *net)/* Returns verdict for packet, and may modify conntrack */ static int gre_packet (struct nf_conn *ct, -const struct sk_buff *skb, +struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_icmp.c +1 -1
@@ -74,7 +74,7 @@ static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple,/* Returns verdict for packet, or -1 for invalid. */ static int icmp_packet (struct nf_conn *ct, -const struct sk_buff *skb, +struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_icmpv6.c +4 -4
@@ -92,10 +92,10 @@ static unsigned int *icmpv6_get_timeouts(struct net *net)/* Returns verdict for packet, or -1 for invalid. */ static int icmpv6_packet (struct nf_conn *ct, -const struct sk_buff *skb, -unsigned int dataoff, -enum ip_conntrack_info ctinfo, -const struct nf_hook_state *state) +struct sk_buff *skb, +unsigned int dataoff, +enum ip_conntrack_info ctinfo, +const struct nf_hook_state *state) {unsigned int *timeout =nf_ct_timeout_lookup (ct);static const u8 valid_new[] = {
net/netfilter/nf_conntrack_proto_sctp.c +1 -1
@@ -332,7 +332,7 @@ sctp_new(struct nf_conn *ct, const struct sk_buff *skb,/* Returns verdict for packet, or -NF_ACCEPT for invalid. */ static int sctp_packet (struct nf_conn *ct, -const struct sk_buff *skb, +struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_tcp.c +1 -1
@@ -844,7 +844,7 @@ static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,/* Returns verdict for packet, or -1 for invalid. */ static int tcp_packet (struct nf_conn *ct, -const struct sk_buff *skb, +struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state)
net/netfilter/nf_conntrack_proto_udp.c +84 -53
216 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 17/31 netfilter: conntrack: avoid using ->error callback if possible
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
The error() handler gets called before allocating or looking up a connection tracking entry.
We can instead use direct calls from the ->packet() handlers which get invoked for every packet anyway.
Only exceptions are icmp and icmpv6, these two special cases will be handled in the next patch.
--- net/netfilter/nf_conntrack_proto_dccp.c | 98 +++++++++++++++------------------ net/netfilter/nf_conntrack_proto_sctp.c | 67 +++++++++++----------- net/netfilter/nf_conntrack_proto_tcp.c | 32 ++++------- 3 files changed, 91 insertions(+), 106 deletions(-)
net/netfilter/nf_conntrack_proto_dccp.c +45 -53
@@ -435,6 +435,48 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh)ntohl (dhack->dccph_ack_nr_low); } +static bool dccp_error (const struct dccp_hdr *dh, +struct sk_buff *skb,unsigned int dataoff, +const struct nf_hook_state *state) +{ +unsigned int dccp_len = skb->len - dataoff; +unsigned int cscov; +const char *msg; + +if (dh->dccph_doff *4 <sizeof (struct dccp_hdr ) || + dh->dccph_doff *4 > dccp_len) { + msg ="nf_ct_dccp: truncated/malformed packet " ; + goto out_invalid; + } + + cscov = dccp_len; +if (dh->dccph_cscov) { + cscov = (dh->dccph_cscov -1 ) *4 ; +if (cscov > dccp_len) { + msg ="nf_ct_dccp: bad checksum coverage " ; + goto out_invalid; + } + } + +if (state->hook ==NF_INET_PRE_ROUTING && + state->net->ct.sysctl_checksum && +nf_checksum_partial (skb, state->hook, dataoff, cscov, +IPPROTO_DCCP , state->pf)) { + msg ="nf_ct_dccp: bad checksum " ; + goto out_invalid; + } + +if (dh->dccph_type >=DCCP_PKT_INVALID ) { + msg ="nf_ct_dccp: reserved packet type " ; + goto out_invalid; + } +return false; +out_invalid: +nf_l4proto_log_invalid (skb, state->net, state->pf, +IPPROTO_DCCP ,"%s" , msg); +return true; +} +static int dccp_packet (struct nf_conn *ct,struct sk_buff *skb,unsigned int dataoff,enum ip_conntrack_info ctinfo,const struct nf_hook_state *state)
@@ -449,6 +491,9 @@ static int dccp_packet(struct nf_conn *ct, struct sk_buff *skb,if (!dh)return NF_DROP ; +if (dccp_error (dh, skb, dataoff, state)) +return -NF_ACCEPT ; + type = dh->dccph_type;if (!nf_ct_is_confirmed (ct) && !dccp_new (ct, skb, dh))return -NF_ACCEPT ;
@@ -529,57 +574,6 @@ static int dccp_packet(struct nf_conn *ct, struct sk_buff *skb,return NF_ACCEPT ; } -static int dccp_error (struct nf_conn *tmpl, -struct sk_buff *skb,unsigned int dataoff, -const struct nf_hook_state *state) -{ -struct dccp_hdr _dh, *dh; -unsigned int dccp_len = skb->len - dataoff; -unsigned int cscov; -const char *msg; - - dh =skb_header_pointer (skb, dataoff,sizeof (_dh), &_dh); -if (dh ==NULL ) { - msg ="nf_ct_dccp: short packet " ; - goto out_invalid; - } - -if (dh->dccph_doff *4 <sizeof (struct dccp_hdr ) || - dh->dccph_doff *4 > dccp_len) { - msg ="nf_ct_dccp: truncated/malformed packet " ; - goto out_invalid; - } - - cscov = dccp_len; -if (dh->dccph_cscov) { - cscov = (dh->dccph_cscov -1 ) *4 ; -if (cscov > dccp_len) { - msg ="nf_ct_dccp: bad checksum coverage " ; - goto out_invalid; - } - } - -if (state->hook ==NF_INET_PRE_ROUTING && - state->net->ct.sysctl_checksum && -nf_checksum_partial (skb, state->hook, dataoff, cscov, -IPPROTO_DCCP , state->pf)) { - msg ="nf_ct_dccp: bad checksum " ; - goto out_invalid; - } - -if (dh->dccph_type >=DCCP_PKT_INVALID ) { - msg ="nf_ct_dccp: reserved packet type " ; - goto out_invalid; - } - -return NF_ACCEPT ; - -out_invalid: -nf_l4proto_log_invalid (skb, state->net, state->pf, -IPPROTO_DCCP ,"%s" , msg); -return -NF_ACCEPT ; -} -static bool dccp_can_early_drop (const struct nf_conn *ct) {switch (ct->proto.dccp.state) {
@@ -852,7 +846,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { .l3proto = AF_INET, .l4proto = IPPROTO_DCCP, .packet = dccp_packet, - .error = dccp_error, .can_early_drop = dccp_can_early_drop, #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = dccp_print_conntrack,
@@ -884,7 +877,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { .l3proto = AF_INET6, .l4proto = IPPROTO_DCCP, .packet = dccp_packet, - .error = dccp_error, .can_early_drop = dccp_can_early_drop, #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = dccp_print_conntrack,
net/netfilter/nf_conntrack_proto_sctp.c +34 -33
97 lines not on this page · raw message
net/netfilter/nf_conntrack_proto_tcp.c +12 -20
@@ -725,27 +725,18 @@ static void tcp_error_log(const struct sk_buff *skb, }/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */ -static int tcp_error (struct nf_conn *tmpl, -struct sk_buff *skb, -unsigned int dataoff, -const struct nf_hook_state *state) +static bool tcp_error (const struct tcphdr *th, +struct sk_buff *skb, +unsigned int dataoff, +const struct nf_hook_state *state) { -const struct tcphdr *th; -struct tcphdr _tcph;unsigned int tcplen = skb->len - dataoff; -u_int8_t tcpflags; - -/* Smaller that minimal TCP header? */ - th =skb_header_pointer (skb, dataoff,sizeof (_tcph), &_tcph); -if (th ==NULL ) { -tcp_error_log (skb, state,"short packet" ); -return -NF_ACCEPT ; - } +u8 tcpflags;/* Not whole TCP header or malformed packet */ if (th->doff*4 <sizeof (struct tcphdr ) || tcplen < th->doff*4 ) {tcp_error_log (skb, state,"truncated packet" ); -return -NF_ACCEPT ; +return true; }/* Checksum invalid? Ignore.
@@ -757,17 +748,17 @@ static int tcp_error(struct nf_conn *tmpl, state->hook == NF_INET_PRE_ROUTING && nf_checksum(skb, state->hook, dataoff, IPPROTO_TCP, state->pf)) {tcp_error_log (skb, state,"bad checksum" ); -return -NF_ACCEPT ; +return true; }/* Check TCP flags. */ tcpflags = (tcp_flag_byte (th) & ~(TCPHDR_ECE |TCPHDR_CWR |TCPHDR_PSH ));if (!tcp_valid_flags[tcpflags]) {tcp_error_log (skb, state,"invalid tcp flag combination" ); -return -NF_ACCEPT ; +return true; } -return NF_ACCEPT ; +return false; } static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
@@ -863,6 +854,9 @@ static int tcp_packet(struct nf_conn *ct,if (th ==NULL )return -NF_ACCEPT ; +if (tcp_error (th, skb, dataoff, state)) +return -NF_ACCEPT ; +if (!nf_ct_is_confirmed (ct) && !tcp_new (ct, skb, dataoff, th))return -NF_ACCEPT ;
@@ -1548,7 +1542,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = .print_conntrack = tcp_print_conntrack, #endif .packet = tcp_packet, - .error = tcp_error, .can_early_drop = tcp_can_early_drop,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .to_nlattr = tcp_to_nlattr,
@@ -1582,7 +1575,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = .print_conntrack = tcp_print_conntrack, #endif .packet = tcp_packet, - .error = tcp_error, .can_early_drop = tcp_can_early_drop,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .nlattr_size = TCP_NLATTR_SIZE,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 18/31 netfilter: conntrack: remove error callback and handle icmp from core
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
icmp(v6) are the only two layer four protocols that need the error() callback (to handle icmp errors that are related to an established connections, e.g. packet too big, port unreachable and the like).
Remove the error callback and handle these two special cases from the core.
--- include/net/netfilter/nf_conntrack_l4proto.h | 13 ++++++--- net/netfilter/nf_conntrack_core.c | 43 +++++++++++++++++++++++----- net/netfilter/nf_conntrack_proto_icmp.c | 8 ++---- net/netfilter/nf_conntrack_proto_icmpv6.c | 10 +++---- 4 files changed, 52 insertions(+), 22 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +9 -4
@@ -51,10 +51,6 @@ struct nf_conntrack_l4proto {/* Called when a conntrack entry is destroyed */ void (*destroy)(struct nf_conn *ct); -int (*error)(struct nf_conn *tmpl,struct sk_buff *skb, -unsigned int dataoff, -const struct nf_hook_state *state); -/* called by gc worker if table is full */ bool (*can_early_drop)(const struct nf_conn *ct);
@@ -97,6 +93,15 @@ struct nf_conntrack_l4proto {struct module *me; }; +int nf_conntrack_icmpv4_error (struct nf_conn *tmpl, +struct sk_buff *skb, +unsigned int dataoff, +const struct nf_hook_state *state); + +int nf_conntrack_icmpv6_error (struct nf_conn *tmpl, +struct sk_buff *skb, +unsigned int dataoff, +const struct nf_hook_state *state);/* Existing built-in generic protocol */ extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
net/netfilter/nf_conntrack_core.c +36 -7
56 lines not on this page · raw message
net/netfilter/nf_conntrack_proto_icmp.c +3 -5
@@ -165,10 +165,9 @@ static void icmp_error_log(const struct sk_buff *skb, }/* Small and modified version of icmp_rcv */ -static int -icmp_error (struct nf_conn *tmpl, -struct sk_buff *skb,unsigned int dataoff, -const struct nf_hook_state *state) +int nf_conntrack_icmpv4_error (struct nf_conn *tmpl, +struct sk_buff *skb,unsigned int dataoff, +const struct nf_hook_state *state) {const struct icmphdr *icmph;struct icmphdr _ih;
@@ -355,7 +354,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = .pkt_to_tuple = icmp_pkt_to_tuple, .invert_tuple = icmp_invert_tuple, .packet = icmp_packet, - .error = icmp_error, .destroy = NULL, .me = NULL,#if IS_ENABLED (CONFIG_NF_CT_NETLINK )
net/netfilter/nf_conntrack_proto_icmpv6.c +4 -6
@@ -184,11 +184,10 @@ static void icmpv6_error_log(const struct sk_buff *skb, IPPROTO_ICMPV6, "%s", msg); } -static int -icmpv6_error (struct nf_conn *tmpl, -struct sk_buff *skb, -unsigned int dataoff, -const struct nf_hook_state *state) +int nf_conntrack_icmpv6_error (struct nf_conn *tmpl, +struct sk_buff *skb, +unsigned int dataoff, +const struct nf_hook_state *state) {const struct icmp6hdr *icmp6h;struct icmp6hdr _ih;
@@ -366,7 +365,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = .pkt_to_tuple = icmpv6_pkt_to_tuple, .invert_tuple = icmpv6_invert_tuple, .packet = icmpv6_packet, - .error = icmpv6_error,#if IS_ENABLED (CONFIG_NF_CT_NETLINK ) .tuple_to_nlattr = icmpv6_tuple_to_nlattr, .nlattr_tuple_size = icmpv6_nlattr_tuple_size,
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 19/31 netfilter: conntrack: remove unused proto arg from netns init functions
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
Its unused, next patch will remove l4proto->l3proto number to simplify l4 protocol demuxer lookup.
--- include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/netfilter/nf_conntrack_proto.c | 5 ++--- net/netfilter/nf_conntrack_proto_dccp.c | 2 +- net/netfilter/nf_conntrack_proto_generic.c | 2 +- net/netfilter/nf_conntrack_proto_gre.c | 2 +- net/netfilter/nf_conntrack_proto_icmp.c | 2 +- net/netfilter/nf_conntrack_proto_icmpv6.c | 2 +- net/netfilter/nf_conntrack_proto_sctp.c | 2 +- net/netfilter/nf_conntrack_proto_tcp.c | 2 +- net/netfilter/nf_conntrack_proto_udp.c | 2 +- 10 files changed, 11 insertions(+), 12 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +1 -1
@@ -84,7 +84,7 @@ struct nf_conntrack_l4proto {#endif unsigned int *net_id;/* Init l4proto pernet data */ -int (*init_net)(struct net *net,u_int16_t proto); +int (*init_net)(struct net *net);/* Return the per-net protocol part. */ struct nf_proto_net *(*get_net_proto)(struct net *net);
net/netfilter/nf_conntrack_proto.c +2 -3
@@ -274,7 +274,7 @@ int nf_ct_l4proto_pernet_register_one(struct net *net,struct nf_proto_net *pn =NULL ;if (l4proto->init_net) { - ret = l4proto->init_net (net, l4proto->l3proto); + ret = l4proto->init_net (net);if (ret <0 ) goto out; }
@@ -988,8 +988,7 @@ int nf_conntrack_proto_pernet_init(struct net *net)struct nf_proto_net *pn =nf_ct_l4proto_net (net, &nf_conntrack_l4proto_generic); - err = nf_conntrack_l4proto_generic.init_net (net, - nf_conntrack_l4proto_generic.l3proto); + err = nf_conntrack_l4proto_generic.init_net (net);if (err <0 )return err; err = nf_ct_l4proto_register_sysctl(net,
net/netfilter/nf_conntrack_proto_dccp.c +1 -1
@@ -812,7 +812,7 @@ static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,return 0 ; } -static int dccp_init_net (struct net *net,u_int16_t proto) +static int dccp_init_net (struct net *net) {struct nf_dccp_net *dn =dccp_pernet (net);struct nf_proto_net *pn = &dn->pn;
net/netfilter/nf_conntrack_proto_generic.c +1 -1
@@ -136,7 +136,7 @@ static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn,return 0 ; } -static int generic_init_net (struct net *net,u_int16_t proto) +static int generic_init_net (struct net *net) {struct nf_generic_net *gn =generic_pernet (net);struct nf_proto_net *pn = &gn->pn;
net/netfilter/nf_conntrack_proto_gre.c +1 -1
@@ -329,7 +329,7 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = { };#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ -static int gre_init_net (struct net *net,u_int16_t proto) +static int gre_init_net (struct net *net) {struct netns_proto_gre *net_gre =gre_pernet (net);int i;
net/netfilter/nf_conntrack_proto_icmp.c +1 -1
@@ -332,7 +332,7 @@ static int icmp_kmemdup_sysctl_table(struct nf_proto_net *pn,return 0 ; } -static int icmp_init_net (struct net *net,u_int16_t proto) +static int icmp_init_net (struct net *net) {struct nf_icmp_net *in =icmp_pernet (net);struct nf_proto_net *pn = &in->pn;
net/netfilter/nf_conntrack_proto_icmpv6.c +1 -1
@@ -343,7 +343,7 @@ static int icmpv6_kmemdup_sysctl_table(struct nf_proto_net *pn,return 0 ; } -static int icmpv6_init_net (struct net *net,u_int16_t proto) +static int icmpv6_init_net (struct net *net) {struct nf_icmp_net *in =icmpv6_pernet (net);struct nf_proto_net *pn = &in->pn;
net/netfilter/nf_conntrack_proto_sctp.c +1 -1
@@ -734,7 +734,7 @@ static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,return 0 ; } -static int sctp_init_net (struct net *net,u_int16_t proto) +static int sctp_init_net (struct net *net) {struct nf_sctp_net *sn =sctp_pernet (net);struct nf_proto_net *pn = &sn->pn;
net/netfilter/nf_conntrack_proto_tcp.c +1 -1
@@ -1506,7 +1506,7 @@ static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn,return 0 ; } -static int tcp_init_net (struct net *net,u_int16_t proto) +static int tcp_init_net (struct net *net) {struct nf_tcp_net *tn =tcp_pernet (net);struct nf_proto_net *pn = &tn->pn;
net/netfilter/nf_conntrack_proto_udp.c +1 -1
@@ -290,7 +290,7 @@ static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn,return 0 ; } -static int udp_init_net (struct net *net,u_int16_t proto) +static int udp_init_net (struct net *net) {struct nf_udp_net *un =udp_pernet (net);struct nf_proto_net *pn = &un->pn;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 20/31 netfilter: conntrack: remove l3->l4 mapping information
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
l4 protocols are demuxed by l3num, l4num pair.
However, almost all l4 trackers are l3 agnostic.
Only exceptions are:
- gre, icmp (ipv4 only)
- icmpv6 (ipv6 only)
This commit gets rid of the l3 mapping, l4 trackers can now be looked up by their IPPROTO_XXX value alone, which gets rid of the additional l3 indirection.
For icmp, ipcmp6 and gre, add a check on state->pf and return -NF_ACCEPT in case we're asked to track e.g. icmpv6-in-ipv4, this seems more fitting than using the generic tracker.
Additionally we can kill the 2nd l4proto definitions that were needed for v4/v6 split -- they are now the same so we can use single l4proto struct for each protocol, rather than two.
The EXPORT_SYMBOLs can be removed as all these object files are part of nf_conntrack with no external references.
--- include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 13 ++-- include/net/netfilter/ipv6/nf_conntrack_ipv6.h | 13 ---- include/net/netfilter/nf_conntrack_l4proto.h | 9 +-- net/netfilter/nf_conntrack_core.c | 15 ++-- net/netfilter/nf_conntrack_expect.c | 3 +- net/netfilter/nf_conntrack_netlink.c | 14 ++-- net/netfilter/nf_conntrack_proto.c | 104 +++++++------------------ net/netfilter/nf_conntrack_proto_dccp.c | 35 +-------- net/netfilter/nf_conntrack_proto_generic.c | 1 - net/netfilter/nf_conntrack_proto_gre.c | 4 +- net/netfilter/nf_conntrack_proto_icmp.c | 6 +- net/netfilter/nf_conntrack_proto_icmpv6.c | 6 +- net/netfilter/nf_conntrack_proto_sctp.c | 36 +-------- net/netfilter/nf_conntrack_proto_tcp.c | 37 +-------- net/netfilter/nf_conntrack_proto_udp.c | 62 +-------------- net/netfilter/nf_conntrack_standalone.c | 2 +- net/netfilter/nf_flow_table_core.c | 2 +- net/netfilter/nfnetlink_cttimeout.c | 11 +-- net/netfilter/nft_ct.c | 2 +- net/netfilter/xt_CT.c | 2 +- 20 files changed, 76 insertions(+), 301 deletions(-)
include/net/netfilter/ipv4/nf_conntrack_ipv4.h +5 -8
@@ -10,20 +10,17 @@#ifndef _NF_CONNTRACK_IPV4_H#define _NF_CONNTRACK_IPV4_H -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp;extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;#ifdef CONFIG_NF_CT_PROTO_DCCP -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp;#endif #ifdef CONFIG_NF_CT_PROTO_SCTP -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp;#endif #ifdef CONFIG_NF_CT_PROTO_UDPLITE -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4; +extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite;#endif -int nf_conntrack_ipv4_compat_init (void ); -void nf_conntrack_ipv4_compat_fini (void ); -#endif /*_NF_CONNTRACK_IPV4_H*/
include/net/netfilter/ipv6/nf_conntrack_ipv6.h +0 -13
@@ -2,20 +2,7 @@#ifndef _NF_CONNTRACK_IPV6_H#define _NF_CONNTRACK_IPV6_H -extern const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6; - -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6; -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6; -#ifdef CONFIG_NF_CT_PROTO_DCCP -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6; -#endif -#ifdef CONFIG_NF_CT_PROTO_SCTP -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6; -#endif -#ifdef CONFIG_NF_CT_PROTO_UDPLITE -extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6; -#endif #include <linux/sysctl.h> extern struct ctl_table nf_ct_ipv6_sysctl_table[];
include/net/netfilter/nf_conntrack_l4proto.h +2 -7
@@ -18,9 +18,6 @@struct seq_file ;struct nf_conntrack_l4proto { -/* L3 Protocol number. */ -u_int16_t l3proto; -/* L4 Protocol number. */ u_int8_t l4proto;
@@ -107,11 +104,9 @@ extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;#define MAX_NF_CT_PROTO 256 -const struct nf_conntrack_l4proto *__nf_ct_l4proto_find (u_int16_t l3proto, -u_int8_t l4proto); +const struct nf_conntrack_l4proto *__nf_ct_l4proto_find (u8 l4proto); -const struct nf_conntrack_l4proto *nf_ct_l4proto_find_get (u_int16_t l3proto, -u_int8_t l4proto); +const struct nf_conntrack_l4proto *nf_ct_l4proto_find_get (u8 l4proto);void nf_ct_l4proto_put (const struct nf_conntrack_l4proto *p);/* Protocol pernet registration. */
net/netfilter/nf_conntrack_core.c +7 -8
@@ -379,7 +379,7 @@ bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,return false; } - l4proto =__nf_ct_l4proto_find (l3num, protonum); + l4proto =__nf_ct_l4proto_find (protonum); ret =nf_ct_get_tuple (skb, nhoff, protoff, l3num, protonum, net, tuple, l4proto);
@@ -539,7 +539,7 @@ destroy_conntrack(struct nf_conntrack *nfct)nf_ct_tmpl_free (ct);return ; } - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); + l4proto =__nf_ct_l4proto_find (nf_ct_protonum (ct));if (l4proto->destroy) l4proto->destroy (ct);
@@ -840,7 +840,7 @@ static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,enum ip_conntrack_info oldinfo;struct nf_conn *loser_ct =nf_ct_get (skb, &oldinfo); - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); + l4proto =__nf_ct_l4proto_find (nf_ct_protonum (ct));if (l4proto->allow_clash && !nf_ct_is_dying (ct) &&atomic_inc_not_zero (&ct->ct_general.use)) {
@@ -1109,7 +1109,7 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)if (!test_bit (IPS_ASSURED_BIT , &ct->status))return true; - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); + l4proto =__nf_ct_l4proto_find (nf_ct_protonum (ct));if (l4proto->can_early_drop && l4proto->can_early_drop (ct))return true;
@@ -1549,7 +1549,7 @@ nf_conntrack_in(struct sk_buff *skb, const struct nf_hook_state *state) goto out; } - l4proto =__nf_ct_l4proto_find (state->pf, protonum); + l4proto =__nf_ct_l4proto_find (protonum);if (protonum ==IPPROTO_ICMP || protonum ==IPPROTO_ICMPV6 ) { ret = nf_conntrack_handle_icmp(tmpl, skb, dataoff,
@@ -1618,8 +1618,7 @@ bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,rcu_read_lock (); ret =nf_ct_invert_tuple (inverse, orig, -__nf_ct_l4proto_find (orig->src.l3num, - orig->dst.protonum)); +__nf_ct_l4proto_find (orig->dst.protonum));rcu_read_unlock ();return ret; }
@@ -1776,7 +1775,7 @@ static int nf_conntrack_update(struct net *net, struct sk_buff *skb)if (dataoff <=0 )return -1 ; - l4proto =nf_ct_l4proto_find_get (l3num, l4num); + l4proto =nf_ct_l4proto_find_get (l4num);if (!nf_ct_get_tuple (skb,skb_network_offset (skb), dataoff, l3num, l4num, net, &tuple, l4proto))
net/netfilter/nf_conntrack_expect.c +1 -2
@@ -610,8 +610,7 @@ static int exp_seq_show(struct seq_file *s, void *v) expect->tuple.src.l3num, expect->tuple.dst.protonum);print_tuple (s, &expect->tuple, -__nf_ct_l4proto_find (expect->tuple.src.l3num, - expect->tuple.dst.protonum)); +__nf_ct_l4proto_find (expect->tuple.dst.protonum));if (expect->flags &NF_CT_EXPECT_PERMANENT ) {seq_puts (s,"PERMANENT" );
net/netfilter/nf_conntrack_netlink.c +6 -8
@@ -135,8 +135,7 @@ static int ctnetlink_dump_tuples(struct sk_buff *skb, ret =ctnetlink_dump_tuples_ip (skb, tuple);if (ret >=0 ) { - l4proto =__nf_ct_l4proto_find (tuple->src.l3num, - tuple->dst.protonum); + l4proto =__nf_ct_l4proto_find (tuple->dst.protonum); ret =ctnetlink_dump_tuples_proto (skb, tuple, l4proto); }rcu_read_unlock ();
@@ -184,7 +183,7 @@ static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct)struct nlattr *nest_proto;int ret; - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); + l4proto =__nf_ct_l4proto_find (nf_ct_protonum (ct));if (!l4proto->to_nlattr)return 0 ;
@@ -592,7 +591,7 @@ static size_t ctnetlink_proto_size(const struct nf_conn *ct) len =nla_policy_len (cta_ip_nla_policy,CTA_IP_MAX +1 ); len *=3u ;/* ORIG, REPLY, MASTER */ - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); + l4proto =__nf_ct_l4proto_find (nf_ct_protonum (ct)); len += l4proto->nlattr_size;if (l4proto->nlattr_tuple_size) { len4 = l4proto->nlattr_tuple_size ();
@@ -1054,7 +1053,7 @@ static int ctnetlink_parse_tuple_proto(struct nlattr *attr, tuple->dst.protonum =nla_get_u8 (tb[CTA_PROTO_NUM ]);rcu_read_lock (); - l4proto =__nf_ct_l4proto_find (tuple->src.l3num, tuple->dst.protonum); + l4proto =__nf_ct_l4proto_find (tuple->dst.protonum);if (likely (l4proto->nlattr_to_tuple)) { ret = nla_validate_nested(attr, CTA_PROTO_MAX,
@@ -1702,7 +1701,7 @@ static int ctnetlink_change_protoinfo(struct nf_conn *ct,return err;rcu_read_lock (); - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); + l4proto =__nf_ct_l4proto_find (nf_ct_protonum (ct));if (l4proto->from_nlattr) err = l4proto->from_nlattr (tb, ct);rcu_read_unlock ();
@@ -2662,8 +2661,7 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb,rcu_read_lock (); ret =ctnetlink_dump_tuples_ip (skb, &m);if (ret >=0 ) { - l4proto =__nf_ct_l4proto_find (tuple->src.l3num, - tuple->dst.protonum); + l4proto =__nf_ct_l4proto_find (tuple->dst.protonum); ret =ctnetlink_dump_tuples_proto (skb, &m, l4proto); }rcu_read_unlock ();
net/netfilter/nf_conntrack_proto.c +29 -75
213 lines not on this page · raw message
net/netfilter/nf_conntrack_proto_dccp.c +1 -34
@@ -842,8 +842,7 @@ static struct nf_proto_net *dccp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.dccp.pn; } -const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { - .l3proto =AF_INET , +const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp = { .l4proto =IPPROTO_DCCP , .packet = dccp_packet, .can_early_drop = dccp_can_early_drop,
@@ -871,35 +870,3 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { .init_net = dccp_init_net, .get_net_proto = dccp_get_net_proto, }; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_dccp4); - -const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { - .l3proto =AF_INET6 , - .l4proto =IPPROTO_DCCP , - .packet = dccp_packet, - .can_early_drop = dccp_can_early_drop, -#ifdef CONFIG_NF_CONNTRACK_PROCFS - .print_conntrack = dccp_print_conntrack, -#endif -#if IS_ENABLED(CONFIG_NF_CT_NETLINK) - .nlattr_size =DCCP_NLATTR_SIZE , - .to_nlattr = dccp_to_nlattr, - .from_nlattr = nlattr_to_dccp, - .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, - .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, - .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, - .nla_policy = nf_ct_port_nla_policy, -#endif -#ifdef CONFIG_NF_CONNTRACK_TIMEOUT - .ctnl_timeout = { - .nlattr_to_obj = dccp_timeout_nlattr_to_obj, - .obj_to_nlattr = dccp_timeout_obj_to_nlattr, - .nlattr_max =CTA_TIMEOUT_DCCP_MAX , - .obj_size =sizeof (unsigned int ) *CT_DCCP_MAX , - .nla_policy = dccp_timeout_nla_policy, - }, -#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ - .init_net = dccp_init_net, - .get_net_proto = dccp_get_net_proto, -}; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_dccp6);
net/netfilter/nf_conntrack_proto_generic.c +0 -1
@@ -153,7 +153,6 @@ static struct nf_proto_net *generic_get_net_proto(struct net *net)const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = { - .l3proto =PF_UNSPEC , .l4proto =255 , .pkt_to_tuple = generic_pkt_to_tuple, .packet = generic_packet,
net/netfilter/nf_conntrack_proto_gre.c +3 -1
@@ -238,6 +238,9 @@ static int gre_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo, const struct nf_hook_state *state) { +if (state->pf !=NFPROTO_IPV4 ) +return -NF_ACCEPT ; +if (!nf_ct_is_confirmed (ct)) {unsigned int *timeouts =nf_ct_timeout_lookup (ct);
@@ -344,7 +347,6 @@ static int gre_init_net(struct net *net)/* protocol helper struct */ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { - .l3proto =AF_INET , .l4proto =IPPROTO_GRE , .pkt_to_tuple = gre_pkt_to_tuple, #ifdef CONFIG_NF_CONNTRACK_PROCFS
net/netfilter/nf_conntrack_proto_icmp.c +4 -2
@@ -90,6 +90,9 @@ static int icmp_packet(struct nf_conn *ct, [ICMP_ADDRESS] = 1 }; +if (state->pf !=NFPROTO_IPV4 ) +return -NF_ACCEPT ; +if (ct->tuplehash[0 ].tuple.dst.u.icmp.type >=sizeof (valid_new) || !valid_new[ct->tuplehash[0 ].tuple.dst.u.icmp.type]) {/* Can't create a new ICMP `conn' with this. */
@@ -131,7 +134,7 @@ icmp_error_message(struct nf_conn *tmpl, struct sk_buff *skb, }/* rcu_read_lock()ed by nf_hook_thresh */ - innerproto =__nf_ct_l4proto_find (PF_INET , origtuple.dst.protonum); + innerproto =__nf_ct_l4proto_find (origtuple.dst.protonum);/* Ordinarily, we'd expect the inverted tupleproto, but it's been preserved inside the ICMP. */
@@ -349,7 +352,6 @@ static struct nf_proto_net *icmp_get_net_proto(struct net *net)const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = { - .l3proto =PF_INET , .l4proto =IPPROTO_ICMP , .pkt_to_tuple = icmp_pkt_to_tuple, .invert_tuple = icmp_invert_tuple,
net/netfilter/nf_conntrack_proto_icmpv6.c +4 -2
@@ -103,6 +103,9 @@ static int icmpv6_packet(struct nf_conn *ct, [ICMPV6_NI_QUERY - 128] = 1 }; +if (state->pf !=NFPROTO_IPV6 ) +return -NF_ACCEPT ; +if (!nf_ct_is_confirmed (ct)) {int type = ct->tuplehash[0 ].tuple.dst.u.icmp.type -128 ;
@@ -150,7 +153,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl, }/* rcu_read_lock()ed by nf_hook_thresh */ - inproto =__nf_ct_l4proto_find (PF_INET6 , origtuple.dst.protonum); + inproto =__nf_ct_l4proto_find (origtuple.dst.protonum);/* Ordinarily, we'd expect the inverted tupleproto, but it's been preserved inside the ICMP. */
@@ -360,7 +363,6 @@ static struct nf_proto_net *icmpv6_get_net_proto(struct net *net)const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = { - .l3proto =PF_INET6 , .l4proto =IPPROTO_ICMPV6 , .pkt_to_tuple = icmpv6_pkt_to_tuple, .invert_tuple = icmpv6_invert_tuple,
net/netfilter/nf_conntrack_proto_sctp.c +1 -35
@@ -759,8 +759,7 @@ static struct nf_proto_net *sctp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.sctp.pn; } -const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { - .l3proto =PF_INET , +const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = { .l4proto =IPPROTO_SCTP , #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = sctp_print_conntrack,
@@ -789,36 +788,3 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { .init_net = sctp_init_net, .get_net_proto = sctp_get_net_proto, }; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_sctp4); - -const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { - .l3proto =PF_INET6 , - .l4proto =IPPROTO_SCTP , -#ifdef CONFIG_NF_CONNTRACK_PROCFS - .print_conntrack = sctp_print_conntrack, -#endif - .packet = sctp_packet, - .can_early_drop = sctp_can_early_drop, - .me =THIS_MODULE , -#if IS_ENABLED(CONFIG_NF_CT_NETLINK) - .nlattr_size =SCTP_NLATTR_SIZE , - .to_nlattr = sctp_to_nlattr, - .from_nlattr = nlattr_to_sctp, - .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, - .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, - .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, - .nla_policy = nf_ct_port_nla_policy, -#endif -#ifdef CONFIG_NF_CONNTRACK_TIMEOUT - .ctnl_timeout = { - .nlattr_to_obj = sctp_timeout_nlattr_to_obj, - .obj_to_nlattr = sctp_timeout_obj_to_nlattr, - .nlattr_max =CTA_TIMEOUT_SCTP_MAX , - .obj_size =sizeof (unsigned int ) *SCTP_CONNTRACK_MAX , - .nla_policy = sctp_timeout_nla_policy, - }, -#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ - .init_net = sctp_init_net, - .get_net_proto = sctp_get_net_proto, -}; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_sctp6);
net/netfilter/nf_conntrack_proto_tcp.c +1 -36
@@ -1534,9 +1534,8 @@ static struct nf_proto_net *tcp_get_net_proto(struct net *net)return &net->ct.nf_ct_proto.tcp.pn; } -const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = +const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp = { - .l3proto =PF_INET , .l4proto =IPPROTO_TCP , #ifdef CONFIG_NF_CONNTRACK_PROCFS .print_conntrack = tcp_print_conntrack,
@@ -1565,37 +1564,3 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 = .init_net = tcp_init_net, .get_net_proto = tcp_get_net_proto, }; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp4); - -const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 = -{ - .l3proto =PF_INET6 , - .l4proto =IPPROTO_TCP , -#ifdef CONFIG_NF_CONNTRACK_PROCFS - .print_conntrack = tcp_print_conntrack, -#endif - .packet = tcp_packet, - .can_early_drop = tcp_can_early_drop, -#if IS_ENABLED(CONFIG_NF_CT_NETLINK) - .nlattr_size =TCP_NLATTR_SIZE , - .to_nlattr = tcp_to_nlattr, - .from_nlattr = nlattr_to_tcp, - .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, - .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, - .nlattr_tuple_size = tcp_nlattr_tuple_size, - .nla_policy = nf_ct_port_nla_policy, -#endif -#ifdef CONFIG_NF_CONNTRACK_TIMEOUT - .ctnl_timeout = { - .nlattr_to_obj = tcp_timeout_nlattr_to_obj, - .obj_to_nlattr = tcp_timeout_obj_to_nlattr, - .nlattr_max =CTA_TIMEOUT_TCP_MAX , - .obj_size =sizeof (unsigned int ) * -TCP_CONNTRACK_TIMEOUT_MAX , - .nla_policy = tcp_timeout_nla_policy, - }, -#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ - .init_net = tcp_init_net, - .get_net_proto = tcp_get_net_proto, -}; -EXPORT_SYMBOL_GPL (nf_conntrack_l4proto_tcp6);
net/netfilter/nf_conntrack_proto_udp.c +2 -60
82 lines not on this page · raw message
net/netfilter/nf_conntrack_standalone.c +1 -1
@@ -292,7 +292,7 @@ static int ct_seq_show(struct seq_file *s, void *v)if (!net_eq (nf_ct_net (ct), net)) goto release; - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct),nf_ct_protonum (ct)); + l4proto =__nf_ct_l4proto_find (nf_ct_protonum (ct));WARN_ON (!l4proto); ret = -ENOSPC ;
net/netfilter/nf_flow_table_core.c +1 -1
@@ -120,7 +120,7 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct)if (l4num ==IPPROTO_TCP )flow_offload_fixup_tcp (&ct->proto.tcp); - l4proto =__nf_ct_l4proto_find (nf_ct_l3num (ct), l4num); + l4proto =__nf_ct_l4proto_find (l4num);if (!l4proto)return ;
net/netfilter/nfnetlink_cttimeout.c +6 -5
@@ -122,7 +122,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,return -EBUSY ; } - l4proto =nf_ct_l4proto_find_get (l3num, l4num); + l4proto =nf_ct_l4proto_find_get (l4num);/* This protocol is not supportted, skip. */ if (l4proto->l4proto != l4num) {
@@ -361,7 +361,7 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl, l3num =ntohs (nla_get_be16 (cda[CTA_TIMEOUT_L3PROTO ])); l4num =nla_get_u8 (cda[CTA_TIMEOUT_L4PROTO ]); - l4proto =nf_ct_l4proto_find_get (l3num, l4num); + l4proto =nf_ct_l4proto_find_get (l4num);/* This protocol is not supported, skip. */ if (l4proto->l4proto != l4num) {
@@ -383,7 +383,7 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl,static int cttimeout_default_fill_info (struct net *net,struct sk_buff *skb,u32 portid, -u32 seq,u32 type,int event, +u32 seq,u32 type,int event,u16 l3num,const struct nf_conntrack_l4proto *l4proto) {struct nlmsghdr *nlh;
@@ -402,7 +402,7 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid, nfmsg->version =NFNETLINK_V0 ; nfmsg->res_id =0 ; -if (nla_put_be16 (skb,CTA_TIMEOUT_L3PROTO ,htons (l4proto->l3proto)) || +if (nla_put_be16 (skb,CTA_TIMEOUT_L3PROTO ,htons (l3num)) ||nla_put_u8 (skb,CTA_TIMEOUT_L4PROTO , l4proto->l4proto)) goto nla_put_failure;
@@ -442,7 +442,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, l3num =ntohs (nla_get_be16 (cda[CTA_TIMEOUT_L3PROTO ])); l4num =nla_get_u8 (cda[CTA_TIMEOUT_L4PROTO ]); - l4proto =nf_ct_l4proto_find_get (l3num, l4num); + l4proto =nf_ct_l4proto_find_get (l4num);/* This protocol is not supported, skip. */ if (l4proto->l4proto != l4num) {
@@ -460,6 +460,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, nlh->nlmsg_seq,NFNL_MSG_TYPE (nlh->nlmsg_type),IPCTNL_MSG_TIMEOUT_DEFAULT_SET , + l3num, l4proto);if (ret <=0 ) {kfree_skb (skb2);
net/netfilter/nft_ct.c +1 -1
@@ -855,7 +855,7 @@ static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx, l4num =nla_get_u8 (tb[NFTA_CT_TIMEOUT_L4PROTO ]); priv->l4proto = l4num; - l4proto =nf_ct_l4proto_find_get (l3num, l4num); + l4proto =nf_ct_l4proto_find_get (l4num);if (l4proto->l4proto != l4num) { ret = -EOPNOTSUPP ;
net/netfilter/xt_CT.c +1 -1
@@ -159,7 +159,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,/* Make sure the timeout policy matches any existing protocol tracker, * otherwise default to generic. */ - l4proto =__nf_ct_l4proto_find (par->family, proto); + l4proto =__nf_ct_l4proto_find (proto);if (timeout->l4proto->l4proto != l4proto->l4proto) { ret = -EINVAL ; pr_info_ratelimited("Timeout policy `%s' can only be used by L%d protocol number %d\n",
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 21/31 netfilter: conntrack: clamp l4proto array size at largers supported protocol
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
All higher l4proto numbers are handled by the generic tracker; the l4proto lookup function already returns generic one in case the l4proto number exceeds max size.
--- include/net/netfilter/nf_conntrack_l4proto.h | 2 +- net/netfilter/nf_conntrack_proto.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
include/net/netfilter/nf_conntrack_l4proto.h +1 -1
@@ -102,7 +102,7 @@ int nf_conntrack_icmpv6_error(struct nf_conn *tmpl,/* Existing built-in generic protocol */ extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic; -#define MAX_NF_CT_PROTO 256 +#define MAX_NF_CT_PROTO IPPROTO_UDPLITEconst struct nf_conntrack_l4proto *__nf_ct_l4proto_find (u8 l4proto);
net/netfilter/nf_conntrack_proto.c +1 -1
@@ -43,7 +43,7 @@extern unsigned int nf_conntrack_net_id; -static struct nf_conntrack_l4proto __rcu *nf_ct_protos[MAX_NF_CT_PROTO ]__read_mostly ; +static struct nf_conntrack_l4proto __rcu *nf_ct_protos[MAX_NF_CT_PROTO +1 ]__read_mostly ;static DEFINE_MUTEX (nf_ct_proto_mutex);
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 22/31 netfilter: nat: remove duplicate skb_is_nonlinear() in __nf_nat_mangle_tcp_packet()
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
__nf_nat_mangle_tcp_packet() and nf_nat_mangle_udp_packet() call mangle_contents(). and __nf_nat_mangle_tcp_packet()
and mangle_contents() call skb_is_nonlinear(). so that skb_is_nonlinear() in __nf_nat_mangle_tcp_packet() is unnecessary.
--- net/netfilter/nf_nat_helper.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
net/netfilter/nf_nat_helper.c +1 -3
@@ -37,7 +37,7 @@ static void mangle_contents(struct sk_buff *skb, {unsigned char *data; -BUG_ON (skb_is_nonlinear (skb)); +SKB_LINEAR_ASSERT (skb); data =skb_network_header (skb) + dataoff;/* move post-replacement */
@@ -110,8 +110,6 @@ bool __nf_nat_mangle_tcp_packet(struct sk_buff *skb, !enlarge_skb(skb, rep_len - match_len))return false; -SKB_LINEAR_ASSERT (skb); - tcph = (void *)skb->data + protoff; oldlen = skb->len - protoff;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 23/31 netfilter: nf_tables: use rhashtable_walk_enter instead of rhashtable_walk_init
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
rhashtable_walk_init() is deprecated and rhashtable_walk_enter() can be used instead. rhashtable_walk_init() is wrapper function of rhashtable_walk_enter() so that logic is actually same.
But rhashtable_walk_enter() doesn't return error hence error path code can be removed.
--- net/netfilter/nf_flow_table_core.c | 35 +++++++++++------------------------ net/netfilter/nft_set_hash.c | 30 ++++++++---------------------- 2 files changed, 19 insertions(+), 46 deletions(-)
net/netfilter/nf_flow_table_core.c +11 -24
@@ -254,20 +254,17 @@ int nf_flow_table_iterate(struct nf_flowtable *flow_table,struct flow_offload_tuple_rhash *tuplehash;struct rhashtable_iter hti;struct flow_offload *flow; -int err; - - err =rhashtable_walk_init (&flow_table->rhashtable, &hti,GFP_KERNEL ); -if (err) -return err; +int err =0 ; +rhashtable_walk_enter (&flow_table->rhashtable, &hti);rhashtable_walk_start (&hti);while ((tuplehash =rhashtable_walk_next (&hti))) {if (IS_ERR (tuplehash)) { - err =PTR_ERR (tuplehash); -if (err != -EAGAIN ) - goto out; - +if (PTR_ERR (tuplehash) != -EAGAIN ) { + err =PTR_ERR (tuplehash); +break ; + }continue ; }if (tuplehash->tuple.dir)
@@ -277,7 +274,6 @@ int nf_flow_table_iterate(struct nf_flowtable *flow_table,iter (flow, data); } -out:rhashtable_walk_stop (&hti);rhashtable_walk_exit (&hti);
@@ -290,25 +286,19 @@ static inline bool nf_flow_has_expired(const struct flow_offload *flow)return (__s32)(flow->timeout - (u32 )jiffies) <=0 ; } -static int nf_flow_offload_gc_step (struct nf_flowtable *flow_table) +static void nf_flow_offload_gc_step (struct nf_flowtable *flow_table) {struct flow_offload_tuple_rhash *tuplehash;struct rhashtable_iter hti;struct flow_offload *flow; -int err; - - err =rhashtable_walk_init (&flow_table->rhashtable, &hti,GFP_KERNEL ); -if (err) -return 0 ; +rhashtable_walk_enter (&flow_table->rhashtable, &hti);rhashtable_walk_start (&hti);while ((tuplehash =rhashtable_walk_next (&hti))) {if (IS_ERR (tuplehash)) { - err =PTR_ERR (tuplehash); -if (err != -EAGAIN ) - goto out; - +if (PTR_ERR (tuplehash) != -EAGAIN ) +break ;continue ; }if (tuplehash->tuple.dir)
@@ -321,11 +311,8 @@ static int nf_flow_offload_gc_step(struct nf_flowtable *flow_table) FLOW_OFFLOAD_TEARDOWN)))flow_offload_del (flow_table ,flow ); } -out:rhashtable_walk_stop (&hti);rhashtable_walk_exit (&hti); - -return 1 ; }static void nf_flow_offload_work_gc (struct work_struct *work)
@@ -514,7 +501,7 @@ void nf_flow_table_free(struct nf_flowtable *flow_table)mutex_unlock (&flowtable_lock);cancel_delayed_work_sync (&flow_table->gc_work);nf_flow_table_iterate (flow_table, nf_flow_table_do_cleanup,NULL ); -WARN_ON (!nf_flow_offload_gc_step (flow_table)); +nf_flow_offload_gc_step (flow_table);rhashtable_destroy (&flow_table->rhashtable); }EXPORT_SYMBOL_GPL (nf_flow_table_free);
net/netfilter/nft_set_hash.c +8 -22
@@ -244,21 +244,15 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set,struct nft_rhash_elem *he;struct rhashtable_iter hti;struct nft_set_elem elem; -int err; - - err =rhashtable_walk_init (&priv->ht, &hti,GFP_ATOMIC ); - iter->err = err; -if (err) -return ; +rhashtable_walk_enter (&priv->ht, &hti);rhashtable_walk_start (&hti);while ((he =rhashtable_walk_next (&hti))) {if (IS_ERR (he)) { - err =PTR_ERR (he); -if (err != -EAGAIN ) { - iter->err = err; - goto out; +if (PTR_ERR (he) != -EAGAIN ) { + iter->err =PTR_ERR (he); +break ; }continue ;
@@ -275,13 +269,11 @@ static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, iter->err = iter->fn (ctx, set, iter, &elem);if (iter->err <0 ) - goto out; +break ; cont: iter->count++; } - -out:rhashtable_walk_stop (&hti);rhashtable_walk_exit (&hti); }
@@ -293,21 +285,17 @@ static void nft_rhash_gc(struct work_struct *work)struct nft_rhash *priv;struct nft_set_gc_batch *gcb =NULL ;struct rhashtable_iter hti; -int err; priv = container_of(work, struct nft_rhash, gc_work.work); set =nft_set_container_of (priv); - err =rhashtable_walk_init (&priv->ht, &hti,GFP_KERNEL ); -if (err) - goto schedule; - +rhashtable_walk_enter (&priv->ht, &hti);rhashtable_walk_start (&hti);while ((he =rhashtable_walk_next (&hti))) {if (IS_ERR (he)) {if (PTR_ERR (he) != -EAGAIN ) - goto out; +break ;continue ; }
@@ -326,17 +314,15 @@ static void nft_rhash_gc(struct work_struct *work) gcb =nft_set_gc_batch_check (set, gcb,GFP_ATOMIC );if (gcb ==NULL ) - goto out; +break ;rhashtable_remove_fast (&priv->ht, &he->node, nft_rhash_params);atomic_dec (&set->nelems);nft_set_gc_batch_add (gcb, he); } -out:rhashtable_walk_stop (&hti);rhashtable_walk_exit (&hti);nft_set_gc_batch_complete (gcb); -schedule:queue_delayed_work (system_power_efficient_wq, &priv->gc_work,nft_set_gc_interval (set)); }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 24/31 netfilter: ctnetlink: must check mark attributes vs NULL
In reply to Pablo Neira AyusoFrom: Florian Westphal <[email protected]>
else we will oops (null deref) when the attributes aren't present.
Also add back the EOPNOTSUPP in case MARK filtering is requested but kernel doesn't support it.
--- net/netfilter/nf_conntrack_netlink.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
net/netfilter/nf_conntrack_netlink.c +9 -2
@@ -832,6 +832,11 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family) {struct ctnetlink_filter *filter; +#ifndef CONFIG_NF_CONNTRACK_MARK +if (cda[CTA_MARK ] && cda[CTA_MARK_MASK ]) +return ERR_PTR (-EOPNOTSUPP ); +#endif + filter =kzalloc (sizeof (*filter),GFP_KERNEL );if (filter ==NULL )return ERR_PTR (-ENOMEM );
@@ -839,8 +844,10 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family) filter->family = family;#ifdef CONFIG_NF_CONNTRACK_MARK - filter->mark.val =ntohl (nla_get_be32 (cda[CTA_MARK ])); - filter->mark.mask =ntohl (nla_get_be32 (cda[CTA_MARK_MASK ])); +if (cda[CTA_MARK ] && cda[CTA_MARK_MASK ]) { + filter->mark.val =ntohl (nla_get_be32 (cda[CTA_MARK ])); + filter->mark.mask =ntohl (nla_get_be32 (cda[CTA_MARK_MASK ])); + }#endif return filter; }
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 25/31 netfilter: masquerade: don't flush all conntracks if only one address deleted on device
In reply to Pablo Neira AyusoFrom: Tan Hu <[email protected]>
We configured iptables as below, which only allowed incoming data on established connections:
iptables -t mangle -A PREROUTING -m state --state ESTABLISHED -j ACCEPT iptables -t mangle -P PREROUTING DROP
When deleting a secondary address, current masquerade implements would flush all conntracks on this device. All the established connections on primary address also be deleted, then subsequent incoming data on the connections would be dropped wrongly because it was identified as NEW connection.
So when an address was delete, it should only flush connections related with the address.
--- net/ipv4/netfilter/nf_nat_masquerade_ipv4.c | 22 +++++++++++++++++++--- net/ipv6/netfilter/nf_nat_masquerade_ipv6.c | 19 ++++++++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-)
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c +19 -3
@@ -104,12 +104,26 @@ static int masq_device_event(struct notifier_block *this,return NOTIFY_DONE ; } +static int inet_cmp (struct nf_conn *ct,void *ptr) +{ +struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; +struct net_device *dev = ifa->ifa_dev->dev; +struct nf_conntrack_tuple *tuple; + +if (!device_cmp (ct, (void *)(long )dev->ifindex)) +return 0 ; + + tuple = &ct->tuplehash[IP_CT_DIR_REPLY ].tuple; + +return ifa->ifa_address == tuple->dst.u3.ip; +} +static int masq_inet_event (struct notifier_block *this,unsigned long event,void *ptr) {struct in_device *idev = ((struct in_ifaddr *)ptr)->ifa_dev; -struct netdev_notifier_info info; +struct net *net =dev_net (idev->dev);/* The masq_dev_notifier will catch the case of the device going * down. So if the inetdev is dead and being destroyed we have
@@ -119,8 +133,10 @@ static int masq_inet_event(struct notifier_block *this,if (idev->dead)return NOTIFY_DONE ; -netdev_notifier_info_init (&info, idev->dev); -return masq_device_event (this, event, &info); +if (event ==NETDEV_DOWN ) +nf_ct_iterate_cleanup_net (net, inet_cmp, ptr,0 ,0 ); + +return NOTIFY_DONE ; }static struct notifier_block masq_dev_notifier = {
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c +16 -3
@@ -87,18 +87,30 @@ static struct notifier_block masq_dev_notifier = {struct masq_dev_work {struct work_struct work;struct net *net; +struct in6_addr addr;int ifindex; }; +static int inet_cmp (struct nf_conn *ct,void *work) +{ +struct masq_dev_work *w = (struct masq_dev_work *)work; +struct nf_conntrack_tuple *tuple; + +if (!device_cmp (ct, (void *)(long )w->ifindex)) +return 0 ; + + tuple = &ct->tuplehash[IP_CT_DIR_REPLY ].tuple; + +return ipv6_addr_equal (&w->addr, &tuple->dst.u3.in6); +} +static void iterate_cleanup_work (struct work_struct *work) {struct masq_dev_work *w; -long index; w = container_of(work, struct masq_dev_work, work); - index = w->ifindex; -nf_ct_iterate_cleanup_net (w->net, device_cmp, (void *)index,0 ,0 ); +nf_ct_iterate_cleanup_net (w->net, inet_cmp, (void *)w,0 ,0 );put_net (w->net);kfree (w);
@@ -147,6 +159,7 @@ static int masq_inet_event(struct notifier_block *this,INIT_WORK (&w->work, iterate_cleanup_work); w->ifindex = dev->ifindex; w->net = net; + w->addr = ifa->addr;schedule_work (&w->work);return NOTIFY_DONE ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 26/31 netfilter: nf_tables: add SECMARK support
In reply to Pablo Neira AyusoFrom: Christian Göttsche <[email protected]>
Add the ability to set the security context of packets within the nf_tables framework. Add a nft_object for holding security contexts in the kernel and manipulating packets on the wire.
Convert the security context strings at rule addition time to security identifiers. This is the same behavior like in xt_SECMARK and offers better performance than computing it per packet.
Set the maximum security context length to 256.
--- include/net/netfilter/nf_tables_core.h | 4 ++ include/uapi/linux/netfilter/nf_tables.h | 18 +++++- net/netfilter/nf_tables_core.c | 28 ++++++-- net/netfilter/nft_meta.c | 108 +++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 5 deletions(-)
include/net/netfilter/nf_tables_core.h +4 -0
@@ -16,6 +16,10 @@ extern struct nft_expr_type nft_meta_type;extern struct nft_expr_type nft_rt_type;extern struct nft_expr_type nft_exthdr_type; +#ifdef CONFIG_NETWORK_SECMARK +extern struct nft_object_type nft_secmark_obj_type; +#endif +int nf_tables_core_module_init (void );void nf_tables_core_module_exit (void );
include/uapi/linux/netfilter/nf_tables.h +17 -1
@@ -1177,6 +1177,21 @@ enum nft_quota_attributes {#define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1)/** +* enum nft_secmark_attributes - nf_tables secmark object netlink attributes +* +* @NFTA_SECMARK_CTX: security context (NLA_STRING) +*/ +enum nft_secmark_attributes { +NFTA_SECMARK_UNSPEC , +NFTA_SECMARK_CTX , + __NFTA_SECMARK_MAX, +}; +#define NFTA_SECMARK_MAX (__NFTA_SECMARK_MAX - 1) + +/* Max security context length */ +#define NFT_SECMARK_CTX_MAXLEN 256 + +/** * enum nft_reject_types - nf_tables reject expression reject types * * @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
@@ -1432,7 +1447,8 @@ enum nft_ct_timeout_timeout_attributes {#define NFT_OBJECT_CONNLIMIT 5#define NFT_OBJECT_TUNNEL 6#define NFT_OBJECT_CT_TIMEOUT 7 -#define __NFT_OBJECT_MAX 8 +#define NFT_OBJECT_SECMARK 8 +#define __NFT_OBJECT_MAX 9#define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1)/**
net/netfilter/nf_tables_core.c +24 -4
@@ -249,12 +249,24 @@ static struct nft_expr_type *nft_basic_types[] = { &nft_exthdr_type, }; +static struct nft_object_type *nft_basic_objects[] = { +#ifdef CONFIG_NETWORK_SECMARK + &nft_secmark_obj_type, +#endif +}; +int __init nf_tables_core_module_init (void ) { -int err, i; +int err, i, j =0 ; + +for (i =0 ; i <ARRAY_SIZE (nft_basic_objects); i++) { + err =nft_register_obj (nft_basic_objects[i]); +if (err) + goto err; + } -for (i =0 ; i <ARRAY_SIZE (nft_basic_types); i++) { - err =nft_register_expr (nft_basic_types[i]); +for (j =0 ; j <ARRAY_SIZE (nft_basic_types); j++) { + err =nft_register_expr (nft_basic_types[j]);if (err) goto err; }
@@ -262,8 +274,12 @@ int __init nf_tables_core_module_init(void)return 0 ; err: +while (j-- >0 ) +nft_unregister_expr (nft_basic_types[j]); +while (i-- >0 ) -nft_unregister_expr (nft_basic_types[i]); +nft_unregister_obj (nft_basic_objects[i]); +return err; }
@@ -274,4 +290,8 @@ void nf_tables_core_module_exit(void) i =ARRAY_SIZE (nft_basic_types);while (i-- >0 )nft_unregister_expr (nft_basic_types[i]); + + i =ARRAY_SIZE (nft_basic_objects); +while (i-- >0 ) +nft_unregister_obj (nft_basic_objects[i]); }
net/netfilter/nft_meta.c +108 -0
111 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 27/31 netfilter: nf_tables: add requirements for connsecmark support
In reply to Pablo Neira AyusoFrom: Christian Göttsche <[email protected]>
Add ability to set the connection tracking secmark value.
Add ability to set the meta secmark value.
--- net/netfilter/nft_ct.c | 17 ++++++++++++++++- net/netfilter/nft_meta.c | 8 ++++++++ 2 files changed, 24 insertions(+), 1 deletion(-)
net/netfilter/nft_ct.c +16 -1
@@ -279,7 +279,7 @@ static void nft_ct_set_eval(const struct nft_expr *expr, {const struct nft_ct *priv =nft_expr_priv (expr);struct sk_buff *skb = pkt->skb; -#ifdef CONFIG_NF_CONNTRACK_MARK +#if defined(CONFIG_NF_CONNTRACK_MARK ) || defined(CONFIG_NF_CONNTRACK_SECMARK )u32 value = regs->data[priv->sreg];#endif enum ip_conntrack_info ctinfo;
@@ -298,6 +298,14 @@ static void nft_ct_set_eval(const struct nft_expr *expr, }break ;#endif +#ifdef CONFIG_NF_CONNTRACK_SECMARK +case NFT_CT_SECMARK : +if (ct->secmark != value) { + ct->secmark = value; +nf_conntrack_event_cache (IPCT_SECMARK , ct); + } +break ; +#endif #ifdef CONFIG_NF_CONNTRACK_LABELS case NFT_CT_LABELS : nf_connlabels_replace(ct,
@@ -565,6 +573,13 @@ static int nft_ct_set_init(const struct nft_ctx *ctx, len =sizeof (u32);break ;#endif +#ifdef CONFIG_NF_CONNTRACK_SECMARK +case NFT_CT_SECMARK : +if (tb[NFTA_CT_DIRECTION ]) +return -EINVAL ; + len =sizeof (u32); +break ; +#endif default :return -EOPNOTSUPP ; }
net/netfilter/nft_meta.c +8 -0
@@ -284,6 +284,11 @@ static void nft_meta_set_eval(const struct nft_expr *expr, skb->nf_trace = !!value8;break ; +#ifdef CONFIG_NETWORK_SECMARK +case NFT_META_SECMARK : + skb->secmark = value; +break ; +#endif default :WARN_ON (1 ); }
@@ -436,6 +441,9 @@ static int nft_meta_set_init(const struct nft_ctx *ctx,switch (priv->key) {case NFT_META_MARK :case NFT_META_PRIORITY : +#ifdef CONFIG_NETWORK_SECMARK +case NFT_META_SECMARK : +#endif len =sizeof (u32);break ;case NFT_META_NFTRACE :
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 28/31 netfilter: nf_flow_table: remove unnecessary nat flag check code
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
nf_flow_offload_{ip/ipv6}_hook() check nat flag then, call nf_flow_nat_{ip/ipv6} but that also check nat flag. so that nat flag check code in nf_flow_offload_{ip/ipv6}_hook() are unnecessary.
--- net/netfilter/nf_flow_table_ip.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/netfilter/nf_flow_table_ip.c +2 -4
@@ -254,8 +254,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,if (nf_flow_state_check (flow,ip_hdr (skb)->protocol, skb, thoff))return NF_ACCEPT ; -if (flow->flags & (FLOW_OFFLOAD_SNAT |FLOW_OFFLOAD_DNAT ) && -nf_flow_nat_ip (flow, skb, thoff, dir) <0 ) +if (nf_flow_nat_ip (flow, skb, thoff, dir) <0 )return NF_DROP ; flow->timeout = (u32 )jiffies +NF_FLOW_TIMEOUT ;
@@ -471,8 +470,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,if (skb_try_make_writable (skb,sizeof (*ip6h)))return NF_DROP ; -if (flow->flags & (FLOW_OFFLOAD_SNAT |FLOW_OFFLOAD_DNAT ) && -nf_flow_nat_ipv6 (flow, skb, dir) <0 ) +if (nf_flow_nat_ipv6 (flow, skb, dir) <0 )return NF_DROP ; flow->timeout = (u32 )jiffies +NF_FLOW_TIMEOUT ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 29/31 netfilter: nf_tables: use rhashtable_lookup() instead of rhashtable_lookup_fast()
In reply to Pablo Neira AyusoFrom: Taehee Yoo <[email protected]>
Internally, rhashtable_lookup_fast() calls rcu_read_lock() then, calls rhashtable_lookup(). so that in places where are guaranteed by rcu read lock, rhashtable_lookup() is enough.
--- net/netfilter/nf_flow_table_core.c | 4 ++-- net/netfilter/nft_set_hash.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-)
net/netfilter/nf_flow_table_core.c +2 -2
@@ -233,8 +233,8 @@ flow_offload_lookup(struct nf_flowtable *flow_table,struct flow_offload *flow;int dir; - tuplehash =rhashtable_lookup_fast (&flow_table->rhashtable, tuple, - nf_flow_offload_rhash_params); + tuplehash =rhashtable_lookup (&flow_table->rhashtable, tuple, + nf_flow_offload_rhash_params);if (!tuplehash)return NULL ;
net/netfilter/nft_set_hash.c +4 -4
@@ -88,7 +88,7 @@ static bool nft_rhash_lookup(const struct net *net, const struct nft_set *set, .key = key, }; - he =rhashtable_lookup_fast (&priv->ht, &arg, nft_rhash_params); + he =rhashtable_lookup (&priv->ht, &arg, nft_rhash_params);if (he !=NULL ) *ext = &he->ext;
@@ -106,7 +106,7 @@ static void *nft_rhash_get(const struct net *net, const struct nft_set *set, .key = elem->key.val.data, }; - he =rhashtable_lookup_fast (&priv->ht, &arg, nft_rhash_params); + he =rhashtable_lookup (&priv->ht, &arg, nft_rhash_params);if (he !=NULL )return he;
@@ -129,7 +129,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key, .key = key, }; - he =rhashtable_lookup_fast (&priv->ht, &arg, nft_rhash_params); + he =rhashtable_lookup (&priv->ht, &arg, nft_rhash_params);if (he !=NULL ) goto out;
@@ -217,7 +217,7 @@ static void *nft_rhash_deactivate(const struct net *net, };rcu_read_lock (); - he =rhashtable_lookup_fast (&priv->ht, &arg, nft_rhash_params); + he =rhashtable_lookup (&priv->ht, &arg, nft_rhash_params);if (he !=NULL && !nft_rhash_flush (net, set, he)) he =NULL ;
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 30/31 netfilter: xt_quota: fix the behavior of xt_quota module
In reply to Pablo Neira AyusoFrom: Chenbo Feng <[email protected]>
A major flaw of the current xt_quota module is that quota in a specific rule gets reset every time there is a rule change in the same table. It makes the xt_quota module not very useful in a table in which iptables rules are changed at run time. This fix introduces a new counter that is visible to userspace as the remaining quota of the current rule. When userspace restores the rules in a table, it can restore the counter to the remaining quota instead of resetting it to the full quota.
--- include/uapi/linux/netfilter/xt_quota.h | 8 +++-- net/netfilter/xt_quota.c | 55 +++++++++++++-------------------- 2 files changed, 27 insertions(+), 36 deletions(-)
include/uapi/linux/netfilter/xt_quota.h +5 -3
@@ -15,9 +15,11 @@ struct xt_quota_info {__u32 flags;__u32 pad;__aligned_u64 quota; - -/* Used internally by the kernel */ - struct xt_quota_priv *master; +#ifdef __KERNEL__ +atomic64_t counter; +#else +__aligned_u64 remain; +#endif };#endif /* _XT_QUOTA_H */
net/netfilter/xt_quota.c +22 -33
87 lines not on this page · raw message
Signature · 1 line
2.11.0
Pablo Neira Ayuso
maintainerPATCH 31/31 netfilter: xt_quota: Don't use aligned attribute in sizeof
In reply to Pablo Neira AyusoFrom: Nathan Chancellor <[email protected]>
Clang warns:
net/netfilter/xt_quota.c:47:44: warning: 'aligned' attribute ignored when parsing type [-Wignored-attributes]
BUILD_BUG_ON(sizeof(atomic64_t) != sizeof(__aligned_u64));
^~~~~~~~~~~~~Use 'sizeof(__u64)' instead, as the alignment doesn't affect the size of the type.
--- net/netfilter/xt_quota.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/xt_quota.c +1 -1
@@ -44,7 +44,7 @@ static int quota_mt_check(const struct xt_mtchk_param *par) {struct xt_quota_info *q = par->matchinfo; -BUILD_BUG_ON (sizeof (atomic64_t) !=sizeof (__aligned_u64)); +BUILD_BUG_ON (sizeof (atomic64_t) !=sizeof (__u64));if (q->flags & ~XT_QUOTA_MASK )return -EINVAL ;
Signature · 1 line
2.11.0
David Miller
maintainerFrom: Pablo Neira Ayuso <[email protected]>
Date: Tue, 9 Oct 2018 01:00:54 +0200
Quoted 2 lines
The following patchset contains Netfilter updates for your net-next tree:
Pulled, thanks.