From 13a3585b264bfeba018941a713b8d7fc9b8221a2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Mar 2022 20:25:18 +0100 Subject: [PATCH 1/6] nfc: llcp: nullify llcp_sock->dev on connect() error paths Nullify the llcp_sock->dev on llcp_sock_connect() error paths, symmetrically to the code llcp_sock_bind(). The non-NULL value of llcp_sock->dev is used in a few places to check whether the socket is still valid. There was no particular issue observed with missing NULL assignment in connect() error path, however a similar case - in the bind() error path - was triggereable. That one was fixed in commit 4ac06a1e013c ("nfc: fix NULL ptr dereference in llcp_sock_getname() after failed connect"), so the change here seems logical as well. Signed-off-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 0b93a17b9f11..e92440c0c4c7 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -764,6 +764,7 @@ sock_llcp_release: llcp_sock->local = NULL; put_dev: + llcp_sock->dev = NULL; nfc_put_device(dev); error: From ec10fd154d934cc4195da3cbd017a12817b41d51 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Mar 2022 20:25:19 +0100 Subject: [PATCH 2/6] nfc: llcp: simplify llcp_sock_connect() error paths The llcp_sock_connect() error paths were using a mixed way of central exit (goto) and cleanup Signed-off-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index e92440c0c4c7..fdf0856182c6 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -712,10 +712,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, llcp_sock->local = nfc_llcp_local_get(local); llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { - nfc_llcp_local_put(llcp_sock->local); - llcp_sock->local = NULL; ret = -ENOMEM; - goto put_dev; + goto sock_llcp_put_local; } llcp_sock->reserved_ssap = llcp_sock->ssap; @@ -760,11 +758,13 @@ sock_unlink: sock_llcp_release: nfc_llcp_put_ssap(local, llcp_sock->ssap); + +sock_llcp_put_local: nfc_llcp_local_put(llcp_sock->local); llcp_sock->local = NULL; + llcp_sock->dev = NULL; put_dev: - llcp_sock->dev = NULL; nfc_put_device(dev); error: From 4dbbf673f7d711e3f26396c43cbd391dc8f6c354 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Mar 2022 20:25:20 +0100 Subject: [PATCH 3/6] nfc: llcp: use centralized exiting of bind on errors Coding style encourages centralized exiting of functions, so rewrite llcp_sock_bind() error paths to use such pattern. This reduces the duplicated cleanup code, make success path visually shorter and also cleans up the errors in proper order (in reversed way from initialization). No functional impact expected. Signed-off-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index fdf0856182c6..c9d5c427f035 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -108,21 +108,13 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) llcp_sock->service_name_len, GFP_KERNEL); if (!llcp_sock->service_name) { - nfc_llcp_local_put(llcp_sock->local); - llcp_sock->local = NULL; - llcp_sock->dev = NULL; ret = -ENOMEM; - goto put_dev; + goto sock_llcp_put_local; } llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); if (llcp_sock->ssap == LLCP_SAP_MAX) { - nfc_llcp_local_put(llcp_sock->local); - llcp_sock->local = NULL; - kfree(llcp_sock->service_name); - llcp_sock->service_name = NULL; - llcp_sock->dev = NULL; ret = -EADDRINUSE; - goto put_dev; + goto free_service_name; } llcp_sock->reserved_ssap = llcp_sock->ssap; @@ -132,6 +124,19 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) pr_debug("Socket bound to SAP %d\n", llcp_sock->ssap); sk->sk_state = LLCP_BOUND; + nfc_put_device(dev); + release_sock(sk); + + return 0; + +free_service_name: + kfree(llcp_sock->service_name); + llcp_sock->service_name = NULL; + +sock_llcp_put_local: + nfc_llcp_local_put(llcp_sock->local); + llcp_sock->local = NULL; + llcp_sock->dev = NULL; put_dev: nfc_put_device(dev); From a736491239f4b434fc76a2ba0c1bdb8eaf9eb792 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Mar 2022 20:25:21 +0100 Subject: [PATCH 4/6] nfc: llcp: use test_bit() Use test_bit() instead of open-coding it, just like in other places touching the bitmap. Signed-off-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- net/nfc/llcp_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 5ad5157aa9c5..b70d5042bf74 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -383,7 +383,7 @@ u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, pr_debug("WKS %d\n", ssap); /* This is a WKS, let's check if it's free */ - if (local->local_wks & BIT(ssap)) { + if (test_bit(ssap, &local->local_wks)) { mutex_unlock(&local->sdp_lock); return LLCP_SAP_MAX; From a06b8044169f6d5c3eb34772c13d2c0c1b205352 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Mar 2022 20:25:22 +0100 Subject: [PATCH 5/6] nfc: llcp: protect nfc_llcp_sock_unlink() calls nfc_llcp_sock_link() is called in all paths (bind/connect) as a last action, still protected with lock_sock(). When cleaning up in llcp_sock_release(), call nfc_llcp_sock_unlink() in a mirrored way: earlier and still under the lock_sock(). Signed-off-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index c9d5c427f035..5c5705f5028b 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -631,6 +631,11 @@ static int llcp_sock_release(struct socket *sock) } } + if (sock->type == SOCK_RAW) + nfc_llcp_sock_unlink(&local->raw_sockets, sk); + else + nfc_llcp_sock_unlink(&local->sockets, sk); + if (llcp_sock->reserved_ssap < LLCP_SAP_MAX) nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); @@ -643,11 +648,6 @@ static int llcp_sock_release(struct socket *sock) if (sk->sk_state == LLCP_DISCONNECTING) return err; - if (sock->type == SOCK_RAW) - nfc_llcp_sock_unlink(&local->raw_sockets, sk); - else - nfc_llcp_sock_unlink(&local->sockets, sk); - out: sock_orphan(sk); sock_put(sk); From 44cd5765495b30bc2527463f4a4b8c028e11535b Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 2 Mar 2022 20:25:23 +0100 Subject: [PATCH 6/6] nfc: llcp: Revert "NFC: Keep socket alive until the DISC PDU is actually sent" This reverts commit 17f7ae16aef1f58bc4af4c7a16b8778a91a30255. The commit brought a new socket state LLCP_DISCONNECTING, which was never set, only read, so socket could never set to such state. Remove the dead code. Signed-off-by: Krzysztof Kozlowski Signed-off-by: David S. Miller --- net/nfc/llcp.h | 1 - net/nfc/llcp_core.c | 7 ------- net/nfc/llcp_sock.c | 7 ------- 3 files changed, 15 deletions(-) diff --git a/net/nfc/llcp.h b/net/nfc/llcp.h index d49d4bf2e37c..c1d9be636933 100644 --- a/net/nfc/llcp.h +++ b/net/nfc/llcp.h @@ -6,7 +6,6 @@ enum llcp_state { LLCP_CONNECTED = 1, /* wait_for_packet() wants that */ LLCP_CONNECTING, - LLCP_DISCONNECTING, LLCP_CLOSED, LLCP_BOUND, LLCP_LISTEN, diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index b70d5042bf74..3364caabef8b 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c @@ -737,13 +737,6 @@ static void nfc_llcp_tx_work(struct work_struct *work) print_hex_dump_debug("LLCP Tx: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, skb->len, true); - if (ptype == LLCP_PDU_DISC && sk != NULL && - sk->sk_state == LLCP_DISCONNECTING) { - nfc_llcp_sock_unlink(&local->sockets, sk); - sock_orphan(sk); - sock_put(sk); - } - if (ptype == LLCP_PDU_I) copy_skb = skb_copy(skb, GFP_ATOMIC); diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 5c5705f5028b..4ca35791c93b 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -641,13 +641,6 @@ static int llcp_sock_release(struct socket *sock) release_sock(sk); - /* Keep this sock alive and therefore do not remove it from the sockets - * list until the DISC PDU has been actually sent. Otherwise we would - * reply with DM PDUs before sending the DISC one. - */ - if (sk->sk_state == LLCP_DISCONNECTING) - return err; - out: sock_orphan(sk); sock_put(sk);