Commit cceac926 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'nf-23-05-10' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf

Pablo Neira Ayuso says:

====================
Netfilter updates for net

The following patchset contains Netfilter fixes for net:

1) Fix UAF when releasing netnamespace, from Florian Westphal.

2) Fix possible BUG_ON when nf_conntrack is enabled with enable_hooks,
   from Florian Westphal.

3) Fixes for nft_flowtable.sh selftest, from Boris Sukholitko.

4) Extend nft_flowtable.sh selftest to cover integration with
   ingress/egress hooks, from Florian Westphal.

* tag 'nf-23-05-10' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  selftests: nft_flowtable.sh: check ingress/egress chain too
  selftests: nft_flowtable.sh: monitor result file sizes
  selftests: nft_flowtable.sh: wait for specific nc pids
  selftests: nft_flowtable.sh: no need for ps -x option
  selftests: nft_flowtable.sh: use /proc for pid checking
  netfilter: conntrack: fix possible bug_on with enable_hooks=1
  netfilter: nf_tables: always release netdev hooks from notifier
====================

Link: https://lore.kernel.org/r/20230510083313.152961-1-pablo@netfilter.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 33dcee99 3acf8f6c
...@@ -711,9 +711,11 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct) ...@@ -711,9 +711,11 @@ void nf_conntrack_destroy(struct nf_conntrack *nfct)
rcu_read_lock(); rcu_read_lock();
ct_hook = rcu_dereference(nf_ct_hook); ct_hook = rcu_dereference(nf_ct_hook);
BUG_ON(ct_hook == NULL); if (ct_hook)
ct_hook->destroy(nfct); ct_hook->destroy(nfct);
rcu_read_unlock(); rcu_read_unlock();
WARN_ON(!ct_hook);
} }
EXPORT_SYMBOL(nf_conntrack_destroy); EXPORT_SYMBOL(nf_conntrack_destroy);
......
...@@ -1218,11 +1218,12 @@ static int __init nf_conntrack_standalone_init(void) ...@@ -1218,11 +1218,12 @@ static int __init nf_conntrack_standalone_init(void)
nf_conntrack_htable_size_user = nf_conntrack_htable_size; nf_conntrack_htable_size_user = nf_conntrack_htable_size;
#endif #endif
nf_conntrack_init_end();
ret = register_pernet_subsys(&nf_conntrack_net_ops); ret = register_pernet_subsys(&nf_conntrack_net_ops);
if (ret < 0) if (ret < 0)
goto out_pernet; goto out_pernet;
nf_conntrack_init_end();
return 0; return 0;
out_pernet: out_pernet:
......
...@@ -344,6 +344,12 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev, ...@@ -344,6 +344,12 @@ static void nft_netdev_event(unsigned long event, struct net_device *dev,
return; return;
} }
/* UNREGISTER events are also happening on netns exit.
*
* Although nf_tables core releases all tables/chains, only this event
* handler provides guarantee that hook->ops.dev is still accessible,
* so we cannot skip exiting net namespaces.
*/
__nft_release_basechain(ctx); __nft_release_basechain(ctx);
} }
...@@ -362,9 +368,6 @@ static int nf_tables_netdev_event(struct notifier_block *this, ...@@ -362,9 +368,6 @@ static int nf_tables_netdev_event(struct notifier_block *this,
event != NETDEV_CHANGENAME) event != NETDEV_CHANGENAME)
return NOTIFY_DONE; return NOTIFY_DONE;
if (!check_net(ctx.net))
return NOTIFY_DONE;
nft_net = nft_pernet(ctx.net); nft_net = nft_pernet(ctx.net);
mutex_lock(&nft_net->commit_mutex); mutex_lock(&nft_net->commit_mutex);
list_for_each_entry(table, &nft_net->tables, list) { list_for_each_entry(table, &nft_net->tables, list) {
......
...@@ -188,6 +188,26 @@ if [ $? -ne 0 ]; then ...@@ -188,6 +188,26 @@ if [ $? -ne 0 ]; then
exit $ksft_skip exit $ksft_skip
fi fi
ip netns exec $ns2 nft -f - <<EOF
table inet filter {
counter ip4dscp0 { }
counter ip4dscp3 { }
chain input {
type filter hook input priority 0; policy accept;
meta l4proto tcp goto {
ip dscp cs3 counter name ip4dscp3 accept
ip dscp 0 counter name ip4dscp0 accept
}
}
}
EOF
if [ $? -ne 0 ]; then
echo "SKIP: Could not load nft ruleset"
exit $ksft_skip
fi
# test basic connectivity # test basic connectivity
if ! ip netns exec $ns1 ping -c 1 -q 10.0.2.99 > /dev/null; then if ! ip netns exec $ns1 ping -c 1 -q 10.0.2.99 > /dev/null; then
echo "ERROR: $ns1 cannot reach ns2" 1>&2 echo "ERROR: $ns1 cannot reach ns2" 1>&2
...@@ -255,6 +275,60 @@ check_counters() ...@@ -255,6 +275,60 @@ check_counters()
fi fi
} }
check_dscp()
{
local what=$1
local ok=1
local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp3 | grep packets)
local pc4=${counter%*bytes*}
local pc4=${pc4#*packets}
local counter=$(ip netns exec $ns2 nft reset counter inet filter ip4dscp0 | grep packets)
local pc4z=${counter%*bytes*}
local pc4z=${pc4z#*packets}
case "$what" in
"dscp_none")
if [ $pc4 -gt 0 ] || [ $pc4z -eq 0 ]; then
echo "FAIL: dscp counters do not match, expected dscp3 == 0, dscp0 > 0, but got $pc4,$pc4z" 1>&2
ret=1
ok=0
fi
;;
"dscp_fwd")
if [ $pc4 -eq 0 ] || [ $pc4z -eq 0 ]; then
echo "FAIL: dscp counters do not match, expected dscp3 and dscp0 > 0 but got $pc4,$pc4z" 1>&2
ret=1
ok=0
fi
;;
"dscp_ingress")
if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
ret=1
ok=0
fi
;;
"dscp_egress")
if [ $pc4 -eq 0 ] || [ $pc4z -gt 0 ]; then
echo "FAIL: dscp counters do not match, expected dscp3 > 0, dscp0 == 0 but got $pc4,$pc4z" 1>&2
ret=1
ok=0
fi
;;
*)
echo "FAIL: Unknown DSCP check" 1>&2
ret=1
ok=0
esac
if [ $ok -eq 1 ] ;then
echo "PASS: $what: dscp packet counters match"
fi
}
check_transfer() check_transfer()
{ {
in=$1 in=$1
...@@ -286,17 +360,26 @@ test_tcp_forwarding_ip() ...@@ -286,17 +360,26 @@ test_tcp_forwarding_ip()
ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$nsin" > "$ns1out" & ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$nsin" > "$ns1out" &
cpid=$! cpid=$!
sleep 3 sleep 1
if ps -p $lpid > /dev/null;then prev="$(ls -l $ns1out $ns2out)"
sleep 1
while [[ "$prev" != "$(ls -l $ns1out $ns2out)" ]]; do
sleep 1;
prev="$(ls -l $ns1out $ns2out)"
done
if test -d /proc/"$lpid"/; then
kill $lpid kill $lpid
fi fi
if ps -p $cpid > /dev/null;then if test -d /proc/"$cpid"/; then
kill $cpid kill $cpid
fi fi
wait wait $lpid
wait $cpid
if ! check_transfer "$nsin" "$ns2out" "ns1 -> ns2"; then if ! check_transfer "$nsin" "$ns2out" "ns1 -> ns2"; then
lret=1 lret=1
...@@ -316,6 +399,51 @@ test_tcp_forwarding() ...@@ -316,6 +399,51 @@ test_tcp_forwarding()
return $? return $?
} }
test_tcp_forwarding_set_dscp()
{
check_dscp "dscp_none"
ip netns exec $nsr1 nft -f - <<EOF
table netdev dscpmangle {
chain setdscp0 {
type filter hook ingress device "veth0" priority 0; policy accept
ip dscp set cs3
}
}
EOF
if [ $? -eq 0 ]; then
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
check_dscp "dscp_ingress"
ip netns exec $nsr1 nft delete table netdev dscpmangle
else
echo "SKIP: Could not load netdev:ingress for veth0"
fi
ip netns exec $nsr1 nft -f - <<EOF
table netdev dscpmangle {
chain setdscp0 {
type filter hook egress device "veth1" priority 0; policy accept
ip dscp set cs3
}
}
EOF
if [ $? -eq 0 ]; then
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
check_dscp "dscp_egress"
ip netns exec $nsr1 nft flush table netdev dscpmangle
else
echo "SKIP: Could not load netdev:egress for veth1"
fi
# partial. If flowtable really works, then both dscp-is-0 and dscp-is-cs3
# counters should have seen packets (before and after ft offload kicks in).
ip netns exec $nsr1 nft -a insert rule inet filter forward ip dscp set cs3
test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
check_dscp "dscp_fwd"
}
test_tcp_forwarding_nat() test_tcp_forwarding_nat()
{ {
local lret local lret
...@@ -385,6 +513,11 @@ table ip nat { ...@@ -385,6 +513,11 @@ table ip nat {
} }
EOF EOF
if ! test_tcp_forwarding_set_dscp $ns1 $ns2 0 ""; then
echo "FAIL: flow offload for ns1/ns2 with dscp update" 1>&2
exit 0
fi
if ! test_tcp_forwarding_nat $ns1 $ns2 0 ""; then if ! test_tcp_forwarding_nat $ns1 $ns2 0 ""; then
echo "FAIL: flow offload for ns1/ns2 with NAT" 1>&2 echo "FAIL: flow offload for ns1/ns2 with NAT" 1>&2
ip netns exec $nsr1 nft list ruleset ip netns exec $nsr1 nft list ruleset
...@@ -489,8 +622,8 @@ ip -net $nsr1 addr add 10.0.1.1/24 dev veth0 ...@@ -489,8 +622,8 @@ ip -net $nsr1 addr add 10.0.1.1/24 dev veth0
ip -net $nsr1 addr add dead:1::1/64 dev veth0 ip -net $nsr1 addr add dead:1::1/64 dev veth0
ip -net $nsr1 link set up dev veth0 ip -net $nsr1 link set up dev veth0
KEY_SHA="0x"$(ps -xaf | sha1sum | cut -d " " -f 1) KEY_SHA="0x"$(ps -af | sha1sum | cut -d " " -f 1)
KEY_AES="0x"$(ps -xaf | md5sum | cut -d " " -f 1) KEY_AES="0x"$(ps -af | md5sum | cut -d " " -f 1)
SPI1=$RANDOM SPI1=$RANDOM
SPI2=$RANDOM SPI2=$RANDOM
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment