bd2f1e
From d6f4bdc3bca4ddcdc60c0544d85ecf7670ee1c53 Mon Sep 17 00:00:00 2001
bd2f1e
From: Duoming Zhou <duoming@zju.edu.cn>
bd2f1e
Date: Sat, 26 Mar 2022 18:43:46 +0800
bd2f1e
Subject: [PATCH] net/x25: Fix null-ptr-deref caused by x25_disconnect
bd2f1e
Git-commit: 7781607938c8371d4c2b243527430241c62e39c2
bd2f1e
Patch-mainline: v5.18-rc1
bd2f1e
References: CVE-2022-1516 bsc#1199012
bd2f1e
bd2f1e
When the link layer is terminating, x25->neighbour will be set to NULL
bd2f1e
in x25_disconnect(). As a result, it could cause null-ptr-deref bugs in
bd2f1e
x25_sendmsg(),x25_recvmsg() and x25_connect(). One of the bugs is
bd2f1e
shown below.
bd2f1e
bd2f1e
    (Thread 1)                 |  (Thread 2)
bd2f1e
x25_link_terminated()          | x25_recvmsg()
bd2f1e
 x25_kill_by_neigh()           |  ...
bd2f1e
  x25_disconnect()             |  lock_sock(sk)
bd2f1e
   ...                         |  ...
bd2f1e
   x25->neighbour = NULL //(1) |
bd2f1e
   ...                         |  x25->neighbour->extended //(2)
bd2f1e
bd2f1e
The code sets NULL to x25->neighbour in position (1) and dereferences
bd2f1e
x25->neighbour in position (2), which could cause null-ptr-deref bug.
bd2f1e
bd2f1e
This patch adds lock_sock() in x25_kill_by_neigh() in order to synchronize
bd2f1e
with x25_sendmsg(), x25_recvmsg() and x25_connect(). What`s more, the
bd2f1e
sock held by lock_sock() is not NULL, because it is extracted from x25_list
bd2f1e
and uses x25_list_lock to synchronize.
bd2f1e
bd2f1e
Fixes: 4becb7ee5b3d ("net/x25: Fix x25_neigh refcnt leak when x25 disconnect")
bd2f1e
Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
bd2f1e
Reviewed-by: Lin Ma <linma@zju.edu.cn>
bd2f1e
Signed-off-by: David S. Miller <davem@davemloft.net>
bd2f1e
Signed-off-by: Denis Kirjanov <denis.kirjanov@suse.com>
bd2f1e
---
bd2f1e
 net/x25/af_x25.c | 11 ++++++++---
bd2f1e
 1 file changed, 8 insertions(+), 3 deletions(-)
bd2f1e
bd2f1e
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
bd2f1e
index b7e91af375a9..bdf6e80c8597 100644
bd2f1e
--- a/net/x25/af_x25.c
bd2f1e
+++ b/net/x25/af_x25.c
bd2f1e
@@ -1789,10 +1789,15 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
bd2f1e
 
bd2f1e
 	write_lock_bh(&x25_list_lock);
bd2f1e
 
bd2f1e
-	sk_for_each(s, &x25_list)
bd2f1e
-		if (x25_sk(s)->neighbour == nb)
bd2f1e
+	sk_for_each(s, &x25_list) {
bd2f1e
+		if (x25_sk(s)->neighbour == nb) {
bd2f1e
+			write_unlock_bh(&x25_list_lock);
bd2f1e
+			lock_sock(s);
bd2f1e
 			x25_disconnect(s, ENETUNREACH, 0, 0);
bd2f1e
-
bd2f1e
+			release_sock(s);
bd2f1e
+			write_lock_bh(&x25_list_lock);
bd2f1e
+		}
bd2f1e
+	}
bd2f1e
 	write_unlock_bh(&x25_list_lock);
bd2f1e
 
bd2f1e
 	/* Remove any related forwards */
bd2f1e
-- 
bd2f1e
2.16.4
bd2f1e