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

Configure Feed

Select the types of activity you want to include in your feed.

netdev: prevent accessing NAPI instances from another namespace

The NAPI IDs were not fully exposed to user space prior to the netlink
API, so they were never namespaced. The netlink API must ensure that
at the very least NAPI instance belongs to the same netns as the owner
of the genl sock.

napi_by_id() can become static now, but it needs to move because of
dev_get_by_napi_id().

Cc: stable@vger.kernel.org
Fixes: 1287c1ae0fc2 ("netdev-genl: Support setting per-NAPI config values")
Fixes: 27f91aaf49b3 ("netdev-genl: Add netlink framework functions for napi")
Reviewed-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Reviewed-by: Joe Damato <jdamato@fastly.com>
Link: https://patch.msgid.link/20250106180137.1861472-1-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+34 -18
+30 -13
net/core/dev.c
··· 753 753 } 754 754 EXPORT_SYMBOL_GPL(dev_fill_forward_path); 755 755 756 + /* must be called under rcu_read_lock(), as we dont take a reference */ 757 + static struct napi_struct *napi_by_id(unsigned int napi_id) 758 + { 759 + unsigned int hash = napi_id % HASH_SIZE(napi_hash); 760 + struct napi_struct *napi; 761 + 762 + hlist_for_each_entry_rcu(napi, &napi_hash[hash], napi_hash_node) 763 + if (napi->napi_id == napi_id) 764 + return napi; 765 + 766 + return NULL; 767 + } 768 + 769 + /* must be called under rcu_read_lock(), as we dont take a reference */ 770 + struct napi_struct *netdev_napi_by_id(struct net *net, unsigned int napi_id) 771 + { 772 + struct napi_struct *napi; 773 + 774 + napi = napi_by_id(napi_id); 775 + if (!napi) 776 + return NULL; 777 + 778 + if (WARN_ON_ONCE(!napi->dev)) 779 + return NULL; 780 + if (!net_eq(net, dev_net(napi->dev))) 781 + return NULL; 782 + 783 + return napi; 784 + } 785 + 756 786 /** 757 787 * __dev_get_by_name - find a device by its name 758 788 * @net: the applicable net namespace ··· 6322 6292 return ret; 6323 6293 } 6324 6294 EXPORT_SYMBOL(napi_complete_done); 6325 - 6326 - /* must be called under rcu_read_lock(), as we dont take a reference */ 6327 - struct napi_struct *napi_by_id(unsigned int napi_id) 6328 - { 6329 - unsigned int hash = napi_id % HASH_SIZE(napi_hash); 6330 - struct napi_struct *napi; 6331 - 6332 - hlist_for_each_entry_rcu(napi, &napi_hash[hash], napi_hash_node) 6333 - if (napi->napi_id == napi_id) 6334 - return napi; 6335 - 6336 - return NULL; 6337 - } 6338 6295 6339 6296 static void skb_defer_free_flush(struct softnet_data *sd) 6340 6297 {
+2 -1
net/core/dev.h
··· 22 22 23 23 extern int netdev_flow_limit_table_len; 24 24 25 + struct napi_struct *netdev_napi_by_id(struct net *net, unsigned int napi_id); 26 + 25 27 #ifdef CONFIG_PROC_FS 26 28 int __init dev_proc_init(void); 27 29 #else ··· 271 269 static inline void xdp_do_check_flushed(struct napi_struct *napi) { } 272 270 #endif 273 271 274 - struct napi_struct *napi_by_id(unsigned int napi_id); 275 272 void kick_defer_list_purge(struct softnet_data *sd, unsigned int cpu); 276 273 277 274 #define XMIT_RECURSION_LIMIT 8
+2 -4
net/core/netdev-genl.c
··· 167 167 void *hdr; 168 168 pid_t pid; 169 169 170 - if (WARN_ON_ONCE(!napi->dev)) 171 - return -EINVAL; 172 170 if (!(napi->dev->flags & IFF_UP)) 173 171 return 0; 174 172 ··· 232 234 rtnl_lock(); 233 235 rcu_read_lock(); 234 236 235 - napi = napi_by_id(napi_id); 237 + napi = netdev_napi_by_id(genl_info_net(info), napi_id); 236 238 if (napi) { 237 239 err = netdev_nl_napi_fill_one(rsp, napi, info); 238 240 } else { ··· 353 355 rtnl_lock(); 354 356 rcu_read_lock(); 355 357 356 - napi = napi_by_id(napi_id); 358 + napi = netdev_napi_by_id(genl_info_net(info), napi_id); 357 359 if (napi) { 358 360 err = netdev_nl_napi_set_config(napi, info); 359 361 } else {