From: Greg Kroah-Hartman Date: Fri, 7 Jan 2022 14:01:17 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.4.299~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ff05ec58b10bc6aed0ed84e28c235f0fc75846e3;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: i40e-fix-incorrect-netdev-s-real-number-of-rx-tx-queues.patch i40e-fix-use-after-free-in-i40e_sync_filters_subtask.patch ipv6-check-attribute-length-for-rta_gateway-in-multipath-route.patch ipv6-check-attribute-length-for-rta_gateway-when-deleting-multipath-route.patch sch_qfq-prevent-shift-out-of-bounds-in-qfq_init_qdisc.patch --- diff --git a/queue-4.14/i40e-fix-incorrect-netdev-s-real-number-of-rx-tx-queues.patch b/queue-4.14/i40e-fix-incorrect-netdev-s-real-number-of-rx-tx-queues.patch new file mode 100644 index 00000000000..67043690eeb --- /dev/null +++ b/queue-4.14/i40e-fix-incorrect-netdev-s-real-number-of-rx-tx-queues.patch @@ -0,0 +1,86 @@ +From e738451d78b2f8a9635d66c6a87f304b4d965f7a Mon Sep 17 00:00:00 2001 +From: Jedrzej Jagielski +Date: Fri, 17 Dec 2021 14:29:05 +0000 +Subject: i40e: Fix incorrect netdev's real number of RX/TX queues + +From: Jedrzej Jagielski + +commit e738451d78b2f8a9635d66c6a87f304b4d965f7a upstream. + +There was a wrong queues representation in sysfs during +driver's reinitialization in case of online cpus number is +less than combined queues. It was caused by stopped +NetworkManager, which is responsible for calling vsi_open +function during driver's initialization. +In specific situation (ex. 12 cpus online) there were 16 queues +in /sys/class/net//queues. In case of modifying queues with +value higher, than number of online cpus, then it caused write +errors and other errors. +Add updating of sysfs's queues representation during driver +initialization. + +Fixes: 41c445ff0f48 ("i40e: main driver core") +Signed-off-by: Lukasz Cieplicki +Signed-off-by: Jedrzej Jagielski +Tested-by: Gurucharan G +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 32 +++++++++++++++++++++------- + 1 file changed, 25 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -5730,6 +5730,27 @@ int i40e_open(struct net_device *netdev) + } + + /** ++ * i40e_netif_set_realnum_tx_rx_queues - Update number of tx/rx queues ++ * @vsi: vsi structure ++ * ++ * This updates netdev's number of tx/rx queues ++ * ++ * Returns status of setting tx/rx queues ++ **/ ++static int i40e_netif_set_realnum_tx_rx_queues(struct i40e_vsi *vsi) ++{ ++ int ret; ++ ++ ret = netif_set_real_num_rx_queues(vsi->netdev, ++ vsi->num_queue_pairs); ++ if (ret) ++ return ret; ++ ++ return netif_set_real_num_tx_queues(vsi->netdev, ++ vsi->num_queue_pairs); ++} ++ ++/** + * i40e_vsi_open - + * @vsi: the VSI to open + * +@@ -5765,13 +5786,7 @@ int i40e_vsi_open(struct i40e_vsi *vsi) + goto err_setup_rx; + + /* Notify the stack of the actual queue counts. */ +- err = netif_set_real_num_tx_queues(vsi->netdev, +- vsi->num_queue_pairs); +- if (err) +- goto err_set_queues; +- +- err = netif_set_real_num_rx_queues(vsi->netdev, +- vsi->num_queue_pairs); ++ err = i40e_netif_set_realnum_tx_rx_queues(vsi); + if (err) + goto err_set_queues; + +@@ -10455,6 +10470,9 @@ struct i40e_vsi *i40e_vsi_setup(struct i + ret = i40e_config_netdev(vsi); + if (ret) + goto err_netdev; ++ ret = i40e_netif_set_realnum_tx_rx_queues(vsi); ++ if (ret) ++ goto err_netdev; + ret = register_netdev(vsi->netdev); + if (ret) + goto err_netdev; diff --git a/queue-4.14/i40e-fix-use-after-free-in-i40e_sync_filters_subtask.patch b/queue-4.14/i40e-fix-use-after-free-in-i40e_sync_filters_subtask.patch new file mode 100644 index 00000000000..b6f5d3e3dc1 --- /dev/null +++ b/queue-4.14/i40e-fix-use-after-free-in-i40e_sync_filters_subtask.patch @@ -0,0 +1,138 @@ +From 3116f59c12bd24c513194cd3acb3ec1f7d468954 Mon Sep 17 00:00:00 2001 +From: Di Zhu +Date: Mon, 29 Nov 2021 19:52:01 +0600 +Subject: i40e: fix use-after-free in i40e_sync_filters_subtask() + +From: Di Zhu + +commit 3116f59c12bd24c513194cd3acb3ec1f7d468954 upstream. + +Using ifconfig command to delete the ipv6 address will cause +the i40e network card driver to delete its internal mac_filter and +i40e_service_task kernel thread will concurrently access the mac_filter. +These two processes are not protected by lock +so causing the following use-after-free problems. + + print_address_description+0x70/0x360 + ? vprintk_func+0x5e/0xf0 + kasan_report+0x1b2/0x330 + i40e_sync_vsi_filters+0x4f0/0x1850 [i40e] + i40e_sync_filters_subtask+0xe3/0x130 [i40e] + i40e_service_task+0x195/0x24c0 [i40e] + process_one_work+0x3f5/0x7d0 + worker_thread+0x61/0x6c0 + ? process_one_work+0x7d0/0x7d0 + kthread+0x1c3/0x1f0 + ? kthread_park+0xc0/0xc0 + ret_from_fork+0x35/0x40 + +Allocated by task 2279810: + kasan_kmalloc+0xa0/0xd0 + kmem_cache_alloc_trace+0xf3/0x1e0 + i40e_add_filter+0x127/0x2b0 [i40e] + i40e_add_mac_filter+0x156/0x190 [i40e] + i40e_addr_sync+0x2d/0x40 [i40e] + __hw_addr_sync_dev+0x154/0x210 + i40e_set_rx_mode+0x6d/0xf0 [i40e] + __dev_set_rx_mode+0xfb/0x1f0 + __dev_mc_add+0x6c/0x90 + igmp6_group_added+0x214/0x230 + __ipv6_dev_mc_inc+0x338/0x4f0 + addrconf_join_solict.part.7+0xa2/0xd0 + addrconf_dad_work+0x500/0x980 + process_one_work+0x3f5/0x7d0 + worker_thread+0x61/0x6c0 + kthread+0x1c3/0x1f0 + ret_from_fork+0x35/0x40 + +Freed by task 2547073: + __kasan_slab_free+0x130/0x180 + kfree+0x90/0x1b0 + __i40e_del_filter+0xa3/0xf0 [i40e] + i40e_del_mac_filter+0xf3/0x130 [i40e] + i40e_addr_unsync+0x85/0xa0 [i40e] + __hw_addr_sync_dev+0x9d/0x210 + i40e_set_rx_mode+0x6d/0xf0 [i40e] + __dev_set_rx_mode+0xfb/0x1f0 + __dev_mc_del+0x69/0x80 + igmp6_group_dropped+0x279/0x510 + __ipv6_dev_mc_dec+0x174/0x220 + addrconf_leave_solict.part.8+0xa2/0xd0 + __ipv6_ifa_notify+0x4cd/0x570 + ipv6_ifa_notify+0x58/0x80 + ipv6_del_addr+0x259/0x4a0 + inet6_addr_del+0x188/0x260 + addrconf_del_ifaddr+0xcc/0x130 + inet6_ioctl+0x152/0x190 + sock_do_ioctl+0xd8/0x2b0 + sock_ioctl+0x2e5/0x4c0 + do_vfs_ioctl+0x14e/0xa80 + ksys_ioctl+0x7c/0xa0 + __x64_sys_ioctl+0x42/0x50 + do_syscall_64+0x98/0x2c0 + entry_SYSCALL_64_after_hwframe+0x65/0xca + +Fixes: 41c445ff0f48 ("i40e: main driver core") +Signed-off-by: Di Zhu +Signed-off-by: Rui Zhang +Tested-by: Gurucharan G +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -114,6 +114,24 @@ MODULE_VERSION(DRV_VERSION); + + static struct workqueue_struct *i40e_wq; + ++static void netdev_hw_addr_refcnt(struct i40e_mac_filter *f, ++ struct net_device *netdev, int delta) ++{ ++ struct netdev_hw_addr *ha; ++ ++ if (!f || !netdev) ++ return; ++ ++ netdev_for_each_mc_addr(ha, netdev) { ++ if (ether_addr_equal(ha->addr, f->macaddr)) { ++ ha->refcount += delta; ++ if (ha->refcount <= 0) ++ ha->refcount = 1; ++ break; ++ } ++ } ++} ++ + /** + * i40e_allocate_dma_mem_d - OS specific memory alloc for shared code + * @hw: pointer to the HW structure +@@ -1827,6 +1845,7 @@ static void i40e_undo_add_filter_entries + hlist_for_each_entry_safe(new, h, from, hlist) { + /* We can simply free the wrapper structure */ + hlist_del(&new->hlist); ++ netdev_hw_addr_refcnt(new->f, vsi->netdev, -1); + kfree(new); + } + } +@@ -2093,6 +2112,10 @@ int i40e_sync_vsi_filters(struct i40e_vs + &tmp_add_list, + &tmp_del_list, + vlan_filters); ++ ++ hlist_for_each_entry(new, &tmp_add_list, hlist) ++ netdev_hw_addr_refcnt(new->f, vsi->netdev, 1); ++ + if (retval) + goto err_no_memory_locked; + +@@ -2232,6 +2255,7 @@ int i40e_sync_vsi_filters(struct i40e_vs + if (new->f->state == I40E_FILTER_NEW) + new->f->state = new->state; + hlist_del(&new->hlist); ++ netdev_hw_addr_refcnt(new->f, vsi->netdev, -1); + kfree(new); + } + spin_unlock_bh(&vsi->mac_filter_hash_lock); diff --git a/queue-4.14/ipv6-check-attribute-length-for-rta_gateway-in-multipath-route.patch b/queue-4.14/ipv6-check-attribute-length-for-rta_gateway-in-multipath-route.patch new file mode 100644 index 00000000000..abf1fe06a0c --- /dev/null +++ b/queue-4.14/ipv6-check-attribute-length-for-rta_gateway-in-multipath-route.patch @@ -0,0 +1,60 @@ +From 4619bcf91399f00a40885100fb61d594d8454033 Mon Sep 17 00:00:00 2001 +From: David Ahern +Date: Thu, 30 Dec 2021 17:36:33 -0700 +Subject: ipv6: Check attribute length for RTA_GATEWAY in multipath route + +From: David Ahern + +commit 4619bcf91399f00a40885100fb61d594d8454033 upstream. + +Commit referenced in the Fixes tag used nla_memcpy for RTA_GATEWAY as +does the current nla_get_in6_addr. nla_memcpy protects against accessing +memory greater than what is in the attribute, but there is no check +requiring the attribute to have an IPv6 address. Add it. + +Fixes: 51ebd3181572 ("ipv6: add support of equal cost multipath (ECMP)") +Signed-off-by: David Ahern +Cc: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/route.c | 21 ++++++++++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -3183,6 +3183,19 @@ static void ip6_route_mpath_notify(struc + inet6_rt_notify(RTM_NEWROUTE, rt, info, nlflags); + } + ++static int fib6_gw_from_attr(struct in6_addr *gw, struct nlattr *nla, ++ struct netlink_ext_ack *extack) ++{ ++ if (nla_len(nla) < sizeof(*gw)) { ++ NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_GATEWAY"); ++ return -EINVAL; ++ } ++ ++ *gw = nla_get_in6_addr(nla); ++ ++ return 0; ++} ++ + static int ip6_route_multipath_add(struct fib6_config *cfg, + struct netlink_ext_ack *extack) + { +@@ -3223,7 +3236,13 @@ static int ip6_route_multipath_add(struc + + nla = nla_find(attrs, attrlen, RTA_GATEWAY); + if (nla) { +- r_cfg.fc_gateway = nla_get_in6_addr(nla); ++ int ret; ++ ++ ret = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, ++ extack); ++ if (ret) ++ return ret; ++ + r_cfg.fc_flags |= RTF_GATEWAY; + } + r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); diff --git a/queue-4.14/ipv6-check-attribute-length-for-rta_gateway-when-deleting-multipath-route.patch b/queue-4.14/ipv6-check-attribute-length-for-rta_gateway-when-deleting-multipath-route.patch new file mode 100644 index 00000000000..393682d555f --- /dev/null +++ b/queue-4.14/ipv6-check-attribute-length-for-rta_gateway-when-deleting-multipath-route.patch @@ -0,0 +1,36 @@ +From 1ff15a710a862db1101b97810af14aedc835a86a Mon Sep 17 00:00:00 2001 +From: David Ahern +Date: Thu, 30 Dec 2021 17:36:34 -0700 +Subject: ipv6: Check attribute length for RTA_GATEWAY when deleting multipath route + +From: David Ahern + +commit 1ff15a710a862db1101b97810af14aedc835a86a upstream. + +Make sure RTA_GATEWAY for IPv6 multipath route has enough bytes to hold +an IPv6 address. + +Fixes: 6b9ea5a64ed5 ("ipv6: fix multipath route replace error recovery") +Signed-off-by: David Ahern +Cc: Roopa Prabhu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/route.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -3365,7 +3365,11 @@ static int ip6_route_multipath_del(struc + + nla = nla_find(attrs, attrlen, RTA_GATEWAY); + if (nla) { +- nla_memcpy(&r_cfg.fc_gateway, nla, 16); ++ err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, ++ extack); ++ if (err) ++ return err; ++ + r_cfg.fc_flags |= RTF_GATEWAY; + } + } diff --git a/queue-4.14/sch_qfq-prevent-shift-out-of-bounds-in-qfq_init_qdisc.patch b/queue-4.14/sch_qfq-prevent-shift-out-of-bounds-in-qfq_init_qdisc.patch new file mode 100644 index 00000000000..1be195e5af4 --- /dev/null +++ b/queue-4.14/sch_qfq-prevent-shift-out-of-bounds-in-qfq_init_qdisc.patch @@ -0,0 +1,65 @@ +From 7d18a07897d07495ee140dd319b0e9265c0f68ba Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 4 Jan 2022 01:45:08 -0800 +Subject: sch_qfq: prevent shift-out-of-bounds in qfq_init_qdisc + +From: Eric Dumazet + +commit 7d18a07897d07495ee140dd319b0e9265c0f68ba upstream. + +tx_queue_len can be set to ~0U, we need to be more +careful about overflows. + +__fls(0) is undefined, as this report shows: + +UBSAN: shift-out-of-bounds in net/sched/sch_qfq.c:1430:24 +shift exponent 51770272 is too large for 32-bit type 'int' +CPU: 0 PID: 25574 Comm: syz-executor.0 Not tainted 5.16.0-rc7-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + + __dump_stack lib/dump_stack.c:88 [inline] + dump_stack_lvl+0x201/0x2d8 lib/dump_stack.c:106 + ubsan_epilogue lib/ubsan.c:151 [inline] + __ubsan_handle_shift_out_of_bounds+0x494/0x530 lib/ubsan.c:330 + qfq_init_qdisc+0x43f/0x450 net/sched/sch_qfq.c:1430 + qdisc_create+0x895/0x1430 net/sched/sch_api.c:1253 + tc_modify_qdisc+0x9d9/0x1e20 net/sched/sch_api.c:1660 + rtnetlink_rcv_msg+0x934/0xe60 net/core/rtnetlink.c:5571 + netlink_rcv_skb+0x200/0x470 net/netlink/af_netlink.c:2496 + netlink_unicast_kernel net/netlink/af_netlink.c:1319 [inline] + netlink_unicast+0x814/0x9f0 net/netlink/af_netlink.c:1345 + netlink_sendmsg+0xaea/0xe60 net/netlink/af_netlink.c:1921 + sock_sendmsg_nosec net/socket.c:704 [inline] + sock_sendmsg net/socket.c:724 [inline] + ____sys_sendmsg+0x5b9/0x910 net/socket.c:2409 + ___sys_sendmsg net/socket.c:2463 [inline] + __sys_sendmsg+0x280/0x370 net/socket.c:2492 + do_syscall_x64 arch/x86/entry/common.c:50 [inline] + do_syscall_64+0x44/0xd0 arch/x86/entry/common.c:80 + entry_SYSCALL_64_after_hwframe+0x44/0xae + +Fixes: 462dbc9101ac ("pkt_sched: QFQ Plus: fair-queueing service at DRR cost") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_qfq.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +--- a/net/sched/sch_qfq.c ++++ b/net/sched/sch_qfq.c +@@ -1425,10 +1425,8 @@ static int qfq_init_qdisc(struct Qdisc * + if (err < 0) + return err; + +- if (qdisc_dev(sch)->tx_queue_len + 1 > QFQ_MAX_AGG_CLASSES) +- max_classes = QFQ_MAX_AGG_CLASSES; +- else +- max_classes = qdisc_dev(sch)->tx_queue_len + 1; ++ max_classes = min_t(u64, (u64)qdisc_dev(sch)->tx_queue_len + 1, ++ QFQ_MAX_AGG_CLASSES); + /* max_cl_shift = floor(log_2(max_classes)) */ + max_cl_shift = __fls(max_classes); + q->max_agg_classes = 1<