mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
Merge branch 'ipv6-fix-suspicious-rcu-usage-in-route-hardware-flags-notification'
Ido Schimmel says: ==================== ipv6: Fix suspicious RCU usage in route hardware flags notification fib6_info_hw_flags_set() is called by drivers to update the hardware flags of an IPv6 route and to emit a notification when fib_notify_on_flag_change is set. Drivers call it from process context without RTNL or RCU, so when the route uses a nexthop object, building the notification triggers suspicious RCU usage splats. Patch #1 fixes the problem by holding RCU while building the notification. Patch #2 adds IPv4 and IPv6 test cases for routes that use nexthop objects. Without patch #1, the IPv6 one triggers the splats. ==================== Link: https://patch.msgid.link/20261019140337.2886875-1-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
06d870fe6c
|
|
@ -6509,7 +6509,9 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
|
|||
if (!fib_notify_on_flag_change)
|
||||
return;
|
||||
|
||||
skb = nlmsg_new(rt6_nlmsg_size(f6i), GFP_KERNEL);
|
||||
rcu_read_lock();
|
||||
|
||||
skb = nlmsg_new(rt6_nlmsg_size(f6i), GFP_ATOMIC);
|
||||
if (!skb) {
|
||||
err = -ENOBUFS;
|
||||
goto errout;
|
||||
|
|
@ -6522,10 +6524,13 @@ void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
|
|||
goto errout;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_IPV6_ROUTE, NULL, GFP_KERNEL);
|
||||
return;
|
||||
|
||||
errout:
|
||||
rcu_read_unlock();
|
||||
rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
|
||||
}
|
||||
EXPORT_SYMBOL(fib6_info_hw_flags_set);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,12 @@ ALL_TESTS="
|
|||
ipv4_route_deletion_test
|
||||
ipv4_route_replacement_test
|
||||
ipv4_route_offload_failed_test
|
||||
ipv4_route_nexthop_test
|
||||
ipv6_route_addition_test
|
||||
ipv6_route_deletion_test
|
||||
ipv6_route_replacement_test
|
||||
ipv6_route_offload_failed_test
|
||||
ipv6_route_nexthop_test
|
||||
"
|
||||
|
||||
NETDEVSIM_PATH=/sys/bus/netdevsim/
|
||||
|
|
@ -269,6 +271,50 @@ ipv4_route_offload_failed_test()
|
|||
log_test "IPv4 route offload failed"
|
||||
}
|
||||
|
||||
route_nexthop_check()
|
||||
{
|
||||
local ip=$1; shift
|
||||
local route=$1; shift
|
||||
local nhid=$1; shift
|
||||
local expected_num_notifications=$1; shift
|
||||
local outfile
|
||||
|
||||
ip netns exec testns1 sysctl -qw net.$ip.fib_notify_on_flag_change=1
|
||||
|
||||
outfile=$(mktemp)
|
||||
|
||||
$IP monitor route &> $outfile &
|
||||
sleep 1
|
||||
$IP route add $route nhid $nhid
|
||||
sleep 1
|
||||
kill_process %%
|
||||
|
||||
route_notify_check $outfile $expected_num_notifications
|
||||
rm -f $outfile
|
||||
|
||||
$IP route del $route nhid $nhid
|
||||
}
|
||||
|
||||
ipv4_route_nexthop_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
local ip="ipv4"
|
||||
local route=192.0.2.0/24
|
||||
local nhid=1
|
||||
|
||||
$IP -4 nexthop add id $nhid dev dummy1
|
||||
|
||||
# Make sure two notifications will be emitted for a programmed route
|
||||
# that uses a nexthop object.
|
||||
local expected_num_notifications=2
|
||||
route_nexthop_check $ip $route $nhid $expected_num_notifications
|
||||
|
||||
$IP nexthop del id $nhid
|
||||
|
||||
log_test "IPv4 route with nexthop object"
|
||||
}
|
||||
|
||||
ipv6_route_addition_test()
|
||||
{
|
||||
RET=0
|
||||
|
|
@ -385,6 +431,26 @@ ipv6_route_offload_failed_test()
|
|||
log_test "IPv6 route offload failed"
|
||||
}
|
||||
|
||||
ipv6_route_nexthop_test()
|
||||
{
|
||||
RET=0
|
||||
|
||||
local ip="ipv6"
|
||||
local route=2001:db8:1::/64
|
||||
local nhid=1
|
||||
|
||||
$IP -6 nexthop add id $nhid dev dummy1
|
||||
|
||||
# Make sure two notifications will be emitted for a programmed route
|
||||
# that uses a nexthop object.
|
||||
local expected_num_notifications=2
|
||||
route_nexthop_check $ip $route $nhid $expected_num_notifications
|
||||
|
||||
$IP nexthop del id $nhid
|
||||
|
||||
log_test "IPv6 route with nexthop object"
|
||||
}
|
||||
|
||||
setup_prepare()
|
||||
{
|
||||
modprobe netdevsim &> /dev/null
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user