From: Greg Kroah-Hartman Date: Tue, 18 Jul 2017 09:38:55 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.12.3~24 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e18fb2ae441a4b8c2681a9a9de644f5cf3d8a563;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch --- diff --git a/queue-4.4/brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch b/queue-4.4/brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch new file mode 100644 index 00000000000..4899197336c --- /dev/null +++ b/queue-4.4/brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch @@ -0,0 +1,45 @@ +From 8f44c9a41386729fea410e688959ddaa9d51be7c Mon Sep 17 00:00:00 2001 +From: Arend van Spriel +Date: Fri, 7 Jul 2017 21:09:06 +0100 +Subject: brcmfmac: fix possible buffer overflow in brcmf_cfg80211_mgmt_tx() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Arend van Spriel + +commit 8f44c9a41386729fea410e688959ddaa9d51be7c upstream. + +The lower level nl80211 code in cfg80211 ensures that "len" is between +25 and NL80211_ATTR_FRAME (2304). We subtract DOT11_MGMT_HDR_LEN (24) from +"len" so thats's max of 2280. However, the action_frame->data[] buffer is +only BRCMF_FIL_ACTION_FRAME_SIZE (1800) bytes long so this memcpy() can +overflow. + + memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], + le16_to_cpu(action_frame->len)); + +Fixes: 18e2f61db3b70 ("brcmfmac: P2P action frame tx.") +Reported-by: "freenerguo(郭大兴)" +Signed-off-by: Arend van Spriel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +@@ -4472,6 +4472,11 @@ brcmf_cfg80211_mgmt_tx(struct wiphy *wip + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, + GFP_KERNEL); + } else if (ieee80211_is_action(mgmt->frame_control)) { ++ if (len > BRCMF_FIL_ACTION_FRAME_SIZE + DOT11_MGMT_HDR_LEN) { ++ brcmf_err("invalid action frame length\n"); ++ err = -EINVAL; ++ goto exit; ++ } + af_params = kzalloc(sizeof(*af_params), GFP_KERNEL); + if (af_params == NULL) { + brcmf_err("unable to allocate frame\n"); diff --git a/queue-4.4/ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch b/queue-4.4/ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch new file mode 100644 index 00000000000..c3cffb78ec4 --- /dev/null +++ b/queue-4.4/ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch @@ -0,0 +1,80 @@ +From ec8add2a4c9df723c94a863b8fcd6d93c472deed Mon Sep 17 00:00:00 2001 +From: Sabrina Dubroca +Date: Thu, 29 Jun 2017 16:56:54 +0200 +Subject: ipv6: dad: don't remove dynamic addresses if link is down + +From: Sabrina Dubroca + +commit ec8add2a4c9df723c94a863b8fcd6d93c472deed upstream. + +Currently, when the link for $DEV is down, this command succeeds but the +address is removed immediately by DAD (1): + + ip addr add 1111::12/64 dev $DEV valid_lft 3600 preferred_lft 1800 + +In the same situation, this will succeed and not remove the address (2): + + ip addr add 1111::12/64 dev $DEV + ip addr change 1111::12/64 dev $DEV valid_lft 3600 preferred_lft 1800 + +The comment in addrconf_dad_begin() when !IF_READY makes it look like +this is the intended behavior, but doesn't explain why: + + * If the device is not ready: + * - keep it tentative if it is a permanent address. + * - otherwise, kill it. + +We clearly cannot prevent userspace from doing (2), but we can make (1) +work consistently with (2). + +addrconf_dad_stop() is only called in two cases: if DAD failed, or to +skip DAD when the link is down. In that second case, the fix is to avoid +deleting the address, like we already do for permanent addresses. + +Fixes: 3c21edbd1137 ("[IPV6]: Defer IPv6 device initialization until the link becomes ready.") +Signed-off-by: Sabrina Dubroca +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/ipv6/addrconf.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1772,17 +1772,7 @@ struct inet6_ifaddr *ipv6_get_ifaddr(str + + static void addrconf_dad_stop(struct inet6_ifaddr *ifp, int dad_failed) + { +- if (ifp->flags&IFA_F_PERMANENT) { +- spin_lock_bh(&ifp->lock); +- addrconf_del_dad_work(ifp); +- ifp->flags |= IFA_F_TENTATIVE; +- if (dad_failed) +- ifp->flags |= IFA_F_DADFAILED; +- spin_unlock_bh(&ifp->lock); +- if (dad_failed) +- ipv6_ifa_notify(0, ifp); +- in6_ifa_put(ifp); +- } else if (ifp->flags&IFA_F_TEMPORARY) { ++ if (ifp->flags&IFA_F_TEMPORARY) { + struct inet6_ifaddr *ifpub; + spin_lock_bh(&ifp->lock); + ifpub = ifp->ifpub; +@@ -1795,6 +1785,16 @@ static void addrconf_dad_stop(struct ine + spin_unlock_bh(&ifp->lock); + } + ipv6_del_addr(ifp); ++ } else if (ifp->flags&IFA_F_PERMANENT || !dad_failed) { ++ spin_lock_bh(&ifp->lock); ++ addrconf_del_dad_work(ifp); ++ ifp->flags |= IFA_F_TENTATIVE; ++ if (dad_failed) ++ ifp->flags |= IFA_F_DADFAILED; ++ spin_unlock_bh(&ifp->lock); ++ if (dad_failed) ++ ipv6_ifa_notify(0, ifp); ++ in6_ifa_put(ifp); + } else { + ipv6_del_addr(ifp); + } diff --git a/queue-4.4/net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch b/queue-4.4/net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch new file mode 100644 index 00000000000..e664de43c3a --- /dev/null +++ b/queue-4.4/net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch @@ -0,0 +1,95 @@ +From f06b7549b79e29a672336d4e134524373fb7a232 Mon Sep 17 00:00:00 2001 +From: David Ahern +Date: Wed, 5 Jul 2017 14:41:46 -0600 +Subject: net: ipv6: Compare lwstate in detecting duplicate nexthops +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Ahern + +commit f06b7549b79e29a672336d4e134524373fb7a232 upstream. + +Lennert reported a failure to add different mpls encaps in a multipath +route: + + $ ip -6 route add 1234::/16 \ + nexthop encap mpls 10 via fe80::1 dev ens3 \ + nexthop encap mpls 20 via fe80::1 dev ens3 + RTNETLINK answers: File exists + +The problem is that the duplicate nexthop detection does not compare +lwtunnel configuration. Add it. + +Fixes: 19e42e451506 ("ipv6: support for fib route lwtunnel encap attributes") +Signed-off-by: David Ahern +Reported-by: João Taveira Araújo +Reported-by: Lennert Buytenhek +Acked-by: Roopa Prabhu +Tested-by: Lennert Buytenhek +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + include/net/ip6_route.h | 8 ++++++++ + net/ipv6/ip6_fib.c | 5 +---- + net/ipv6/route.c | 8 +------- + 3 files changed, 10 insertions(+), 11 deletions(-) + +--- a/include/net/ip6_route.h ++++ b/include/net/ip6_route.h +@@ -21,6 +21,7 @@ struct route_info { + #include + #include + #include ++#include + #include + #include + #include +@@ -208,4 +209,11 @@ static inline struct in6_addr *rt6_nexth + return daddr; + } + ++static inline bool rt6_duplicate_nexthop(struct rt6_info *a, struct rt6_info *b) ++{ ++ return a->dst.dev == b->dst.dev && ++ a->rt6i_idev == b->rt6i_idev && ++ ipv6_addr_equal(&a->rt6i_gateway, &b->rt6i_gateway) && ++ !lwtunnel_cmp_encap(a->dst.lwtstate, b->dst.lwtstate); ++} + #endif +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -767,10 +767,7 @@ static int fib6_add_rt2node(struct fib6_ + goto next_iter; + } + +- if (iter->dst.dev == rt->dst.dev && +- iter->rt6i_idev == rt->rt6i_idev && +- ipv6_addr_equal(&iter->rt6i_gateway, +- &rt->rt6i_gateway)) { ++ if (rt6_duplicate_nexthop(iter, rt)) { + if (rt->rt6i_nsiblings) + rt->rt6i_nsiblings = 0; + if (!(iter->rt6i_flags & RTF_EXPIRES)) +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -2833,17 +2833,11 @@ static int ip6_route_info_append(struct + struct rt6_info *rt, struct fib6_config *r_cfg) + { + struct rt6_nh *nh; +- struct rt6_info *rtnh; + int err = -EEXIST; + + list_for_each_entry(nh, rt6_nh_list, next) { + /* check if rt6_info already exists */ +- rtnh = nh->rt6_info; +- +- if (rtnh->dst.dev == rt->dst.dev && +- rtnh->rt6i_idev == rt->rt6i_idev && +- ipv6_addr_equal(&rtnh->rt6i_gateway, +- &rt->rt6i_gateway)) ++ if (rt6_duplicate_nexthop(nh->rt6_info, rt)) + return err; + } + diff --git a/queue-4.4/rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch b/queue-4.4/rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch new file mode 100644 index 00000000000..ef670af44e4 --- /dev/null +++ b/queue-4.4/rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch @@ -0,0 +1,38 @@ +From 0933a578cd55b02dc80f219dc8f2efb17ec61c9a Mon Sep 17 00:00:00 2001 +From: Sowmini Varadhan +Date: Thu, 6 Jul 2017 08:15:06 -0700 +Subject: rds: tcp: use sock_create_lite() to create the accept socket + +From: Sowmini Varadhan + +commit 0933a578cd55b02dc80f219dc8f2efb17ec61c9a upstream. + +There are two problems with calling sock_create_kern() from +rds_tcp_accept_one() +1. it sets up a new_sock->sk that is wasteful, because this ->sk + is going to get replaced by inet_accept() in the subsequent ->accept() +2. The new_sock->sk is a leaked reference in sock_graft() which + expects to find a null parent->sk + +Avoid these problems by calling sock_create_lite(). + +Signed-off-by: Sowmini Varadhan +Acked-by: Santosh Shilimkar +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + net/rds/tcp_listen.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/rds/tcp_listen.c ++++ b/net/rds/tcp_listen.c +@@ -78,7 +78,7 @@ int rds_tcp_accept_one(struct socket *so + struct inet_sock *inet; + struct rds_tcp_connection *rs_tcp; + +- ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family, ++ ret = sock_create_lite(sock->sk->sk_family, + sock->sk->sk_type, sock->sk->sk_protocol, + &new_sock); + if (ret) diff --git a/queue-4.4/series b/queue-4.4/series index 14b147e0a5f..12a3e21dd75 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -7,3 +7,8 @@ tcp-reset-sk_rx_dst-in-tcp_disconnect.patch net-prevent-sign-extension-in-dev_get_stats.patch bpf-prevent-leaking-pointer-via-xadd-on-unpriviledged.patch net-handle-napi_gro_free_stolen_head-case-also-in-napi_frags_finish.patch +ipv6-dad-don-t-remove-dynamic-addresses-if-link-is-down.patch +net-ipv6-compare-lwstate-in-detecting-duplicate-nexthops.patch +vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch +rds-tcp-use-sock_create_lite-to-create-the-accept-socket.patch +brcmfmac-fix-possible-buffer-overflow-in-brcmf_cfg80211_mgmt_tx.patch diff --git a/queue-4.4/vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch b/queue-4.4/vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch new file mode 100644 index 00000000000..293defc0f8c --- /dev/null +++ b/queue-4.4/vrf-fix-bug_on-triggered-by-rx-when-destroying-a-vrf.patch @@ -0,0 +1,125 @@ +From f630c38ef0d785101363a8992bbd4f302180f86f Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Thu, 6 Jul 2017 15:24:40 +0300 +Subject: vrf: fix bug_on triggered by rx when destroying a vrf + +From: Nikolay Aleksandrov + +commit f630c38ef0d785101363a8992bbd4f302180f86f upstream. + +When destroying a VRF device we cleanup the slaves in its ndo_uninit() +function, but that causes packets to be switched (skb->dev == vrf being +destroyed) even though we're pass the point where the VRF should be +receiving any packets while it is being dismantled. This causes a BUG_ON +to trigger if we have raw sockets (trace below). +The reason is that the inetdev of the VRF has been destroyed but we're +still sending packets up the stack with it, so let's free the slaves in +the dellink callback as David Ahern suggested. + +Note that this fix doesn't prevent packets from going up when the VRF +device is admin down. + +[ 35.631371] ------------[ cut here ]------------ +[ 35.631603] kernel BUG at net/ipv4/fib_frontend.c:285! +[ 35.631854] invalid opcode: 0000 [#1] SMP +[ 35.631977] Modules linked in: +[ 35.632081] CPU: 2 PID: 22 Comm: ksoftirqd/2 Not tainted 4.12.0-rc7+ #45 +[ 35.632247] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 +[ 35.632477] task: ffff88005ad68000 task.stack: ffff88005ad64000 +[ 35.632632] RIP: 0010:fib_compute_spec_dst+0xfc/0x1ee +[ 35.632769] RSP: 0018:ffff88005ad67978 EFLAGS: 00010202 +[ 35.632910] RAX: 0000000000000001 RBX: ffff880059a7f200 RCX: 0000000000000000 +[ 35.633084] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff82274af0 +[ 35.633256] RBP: ffff88005ad679f8 R08: 000000000001ef70 R09: 0000000000000046 +[ 35.633430] R10: ffff88005ad679f8 R11: ffff880037731cb0 R12: 0000000000000001 +[ 35.633603] R13: ffff8800599e3000 R14: 0000000000000000 R15: ffff8800599cb852 +[ 35.634114] FS: 0000000000000000(0000) GS:ffff88005d900000(0000) knlGS:0000000000000000 +[ 35.634306] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 35.634456] CR2: 00007f3563227095 CR3: 000000000201d000 CR4: 00000000000406e0 +[ 35.634632] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 35.634865] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 35.635055] Call Trace: +[ 35.635271] ? __lock_acquire+0xf0d/0x1117 +[ 35.635522] ipv4_pktinfo_prepare+0x82/0x151 +[ 35.635831] raw_rcv_skb+0x17/0x3c +[ 35.636062] raw_rcv+0xe5/0xf7 +[ 35.636287] raw_local_deliver+0x169/0x1d9 +[ 35.636534] ip_local_deliver_finish+0x87/0x1c4 +[ 35.636820] ip_local_deliver+0x63/0x7f +[ 35.637058] ip_rcv_finish+0x340/0x3a1 +[ 35.637295] ip_rcv+0x314/0x34a +[ 35.637525] __netif_receive_skb_core+0x49f/0x7c5 +[ 35.637780] ? lock_acquire+0x13f/0x1d7 +[ 35.638018] ? lock_acquire+0x15e/0x1d7 +[ 35.638259] __netif_receive_skb+0x1e/0x94 +[ 35.638502] ? __netif_receive_skb+0x1e/0x94 +[ 35.638748] netif_receive_skb_internal+0x74/0x300 +[ 35.639002] ? dev_gro_receive+0x2ed/0x411 +[ 35.639246] ? lock_is_held_type+0xc4/0xd2 +[ 35.639491] napi_gro_receive+0x105/0x1a0 +[ 35.639736] receive_buf+0xc32/0xc74 +[ 35.639965] ? detach_buf+0x67/0x153 +[ 35.640201] ? virtqueue_get_buf_ctx+0x120/0x176 +[ 35.640453] virtnet_poll+0x128/0x1c5 +[ 35.640690] net_rx_action+0x103/0x343 +[ 35.640932] __do_softirq+0x1c7/0x4b7 +[ 35.641171] run_ksoftirqd+0x23/0x5c +[ 35.641403] smpboot_thread_fn+0x24f/0x26d +[ 35.641646] ? sort_range+0x22/0x22 +[ 35.641878] kthread+0x129/0x131 +[ 35.642104] ? __list_add+0x31/0x31 +[ 35.642335] ? __list_add+0x31/0x31 +[ 35.642568] ret_from_fork+0x2a/0x40 +[ 35.642804] Code: 05 bd 87 a3 00 01 e8 1f ef 98 ff 4d 85 f6 48 c7 c7 f0 4a 27 82 41 0f 94 c4 31 c9 31 d2 41 0f b6 f4 e8 04 71 a1 ff 45 84 e4 74 02 <0f> 0b 0f b7 93 c4 00 00 00 4d 8b a5 80 05 00 00 48 03 93 d0 00 +[ 35.644342] RIP: fib_compute_spec_dst+0xfc/0x1ee RSP: ffff88005ad67978 + +Fixes: 193125dbd8eb ("net: Introduce VRF device driver") +Reported-by: Chris Cormier +Signed-off-by: Nikolay Aleksandrov +Acked-by: David Ahern +Signed-off-by: David S. Miller +[backport to 4.4 - gregkh] +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/vrf.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -733,15 +733,15 @@ static int vrf_del_slave(struct net_devi + static void vrf_dev_uninit(struct net_device *dev) + { + struct net_vrf *vrf = netdev_priv(dev); +- struct slave_queue *queue = &vrf->queue; +- struct list_head *head = &queue->all_slaves; +- struct slave *slave, *next; ++// struct slave_queue *queue = &vrf->queue; ++// struct list_head *head = &queue->all_slaves; ++// struct slave *slave, *next; + + vrf_rtable_destroy(vrf); + vrf_rt6_destroy(vrf); + +- list_for_each_entry_safe(slave, next, head, list) +- vrf_del_slave(dev, slave->dev); ++// list_for_each_entry_safe(slave, next, head, list) ++// vrf_del_slave(dev, slave->dev); + + free_percpu(dev->dstats); + dev->dstats = NULL; +@@ -914,6 +914,14 @@ static int vrf_validate(struct nlattr *t + + static void vrf_dellink(struct net_device *dev, struct list_head *head) + { ++ struct net_vrf *vrf = netdev_priv(dev); ++ struct slave_queue *queue = &vrf->queue; ++ struct list_head *all_slaves = &queue->all_slaves; ++ struct slave *slave, *next; ++ ++ list_for_each_entry_safe(slave, next, all_slaves, list) ++ vrf_del_slave(dev, slave->dev); ++ + unregister_netdevice_queue(dev, head); + } +