Thomas Bogendoerfer 28b972
From: John Fastabend <john.fastabend@gmail.com>
Thomas Bogendoerfer 28b972
Date: Thu, 21 Nov 2019 08:25:09 -0800
Thomas Bogendoerfer 28b972
Subject: bpf: skmsg, fix potential psock NULL pointer dereference
Thomas Bogendoerfer 28b972
Patch-mainline: v5.5-rc1
Thomas Bogendoerfer 28b972
Git-commit: 8163999db445021f2651a8a47b5632483e8722ea
Thomas Bogendoerfer 28b972
References: bsc#1109837
Thomas Bogendoerfer 28b972
Thomas Bogendoerfer 28b972
Report from Dan Carpenter,
Thomas Bogendoerfer 28b972
Thomas Bogendoerfer 28b972
 net/core/skmsg.c:792 sk_psock_write_space()
Thomas Bogendoerfer 28b972
 error: we previously assumed 'psock' could be null (see line 790)
Thomas Bogendoerfer 28b972
Thomas Bogendoerfer 28b972
 net/core/skmsg.c
Thomas Bogendoerfer 28b972
   789 psock = sk_psock(sk);
Thomas Bogendoerfer 28b972
   790 if (likely(psock && sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)))
Thomas Bogendoerfer 28b972
 Check for NULL
Thomas Bogendoerfer 28b972
   791 schedule_work(&psock->work);
Thomas Bogendoerfer 28b972
   792 write_space = psock->saved_write_space;
Thomas Bogendoerfer 28b972
                     ^^^^^^^^^^^^^^^^^^^^^^^^
Thomas Bogendoerfer 28b972
   793          rcu_read_unlock();
Thomas Bogendoerfer 28b972
   794          write_space(sk);
Thomas Bogendoerfer 28b972
Thomas Bogendoerfer 28b972
Ensure psock dereference on line 792 only occurs if psock is not null.
Thomas Bogendoerfer 28b972
Thomas Bogendoerfer 28b972
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Thomas Bogendoerfer 28b972
Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
Thomas Bogendoerfer 28b972
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Thomas Bogendoerfer 28b972
Signed-off-by: David S. Miller <davem@davemloft.net>
Thomas Bogendoerfer 28b972
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Thomas Bogendoerfer 28b972
---
Thomas Bogendoerfer 28b972
 net/core/skmsg.c |   13 ++++++++-----
Thomas Bogendoerfer 28b972
 1 file changed, 8 insertions(+), 5 deletions(-)
Thomas Bogendoerfer 28b972
Thomas Bogendoerfer 28b972
--- a/net/core/skmsg.c
Thomas Bogendoerfer 28b972
+++ b/net/core/skmsg.c
Thomas Bogendoerfer 28b972
@@ -757,15 +757,18 @@ static void sk_psock_strp_data_ready(str
Thomas Bogendoerfer 28b972
 static void sk_psock_write_space(struct sock *sk)
Thomas Bogendoerfer 28b972
 {
Thomas Bogendoerfer 28b972
 	struct sk_psock *psock;
Thomas Bogendoerfer 28b972
-	void (*write_space)(struct sock *sk);
Thomas Bogendoerfer 28b972
+	void (*write_space)(struct sock *sk) = NULL;
Thomas Bogendoerfer 28b972
 
Thomas Bogendoerfer 28b972
 	rcu_read_lock();
Thomas Bogendoerfer 28b972
 	psock = sk_psock(sk);
Thomas Bogendoerfer 28b972
-	if (likely(psock && sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)))
Thomas Bogendoerfer 28b972
-		schedule_work(&psock->work);
Thomas Bogendoerfer 28b972
-	write_space = psock->saved_write_space;
Thomas Bogendoerfer 28b972
+	if (likely(psock)) {
Thomas Bogendoerfer 28b972
+		if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
Thomas Bogendoerfer 28b972
+			schedule_work(&psock->work);
Thomas Bogendoerfer 28b972
+		write_space = psock->saved_write_space;
Thomas Bogendoerfer 28b972
+	}
Thomas Bogendoerfer 28b972
 	rcu_read_unlock();
Thomas Bogendoerfer 28b972
-	write_space(sk);
Thomas Bogendoerfer 28b972
+	if (write_space)
Thomas Bogendoerfer 28b972
+		write_space(sk);
Thomas Bogendoerfer 28b972
 }
Thomas Bogendoerfer 28b972
 
Thomas Bogendoerfer 28b972
 int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)