summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Hu <huhai@kylinos.cn>2026-09-12 00:35:14 +0800
committerNamjae Jeon <linkinjeon@kernel.org>2026-10-21 08:55:13 +0900
commita63bb4d91c784f63ad7c063717dff7920d8445be (patch)
tree37a5ea961a035910baa8bdce2a46f3bf6d248036
parent2bc1d25fc8597fa6cbf6b1ff92653881939a6436 (diff)
downloadlinux-a63bb4d91c784f63ad7c063717dff7920d8445be.tar.gz
linux-a63bb4d91c784f63ad7c063717dff7920d8445be.zip
ksmbd: fix unlocked IPv6 addr_list walk in fsctl_query_iface_info_ioctl()
fsctl_query_iface_info_ioctl() walks idev6->addr_list with a plain list_for_each_entry() while holding only rtnl_lock(). rtnl does not serialize all writers of this list: the DAD-failure path (addrconf_dad_failure -> ipv6_add_addr) can insert addresses without holding RTNL. It updates idev->addr_list with list_add_tail_rcu() under write_lock_bh(&idev->lock), so it can race with the unlocked walk. addr_list is RCU managed, so walk it with list_for_each_entry_rcu() under rcu_read_lock(), matching the other lockless readers of the list. Fixes: e2f34481b24d ("cifsd: add server-side procedures for SMB3") Reported-by: Sashiko <sashiko-bot+sashiko@kernel.org> Link: https://sashiko.dev/#/patchset/20260910090818.24479-1-15815827059%40163.com Co-developed-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn> Signed-off-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn> Signed-off-by: Henry Hu <huhai@kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
-rw-r--r--fs/smb/server/smb2pdu.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 007a72005501..8563b7aa4289 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -10589,13 +10589,15 @@ ipv6_retry:
if (!idev6)
continue;
- list_for_each_entry(ifa, &idev6->addr_list, if_list) {
+ rcu_read_lock();
+ list_for_each_entry_rcu(ifa, &idev6->addr_list, if_list) {
if (ifa->flags & (IFA_F_TENTATIVE |
IFA_F_DEPRECATED))
continue;
memcpy(ipv6_addr, ifa->addr.s6_addr, 16);
break;
}
+ rcu_read_unlock();
sockaddr_storage->addr6.ScopeId = 0;
nbytes += sizeof(struct network_interface_info_ioctl_rsp);
}