mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
netdev: avoid skipping objects on race with device disappearance
If the currently dumped device disappears while we were mid-dump we will get the next device without resetting the sub-object ID. This is quite unlikely, it was reported by an AI tool not a real user. Let's fix it for better dump consistency. We only intend to cover the case where device A disappears and we skip over sub-objects of device B which was stable (B existed before and after the dump). We don't intend to provide stable results for any device that gets created or deleted during the dump. Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260903221154.3359889-1-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
daf0972d38
commit
761ae184f8
|
|
@ -312,11 +312,14 @@ int netdev_nl_napi_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
err = -ENODEV;
|
||||
}
|
||||
} else {
|
||||
unsigned long start_ifindex = ctx->ifindex;
|
||||
|
||||
for_each_netdev_lock_scoped(net, netdev, ctx->ifindex) {
|
||||
if (ctx->ifindex != start_ifindex)
|
||||
ctx->napi_id = 0;
|
||||
err = netdev_nl_napi_dump_one(netdev, skb, info, ctx);
|
||||
if (err < 0)
|
||||
break;
|
||||
ctx->napi_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -636,13 +639,17 @@ int netdev_nl_queue_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
err = -ENODEV;
|
||||
}
|
||||
} else {
|
||||
unsigned long start_ifindex = ctx->ifindex;
|
||||
|
||||
for_each_netdev_lock_ops_compat_scoped(net, netdev,
|
||||
ctx->ifindex) {
|
||||
if (ctx->ifindex != start_ifindex) {
|
||||
ctx->rxq_idx = 0;
|
||||
ctx->txq_idx = 0;
|
||||
}
|
||||
err = netdev_nl_queue_dump_one(netdev, skb, info, ctx);
|
||||
if (err < 0)
|
||||
break;
|
||||
ctx->rxq_idx = 0;
|
||||
ctx->txq_idx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -788,8 +795,6 @@ netdev_nl_stats_by_queue(struct net_device *netdev, struct sk_buff *rsp,
|
|||
ctx->txq_idx = ++i;
|
||||
}
|
||||
|
||||
ctx->rxq_idx = 0;
|
||||
ctx->txq_idx = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -904,6 +909,7 @@ int netdev_nl_qstats_get_dumpit(struct sk_buff *skb,
|
|||
struct netdev_nl_dump_ctx *ctx = netdev_dump_ctx(cb);
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
struct net *net = sock_net(skb->sk);
|
||||
unsigned long start_ifindex;
|
||||
struct net_device *netdev;
|
||||
unsigned int ifindex;
|
||||
unsigned int scope;
|
||||
|
|
@ -936,7 +942,13 @@ int netdev_nl_qstats_get_dumpit(struct sk_buff *skb,
|
|||
return err;
|
||||
}
|
||||
|
||||
start_ifindex = ctx->ifindex;
|
||||
|
||||
for_each_netdev_lock_ops_compat_scoped(net, netdev, ctx->ifindex) {
|
||||
if (ctx->ifindex != start_ifindex) {
|
||||
ctx->rxq_idx = 0;
|
||||
ctx->txq_idx = 0;
|
||||
}
|
||||
err = netdev_nl_qstats_get_dump_one(netdev, scope, skb,
|
||||
info, ctx);
|
||||
if (err < 0)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||
struct page_pool_dump_cb *state = (void *)cb->ctx;
|
||||
const struct genl_info *info = genl_info_dump(cb);
|
||||
struct net *net = sock_net(skb->sk);
|
||||
unsigned long start_ifindex;
|
||||
struct net_device *netdev;
|
||||
struct page_pool *pool;
|
||||
int err = 0;
|
||||
|
|
@ -91,6 +92,8 @@ netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||
if (ifindex_attr)
|
||||
state->ifindex = nla_get_u32(ifindex_attr);
|
||||
|
||||
start_ifindex = state->ifindex;
|
||||
|
||||
rtnl_lock();
|
||||
mutex_lock(&page_pools_lock);
|
||||
for_each_netdev_dump(net, netdev, state->ifindex) {
|
||||
|
|
@ -99,6 +102,9 @@ netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||
netdev->ifindex != nla_get_u32(ifindex_attr))
|
||||
break;
|
||||
|
||||
if (state->ifindex != start_ifindex)
|
||||
state->pp_id = 0;
|
||||
|
||||
hlist_for_each_entry(pool, &netdev->page_pools, user.list) {
|
||||
if (state->pp_id && state->pp_id < pool->user.id)
|
||||
continue;
|
||||
|
|
@ -108,8 +114,6 @@ netdev_nl_page_pool_get_dump(struct sk_buff *skb, struct netlink_callback *cb,
|
|||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
state->pp_id = 0;
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&page_pools_lock);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user