Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mptcp: fix lockless access in subflow ULP diag

Since the introduction of the subflow ULP diag interface, the
dump callback accessed all the subflow data with lockless.

We need either to annotate all the read and write operation accordingly,
or acquire the subflow socket lock. Let's do latter, even if slower, to
avoid a diffstat havoc.

Fixes: 5147dfb50832 ("mptcp: allow dumping subflow context to userspace")
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Paolo Abeni and committed by
David S. Miller
b8adb69a 584f3894

+7 -3
+1 -1
include/net/tcp.h
··· 2506 2506 /* cleanup ulp */ 2507 2507 void (*release)(struct sock *sk); 2508 2508 /* diagnostic */ 2509 - int (*get_info)(const struct sock *sk, struct sk_buff *skb); 2509 + int (*get_info)(struct sock *sk, struct sk_buff *skb); 2510 2510 size_t (*get_info_size)(const struct sock *sk); 2511 2511 /* clone ulp */ 2512 2512 void (*clone)(const struct request_sock *req, struct sock *newsk,
+5 -1
net/mptcp/diag.c
··· 13 13 #include <uapi/linux/mptcp.h> 14 14 #include "protocol.h" 15 15 16 - static int subflow_get_info(const struct sock *sk, struct sk_buff *skb) 16 + static int subflow_get_info(struct sock *sk, struct sk_buff *skb) 17 17 { 18 18 struct mptcp_subflow_context *sf; 19 19 struct nlattr *start; 20 20 u32 flags = 0; 21 + bool slow; 21 22 int err; 22 23 23 24 start = nla_nest_start_noflag(skb, INET_ULP_INFO_MPTCP); 24 25 if (!start) 25 26 return -EMSGSIZE; 26 27 28 + slow = lock_sock_fast(sk); 27 29 rcu_read_lock(); 28 30 sf = rcu_dereference(inet_csk(sk)->icsk_ulp_data); 29 31 if (!sf) { ··· 71 69 } 72 70 73 71 rcu_read_unlock(); 72 + unlock_sock_fast(sk, slow); 74 73 nla_nest_end(skb, start); 75 74 return 0; 76 75 77 76 nla_failure: 78 77 rcu_read_unlock(); 78 + unlock_sock_fast(sk, slow); 79 79 nla_nest_cancel(skb, start); 80 80 return err; 81 81 }
+1 -1
net/tls/tls_main.c
··· 1003 1003 return 0; 1004 1004 } 1005 1005 1006 - static int tls_get_info(const struct sock *sk, struct sk_buff *skb) 1006 + static int tls_get_info(struct sock *sk, struct sk_buff *skb) 1007 1007 { 1008 1008 u16 version, cipher_type; 1009 1009 struct tls_context *ctx;