Patch "l2tp: Serialize access to sk_user_data with sk_callback_lock" has been added to the 5.10-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    l2tp: Serialize access to sk_user_data with sk_callback_lock

to the 5.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     l2tp-serialize-access-to-sk_user_data-with-sk_callba.patch
and it can be found in the queue-5.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 6e121ef3f53982e168e775c4dececf3a2556c0fb
Author: Jakub Sitnicki <jakub@xxxxxxxxxxxxxx>
Date:   Mon Nov 14 20:16:19 2022 +0100

    l2tp: Serialize access to sk_user_data with sk_callback_lock
    
    [ Upstream commit b68777d54fac21fc833ec26ea1a2a84f975ab035 ]
    
    sk->sk_user_data has multiple users, which are not compatible with each
    other. Writers must synchronize by grabbing the sk->sk_callback_lock.
    
    l2tp currently fails to grab the lock when modifying the underlying tunnel
    socket fields. Fix it by adding appropriate locking.
    
    We err on the side of safety and grab the sk_callback_lock also inside the
    sk_destruct callback overridden by l2tp, even though there should be no
    refs allowing access to the sock at the time when sk_destruct gets called.
    
    v4:
    - serialize write to sk_user_data in l2tp sk_destruct
    
    v3:
    - switch from sock lock to sk_callback_lock
    - document write-protection for sk_user_data
    
    v2:
    - update Fixes to point to origin of the bug
    - use real names in Reported/Tested-by tags
    
    Cc: Tom Parkin <tparkin@xxxxxxxxxxx>
    Fixes: 3557baabf280 ("[L2TP]: PPP over L2TP driver core")
    Reported-by: Haowei Yan <g1042620637@xxxxxxxxx>
    Signed-off-by: Jakub Sitnicki <jakub@xxxxxxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/include/net/sock.h b/include/net/sock.h
index 90a8b8b26a20..69bbbe8bbf34 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -315,7 +315,7 @@ struct bpf_local_storage;
   *	@sk_tskey: counter to disambiguate concurrent tstamp requests
   *	@sk_zckey: counter to order MSG_ZEROCOPY notifications
   *	@sk_socket: Identd and reporting IO signals
-  *	@sk_user_data: RPC layer private data
+  *	@sk_user_data: RPC layer private data. Write-protected by @sk_callback_lock.
   *	@sk_frag: cached page frag
   *	@sk_peek_off: current peek_offset value
   *	@sk_send_head: front of stuff to transmit
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index dc8987ed08ad..e89852bc5309 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1150,8 +1150,10 @@ static void l2tp_tunnel_destruct(struct sock *sk)
 	}
 
 	/* Remove hooks into tunnel socket */
+	write_lock_bh(&sk->sk_callback_lock);
 	sk->sk_destruct = tunnel->old_sk_destruct;
 	sk->sk_user_data = NULL;
+	write_unlock_bh(&sk->sk_callback_lock);
 
 	/* Call the original destructor */
 	if (sk->sk_destruct)
@@ -1471,16 +1473,18 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 		sock = sockfd_lookup(tunnel->fd, &ret);
 		if (!sock)
 			goto err;
-
-		ret = l2tp_validate_socket(sock->sk, net, tunnel->encap);
-		if (ret < 0)
-			goto err_sock;
 	}
 
+	sk = sock->sk;
+	write_lock(&sk->sk_callback_lock);
+
+	ret = l2tp_validate_socket(sk, net, tunnel->encap);
+	if (ret < 0)
+		goto err_sock;
+
 	tunnel->l2tp_net = net;
 	pn = l2tp_pernet(net);
 
-	sk = sock->sk;
 	sock_hold(sk);
 	tunnel->sock = sk;
 
@@ -1506,7 +1510,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 
 		setup_udp_tunnel_sock(net, sock, &udp_cfg);
 	} else {
-		sk->sk_user_data = tunnel;
+		rcu_assign_sk_user_data(sk, tunnel);
 	}
 
 	tunnel->old_sk_destruct = sk->sk_destruct;
@@ -1520,6 +1524,7 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 	if (tunnel->fd >= 0)
 		sockfd_put(sock);
 
+	write_unlock(&sk->sk_callback_lock);
 	return 0;
 
 err_sock:
@@ -1527,6 +1532,8 @@ int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net,
 		sock_release(sock);
 	else
 		sockfd_put(sock);
+
+	write_unlock(&sk->sk_callback_lock);
 err:
 	return ret;
 }



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux