mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-07-06 22:05:22 +02:00
net: nfc: fix races in nfc_llcp_sock_get() and nfc_llcp_sock_get_sn()
[ Upstream commit31c07dffaf
] 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:8f50020ed9
("NFC: LLCP late binding") Reported-by: Sili Luo <rootlab@huawei.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Willy Tarreau <w@1wt.eu> Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org> Link: https://lore.kernel.org/r/20231009123110.3735515-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
cf5b41a81f
commit
d1af8a39cf
|
@ -203,17 +203,13 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local,
|
||||||
|
|
||||||
if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) {
|
if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) {
|
||||||
llcp_sock = tmp_sock;
|
llcp_sock = tmp_sock;
|
||||||
|
sock_hold(&llcp_sock->sk);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
read_unlock(&local->sockets.lock);
|
read_unlock(&local->sockets.lock);
|
||||||
|
|
||||||
if (llcp_sock == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sock_hold(&llcp_sock->sk);
|
|
||||||
|
|
||||||
return llcp_sock;
|
return llcp_sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,7 +342,8 @@ static int nfc_llcp_wks_sap(const char *service_name, size_t service_name_len)
|
||||||
|
|
||||||
static
|
static
|
||||||
struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
|
struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local,
|
||||||
const u8 *sn, size_t sn_len)
|
const u8 *sn, size_t sn_len,
|
||||||
|
bool needref)
|
||||||
{
|
{
|
||||||
struct sock *sk;
|
struct sock *sk;
|
||||||
struct nfc_llcp_sock *llcp_sock, *tmp_sock;
|
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,
|
||||||
|
|
||||||
if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) {
|
if (memcmp(sn, tmp_sock->service_name, sn_len) == 0) {
|
||||||
llcp_sock = tmp_sock;
|
llcp_sock = tmp_sock;
|
||||||
|
if (needref)
|
||||||
|
sock_hold(&llcp_sock->sk);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,7 +422,8 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
|
||||||
* to this service name.
|
* to this service name.
|
||||||
*/
|
*/
|
||||||
if (nfc_llcp_sock_from_sn(local, sock->service_name,
|
if (nfc_llcp_sock_from_sn(local, sock->service_name,
|
||||||
sock->service_name_len) != NULL) {
|
sock->service_name_len,
|
||||||
|
false) != NULL) {
|
||||||
mutex_unlock(&local->sdp_lock);
|
mutex_unlock(&local->sdp_lock);
|
||||||
|
|
||||||
return LLCP_SAP_MAX;
|
return LLCP_SAP_MAX;
|
||||||
|
@ -824,16 +824,7 @@ out:
|
||||||
static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
|
static struct nfc_llcp_sock *nfc_llcp_sock_get_sn(struct nfc_llcp_local *local,
|
||||||
const u8 *sn, size_t sn_len)
|
const u8 *sn, size_t sn_len)
|
||||||
{
|
{
|
||||||
struct nfc_llcp_sock *llcp_sock;
|
return nfc_llcp_sock_from_sn(local, sn, sn_len, true);
|
||||||
|
|
||||||
llcp_sock = nfc_llcp_sock_from_sn(local, sn, sn_len);
|
|
||||||
|
|
||||||
if (llcp_sock == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sock_hold(&llcp_sock->sk);
|
|
||||||
|
|
||||||
return llcp_sock;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const u8 *nfc_llcp_connect_sn(const struct sk_buff *skb, size_t *sn_len)
|
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,
|
||||||
}
|
}
|
||||||
|
|
||||||
llcp_sock = nfc_llcp_sock_from_sn(local, service_name,
|
llcp_sock = nfc_llcp_sock_from_sn(local, service_name,
|
||||||
service_name_len);
|
service_name_len,
|
||||||
|
true);
|
||||||
if (!llcp_sock) {
|
if (!llcp_sock) {
|
||||||
sap = 0;
|
sap = 0;
|
||||||
goto add_snl;
|
goto add_snl;
|
||||||
|
@ -1318,6 +1310,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
|
||||||
|
|
||||||
if (sap == LLCP_SAP_MAX) {
|
if (sap == LLCP_SAP_MAX) {
|
||||||
sap = 0;
|
sap = 0;
|
||||||
|
nfc_llcp_sock_put(llcp_sock);
|
||||||
goto add_snl;
|
goto add_snl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1335,6 +1328,7 @@ static void nfc_llcp_recv_snl(struct nfc_llcp_local *local,
|
||||||
|
|
||||||
pr_debug("%p %d\n", llcp_sock, sap);
|
pr_debug("%p %d\n", llcp_sock, sap);
|
||||||
|
|
||||||
|
nfc_llcp_sock_put(llcp_sock);
|
||||||
add_snl:
|
add_snl:
|
||||||
sdp = nfc_llcp_build_sdres_tlv(tid, sap);
|
sdp = nfc_llcp_build_sdres_tlv(tid, sap);
|
||||||
if (sdp == NULL)
|
if (sdp == NULL)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user