Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: netdevsim: try to close UDP port harness races

syzbot discovered that we remove the debugfs files after we free
the netdev. Try to clean up the relevant dir while the device
is still around.

Reported-by: syzbot+2e5de9e3ab986b71d2bf@syzkaller.appspotmail.com
Fixes: 424be63ad831 ("netdevsim: add UDP tunnel port offload support")
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Link: https://patch.msgid.link/20250122224503.762705-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+23 -17
+1
drivers/net/netdevsim/netdevsim.h
··· 134 134 u32 sleep; 135 135 u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS]; 136 136 u32 (*ports)[NSIM_UDP_TUNNEL_N_PORTS]; 137 + struct dentry *ddir; 137 138 struct debugfs_u32_array dfs_ports[2]; 138 139 } udp_ports; 139 140
+14 -9
drivers/net/netdevsim/udp_tunnels.c
··· 112 112 struct net_device *dev = file->private_data; 113 113 struct netdevsim *ns = netdev_priv(dev); 114 114 115 - memset(ns->udp_ports.ports, 0, sizeof(ns->udp_ports.__ports)); 116 115 rtnl_lock(); 117 - udp_tunnel_nic_reset_ntf(dev); 116 + if (dev->reg_state == NETREG_REGISTERED) { 117 + memset(ns->udp_ports.ports, 0, sizeof(ns->udp_ports.__ports)); 118 + udp_tunnel_nic_reset_ntf(dev); 119 + } 118 120 rtnl_unlock(); 119 121 120 122 return count; ··· 146 144 else 147 145 ns->udp_ports.ports = nsim_dev->udp_ports.__ports; 148 146 149 - debugfs_create_u32("udp_ports_inject_error", 0600, 150 - ns->nsim_dev_port->ddir, 147 + ns->udp_ports.ddir = debugfs_create_dir("udp_ports", 148 + ns->nsim_dev_port->ddir); 149 + 150 + debugfs_create_u32("inject_error", 0600, ns->udp_ports.ddir, 151 151 &ns->udp_ports.inject_error); 152 152 153 153 ns->udp_ports.dfs_ports[0].array = ns->udp_ports.ports[0]; 154 154 ns->udp_ports.dfs_ports[0].n_elements = NSIM_UDP_TUNNEL_N_PORTS; 155 - debugfs_create_u32_array("udp_ports_table0", 0400, 156 - ns->nsim_dev_port->ddir, 155 + debugfs_create_u32_array("table0", 0400, ns->udp_ports.ddir, 157 156 &ns->udp_ports.dfs_ports[0]); 158 157 159 158 ns->udp_ports.dfs_ports[1].array = ns->udp_ports.ports[1]; 160 159 ns->udp_ports.dfs_ports[1].n_elements = NSIM_UDP_TUNNEL_N_PORTS; 161 - debugfs_create_u32_array("udp_ports_table1", 0400, 162 - ns->nsim_dev_port->ddir, 160 + debugfs_create_u32_array("table1", 0400, ns->udp_ports.ddir, 163 161 &ns->udp_ports.dfs_ports[1]); 164 162 165 - debugfs_create_file("udp_ports_reset", 0200, ns->nsim_dev_port->ddir, 163 + debugfs_create_file("reset", 0200, ns->udp_ports.ddir, 166 164 dev, &nsim_udp_tunnels_info_reset_fops); 167 165 168 166 /* Note: it's not normal to allocate the info struct like this! ··· 198 196 199 197 void nsim_udp_tunnels_info_destroy(struct net_device *dev) 200 198 { 199 + struct netdevsim *ns = netdev_priv(dev); 200 + 201 + debugfs_remove_recursive(ns->udp_ports.ddir); 201 202 kfree(dev->udp_tunnel_nic_info); 202 203 dev->udp_tunnel_nic_info = NULL; 203 204 }
+8 -8
tools/testing/selftests/drivers/net/netdevsim/udp_tunnel_nic.sh
··· 142 142 } 143 143 144 144 function check_table { 145 - local path=$NSIM_DEV_DFS/ports/$port/udp_ports_table$1 145 + local path=$NSIM_DEV_DFS/ports/$port/udp_ports/table$1 146 146 local -n expected=$2 147 147 local last=$3 148 148 ··· 212 212 } 213 213 214 214 function print_table { 215 - local path=$NSIM_DEV_DFS/ports/$port/udp_ports_table$1 215 + local path=$NSIM_DEV_DFS/ports/$port/udp_ports/table$1 216 216 read -a have < $path 217 217 218 218 tree $NSIM_DEV_DFS/ ··· 641 641 NSIM_NETDEV=`get_netdev_name old_netdevs` 642 642 ip link set dev $NSIM_NETDEV up 643 643 644 - echo 110 > $NSIM_DEV_DFS/ports/$port/udp_ports_inject_error 644 + echo 110 > $NSIM_DEV_DFS/ports/$port/udp_ports/inject_error 645 645 646 646 msg="1 - create VxLANs v6" 647 647 exp0=( 0 0 0 0 ) ··· 663 663 new_geneve gnv0 20000 664 664 665 665 msg="2 - destroy GENEVE" 666 - echo 2 > $NSIM_DEV_DFS/ports/$port/udp_ports_inject_error 666 + echo 2 > $NSIM_DEV_DFS/ports/$port/udp_ports/inject_error 667 667 exp1=( `mke 20000 2` 0 0 0 ) 668 668 del_dev gnv0 669 669 ··· 764 764 msg="create VxLANs v4" 765 765 new_vxlan vxlan0 10000 $NSIM_NETDEV 766 766 767 - echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports_reset 767 + echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports/reset 768 768 check_tables 769 769 770 770 msg="NIC device goes down" ··· 775 775 fi 776 776 check_tables 777 777 778 - echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports_reset 778 + echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports/reset 779 779 check_tables 780 780 781 781 msg="NIC device goes up again" ··· 789 789 del_dev vxlan0 790 790 check_tables 791 791 792 - echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports_reset 792 + echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports/reset 793 793 check_tables 794 794 795 795 msg="destroy NIC" ··· 896 896 exp0=( `mke 10000 1` `mke 10004 1` 0 `mke 10003 1` ) 897 897 del_dev vxlan2 898 898 899 - echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports_reset 899 + echo 1 > $NSIM_DEV_DFS/ports/$port/udp_ports/reset 900 900 check_tables 901 901 902 902 msg="tunnels destroyed 2"