Commit a1f1acb9 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_dup{4, 6}: Move duplication check to task_struct



nf_skb_duplicated is a per-CPU variable and relies on disabled BH for its
locking. Without per-CPU locking in local_bh_disable() on PREEMPT_RT
this data structure requires explicit locking.

Due to the recursion involved, the simplest change is to make it a
per-task variable.

Move the per-CPU variable nf_skb_duplicated to task_struct and name it
in_nf_duplicate. Add it to the existing bitfield so it doesn't use
additional memory.

Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Ben Segall <bsegall@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Valentin Schneider <vschneid@redhat.com>
Acked-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 22a9613d
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -497,17 +497,6 @@ struct nf_defrag_hook {
extern const struct nf_defrag_hook __rcu *nf_defrag_v4_hook;
extern const struct nf_defrag_hook __rcu *nf_defrag_v6_hook;

/*
 * nf_skb_duplicated - TEE target has sent a packet
 *
 * When a xtables target sends a packet, the OUTPUT and POSTROUTING
 * hooks are traversed again, i.e. nft and xtables are invoked recursively.
 *
 * This is used by xtables TEE target to prevent the duplicated skb from
 * being duplicated again.
 */
DECLARE_PER_CPU(bool, nf_skb_duplicated);

/*
 * Contains bitmask of ctnetlink event subscribers, if any.
 * Can't be pernet due to NETLINK_LISTEN_ALL_NSID setsockopt flag.
+1 −0
Original line number Diff line number Diff line
@@ -1044,6 +1044,7 @@ struct task_struct {
	/* delay due to memory thrashing */
	unsigned                        in_thrashing:1;
#endif
	unsigned			in_nf_duplicate:1;
#ifdef CONFIG_PREEMPT_RT
	struct netdev_xmit		net_xmit;
#endif
+1 −1
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ ipt_do_table(void *priv,
	 * but it is no problem since absolute verdict is issued by these.
	 */
	if (static_key_false(&xt_tee_enabled))
		jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated);
		jumpstack += private->stacksize * current->in_nf_duplicate;

	e = get_entry(table_base, private->hook_entry[hook]);

+3 −3
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum,
	struct iphdr *iph;

	local_bh_disable();
	if (this_cpu_read(nf_skb_duplicated))
	if (current->in_nf_duplicate)
		goto out;
	/*
	 * Copy the skb, and route the copy. Will later return %XT_CONTINUE for
@@ -86,9 +86,9 @@ void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum,
		--iph->ttl;

	if (nf_dup_ipv4_route(net, skb, gw, oif)) {
		__this_cpu_write(nf_skb_duplicated, true);
		current->in_nf_duplicate = true;
		ip_local_out(net, skb->sk, skb);
		__this_cpu_write(nf_skb_duplicated, false);
		current->in_nf_duplicate = false;
	} else {
		kfree_skb(skb);
	}
+1 −1
Original line number Diff line number Diff line
@@ -292,7 +292,7 @@ ip6t_do_table(void *priv, struct sk_buff *skb,
	 * but it is no problem since absolute verdict is issued by these.
	 */
	if (static_key_false(&xt_tee_enabled))
		jumpstack += private->stacksize * __this_cpu_read(nf_skb_duplicated);
		jumpstack += private->stacksize * current->in_nf_duplicate;

	e = get_entry(table_base, private->hook_entry[hook]);

Loading