From: Greg Kroah-Hartman Date: Thu, 16 Nov 2017 14:22:12 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v3.18.82~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d0076f7430d61746447e0ddf094c6558facf34bb;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: ip6_gre-only-increase-err_count-for-some-certain-type-icmpv6-in-ip6gre_err.patch ipv6-flowlabel-do-not-leave-opt-tot_len-with-garbage.patch l2tp-check-ps-sock-before-running-pppol2tp_session_ioctl.patch net-unix-don-t-show-information-about-sockets-from-other-namespaces.patch packet-avoid-panic-in-packet_getsockopt.patch ppp-fix-race-in-ppp-device-destruction.patch sctp-add-the-missing-sock_owned_by_user-check-in-sctp_icmp_redirect.patch sctp-reset-owner-sk-for-data-chunks-on-out-queues-when-migrating-a-sock.patch tcp-fix-tcp_mtu_probe-vs-highest_sack.patch tun-allow-positive-return-values-on-dev_get_valid_name-call.patch tun-call-dev_get_valid_name-before-register_netdevice.patch tun-tap-sanitize-tunsetsndbuf-input.patch --- diff --git a/queue-4.4/ip6_gre-only-increase-err_count-for-some-certain-type-icmpv6-in-ip6gre_err.patch b/queue-4.4/ip6_gre-only-increase-err_count-for-some-certain-type-icmpv6-in-ip6gre_err.patch new file mode 100644 index 00000000000..2bc59876305 --- /dev/null +++ b/queue-4.4/ip6_gre-only-increase-err_count-for-some-certain-type-icmpv6-in-ip6gre_err.patch @@ -0,0 +1,62 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Xin Long +Date: Thu, 26 Oct 2017 19:23:27 +0800 +Subject: ip6_gre: only increase err_count for some certain type icmpv6 in ip6gre_err + +From: Xin Long + + +[ Upstream commit f8d20b46ce55cf40afb30dcef6d9288f7ef46d9b ] + +The similar fix in patch 'ipip: only increase err_count for some +certain type icmp in ipip_err' is needed for ip6gre_err. + +In Jianlin's case, udp netperf broke even when receiving a TooBig +icmpv6 packet. + +Fixes: c12b395a4664 ("gre: Support GRE over IPv6") +Reported-by: Jianlin Shi +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_gre.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +--- a/net/ipv6/ip6_gre.c ++++ b/net/ipv6/ip6_gre.c +@@ -409,13 +409,16 @@ static void ip6gre_err(struct sk_buff *s + case ICMPV6_DEST_UNREACH: + net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n", + t->parms.name); +- break; ++ if (code != ICMPV6_PORT_UNREACH) ++ break; ++ return; + case ICMPV6_TIME_EXCEED: + if (code == ICMPV6_EXC_HOPLIMIT) { + net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n", + t->parms.name); ++ break; + } +- break; ++ return; + case ICMPV6_PARAMPROB: + teli = 0; + if (code == ICMPV6_HDR_FIELD) +@@ -431,13 +434,13 @@ static void ip6gre_err(struct sk_buff *s + net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n", + t->parms.name); + } +- break; ++ return; + case ICMPV6_PKT_TOOBIG: + mtu = be32_to_cpu(info) - offset; + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + t->dev->mtu = mtu; +- break; ++ return; + } + + if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) diff --git a/queue-4.4/ipv6-flowlabel-do-not-leave-opt-tot_len-with-garbage.patch b/queue-4.4/ipv6-flowlabel-do-not-leave-opt-tot_len-with-garbage.patch new file mode 100644 index 00000000000..a4000bcf2c1 --- /dev/null +++ b/queue-4.4/ipv6-flowlabel-do-not-leave-opt-tot_len-with-garbage.patch @@ -0,0 +1,104 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Eric Dumazet +Date: Sat, 21 Oct 2017 12:26:23 -0700 +Subject: ipv6: flowlabel: do not leave opt->tot_len with garbage + +From: Eric Dumazet + + +[ Upstream commit 864e2a1f8aac05effac6063ce316b480facb46ff ] + +When syzkaller team brought us a C repro for the crash [1] that +had been reported many times in the past, I finally could find +the root cause. + +If FlowLabel info is merged by fl6_merge_options(), we leave +part of the opt_space storage provided by udp/raw/l2tp with random value +in opt_space.tot_len, unless a control message was provided at sendmsg() +time. + +Then ip6_setup_cork() would use this random value to perform a kzalloc() +call. Undefined behavior and crashes. + +Fix is to properly set tot_len in fl6_merge_options() + +At the same time, we can also avoid consuming memory and cpu cycles +to clear it, if every option is copied via a kmemdup(). This is the +change in ip6_setup_cork(). + +[1] +kasan: CONFIG_KASAN_INLINE enabled +kasan: GPF could be caused by NULL-ptr deref or user memory access +general protection fault: 0000 [#1] SMP KASAN +Dumping ftrace buffer: + (ftrace buffer empty) +Modules linked in: +CPU: 0 PID: 6613 Comm: syz-executor0 Not tainted 4.14.0-rc4+ #127 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +task: ffff8801cb64a100 task.stack: ffff8801cc350000 +RIP: 0010:ip6_setup_cork+0x274/0x15c0 net/ipv6/ip6_output.c:1168 +RSP: 0018:ffff8801cc357550 EFLAGS: 00010203 +RAX: dffffc0000000000 RBX: ffff8801cc357748 RCX: 0000000000000010 +RDX: 0000000000000002 RSI: ffffffff842bd1d9 RDI: 0000000000000014 +RBP: ffff8801cc357620 R08: ffff8801cb17f380 R09: ffff8801cc357b10 +R10: ffff8801cb64a100 R11: 0000000000000000 R12: ffff8801cc357ab0 +R13: ffff8801cc357b10 R14: 0000000000000000 R15: ffff8801c3bbf0c0 +FS: 00007f9c5c459700(0000) GS:ffff8801db200000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000020324000 CR3: 00000001d1cf2000 CR4: 00000000001406f0 +DR0: 0000000020001010 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000600 +Call Trace: + ip6_make_skb+0x282/0x530 net/ipv6/ip6_output.c:1729 + udpv6_sendmsg+0x2769/0x3380 net/ipv6/udp.c:1340 + inet_sendmsg+0x11f/0x5e0 net/ipv4/af_inet.c:762 + sock_sendmsg_nosec net/socket.c:633 [inline] + sock_sendmsg+0xca/0x110 net/socket.c:643 + SYSC_sendto+0x358/0x5a0 net/socket.c:1750 + SyS_sendto+0x40/0x50 net/socket.c:1718 + entry_SYSCALL_64_fastpath+0x1f/0xbe +RIP: 0033:0x4520a9 +RSP: 002b:00007f9c5c458c08 EFLAGS: 00000216 ORIG_RAX: 000000000000002c +RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 00000000004520a9 +RDX: 0000000000000001 RSI: 0000000020fd1000 RDI: 0000000000000016 +RBP: 0000000000000086 R08: 0000000020e0afe4 R09: 000000000000001c +R10: 0000000000000000 R11: 0000000000000216 R12: 00000000004bb1ee +R13: 00000000ffffffff R14: 0000000000000016 R15: 0000000000000029 +Code: e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 ea 0f 00 00 48 8d 79 04 48 b8 00 00 00 00 00 fc ff df 45 8b 74 24 04 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 +RIP: ip6_setup_cork+0x274/0x15c0 net/ipv6/ip6_output.c:1168 RSP: ffff8801cc357550 + +Signed-off-by: Eric Dumazet +Reported-by: Dmitry Vyukov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/ip6_flowlabel.c | 1 + + net/ipv6/ip6_output.c | 4 ++-- + 2 files changed, 3 insertions(+), 2 deletions(-) + +--- a/net/ipv6/ip6_flowlabel.c ++++ b/net/ipv6/ip6_flowlabel.c +@@ -315,6 +315,7 @@ struct ipv6_txoptions *fl6_merge_options + } + opt_space->dst1opt = fopt->dst1opt; + opt_space->opt_flen = fopt->opt_flen; ++ opt_space->tot_len = fopt->tot_len; + return opt_space; + } + EXPORT_SYMBOL_GPL(fl6_merge_options); +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1201,11 +1201,11 @@ static int ip6_setup_cork(struct sock *s + if (WARN_ON(v6_cork->opt)) + return -EINVAL; + +- v6_cork->opt = kzalloc(opt->tot_len, sk->sk_allocation); ++ v6_cork->opt = kzalloc(sizeof(*opt), sk->sk_allocation); + if (unlikely(!v6_cork->opt)) + return -ENOBUFS; + +- v6_cork->opt->tot_len = opt->tot_len; ++ v6_cork->opt->tot_len = sizeof(*opt); + v6_cork->opt->opt_flen = opt->opt_flen; + v6_cork->opt->opt_nflen = opt->opt_nflen; + diff --git a/queue-4.4/l2tp-check-ps-sock-before-running-pppol2tp_session_ioctl.patch b/queue-4.4/l2tp-check-ps-sock-before-running-pppol2tp_session_ioctl.patch new file mode 100644 index 00000000000..e4513d44d61 --- /dev/null +++ b/queue-4.4/l2tp-check-ps-sock-before-running-pppol2tp_session_ioctl.patch @@ -0,0 +1,36 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Guillaume Nault +Date: Fri, 13 Oct 2017 19:22:35 +0200 +Subject: l2tp: check ps->sock before running pppol2tp_session_ioctl() + +From: Guillaume Nault + + +[ Upstream commit 5903f594935a3841137c86b9d5b75143a5b7121c ] + +When pppol2tp_session_ioctl() is called by pppol2tp_tunnel_ioctl(), +the session may be unconnected. That is, it was created by +pppol2tp_session_create() and hasn't been connected with +pppol2tp_connect(). In this case, ps->sock is NULL, so we need to check +for this case in order to avoid dereferencing a NULL pointer. + +Fixes: 309795f4bec2 ("l2tp: Add netlink control API for L2TP") +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/l2tp/l2tp_ppp.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/l2tp/l2tp_ppp.c ++++ b/net/l2tp/l2tp_ppp.c +@@ -1015,6 +1015,9 @@ static int pppol2tp_session_ioctl(struct + session->name, cmd, arg); + + sk = ps->sock; ++ if (!sk) ++ return -EBADR; ++ + sock_hold(sk); + + switch (cmd) { diff --git a/queue-4.4/net-unix-don-t-show-information-about-sockets-from-other-namespaces.patch b/queue-4.4/net-unix-don-t-show-information-about-sockets-from-other-namespaces.patch new file mode 100644 index 00000000000..564cb9d6dfa --- /dev/null +++ b/queue-4.4/net-unix-don-t-show-information-about-sockets-from-other-namespaces.patch @@ -0,0 +1,39 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Andrei Vagin +Date: Wed, 25 Oct 2017 10:16:42 -0700 +Subject: net/unix: don't show information about sockets from other namespaces + +From: Andrei Vagin + + +[ Upstream commit 0f5da659d8f1810f44de14acf2c80cd6499623a0 ] + +socket_diag shows information only about sockets from a namespace where +a diag socket lives. + +But if we request information about one unix socket, the kernel don't +check that its netns is matched with a diag socket namespace, so any +user can get information about any unix socket in a system. This looks +like a bug. + +v2: add a Fixes tag + +Fixes: 51d7cccf0723 ("net: make sock diag per-namespace") +Signed-off-by: Andrei Vagin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/unix/diag.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/unix/diag.c ++++ b/net/unix/diag.c +@@ -257,6 +257,8 @@ static int unix_diag_get_exact(struct sk + err = -ENOENT; + if (sk == NULL) + goto out_nosk; ++ if (!net_eq(sock_net(sk), net)) ++ goto out; + + err = sock_diag_check_cookie(sk, req->udiag_cookie); + if (err) diff --git a/queue-4.4/packet-avoid-panic-in-packet_getsockopt.patch b/queue-4.4/packet-avoid-panic-in-packet_getsockopt.patch new file mode 100644 index 00000000000..3a2857fe169 --- /dev/null +++ b/queue-4.4/packet-avoid-panic-in-packet_getsockopt.patch @@ -0,0 +1,86 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Eric Dumazet +Date: Wed, 18 Oct 2017 16:14:52 -0700 +Subject: packet: avoid panic in packet_getsockopt() + +From: Eric Dumazet + + +[ Upstream commit 509c7a1ecc8601f94ffba8a00889fefb239c00c6 ] + +syzkaller got crashes in packet_getsockopt() processing +PACKET_ROLLOVER_STATS command while another thread was managing +to change po->rollover + +Using RCU will fix this bug. We might later add proper RCU annotations +for sparse sake. + +In v2: I replaced kfree(rollover) in fanout_add() to kfree_rcu() +variant, as spotted by John. + +Fixes: a9b6391814d5 ("packet: rollover statistics") +Signed-off-by: Eric Dumazet +Cc: Willem de Bruijn +Cc: John Sperbeck +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/packet/af_packet.c | 24 ++++++++++++++++-------- + 1 file changed, 16 insertions(+), 8 deletions(-) + +--- a/net/packet/af_packet.c ++++ b/net/packet/af_packet.c +@@ -1724,7 +1724,7 @@ static int fanout_add(struct sock *sk, u + + out: + if (err && rollover) { +- kfree(rollover); ++ kfree_rcu(rollover, rcu); + po->rollover = NULL; + } + mutex_unlock(&fanout_mutex); +@@ -1751,8 +1751,10 @@ static struct packet_fanout *fanout_rele + else + f = NULL; + +- if (po->rollover) ++ if (po->rollover) { + kfree_rcu(po->rollover, rcu); ++ po->rollover = NULL; ++ } + } + mutex_unlock(&fanout_mutex); + +@@ -3769,6 +3771,7 @@ static int packet_getsockopt(struct sock + void *data = &val; + union tpacket_stats_u st; + struct tpacket_rollover_stats rstats; ++ struct packet_rollover *rollover; + + if (level != SOL_PACKET) + return -ENOPROTOOPT; +@@ -3847,13 +3850,18 @@ static int packet_getsockopt(struct sock + 0); + break; + case PACKET_ROLLOVER_STATS: +- if (!po->rollover) ++ rcu_read_lock(); ++ rollover = rcu_dereference(po->rollover); ++ if (rollover) { ++ rstats.tp_all = atomic_long_read(&rollover->num); ++ rstats.tp_huge = atomic_long_read(&rollover->num_huge); ++ rstats.tp_failed = atomic_long_read(&rollover->num_failed); ++ data = &rstats; ++ lv = sizeof(rstats); ++ } ++ rcu_read_unlock(); ++ if (!rollover) + return -EINVAL; +- rstats.tp_all = atomic_long_read(&po->rollover->num); +- rstats.tp_huge = atomic_long_read(&po->rollover->num_huge); +- rstats.tp_failed = atomic_long_read(&po->rollover->num_failed); +- data = &rstats; +- lv = sizeof(rstats); + break; + case PACKET_TX_HAS_OFF: + val = po->tp_tx_has_off; diff --git a/queue-4.4/ppp-fix-race-in-ppp-device-destruction.patch b/queue-4.4/ppp-fix-race-in-ppp-device-destruction.patch new file mode 100644 index 00000000000..25a6ca0ec6d --- /dev/null +++ b/queue-4.4/ppp-fix-race-in-ppp-device-destruction.patch @@ -0,0 +1,113 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Guillaume Nault +Date: Fri, 6 Oct 2017 17:05:49 +0200 +Subject: ppp: fix race in ppp device destruction + +From: Guillaume Nault + + +[ Upstream commit 6151b8b37b119e8e3a8401b080d532520c95faf4 ] + +ppp_release() tries to ensure that netdevices are unregistered before +decrementing the unit refcount and running ppp_destroy_interface(). + +This is all fine as long as the the device is unregistered by +ppp_release(): the unregister_netdevice() call, followed by +rtnl_unlock(), guarantee that the unregistration process completes +before rtnl_unlock() returns. + +However, the device may be unregistered by other means (like +ppp_nl_dellink()). If this happens right before ppp_release() calling +rtnl_lock(), then ppp_release() has to wait for the concurrent +unregistration code to release the lock. +But rtnl_unlock() releases the lock before completing the device +unregistration process. This allows ppp_release() to proceed and +eventually call ppp_destroy_interface() before the unregistration +process completes. Calling free_netdev() on this partially unregistered +device will BUG(): + + ------------[ cut here ]------------ + kernel BUG at net/core/dev.c:8141! + invalid opcode: 0000 [#1] SMP + + CPU: 1 PID: 1557 Comm: pppd Not tainted 4.14.0-rc2+ #4 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1.fc26 04/01/2014 + + Call Trace: + ppp_destroy_interface+0xd8/0xe0 [ppp_generic] + ppp_disconnect_channel+0xda/0x110 [ppp_generic] + ppp_unregister_channel+0x5e/0x110 [ppp_generic] + pppox_unbind_sock+0x23/0x30 [pppox] + pppoe_connect+0x130/0x440 [pppoe] + SYSC_connect+0x98/0x110 + ? do_fcntl+0x2c0/0x5d0 + SyS_connect+0xe/0x10 + entry_SYSCALL_64_fastpath+0x1a/0xa5 + + RIP: free_netdev+0x107/0x110 RSP: ffffc28a40573d88 + ---[ end trace ed294ff0cc40eeff ]--- + +We could set the ->needs_free_netdev flag on PPP devices and move the +ppp_destroy_interface() logic in the ->priv_destructor() callback. But +that'd be quite intrusive as we'd first need to unlink from the other +channels and units that depend on the device (the ones that used the +PPPIOCCONNECT and PPPIOCATTACH ioctls). + +Instead, we can just let the netdevice hold a reference on its +ppp_file. This reference is dropped in ->priv_destructor(), at the very +end of the unregistration process, so that neither ppp_release() nor +ppp_disconnect_channel() can call ppp_destroy_interface() in the interim. + +Reported-by: Beniamino Galvani +Fixes: 8cb775bc0a34 ("ppp: fix device unregistration upon netns deletion") +Signed-off-by: Guillaume Nault +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ppp/ppp_generic.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -1110,7 +1110,17 @@ ppp_get_stats64(struct net_device *dev, + static struct lock_class_key ppp_tx_busylock; + static int ppp_dev_init(struct net_device *dev) + { ++ struct ppp *ppp; ++ + dev->qdisc_tx_busylock = &ppp_tx_busylock; ++ ++ ppp = netdev_priv(dev); ++ /* Let the netdevice take a reference on the ppp file. This ensures ++ * that ppp_destroy_interface() won't run before the device gets ++ * unregistered. ++ */ ++ atomic_inc(&ppp->file.refcnt); ++ + return 0; + } + +@@ -1133,6 +1143,15 @@ static void ppp_dev_uninit(struct net_de + wake_up_interruptible(&ppp->file.rwait); + } + ++static void ppp_dev_priv_destructor(struct net_device *dev) ++{ ++ struct ppp *ppp; ++ ++ ppp = netdev_priv(dev); ++ if (atomic_dec_and_test(&ppp->file.refcnt)) ++ ppp_destroy_interface(ppp); ++} ++ + static const struct net_device_ops ppp_netdev_ops = { + .ndo_init = ppp_dev_init, + .ndo_uninit = ppp_dev_uninit, +@@ -1150,6 +1169,7 @@ static void ppp_setup(struct net_device + dev->tx_queue_len = 3; + dev->type = ARPHRD_PPP; + dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; ++ dev->destructor = ppp_dev_priv_destructor; + netif_keep_dst(dev); + } + diff --git a/queue-4.4/sctp-add-the-missing-sock_owned_by_user-check-in-sctp_icmp_redirect.patch b/queue-4.4/sctp-add-the-missing-sock_owned_by_user-check-in-sctp_icmp_redirect.patch new file mode 100644 index 00000000000..1c56708a35a --- /dev/null +++ b/queue-4.4/sctp-add-the-missing-sock_owned_by_user-check-in-sctp_icmp_redirect.patch @@ -0,0 +1,48 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Xin Long +Date: Wed, 18 Oct 2017 21:37:49 +0800 +Subject: sctp: add the missing sock_owned_by_user check in sctp_icmp_redirect + +From: Xin Long + + +[ Upstream commit 1cc276cec9ec574d41cf47dfc0f51406b6f26ab4 ] + +Now sctp processes icmp redirect packet in sctp_icmp_redirect where +it calls sctp_transport_dst_check in which tp->dst can be released. + +The problem is before calling sctp_transport_dst_check, it doesn't +check sock_owned_by_user, which means tp->dst could be freed while +a process is accessing it with owning the socket. + +An use-after-free issue could be triggered by this. + +This patch is to fix it by checking sock_owned_by_user before calling +sctp_transport_dst_check in sctp_icmp_redirect, so that it would not +release tp->dst if users still hold sock lock. + +Besides, the same issue fixed in commit 45caeaa5ac0b ("dccp/tcp: fix +routing redirect race") on sctp also needs this check. + +Fixes: 55be7a9c6074 ("ipv4: Add redirect support to all protocol icmp error handlers") +Reported-by: Eric Dumazet +Signed-off-by: Xin Long +Acked-by: Marcelo Ricardo Leitner +Acked-by: Neil Horman +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/input.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sctp/input.c ++++ b/net/sctp/input.c +@@ -420,7 +420,7 @@ void sctp_icmp_redirect(struct sock *sk, + { + struct dst_entry *dst; + +- if (!t) ++ if (sock_owned_by_user(sk) || !t) + return; + dst = sctp_transport_dst_check(t); + if (dst) diff --git a/queue-4.4/sctp-reset-owner-sk-for-data-chunks-on-out-queues-when-migrating-a-sock.patch b/queue-4.4/sctp-reset-owner-sk-for-data-chunks-on-out-queues-when-migrating-a-sock.patch new file mode 100644 index 00000000000..156576160c0 --- /dev/null +++ b/queue-4.4/sctp-reset-owner-sk-for-data-chunks-on-out-queues-when-migrating-a-sock.patch @@ -0,0 +1,100 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Xin Long +Date: Sat, 28 Oct 2017 02:13:29 +0800 +Subject: sctp: reset owner sk for data chunks on out queues when migrating a sock + +From: Xin Long + + +[ Upstream commit d04adf1b355181e737b6b1e23d801b07f0b7c4c0 ] + +Now when migrating sock to another one in sctp_sock_migrate(), it only +resets owner sk for the data in receive queues, not the chunks on out +queues. + +It would cause that data chunks length on the sock is not consistent +with sk sk_wmem_alloc. When closing the sock or freeing these chunks, +the old sk would never be freed, and the new sock may crash due to +the overflow sk_wmem_alloc. + +syzbot found this issue with this series: + + r0 = socket$inet_sctp() + sendto$inet(r0) + listen(r0) + accept4(r0) + close(r0) + +Although listen() should have returned error when one TCP-style socket +is in connecting (I may fix this one in another patch), it could also +be reproduced by peeling off an assoc. + +This issue is there since very beginning. + +This patch is to reset owner sk for the chunks on out queues so that +sk sk_wmem_alloc has correct value after accept one sock or peeloff +an assoc to one sock. + +Note that when resetting owner sk for chunks on outqueue, it has to +sctp_clear_owner_w/skb_orphan chunks before changing assoc->base.sk +first and then sctp_set_owner_w them after changing assoc->base.sk, +due to that sctp_wfree and it's callees are using assoc->base.sk. + +Reported-by: Dmitry Vyukov +Signed-off-by: Xin Long +Acked-by: Marcelo Ricardo Leitner +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/socket.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -168,6 +168,36 @@ static inline void sctp_set_owner_w(stru + sk_mem_charge(sk, chunk->skb->truesize); + } + ++static void sctp_clear_owner_w(struct sctp_chunk *chunk) ++{ ++ skb_orphan(chunk->skb); ++} ++ ++static void sctp_for_each_tx_datachunk(struct sctp_association *asoc, ++ void (*cb)(struct sctp_chunk *)) ++ ++{ ++ struct sctp_outq *q = &asoc->outqueue; ++ struct sctp_transport *t; ++ struct sctp_chunk *chunk; ++ ++ list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) ++ list_for_each_entry(chunk, &t->transmitted, transmitted_list) ++ cb(chunk); ++ ++ list_for_each_entry(chunk, &q->retransmit, list) ++ cb(chunk); ++ ++ list_for_each_entry(chunk, &q->sacked, list) ++ cb(chunk); ++ ++ list_for_each_entry(chunk, &q->abandoned, list) ++ cb(chunk); ++ ++ list_for_each_entry(chunk, &q->out_chunk_list, list) ++ cb(chunk); ++} ++ + /* Verify that this is a valid address. */ + static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr, + int len) +@@ -7362,7 +7392,9 @@ static void sctp_sock_migrate(struct soc + * paths won't try to lock it and then oldsk. + */ + lock_sock_nested(newsk, SINGLE_DEPTH_NESTING); ++ sctp_for_each_tx_datachunk(assoc, sctp_clear_owner_w); + sctp_assoc_migrate(assoc, newsk); ++ sctp_for_each_tx_datachunk(assoc, sctp_set_owner_w); + + /* If the association on the newsk is already closed before accept() + * is called, set RCV_SHUTDOWN flag. diff --git a/queue-4.4/series b/queue-4.4/series index e3bd503baee..27d49fda240 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -4,3 +4,15 @@ mac80211-don-t-compare-tkip-tx-mic-key-in-reinstall-prevention.patch usb-usbtest-fix-null-pointer-dereference.patch input-ims-psu-check-if-cdc-union-descriptor-is-sane.patch alsa-seq-cancel-pending-autoload-work-at-unbinding-device.patch +tun-tap-sanitize-tunsetsndbuf-input.patch +tcp-fix-tcp_mtu_probe-vs-highest_sack.patch +l2tp-check-ps-sock-before-running-pppol2tp_session_ioctl.patch +tun-call-dev_get_valid_name-before-register_netdevice.patch +sctp-add-the-missing-sock_owned_by_user-check-in-sctp_icmp_redirect.patch +packet-avoid-panic-in-packet_getsockopt.patch +ipv6-flowlabel-do-not-leave-opt-tot_len-with-garbage.patch +net-unix-don-t-show-information-about-sockets-from-other-namespaces.patch +ip6_gre-only-increase-err_count-for-some-certain-type-icmpv6-in-ip6gre_err.patch +tun-allow-positive-return-values-on-dev_get_valid_name-call.patch +sctp-reset-owner-sk-for-data-chunks-on-out-queues-when-migrating-a-sock.patch +ppp-fix-race-in-ppp-device-destruction.patch diff --git a/queue-4.4/tcp-fix-tcp_mtu_probe-vs-highest_sack.patch b/queue-4.4/tcp-fix-tcp_mtu_probe-vs-highest_sack.patch new file mode 100644 index 00000000000..88c7357bb9f --- /dev/null +++ b/queue-4.4/tcp-fix-tcp_mtu_probe-vs-highest_sack.patch @@ -0,0 +1,81 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Eric Dumazet +Date: Mon, 30 Oct 2017 23:08:20 -0700 +Subject: tcp: fix tcp_mtu_probe() vs highest_sack + +From: Eric Dumazet + + +[ Upstream commit 2b7cda9c35d3b940eb9ce74b30bbd5eb30db493d ] + +Based on SNMP values provided by Roman, Yuchung made the observation +that some crashes in tcp_sacktag_walk() might be caused by MTU probing. + +Looking at tcp_mtu_probe(), I found that when a new skb was placed +in front of the write queue, we were not updating tcp highest sack. + +If one skb is freed because all its content was copied to the new skb +(for MTU probing), then tp->highest_sack could point to a now freed skb. + +Bad things would then happen, including infinite loops. + +This patch renames tcp_highest_sack_combine() and uses it +from tcp_mtu_probe() to fix the bug. + +Note that I also removed one test against tp->sacked_out, +since we want to replace tp->highest_sack regardless of whatever +condition, since keeping a stale pointer to freed skb is a recipe +for disaster. + +Fixes: a47e5a988a57 ("[TCP]: Convert highest_sack to sk_buff to allow direct access") +Signed-off-by: Eric Dumazet +Reported-by: Alexei Starovoitov +Reported-by: Roman Gushchin +Reported-by: Oleksandr Natalenko +Acked-by: Alexei Starovoitov +Acked-by: Neal Cardwell +Acked-by: Yuchung Cheng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/tcp.h | 6 +++--- + net/ipv4/tcp_output.c | 3 ++- + 2 files changed, 5 insertions(+), 4 deletions(-) + +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -1612,12 +1612,12 @@ static inline void tcp_highest_sack_rese + tcp_sk(sk)->highest_sack = tcp_write_queue_head(sk); + } + +-/* Called when old skb is about to be deleted (to be combined with new skb) */ +-static inline void tcp_highest_sack_combine(struct sock *sk, ++/* Called when old skb is about to be deleted and replaced by new skb */ ++static inline void tcp_highest_sack_replace(struct sock *sk, + struct sk_buff *old, + struct sk_buff *new) + { +- if (tcp_sk(sk)->sacked_out && (old == tcp_sk(sk)->highest_sack)) ++ if (old == tcp_highest_sack(sk)) + tcp_sk(sk)->highest_sack = new; + } + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -1951,6 +1951,7 @@ static int tcp_mtu_probe(struct sock *sk + nskb->ip_summed = skb->ip_summed; + + tcp_insert_write_queue_before(nskb, skb, sk); ++ tcp_highest_sack_replace(sk, skb, nskb); + + len = 0; + tcp_for_write_queue_from_safe(skb, next, sk) { +@@ -2464,7 +2465,7 @@ static void tcp_collapse_retrans(struct + + BUG_ON(tcp_skb_pcount(skb) != 1 || tcp_skb_pcount(next_skb) != 1); + +- tcp_highest_sack_combine(sk, next_skb, skb); ++ tcp_highest_sack_replace(sk, next_skb, skb); + + tcp_unlink_write_queue(next_skb, sk); + diff --git a/queue-4.4/tun-allow-positive-return-values-on-dev_get_valid_name-call.patch b/queue-4.4/tun-allow-positive-return-values-on-dev_get_valid_name-call.patch new file mode 100644 index 00000000000..9d654405149 --- /dev/null +++ b/queue-4.4/tun-allow-positive-return-values-on-dev_get_valid_name-call.patch @@ -0,0 +1,36 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Julien Gomes +Date: Wed, 25 Oct 2017 11:50:50 -0700 +Subject: tun: allow positive return values on dev_get_valid_name() call + +From: Julien Gomes + + +[ Upstream commit 5c25f65fd1e42685f7ccd80e0621829c105785d9 ] + +If the name argument of dev_get_valid_name() contains "%d", it will try +to assign it a unit number in __dev__alloc_name() and return either the +unit number (>= 0) or an error code (< 0). +Considering positive values as error values prevent tun device creations +relying this mechanism, therefor we should only consider negative values +as errors here. + +Signed-off-by: Julien Gomes +Acked-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tun.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1685,7 +1685,7 @@ static int tun_set_iff(struct net *net, + if (!dev) + return -ENOMEM; + err = dev_get_valid_name(net, dev, name); +- if (err) ++ if (err < 0) + goto err_free_dev; + + dev_net_set(dev, net); diff --git a/queue-4.4/tun-call-dev_get_valid_name-before-register_netdevice.patch b/queue-4.4/tun-call-dev_get_valid_name-before-register_netdevice.patch new file mode 100644 index 00000000000..f2095e1d8cd --- /dev/null +++ b/queue-4.4/tun-call-dev_get_valid_name-before-register_netdevice.patch @@ -0,0 +1,82 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Cong Wang +Date: Fri, 13 Oct 2017 11:58:53 -0700 +Subject: tun: call dev_get_valid_name() before register_netdevice() + +From: Cong Wang + + +[ Upstream commit 0ad646c81b2182f7fa67ec0c8c825e0ee165696d ] + +register_netdevice() could fail early when we have an invalid +dev name, in which case ->ndo_uninit() is not called. For tun +device, this is a problem because a timer etc. are already +initialized and it expects ->ndo_uninit() to clean them up. + +We could move these initializations into a ->ndo_init() so +that register_netdevice() knows better, however this is still +complicated due to the logic in tun_detach(). + +Therefore, I choose to just call dev_get_valid_name() before +register_netdevice(), which is quicker and much easier to audit. +And for this specific case, it is already enough. + +Fixes: 96442e42429e ("tuntap: choose the txq based on rxq") +Reported-by: Dmitry Alexeev +Cc: Jason Wang +Cc: "Michael S. Tsirkin" +Signed-off-by: Cong Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/tun.c | 3 +++ + include/linux/netdevice.h | 3 +++ + net/core/dev.c | 6 +++--- + 3 files changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -1684,6 +1684,9 @@ static int tun_set_iff(struct net *net, + + if (!dev) + return -ENOMEM; ++ err = dev_get_valid_name(net, dev, name); ++ if (err) ++ goto err_free_dev; + + dev_net_set(dev, net); + dev->rtnl_link_ops = &tun_link_ops; +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -3469,6 +3469,9 @@ struct net_device *alloc_netdev_mqs(int + unsigned char name_assign_type, + void (*setup)(struct net_device *), + unsigned int txqs, unsigned int rxqs); ++int dev_get_valid_name(struct net *net, struct net_device *dev, ++ const char *name); ++ + #define alloc_netdev(sizeof_priv, name, name_assign_type, setup) \ + alloc_netdev_mqs(sizeof_priv, name, name_assign_type, setup, 1, 1) + +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -1111,9 +1111,8 @@ static int dev_alloc_name_ns(struct net + return ret; + } + +-static int dev_get_valid_name(struct net *net, +- struct net_device *dev, +- const char *name) ++int dev_get_valid_name(struct net *net, struct net_device *dev, ++ const char *name) + { + BUG_ON(!net); + +@@ -1129,6 +1128,7 @@ static int dev_get_valid_name(struct net + + return 0; + } ++EXPORT_SYMBOL(dev_get_valid_name); + + /** + * dev_change_name - change name of a device diff --git a/queue-4.4/tun-tap-sanitize-tunsetsndbuf-input.patch b/queue-4.4/tun-tap-sanitize-tunsetsndbuf-input.patch new file mode 100644 index 00000000000..6394c12667d --- /dev/null +++ b/queue-4.4/tun-tap-sanitize-tunsetsndbuf-input.patch @@ -0,0 +1,88 @@ +From foo@baz Thu Nov 16 15:08:14 CET 2017 +From: Craig Gallek +Date: Mon, 30 Oct 2017 18:50:11 -0400 +Subject: tun/tap: sanitize TUNSETSNDBUF input + +From: Craig Gallek + + +[ Upstream commit 93161922c658c714715686cd0cf69b090cb9bf1d ] + +Syzkaller found several variants of the lockup below by setting negative +values with the TUNSETSNDBUF ioctl. This patch adds a sanity check +to both the tun and tap versions of this ioctl. + + watchdog: BUG: soft lockup - CPU#0 stuck for 22s! [repro:2389] + Modules linked in: + irq event stamp: 329692056 + hardirqs last enabled at (329692055): [] _raw_spin_unlock_irqrestore+0x31/0x75 + hardirqs last disabled at (329692056): [] apic_timer_interrupt+0x98/0xb0 + softirqs last enabled at (35659740): [] __do_softirq+0x328/0x48c + softirqs last disabled at (35659731): [] irq_exit+0xbc/0xd0 + CPU: 0 PID: 2389 Comm: repro Not tainted 4.14.0-rc7 #23 + Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 + task: ffff880009452140 task.stack: ffff880006a20000 + RIP: 0010:_raw_spin_lock_irqsave+0x11/0x80 + RSP: 0018:ffff880006a27c50 EFLAGS: 00000282 ORIG_RAX: ffffffffffffff10 + RAX: ffff880009ac68d0 RBX: ffff880006a27ce0 RCX: 0000000000000000 + RDX: 0000000000000001 RSI: ffff880006a27ce0 RDI: ffff880009ac6900 + RBP: ffff880006a27c60 R08: 0000000000000000 R09: 0000000000000000 + R10: 0000000000000001 R11: 000000000063ff00 R12: ffff880009ac6900 + R13: ffff880006a27cf8 R14: 0000000000000001 R15: ffff880006a27cf8 + FS: 00007f4be4838700(0000) GS:ffff88000cc00000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 0000000020101000 CR3: 0000000009616000 CR4: 00000000000006f0 + Call Trace: + prepare_to_wait+0x26/0xc0 + sock_alloc_send_pskb+0x14e/0x270 + ? remove_wait_queue+0x60/0x60 + tun_get_user+0x2cc/0x19d0 + ? __tun_get+0x60/0x1b0 + tun_chr_write_iter+0x57/0x86 + __vfs_write+0x156/0x1e0 + vfs_write+0xf7/0x230 + SyS_write+0x57/0xd0 + entry_SYSCALL_64_fastpath+0x1f/0xbe + RIP: 0033:0x7f4be4356df9 + RSP: 002b:00007ffc18101c08 EFLAGS: 00000293 ORIG_RAX: 0000000000000001 + RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f4be4356df9 + RDX: 0000000000000046 RSI: 0000000020101000 RDI: 0000000000000005 + RBP: 00007ffc18101c40 R08: 0000000000000001 R09: 0000000000000001 + R10: 0000000000000001 R11: 0000000000000293 R12: 0000559c75f64780 + R13: 00007ffc18101d30 R14: 0000000000000000 R15: 0000000000000000 + +Fixes: 33dccbb050bb ("tun: Limit amount of queued packets per device") +Fixes: 20d29d7a916a ("net: macvtap driver") +Signed-off-by: Craig Gallek +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/macvtap.c | 2 ++ + drivers/net/tun.c | 4 ++++ + 2 files changed, 6 insertions(+) + +--- a/drivers/net/macvtap.c ++++ b/drivers/net/macvtap.c +@@ -1117,6 +1117,8 @@ static long macvtap_ioctl(struct file *f + case TUNSETSNDBUF: + if (get_user(s, sp)) + return -EFAULT; ++ if (s <= 0) ++ return -EINVAL; + + q->sk.sk_sndbuf = s; + return 0; +--- a/drivers/net/tun.c ++++ b/drivers/net/tun.c +@@ -2065,6 +2065,10 @@ static long __tun_chr_ioctl(struct file + ret = -EFAULT; + break; + } ++ if (sndbuf <= 0) { ++ ret = -EINVAL; ++ break; ++ } + + tun->sndbuf = sndbuf; + tun_set_sndbuf(tun);