| From foo@baz Tue Nov 21 15:37:44 CET 2017 |
| 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 |
| |
| From: Xin Long <lucien.xin@gmail.com> |
| |
| |
| [ Upstream commit df80cd9b28b9ebaa284a41df611dbf3a2d05ca74 ] |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/sctp/socket.c | 4 ++++ |
| 1 file changed, 4 insertions(+) |
| |
| --- a/net/sctp/socket.c |
| +++ b/net/sctp/socket.c |
| @@ -4466,6 +4466,10 @@ int sctp_do_peeloff(struct sock *sk, sct |
| 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; |
| |