Skip to content

Commit 31c07df

Browse files
Eric Dumazetkuba-moo
authored andcommitted
net: nfc: fix races in nfc_llcp_sock_get() and nfc_llcp_sock_get_sn()
Sili Luo reported a race in nfc_llcp_sock_get(), leading to UAF. Getting a reference on the socket found in a lookup while holding a lock should happen before releasing the lock. nfc_llcp_sock_get_sn() has a similar problem. Finally nfc_llcp_recv_snl() needs to make sure the socket found by nfc_llcp_sock_from_sn() does not disappear. Fixes: 8f50020 ("NFC: LLCP late binding") Reported-by: Sili Luo <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Cc: Willy Tarreau <[email protected]> Reviewed-by: Krzysztof Kozlowski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 5093bbf commit 31c07df

File tree

1 file changed

+12
-18
lines changed

1 file changed

+12
-18
lines changed

net/nfc/llcp_core.c

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -203,17 +203,13 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
203203

204204
if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) {
205205
llcp_sock = tmp_sock;
206+
sock_hold(&llcp_sock->sk);
206207
break;
207208
}
208209
}
209210

210211
read_unlock(&local->sockets.lock);
211212

212-
if (llcp_sock == NULL)
213-
return NULL;
214-
215-
sock_hold(&llcp_sock->sk);
216-
217213
return llcp_sock;
218214
}
219215

@@ -346,7 +342,8 @@ static int nfc_llcp_wks_sap(const char *service_name, size_t service_name_len)
346342

347343
static
348344
struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
349-
const u8 *sn, size_t sn_len)
345+
const u8 *sn, size_t sn_len,
346+
bool needref)
350347
{
351348
struct sock *sk;
352349
struct nfc_llcp_sock *llcp_sock, *tmp_sock;
@@ -382,6 +379,8 @@ struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
382379

383380
if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) {
384381
llcp_sock = tmp_sock;
382+
if (needref)
383+
sock_hold(&llcp_sock->sk);
385384
break;
386385
}
387386
}
@@ -423,7 +422,8 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
423422
* to this service name.
424423
*/
425424
if (nfc_llcp_sock_from_sn(local, sock->service_name,
426-
sock->service_name_len) != NULL) {
425+
sock->service_name_len,
426+
false) != NULL) {
427427
mutex_unlock(&local->sdp_lock);
428428

429429
return LLCP_SAP_MAX;
@@ -824,16 +824,7 @@ static struct nfc_llcp_sock *nfc_llcp_connecting_sock_get(struct nfc_llcp_local
824824
static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
825825
const u8 *sn, size_t sn_len)
826826
{
827-
struct nfc_llcp_sock *llcp_sock;
828-
829-
llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len);
830-
831-
if (llcp_sock == NULL)
832-
return NULL;
833-
834-
sock_hold(&llcp_sock->sk);
835-
836-
return llcp_sock;
827+
return nfc_llcp_sock_from_sn(local, sn, sn_len, true);
837828
}
838829

839830
static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len)
@@ -1298,7 +1289,8 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
12981289
}
12991290

13001291
llcp_sock = nfc_llcp_sock_from_sn(local, service_name,
1301-
service_name_len);
1292+
service_name_len,
1293+
true);
13021294
if (!llcp_sock) {
13031295
sap = 0;
13041296
goto add_snl;
@@ -1318,6 +1310,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
13181310

13191311
if (sap == LLCP_SAP_MAX) {
13201312
sap = 0;
1313+
nfc_llcp_sock_put(llcp_sock);
13211314
goto add_snl;
13221315
}
13231316

@@ -1335,6 +1328,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
13351328

13361329
pr_debug("%p %d\n", llcp_sock, sap);
13371330

1331+
nfc_llcp_sock_put(llcp_sock);
13381332
add_snl:
13391333
sdp = nfc_llcp_build_sdres_tlv(tid, sap);
13401334
if (sdp == NULL)

0 commit comments

Comments
 (0)