summaryrefslogtreecommitdiffstats
path: root/sctp-do-not-peel-off-an-assoc-from-one-netns-to-another-one.patch
diff options
context:
space:
mode:
Diffstat (limited to 'sctp-do-not-peel-off-an-assoc-from-one-netns-to-another-one.patch')
-rw-r--r--sctp-do-not-peel-off-an-assoc-from-one-netns-to-another-one.patch62
1 files changed, 62 insertions, 0 deletions
diff --git a/sctp-do-not-peel-off-an-assoc-from-one-netns-to-another-one.patch b/sctp-do-not-peel-off-an-assoc-from-one-netns-to-another-one.patch
new file mode 100644
index 000000000..d44f6cc28
--- /dev/null
+++ b/sctp-do-not-peel-off-an-assoc-from-one-netns-to-another-one.patch
@@ -0,0 +1,62 @@
+From df80cd9b28b9ebaa284a41df611dbf3a2d05ca74 Mon Sep 17 00:00:00 2001
+From: Xin Long <lucien.xin@gmail.com>
+Date: Tue, 17 Oct 2017 23:26:10 +0800
+Subject: sctp: do not peel off an assoc from one netns to another one
+
+Now when peeling off an association to the sock in another netns, all
+transports in this assoc are not to be rehashed and keep use the old
+key in hashtable.
+
+As a transport uses sk->net as the hash key to insert into hashtable,
+it would miss removing these transports from hashtable due to the new
+netns when closing the sock and all transports are being freeed, then
+later an use-after-free issue could be caused when looking up an asoc
+and dereferencing those transports.
+
+This is a very old issue since very beginning, ChunYu found it with
+syzkaller fuzz testing with this series:
+
+ socket$inet6_sctp()
+ bind$inet6()
+ sendto$inet6()
+ unshare(0x40000000)
+ getsockopt$inet_sctp6_SCTP_GET_ASSOC_ID_LIST()
+ getsockopt$inet_sctp6_SCTP_SOCKOPT_PEELOFF()
+
+This patch is to block this call when peeling one assoc off from one
+netns to another one, so that the netns of all transport would not
+go out-sync with the key in hashtable.
+
+Note that this patch didn't fix it by rehashing transports, as it's
+difficult to handle the situation when the tuple is already in use
+in the new netns. Besides, no one would like to peel off one assoc
+to another netns, considering ipaddrs, ifaces, etc. are usually
+different.
+
+Reported-by: ChunYu Wang <chunwang@redhat.com>
+Signed-off-by: Xin Long <lucien.xin@gmail.com>
+Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ net/sctp/socket.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index d4730ad..17841ab 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -4906,6 +4906,10 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
+ struct socket *sock;
+ int err = 0;
+
++ /* Do not peel off from one netns to another one. */
++ if (!net_eq(current->nsproxy->net_ns, sock_net(sk)))
++ return -EINVAL;
++
+ if (!asoc)
+ return -EINVAL;
+
+--
+cgit v1.1
+