Commit 9fce6658 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso
Browse files

netfilter: Exclude LEGACY TABLES on PREEMPT_RT.



The seqcount xt_recseq is used to synchronize the replacement of
xt_table::private in xt_replace_table() against all readers such as
ipt_do_table()

To ensure that there is only one writer, the writing side disables
bottom halves. The sequence counter can be acquired recursively. Only the
first invocation modifies the sequence counter (signaling that a writer
is in progress) while the following (recursive) writer does not modify
the counter.
The lack of a proper locking mechanism for the sequence counter can lead
to live lock on PREEMPT_RT if the high prior reader preempts the
writer. Additionally if the per-CPU lock on PREEMPT_RT is removed from
local_bh_disable() then there is no synchronisation for the per-CPU
sequence counter.

The affected code is "just" the legacy netfilter code which is replaced
by "netfilter tables". That code can be disabled without sacrificing
functionality because everything is provided by the newer
implementation. This will only requires the usage of the "-nft" tools
instead of the "-legacy" ones.
The long term plan is to remove the legacy code so lets accelerate the
progress.

Relax dependencies on iptables legacy, replace select with depends on,
this should cause no harm to existing kernel configs and users can still
toggle IP{6}_NF_IPTABLES_LEGACY in any case.
Make EBTABLES_LEGACY, IPTABLES_LEGACY and ARPTABLES depend on
NETFILTER_XTABLES_LEGACY. Hide xt_recseq and its users,
xt_register_table() and xt_percpu_counter_alloc() behind
NETFILTER_XTABLES_LEGACY. Let NETFILTER_XTABLES_LEGACY depend on
!PREEMPT_RT.

This will break selftest expecing the legacy options enabled and will be
addressed in a following patch.

Co-developed-by: default avatarFlorian Westphal <fw@strlen.de>
Co-developed-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 29f0f4ce
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ config NF_CONNTRACK_BRIDGE
# old sockopt interface and eval loop
config BRIDGE_NF_EBTABLES_LEGACY
	tristate "Legacy EBTABLES support"
	depends on BRIDGE && NETFILTER_XTABLES
	depends on BRIDGE && NETFILTER_XTABLES_LEGACY
	default	n
	help
	 Legacy ebtables packet/frame classifier.
@@ -65,7 +65,7 @@ if BRIDGE_NF_EBTABLES
#
config BRIDGE_EBT_BROUTE
	tristate "ebt: broute table support"
	select BRIDGE_NF_EBTABLES_LEGACY
	depends on BRIDGE_NF_EBTABLES_LEGACY
	help
	  The ebtables broute table is used to define rules that decide between
	  bridging and routing frames, giving Linux the functionality of a
@@ -76,7 +76,7 @@ config BRIDGE_EBT_BROUTE

config BRIDGE_EBT_T_FILTER
	tristate "ebt: filter table support"
	select BRIDGE_NF_EBTABLES_LEGACY
	depends on BRIDGE_NF_EBTABLES_LEGACY
	help
	  The ebtables filter table is used to define frame filtering rules at
	  local input, forwarding and local output. See the man page for
@@ -86,7 +86,7 @@ config BRIDGE_EBT_T_FILTER

config BRIDGE_EBT_T_NAT
	tristate "ebt: nat table support"
	select BRIDGE_NF_EBTABLES_LEGACY
	depends on BRIDGE_NF_EBTABLES_LEGACY
	help
	  The ebtables nat table is used to define rules that alter the MAC
	  source address (MAC SNAT) or the MAC destination address (MAC DNAT).
+12 −12
Original line number Diff line number Diff line
@@ -13,8 +13,8 @@ config NF_DEFRAG_IPV4
# old sockopt interface and eval loop
config IP_NF_IPTABLES_LEGACY
	tristate "Legacy IP tables support"
	default	n
	select NETFILTER_XTABLES
	depends on NETFILTER_XTABLES_LEGACY
	default	m if NETFILTER_XTABLES_LEGACY
	help
	  iptables is a legacy packet classifier.
	  This is not needed if you are using iptables over nftables
@@ -182,8 +182,8 @@ config IP_NF_MATCH_TTL
# `filter', generic and specific targets
config IP_NF_FILTER
	tristate "Packet filtering"
	default m if NETFILTER_ADVANCED=n
	select IP_NF_IPTABLES_LEGACY
	default m if NETFILTER_ADVANCED=n || IP_NF_IPTABLES_LEGACY
	depends on IP_NF_IPTABLES_LEGACY
	help
	  Packet filtering defines a table `filter', which has a series of
	  rules for simple packet filtering at local input, forwarding and
@@ -220,10 +220,10 @@ config IP_NF_TARGET_SYNPROXY
config IP_NF_NAT
	tristate "iptables NAT support"
	depends on NF_CONNTRACK
	depends on IP_NF_IPTABLES_LEGACY
	default m if NETFILTER_ADVANCED=n
	select NF_NAT
	select NETFILTER_XT_NAT
	select IP_NF_IPTABLES_LEGACY
	help
	  This enables the `nat' table in iptables. This allows masquerading,
	  port forwarding and other forms of full Network Address Port
@@ -263,8 +263,8 @@ endif # IP_NF_NAT
# mangle + specific targets
config IP_NF_MANGLE
	tristate "Packet mangling"
	default m if NETFILTER_ADVANCED=n
	select IP_NF_IPTABLES_LEGACY
	default m if NETFILTER_ADVANCED=n || IP_NF_IPTABLES_LEGACY
	depends on IP_NF_IPTABLES_LEGACY
	help
	  This option adds a `mangle' table to iptables: see the man page for
	  iptables(8).  This table is used for various packet alterations
@@ -299,7 +299,7 @@ config IP_NF_TARGET_TTL
# raw + specific targets
config IP_NF_RAW
	tristate  'raw table support (required for NOTRACK/TRACE)'
	select IP_NF_IPTABLES_LEGACY
	depends on IP_NF_IPTABLES_LEGACY
	help
	  This option adds a `raw' table to iptables. This table is the very
	  first in the netfilter framework and hooks in at the PREROUTING
@@ -313,7 +313,7 @@ config IP_NF_SECURITY
	tristate "Security table"
	depends on SECURITY
	depends on NETFILTER_ADVANCED
	select IP_NF_IPTABLES_LEGACY
	depends on IP_NF_IPTABLES_LEGACY
	help
	  This option adds a `security' table to iptables, for use
	  with Mandatory Access Control (MAC) policy.
@@ -325,7 +325,7 @@ endif # IP_NF_IPTABLES
# ARP tables
config IP_NF_ARPTABLES
	tristate "Legacy ARPTABLES support"
	depends on NETFILTER_XTABLES
	depends on NETFILTER_XTABLES_LEGACY
	default	n
	help
	  arptables is a legacy packet classifier.
@@ -342,7 +342,7 @@ config IP_NF_ARPFILTER
	tristate "arptables-legacy packet filtering support"
	select IP_NF_ARPTABLES
	select NETFILTER_FAMILY_ARP
	depends on NETFILTER_XTABLES
	depends on NETFILTER_XTABLES_LEGACY
	help
	  ARP packet filtering defines a table `filter', which has a series of
	  rules for simple ARP packet filtering at local input and
+9 −10
Original line number Diff line number Diff line
@@ -9,9 +9,8 @@ menu "IPv6: Netfilter Configuration"
# old sockopt interface and eval loop
config IP6_NF_IPTABLES_LEGACY
	tristate "Legacy IP6 tables support"
	depends on INET && IPV6
	select NETFILTER_XTABLES
	default n
	depends on INET && IPV6 && NETFILTER_XTABLES_LEGACY
	default	m if NETFILTER_XTABLES_LEGACY
	help
	  ip6tables is a legacy packet classifier.
	  This is not needed if you are using iptables over nftables
@@ -196,8 +195,8 @@ config IP6_NF_TARGET_HL

config IP6_NF_FILTER
	tristate "Packet filtering"
	default m if NETFILTER_ADVANCED=n
	select IP6_NF_IPTABLES_LEGACY
	default m if NETFILTER_ADVANCED=n || IP6_NF_IPTABLES_LEGACY
	depends on IP6_NF_IPTABLES_LEGACY
	tristate
	help
	  Packet filtering defines a table `filter', which has a series of
@@ -233,8 +232,8 @@ config IP6_NF_TARGET_SYNPROXY

config IP6_NF_MANGLE
	tristate "Packet mangling"
	default m if NETFILTER_ADVANCED=n
	select IP6_NF_IPTABLES_LEGACY
	default m if NETFILTER_ADVANCED=n || IP6_NF_IPTABLES_LEGACY
	depends on IP6_NF_IPTABLES_LEGACY
	help
	  This option adds a `mangle' table to iptables: see the man page for
	  iptables(8).  This table is used for various packet alterations
@@ -244,7 +243,7 @@ config IP6_NF_MANGLE

config IP6_NF_RAW
	tristate  'raw table support (required for TRACE)'
	select IP6_NF_IPTABLES_LEGACY
	depends on IP6_NF_IPTABLES_LEGACY
	help
	  This option adds a `raw' table to ip6tables. This table is the very
	  first in the netfilter framework and hooks in at the PREROUTING
@@ -258,7 +257,7 @@ config IP6_NF_SECURITY
	tristate "Security table"
	depends on SECURITY
	depends on NETFILTER_ADVANCED
	select IP6_NF_IPTABLES_LEGACY
	depends on IP6_NF_IPTABLES_LEGACY
	help
	  This option adds a `security' table to iptables, for use
	  with Mandatory Access Control (MAC) policy.
@@ -269,8 +268,8 @@ config IP6_NF_NAT
	tristate "ip6tables NAT support"
	depends on NF_CONNTRACK
	depends on NETFILTER_ADVANCED
	depends on IP6_NF_IPTABLES_LEGACY
	select NF_NAT
	select IP6_NF_IPTABLES_LEGACY
	select NETFILTER_XT_NAT
	help
	  This enables the `nat' table in ip6tables. This allows masquerading,
+10 −0
Original line number Diff line number Diff line
@@ -758,6 +758,16 @@ config NETFILTER_XTABLES_COMPAT

	   If unsure, say N.

config NETFILTER_XTABLES_LEGACY
	bool "Netfilter legacy tables support"
	depends on !PREEMPT_RT
	help
	  Say Y here if you still require support for legacy tables. This is
	  required by the legacy tools (iptables-legacy) and is not needed if
	  you use iptables over nftables (iptables-nft).
	  Legacy support is not limited to IP, it also includes EBTABLES and
	  ARPTABLES.

comment "Xtables combined modules"

config NETFILTER_XT_MARK
+11 −5
Original line number Diff line number Diff line
@@ -1317,12 +1317,13 @@ void xt_compat_unlock(u_int8_t af)
EXPORT_SYMBOL_GPL(xt_compat_unlock);
#endif

DEFINE_PER_CPU(seqcount_t, xt_recseq);
EXPORT_PER_CPU_SYMBOL_GPL(xt_recseq);

struct static_key xt_tee_enabled __read_mostly;
EXPORT_SYMBOL_GPL(xt_tee_enabled);

#ifdef CONFIG_NETFILTER_XTABLES_LEGACY
DEFINE_PER_CPU(seqcount_t, xt_recseq);
EXPORT_PER_CPU_SYMBOL_GPL(xt_recseq);

static int xt_jumpstack_alloc(struct xt_table_info *i)
{
	unsigned int size;
@@ -1514,6 +1515,7 @@ void *xt_unregister_table(struct xt_table *table)
	return private;
}
EXPORT_SYMBOL_GPL(xt_unregister_table);
#endif

#ifdef CONFIG_PROC_FS
static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
@@ -1897,6 +1899,7 @@ void xt_proto_fini(struct net *net, u_int8_t af)
}
EXPORT_SYMBOL_GPL(xt_proto_fini);

#ifdef CONFIG_NETFILTER_XTABLES_LEGACY
/**
 * xt_percpu_counter_alloc - allocate x_tables rule counter
 *
@@ -1951,6 +1954,7 @@ void xt_percpu_counter_free(struct xt_counters *counters)
		free_percpu((void __percpu *)pcnt);
}
EXPORT_SYMBOL_GPL(xt_percpu_counter_free);
#endif

static int __net_init xt_net_init(struct net *net)
{
@@ -1983,9 +1987,11 @@ static int __init xt_init(void)
	unsigned int i;
	int rv;

	if (IS_ENABLED(CONFIG_NETFILTER_XTABLES_LEGACY)) {
		for_each_possible_cpu(i) {
			seqcount_init(&per_cpu(xt_recseq, i));
		}
	}

	xt = kcalloc(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
	if (!xt)