diff options
| author | Breno Leitao <leitao@debian.org> | 2026-05-21 07:32:10 -0700 |
|---|---|---|
| committer | David Heidelberg <david@ixit.cz> | 2026-07-26 21:26:03 +0200 |
| commit | 75fa10dbc2f58c218263ee17fd3724c3f06308f4 (patch) | |
| tree | 1ecc6f8c1d870bf2494b0a4de38f39a1fd23b19c | |
| parent | 9e84e07b205740b07f6769dcf6945560e282075c (diff) | |
| download | linux-next-75fa10dbc2f58c218263ee17fd3724c3f06308f4.tar.gz linux-next-75fa10dbc2f58c218263ee17fd3724c3f06308f4.zip | |
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>
| -rw-r--r-- | net/nfc/llcp_sock.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 4b162df0c3fc..5558d8a4d48b 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; |
