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

Merge branch 'fix-sctp-diag-locking-issues'

Stefan Wiehler says:

====================
Fix SCTP diag locking issues

- Hold RCU read lock while iterating over address list in
inet_diag_msg_sctpaddrs_fill()
- Prevent TOCTOU out-of-bounds write
- Hold sock lock while iterating over address list in sctp_sock_dump_one()
====================

Link: https://patch.msgid.link/20251028161506.3294376-1-stefan.wiehler@nokia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+17 -6
+17 -6
net/sctp/diag.c
··· 73 73 struct nlattr *attr; 74 74 void *info = NULL; 75 75 76 + rcu_read_lock(); 76 77 list_for_each_entry_rcu(laddr, address_list, list) 77 78 addrcnt++; 79 + rcu_read_unlock(); 78 80 79 81 attr = nla_reserve(skb, INET_DIAG_LOCALS, addrlen * addrcnt); 80 82 if (!attr) 81 83 return -EMSGSIZE; 82 84 83 85 info = nla_data(attr); 86 + rcu_read_lock(); 84 87 list_for_each_entry_rcu(laddr, address_list, list) { 85 88 memcpy(info, &laddr->a, sizeof(laddr->a)); 86 89 memset(info + sizeof(laddr->a), 0, addrlen - sizeof(laddr->a)); 87 90 info += addrlen; 91 + 92 + if (!--addrcnt) 93 + break; 88 94 } 95 + rcu_read_unlock(); 89 96 90 97 return 0; 91 98 } ··· 230 223 bool net_admin; 231 224 }; 232 225 233 - static size_t inet_assoc_attr_size(struct sctp_association *asoc) 226 + static size_t inet_assoc_attr_size(struct sock *sk, 227 + struct sctp_association *asoc) 234 228 { 235 229 int addrlen = sizeof(struct sockaddr_storage); 236 230 int addrcnt = 0; 237 231 struct sctp_sockaddr_entry *laddr; 238 232 239 233 list_for_each_entry_rcu(laddr, &asoc->base.bind_addr.address_list, 240 - list) 234 + list, lockdep_sock_is_held(sk)) 241 235 addrcnt++; 242 236 243 237 return nla_total_size(sizeof(struct sctp_info)) ··· 264 256 if (err) 265 257 return err; 266 258 267 - rep = nlmsg_new(inet_assoc_attr_size(assoc), GFP_KERNEL); 268 - if (!rep) 269 - return -ENOMEM; 270 - 271 259 lock_sock(sk); 260 + 261 + rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL); 262 + if (!rep) { 263 + release_sock(sk); 264 + return -ENOMEM; 265 + } 266 + 272 267 if (ep != assoc->ep) { 273 268 err = -EAGAIN; 274 269 goto out;