aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
authorBreno Leitao <leitao@debian.org>2026-05-21 07:32:10 -0700
committerDavid Heidelberg <david@ixit.cz>2026-05-29 12:52:08 +0200
commit94a82f1f0628840453de82335a6de5ad6d598483 (patch)
treeabaf8073bbccea8217daa65e7998a5495fed4cad /net
parent929173aaa7a8912ab770c373a13edac6ca7af40f (diff)
downloadlinux-next-history-94a82f1f0628840453de82335a6de5ad6d598483.tar.gz
nfc: llcp: read llcp_sock->local under the socket lock in getsockopt
nfc_llcp_getsockopt() read llcp_sock->local before lock_sock(sk) and then dereferenced the cached pointer inside the locked region. llcp_sock_bind() assigns and clears llcp_sock->local under the same socket lock, dropping the last reference on its error path. A getsockopt() racing an in-flight bind() can observe the pointer, block on lock_sock(), and then dereference a freed nfc_llcp_local once bind() has unwound. Move the llcp_sock->local read and the NULL check inside the lock_sock(sk) region so bind() cannot mutate or free the pointer between the load and the use. Fixes: 26fd76cab2e6 ("NFC: llcp: Implement socket options") Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20260521-fix_llc-v2-2-ab44cc09179c@debian.org Signed-off-by: David Heidelberg <david@ixit.cz>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/llcp_sock.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index 4b162df0c3fcb..5558d8a4d48b3 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -325,14 +325,16 @@ static int nfc_llcp_getsockopt(struct socket *sock, int level, int optname,
if (len < sizeof(u32))
return -EINVAL;
- local = llcp_sock->local;
- if (!local)
- return -ENODEV;
-
len = min_t(u32, len, sizeof(u32));
lock_sock(sk);
+ local = llcp_sock->local;
+ if (!local) {
+ release_sock(sk);
+ return -ENODEV;
+ }
+
switch (optname) {
case NFC_LLCP_RW:
rw = llcp_sock->rw > LLCP_MAX_RW ? local->rw : llcp_sock->rw;