From 25007c46893936ef1185142b1d2974faf955af59 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 30 Jul 2023 09:27:52 -0400 Subject: [PATCH] Fixes for 5.4 Signed-off-by: Sasha Levin --- ...-value-check-in-be_lancer_xmit_worka.patch | 38 ++++ ...nd-s-flags-when-down-link-is-p2p-dev.patch | 61 +++++++ ...-fix-return-value-check-in-atl1e_tso.patch | 44 +++++ ...-vs-is_err-bug-for-debugfs_create_di.patch | 40 +++++ ...x-bug-where-deleting-a-mngtmpaddr-ca.patch | 96 ++++++++++ ...io-add-extack-to-mqprio_parse_nlattr.patch | 110 ++++++++++++ ...-add-length-check-for-tca_mqprio_-ma.patch | 63 +++++++ ...-refactor-nlattr-parsing-to-a-separa.patch | 165 ++++++++++++++++++ ...x-an-out-of-bounds-check-in-hisi_inn.patch | 44 +++++ ...-laptop-fix-rfkill-out-of-sync-on-ms.patch | 79 +++++++++ queue-5.4/series | 13 ++ ...chance-of-collisions-in-inet6_hashfn.patch | 75 ++++++++ ...s-flags-when-down-link-is-p2p-device.patch | 52 ++++++ ...culate-correct-header-length-for-gpe.patch | 163 +++++++++++++++++ 14 files changed, 1043 insertions(+) create mode 100644 queue-5.4/benet-fix-return-value-check-in-be_lancer_xmit_worka.patch create mode 100644 queue-5.4/bonding-reset-bond-s-flags-when-down-link-is-p2p-dev.patch create mode 100644 queue-5.4/ethernet-atheros-fix-return-value-check-in-atl1e_tso.patch create mode 100644 queue-5.4/i40e-fix-an-null-vs-is_err-bug-for-debugfs_create_di.patch create mode 100644 queue-5.4/ipv6-addrconf-fix-bug-where-deleting-a-mngtmpaddr-ca.patch create mode 100644 queue-5.4/net-sched-mqprio-add-extack-to-mqprio_parse_nlattr.patch create mode 100644 queue-5.4/net-sched-mqprio-add-length-check-for-tca_mqprio_-ma.patch create mode 100644 queue-5.4/net-sched-mqprio-refactor-nlattr-parsing-to-a-separa.patch create mode 100644 queue-5.4/phy-hisilicon-fix-an-out-of-bounds-check-in-hisi_inn.patch create mode 100644 queue-5.4/platform-x86-msi-laptop-fix-rfkill-out-of-sync-on-ms.patch create mode 100644 queue-5.4/tcp-reduce-chance-of-collisions-in-inet6_hashfn.patch create mode 100644 queue-5.4/team-reset-team-s-flags-when-down-link-is-p2p-device.patch create mode 100644 queue-5.4/vxlan-calculate-correct-header-length-for-gpe.patch diff --git a/queue-5.4/benet-fix-return-value-check-in-be_lancer_xmit_worka.patch b/queue-5.4/benet-fix-return-value-check-in-be_lancer_xmit_worka.patch new file mode 100644 index 00000000000..a6fab86f4b2 --- /dev/null +++ b/queue-5.4/benet-fix-return-value-check-in-be_lancer_xmit_worka.patch @@ -0,0 +1,38 @@ +From 9b0401382acbca9fb60758d88d0c7cc788b8fb5a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jul 2023 11:27:26 +0800 +Subject: benet: fix return value check in be_lancer_xmit_workarounds() + +From: Yuanjun Gong + +[ Upstream commit 5c85f7065718a949902b238a6abd8fc907c5d3e0 ] + +in be_lancer_xmit_workarounds(), it should go to label 'tx_drop' +if an unexpected value is returned by pskb_trim(). + +Fixes: 93040ae5cc8d ("be2net: Fix to trim skb for padded vlan packets to workaround an ASIC Bug") +Signed-off-by: Yuanjun Gong +Link: https://lore.kernel.org/r/20230725032726.15002-1-ruc_gongyuanjun@163.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/emulex/benet/be_main.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c +index f1cce7636722e..a7a3e2ee06768 100644 +--- a/drivers/net/ethernet/emulex/benet/be_main.c ++++ b/drivers/net/ethernet/emulex/benet/be_main.c +@@ -1140,7 +1140,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter, + (lancer_chip(adapter) || BE3_chip(adapter) || + skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) { + ip = (struct iphdr *)ip_hdr(skb); +- pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); ++ if (unlikely(pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)))) ++ goto tx_drop; + } + + /* If vlan tag is already inlined in the packet, skip HW VLAN +-- +2.39.2 + diff --git a/queue-5.4/bonding-reset-bond-s-flags-when-down-link-is-p2p-dev.patch b/queue-5.4/bonding-reset-bond-s-flags-when-down-link-is-p2p-dev.patch new file mode 100644 index 00000000000..951bfc98cc6 --- /dev/null +++ b/queue-5.4/bonding-reset-bond-s-flags-when-down-link-is-p2p-dev.patch @@ -0,0 +1,61 @@ +From f115fd4126da673eb2b5fa3627efbeb459b06a6d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jul 2023 12:03:55 +0800 +Subject: bonding: reset bond's flags when down link is P2P device + +From: Hangbin Liu + +[ Upstream commit da19a2b967cf1e2c426f50d28550d1915214a81d ] + +When adding a point to point downlink to the bond, we neglected to reset +the bond's flags, which were still using flags like BROADCAST and +MULTICAST. Consequently, this would initiate ARP/DAD for P2P downlink +interfaces, such as when adding a GRE device to the bonding. + +To address this issue, let's reset the bond's flags for P2P interfaces. + +Before fix: +7: gre0@NONE: mtu 1500 qdisc noqueue master bond0 state UNKNOWN group default qlen 1000 + link/gre6 2006:70:10::1 peer 2006:70:10::2 permaddr 167f:18:f188:: +8: bond0: mtu 1500 qdisc noqueue state UP group default qlen 1000 + link/gre6 2006:70:10::1 brd 2006:70:10::2 + inet6 fe80::200:ff:fe00:0/64 scope link + valid_lft forever preferred_lft forever + +After fix: +7: gre0@NONE: mtu 1500 qdisc noqueue master bond2 state UNKNOWN group default qlen 1000 + link/gre6 2006:70:10::1 peer 2006:70:10::2 permaddr c29e:557a:e9d9:: +8: bond0: mtu 1500 qdisc noqueue state UP group default qlen 1000 + link/gre6 2006:70:10::1 peer 2006:70:10::2 + inet6 fe80::1/64 scope link + valid_lft forever preferred_lft forever + +Reported-by: Liang Li +Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2221438 +Fixes: 872254dd6b1f ("net/bonding: Enable bonding to enslave non ARPHRD_ETHER") +Signed-off-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/bonding/bond_main.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index cdb9efae6032d..dcaefb47d1f2d 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -1153,6 +1153,11 @@ static void bond_setup_by_slave(struct net_device *bond_dev, + + memcpy(bond_dev->broadcast, slave_dev->broadcast, + slave_dev->addr_len); ++ ++ if (slave_dev->flags & IFF_POINTOPOINT) { ++ bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); ++ bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP); ++ } + } + + /* On bonding slaves other than the currently active slave, suppress +-- +2.39.2 + diff --git a/queue-5.4/ethernet-atheros-fix-return-value-check-in-atl1e_tso.patch b/queue-5.4/ethernet-atheros-fix-return-value-check-in-atl1e_tso.patch new file mode 100644 index 00000000000..906acac0342 --- /dev/null +++ b/queue-5.4/ethernet-atheros-fix-return-value-check-in-atl1e_tso.patch @@ -0,0 +1,44 @@ +From c3982e83a6e2c53b7de75e959cf91333fe7d6ab1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jul 2023 22:42:19 +0800 +Subject: ethernet: atheros: fix return value check in atl1e_tso_csum() + +From: Yuanjun Gong + +[ Upstream commit 69a184f7a372aac588babfb0bd681aaed9779f5b ] + +in atl1e_tso_csum, it should check the return value of pskb_trim(), +and return an error code if an unexpected value is returned +by pskb_trim(). + +Fixes: a6a5325239c2 ("atl1e: Atheros L1E Gigabit Ethernet driver") +Signed-off-by: Yuanjun Gong +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20230720144219.39285-1-ruc_gongyuanjun@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +index 4f7b65825c159..6bdd79a057190 100644 +--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c ++++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +@@ -1638,8 +1638,11 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter, + real_len = (((unsigned char *)ip_hdr(skb) - skb->data) + + ntohs(ip_hdr(skb)->tot_len)); + +- if (real_len < skb->len) +- pskb_trim(skb, real_len); ++ if (real_len < skb->len) { ++ err = pskb_trim(skb, real_len); ++ if (err) ++ return err; ++ } + + hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); + if (unlikely(skb->len == hdr_len)) { +-- +2.39.2 + diff --git a/queue-5.4/i40e-fix-an-null-vs-is_err-bug-for-debugfs_create_di.patch b/queue-5.4/i40e-fix-an-null-vs-is_err-bug-for-debugfs_create_di.patch new file mode 100644 index 00000000000..94d7235de29 --- /dev/null +++ b/queue-5.4/i40e-fix-an-null-vs-is_err-bug-for-debugfs_create_di.patch @@ -0,0 +1,40 @@ +From f521525c5f66bcde8d42d96b8b2344aa257bd19e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Jul 2023 09:42:39 +0800 +Subject: i40e: Fix an NULL vs IS_ERR() bug for debugfs_create_dir() + +From: Wang Ming + +[ Upstream commit 043b1f185fb0f3939b7427f634787706f45411c4 ] + +The debugfs_create_dir() function returns error pointers. +It never returns NULL. Most incorrect error checks were fixed, +but the one in i40e_dbg_init() was forgotten. + +Fix the remaining error check. + +Fixes: 02e9c290814c ("i40e: debugfs interface") +Signed-off-by: Wang Ming +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +index 276f04c0e51d6..31f60657f5321 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +@@ -1755,7 +1755,7 @@ void i40e_dbg_pf_exit(struct i40e_pf *pf) + void i40e_dbg_init(void) + { + i40e_dbg_root = debugfs_create_dir(i40e_driver_name, NULL); +- if (!i40e_dbg_root) ++ if (IS_ERR(i40e_dbg_root)) + pr_info("init of debugfs failed\n"); + } + +-- +2.39.2 + diff --git a/queue-5.4/ipv6-addrconf-fix-bug-where-deleting-a-mngtmpaddr-ca.patch b/queue-5.4/ipv6-addrconf-fix-bug-where-deleting-a-mngtmpaddr-ca.patch new file mode 100644 index 00000000000..07a4d3ba48c --- /dev/null +++ b/queue-5.4/ipv6-addrconf-fix-bug-where-deleting-a-mngtmpaddr-ca.patch @@ -0,0 +1,96 @@ +From 569584fbe75516f613e8fd510589c096ec94ae7d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jul 2023 09:00:22 -0700 +Subject: ipv6 addrconf: fix bug where deleting a mngtmpaddr can create a new + temporary address +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej Żenczykowski + +[ Upstream commit 69172f0bcb6a09110c5d2a6d792627f5095a9018 ] + +currently on 6.4 net/main: + + # ip link add dummy1 type dummy + # echo 1 > /proc/sys/net/ipv6/conf/dummy1/use_tempaddr + # ip link set dummy1 up + # ip -6 addr add 2000::1/64 mngtmpaddr dev dummy1 + # ip -6 addr show dev dummy1 + + 11: dummy1: mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 + inet6 2000::44f3:581c:8ca:3983/64 scope global temporary dynamic + valid_lft 604800sec preferred_lft 86172sec + inet6 2000::1/64 scope global mngtmpaddr + valid_lft forever preferred_lft forever + inet6 fe80::e8a8:a6ff:fed5:56d4/64 scope link + valid_lft forever preferred_lft forever + + # ip -6 addr del 2000::44f3:581c:8ca:3983/64 dev dummy1 + + (can wait a few seconds if you want to, the above delete isn't [directly] the problem) + + # ip -6 addr show dev dummy1 + + 11: dummy1: mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 + inet6 2000::1/64 scope global mngtmpaddr + valid_lft forever preferred_lft forever + inet6 fe80::e8a8:a6ff:fed5:56d4/64 scope link + valid_lft forever preferred_lft forever + + # ip -6 addr del 2000::1/64 mngtmpaddr dev dummy1 + # ip -6 addr show dev dummy1 + + 11: dummy1: mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 + inet6 2000::81c9:56b7:f51a:b98f/64 scope global temporary dynamic + valid_lft 604797sec preferred_lft 86169sec + inet6 fe80::e8a8:a6ff:fed5:56d4/64 scope link + valid_lft forever preferred_lft forever + +This patch prevents this new 'global temporary dynamic' address from being +created by the deletion of the related (same subnet prefix) 'mngtmpaddr' +(which is triggered by there already being no temporary addresses). + +Cc: Jiri Pirko +Fixes: 53bd67491537 ("ipv6 addrconf: introduce IFA_F_MANAGETEMPADDR to tell kernel to manage temporary addresses") +Reported-by: Xiao Ma +Signed-off-by: Maciej Żenczykowski +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20230720160022.1887942-1-maze@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/addrconf.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 46e3c939958bb..a4c3cb72bdc6a 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -2541,12 +2541,18 @@ static void manage_tempaddrs(struct inet6_dev *idev, + ipv6_ifa_notify(0, ift); + } + +- if ((create || list_empty(&idev->tempaddr_list)) && +- idev->cnf.use_tempaddr > 0) { ++ /* Also create a temporary address if it's enabled but no temporary ++ * address currently exists. ++ * However, we get called with valid_lft == 0, prefered_lft == 0, create == false ++ * as part of cleanup (ie. deleting the mngtmpaddr). ++ * We don't want that to result in creating a new temporary ip address. ++ */ ++ if (list_empty(&idev->tempaddr_list) && (valid_lft || prefered_lft)) ++ create = true; ++ ++ if (create && idev->cnf.use_tempaddr > 0) { + /* When a new public address is created as described + * in [ADDRCONF], also create a new temporary address. +- * Also create a temporary address if it's enabled but +- * no temporary address currently exists. + */ + read_unlock_bh(&idev->lock); + ipv6_create_tempaddr(ifp, NULL, false); +-- +2.39.2 + diff --git a/queue-5.4/net-sched-mqprio-add-extack-to-mqprio_parse_nlattr.patch b/queue-5.4/net-sched-mqprio-add-extack-to-mqprio_parse_nlattr.patch new file mode 100644 index 00000000000..e875ed1f833 --- /dev/null +++ b/queue-5.4/net-sched-mqprio-add-extack-to-mqprio_parse_nlattr.patch @@ -0,0 +1,110 @@ +From f5d14d18f2767bad0547a6beef9dfdc4bde5b851 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Apr 2023 21:01:51 +0300 +Subject: net/sched: mqprio: add extack to mqprio_parse_nlattr() + +From: Vladimir Oltean + +[ Upstream commit 57f21bf85400abadac0cb2a4db5de1d663f8863f ] + +Netlink attribute parsing in mqprio is a minesweeper game, with many +options having the possibility of being passed incorrectly and the user +being none the wiser. + +Try to make errors less sour by giving user space some information +regarding what went wrong. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Ferenc Fejes +Reviewed-by: Simon Horman +Acked-by: Jamal Hadi Salim +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6c58c8816abb ("net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64") +Signed-off-by: Sasha Levin +--- + net/sched/sch_mqprio.c | 30 +++++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c +index a5df5604e0150..4ec222a5530d1 100644 +--- a/net/sched/sch_mqprio.c ++++ b/net/sched/sch_mqprio.c +@@ -131,7 +131,8 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, + } + + static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, +- struct nlattr *opt) ++ struct nlattr *opt, ++ struct netlink_ext_ack *extack) + { + struct mqprio_sched *priv = qdisc_priv(sch); + struct nlattr *tb[TCA_MQPRIO_MAX + 1]; +@@ -143,8 +144,11 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, + if (err < 0) + return err; + +- if (!qopt->hw) ++ if (!qopt->hw) { ++ NL_SET_ERR_MSG(extack, ++ "mqprio TCA_OPTIONS can only contain netlink attributes in hardware mode"); + return -EINVAL; ++ } + + if (tb[TCA_MQPRIO_MODE]) { + priv->flags |= TC_MQPRIO_F_MODE; +@@ -157,13 +161,19 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, + } + + if (tb[TCA_MQPRIO_MIN_RATE64]) { +- if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) ++ if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) { ++ NL_SET_ERR_MSG_ATTR(extack, tb[TCA_MQPRIO_MIN_RATE64], ++ "min_rate accepted only when shaper is in bw_rlimit mode"); + return -EINVAL; ++ } + i = 0; + nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], + rem) { +- if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) ++ if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) { ++ NL_SET_ERR_MSG_ATTR(extack, attr, ++ "Attribute type expected to be TCA_MQPRIO_MIN_RATE64"); + return -EINVAL; ++ } + if (i >= qopt->num_tc) + break; + priv->min_rate[i] = *(u64 *)nla_data(attr); +@@ -173,13 +183,19 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, + } + + if (tb[TCA_MQPRIO_MAX_RATE64]) { +- if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) ++ if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) { ++ NL_SET_ERR_MSG_ATTR(extack, tb[TCA_MQPRIO_MAX_RATE64], ++ "max_rate accepted only when shaper is in bw_rlimit mode"); + return -EINVAL; ++ } + i = 0; + nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], + rem) { +- if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) ++ if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) { ++ NL_SET_ERR_MSG_ATTR(extack, attr, ++ "Attribute type expected to be TCA_MQPRIO_MAX_RATE64"); + return -EINVAL; ++ } + if (i >= qopt->num_tc) + break; + priv->max_rate[i] = *(u64 *)nla_data(attr); +@@ -224,7 +240,7 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, + + len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt)); + if (len > 0) { +- err = mqprio_parse_nlattr(sch, qopt, opt); ++ err = mqprio_parse_nlattr(sch, qopt, opt, extack); + if (err) + return err; + } +-- +2.39.2 + diff --git a/queue-5.4/net-sched-mqprio-add-length-check-for-tca_mqprio_-ma.patch b/queue-5.4/net-sched-mqprio-add-length-check-for-tca_mqprio_-ma.patch new file mode 100644 index 00000000000..190b16f6756 --- /dev/null +++ b/queue-5.4/net-sched-mqprio-add-length-check-for-tca_mqprio_-ma.patch @@ -0,0 +1,63 @@ +From 8c381c928e69a251d4d9302636f04e879347048b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Jul 2023 10:42:27 +0800 +Subject: net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64 + +From: Lin Ma + +[ Upstream commit 6c58c8816abb7b93b21fa3b1d0c1726402e5e568 ] + +The nla_for_each_nested parsing in function mqprio_parse_nlattr() does +not check the length of the nested attribute. This can lead to an +out-of-attribute read and allow a malformed nlattr (e.g., length 0) to +be viewed as 8 byte integer and passed to priv->max_rate/min_rate. + +This patch adds the check based on nla_len() when check the nla_type(), +which ensures that the length of these two attribute must equals +sizeof(u64). + +Fixes: 4e8b86c06269 ("mqprio: Introduce new hardware offload mode and shaper in mqprio") +Reviewed-by: Victor Nogueira +Signed-off-by: Lin Ma +Link: https://lore.kernel.org/r/20230725024227.426561-1-linma@zju.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sched/sch_mqprio.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c +index 4ec222a5530d1..56d3dc5e95c7c 100644 +--- a/net/sched/sch_mqprio.c ++++ b/net/sched/sch_mqprio.c +@@ -174,6 +174,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, + "Attribute type expected to be TCA_MQPRIO_MIN_RATE64"); + return -EINVAL; + } ++ ++ if (nla_len(attr) != sizeof(u64)) { ++ NL_SET_ERR_MSG_ATTR(extack, attr, ++ "Attribute TCA_MQPRIO_MIN_RATE64 expected to have 8 bytes length"); ++ return -EINVAL; ++ } ++ + if (i >= qopt->num_tc) + break; + priv->min_rate[i] = *(u64 *)nla_data(attr); +@@ -196,6 +203,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, + "Attribute type expected to be TCA_MQPRIO_MAX_RATE64"); + return -EINVAL; + } ++ ++ if (nla_len(attr) != sizeof(u64)) { ++ NL_SET_ERR_MSG_ATTR(extack, attr, ++ "Attribute TCA_MQPRIO_MAX_RATE64 expected to have 8 bytes length"); ++ return -EINVAL; ++ } ++ + if (i >= qopt->num_tc) + break; + priv->max_rate[i] = *(u64 *)nla_data(attr); +-- +2.39.2 + diff --git a/queue-5.4/net-sched-mqprio-refactor-nlattr-parsing-to-a-separa.patch b/queue-5.4/net-sched-mqprio-refactor-nlattr-parsing-to-a-separa.patch new file mode 100644 index 00000000000..7834397a672 --- /dev/null +++ b/queue-5.4/net-sched-mqprio-refactor-nlattr-parsing-to-a-separa.patch @@ -0,0 +1,165 @@ +From ebb82c4e69bb82febb2a619428242e747ecaaf03 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 4 Feb 2023 15:52:55 +0200 +Subject: net/sched: mqprio: refactor nlattr parsing to a separate function + +From: Vladimir Oltean + +[ Upstream commit feb2cf3dcfb930aec2ca65c66d1365543d5ba943 ] + +mqprio_init() is quite large and unwieldy to add more code to. +Split the netlink attribute parsing to a dedicated function. + +Signed-off-by: Vladimir Oltean +Reviewed-by: Jacob Keller +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Stable-dep-of: 6c58c8816abb ("net/sched: mqprio: Add length check for TCA_MQPRIO_{MAX/MIN}_RATE64") +Signed-off-by: Sasha Levin +--- + net/sched/sch_mqprio.c | 114 +++++++++++++++++++++++------------------ + 1 file changed, 63 insertions(+), 51 deletions(-) + +diff --git a/net/sched/sch_mqprio.c b/net/sched/sch_mqprio.c +index 50e15add6068f..a5df5604e0150 100644 +--- a/net/sched/sch_mqprio.c ++++ b/net/sched/sch_mqprio.c +@@ -130,6 +130,67 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla, + return 0; + } + ++static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, ++ struct nlattr *opt) ++{ ++ struct mqprio_sched *priv = qdisc_priv(sch); ++ struct nlattr *tb[TCA_MQPRIO_MAX + 1]; ++ struct nlattr *attr; ++ int i, rem, err; ++ ++ err = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy, ++ sizeof(*qopt)); ++ if (err < 0) ++ return err; ++ ++ if (!qopt->hw) ++ return -EINVAL; ++ ++ if (tb[TCA_MQPRIO_MODE]) { ++ priv->flags |= TC_MQPRIO_F_MODE; ++ priv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]); ++ } ++ ++ if (tb[TCA_MQPRIO_SHAPER]) { ++ priv->flags |= TC_MQPRIO_F_SHAPER; ++ priv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]); ++ } ++ ++ if (tb[TCA_MQPRIO_MIN_RATE64]) { ++ if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) ++ return -EINVAL; ++ i = 0; ++ nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], ++ rem) { ++ if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) ++ return -EINVAL; ++ if (i >= qopt->num_tc) ++ break; ++ priv->min_rate[i] = *(u64 *)nla_data(attr); ++ i++; ++ } ++ priv->flags |= TC_MQPRIO_F_MIN_RATE; ++ } ++ ++ if (tb[TCA_MQPRIO_MAX_RATE64]) { ++ if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) ++ return -EINVAL; ++ i = 0; ++ nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], ++ rem) { ++ if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) ++ return -EINVAL; ++ if (i >= qopt->num_tc) ++ break; ++ priv->max_rate[i] = *(u64 *)nla_data(attr); ++ i++; ++ } ++ priv->flags |= TC_MQPRIO_F_MAX_RATE; ++ } ++ ++ return 0; ++} ++ + static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, + struct netlink_ext_ack *extack) + { +@@ -139,9 +200,6 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, + struct Qdisc *qdisc; + int i, err = -EOPNOTSUPP; + struct tc_mqprio_qopt *qopt = NULL; +- struct nlattr *tb[TCA_MQPRIO_MAX + 1]; +- struct nlattr *attr; +- int rem; + int len; + + BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); +@@ -166,55 +224,9 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, + + len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt)); + if (len > 0) { +- err = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy, +- sizeof(*qopt)); +- if (err < 0) ++ err = mqprio_parse_nlattr(sch, qopt, opt); ++ if (err) + return err; +- +- if (!qopt->hw) +- return -EINVAL; +- +- if (tb[TCA_MQPRIO_MODE]) { +- priv->flags |= TC_MQPRIO_F_MODE; +- priv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]); +- } +- +- if (tb[TCA_MQPRIO_SHAPER]) { +- priv->flags |= TC_MQPRIO_F_SHAPER; +- priv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]); +- } +- +- if (tb[TCA_MQPRIO_MIN_RATE64]) { +- if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) +- return -EINVAL; +- i = 0; +- nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], +- rem) { +- if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) +- return -EINVAL; +- if (i >= qopt->num_tc) +- break; +- priv->min_rate[i] = *(u64 *)nla_data(attr); +- i++; +- } +- priv->flags |= TC_MQPRIO_F_MIN_RATE; +- } +- +- if (tb[TCA_MQPRIO_MAX_RATE64]) { +- if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) +- return -EINVAL; +- i = 0; +- nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], +- rem) { +- if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) +- return -EINVAL; +- if (i >= qopt->num_tc) +- break; +- priv->max_rate[i] = *(u64 *)nla_data(attr); +- i++; +- } +- priv->flags |= TC_MQPRIO_F_MAX_RATE; +- } + } + + /* pre-allocate qdisc, attachment can't fail */ +-- +2.39.2 + diff --git a/queue-5.4/phy-hisilicon-fix-an-out-of-bounds-check-in-hisi_inn.patch b/queue-5.4/phy-hisilicon-fix-an-out-of-bounds-check-in-hisi_inn.patch new file mode 100644 index 00000000000..5617d1b50ca --- /dev/null +++ b/queue-5.4/phy-hisilicon-fix-an-out-of-bounds-check-in-hisi_inn.patch @@ -0,0 +1,44 @@ +From 30bc2a85e4980476ef6a1d6f4b00be6d17ab9ec7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jul 2023 02:05:55 -0700 +Subject: phy: hisilicon: Fix an out of bounds check in hisi_inno_phy_probe() + +From: Harshit Mogalapalli + +[ Upstream commit 13c088cf3657d70893d75cf116be937f1509cc0f ] + +The size of array 'priv->ports[]' is INNO_PHY_PORT_NUM. + +In the for loop, 'i' is used as the index for array 'priv->ports[]' +with a check (i > INNO_PHY_PORT_NUM) which indicates that +INNO_PHY_PORT_NUM is allowed value for 'i' in the same loop. + +This > comparison needs to be changed to >=, otherwise it potentially leads +to an out of bounds write on the next iteration through the loop + +Fixes: ba8b0ee81fbb ("phy: add inno-usb2-phy driver for hi3798cv200 SoC") +Reported-by: Dan Carpenter +Signed-off-by: Harshit Mogalapalli +Link: https://lore.kernel.org/r/20230721090558.3588613-1-harshit.m.mogalapalli@oracle.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + drivers/phy/hisilicon/phy-hisi-inno-usb2.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c +index 9b16f13b5ab29..96162b9a2e53d 100644 +--- a/drivers/phy/hisilicon/phy-hisi-inno-usb2.c ++++ b/drivers/phy/hisilicon/phy-hisi-inno-usb2.c +@@ -155,7 +155,7 @@ static int hisi_inno_phy_probe(struct platform_device *pdev) + phy_set_drvdata(phy, &priv->ports[i]); + i++; + +- if (i > INNO_PHY_PORT_NUM) { ++ if (i >= INNO_PHY_PORT_NUM) { + dev_warn(dev, "Support %d ports in maximum\n", i); + break; + } +-- +2.39.2 + diff --git a/queue-5.4/platform-x86-msi-laptop-fix-rfkill-out-of-sync-on-ms.patch b/queue-5.4/platform-x86-msi-laptop-fix-rfkill-out-of-sync-on-ms.patch new file mode 100644 index 00000000000..9844a56242e --- /dev/null +++ b/queue-5.4/platform-x86-msi-laptop-fix-rfkill-out-of-sync-on-ms.patch @@ -0,0 +1,79 @@ +From ad64e552e66dcafbb43c6e178000a97dfc861f32 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jul 2023 17:54:23 +0300 +Subject: platform/x86: msi-laptop: Fix rfkill out-of-sync on MSI Wind U100 + +From: Maxim Mikityanskiy + +[ Upstream commit ad084a6d99bc182bf109c190c808e2ea073ec57b ] + +Only the HW rfkill state is toggled on laptops with quirks->ec_read_only +(so far only MSI Wind U90/U100). There are, however, a few issues with +the implementation: + +1. The initial HW state is always unblocked, regardless of the actual + state on boot, because msi_init_rfkill only sets the SW state, + regardless of ec_read_only. + +2. The initial SW state corresponds to the actual state on boot, but it + can't be changed afterwards, because set_device_state returns + -EOPNOTSUPP. It confuses the userspace, making Wi-Fi and/or Bluetooth + unusable if it was blocked on boot, and breaking the airplane mode if + the rfkill was unblocked on boot. + +Address the above issues by properly initializing the HW state on +ec_read_only laptops and by allowing the userspace to toggle the SW +state. Don't set the SW state ourselves and let the userspace fully +control it. Toggling the SW state is a no-op, however, it allows the +userspace to properly toggle the airplane mode. The actual SW radio +disablement is handled by the corresponding rtl818x_pci and btusb +drivers that have their own rfkills. + +Tested on MSI Wind U100 Plus, BIOS ver 1.0G, EC ver 130. + +Fixes: 0816392b97d4 ("msi-laptop: merge quirk tables to one") +Fixes: 0de6575ad0a8 ("msi-laptop: Add MSI Wind U90/U100 support") +Signed-off-by: Maxim Mikityanskiy +Link: https://lore.kernel.org/r/20230721145423.161057-1-maxtram95@gmail.com +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/msi-laptop.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c +index 0e804b6c2d242..dfb4af759aa75 100644 +--- a/drivers/platform/x86/msi-laptop.c ++++ b/drivers/platform/x86/msi-laptop.c +@@ -210,7 +210,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask) + return -EINVAL; + + if (quirks->ec_read_only) +- return -EOPNOTSUPP; ++ return 0; + + /* read current device state */ + result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata); +@@ -841,15 +841,15 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str, + static void msi_init_rfkill(struct work_struct *ignored) + { + if (rfk_wlan) { +- rfkill_set_sw_state(rfk_wlan, !wlan_s); ++ msi_rfkill_set_state(rfk_wlan, !wlan_s); + rfkill_wlan_set(NULL, !wlan_s); + } + if (rfk_bluetooth) { +- rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s); ++ msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s); + rfkill_bluetooth_set(NULL, !bluetooth_s); + } + if (rfk_threeg) { +- rfkill_set_sw_state(rfk_threeg, !threeg_s); ++ msi_rfkill_set_state(rfk_threeg, !threeg_s); + rfkill_threeg_set(NULL, !threeg_s); + } + } +-- +2.39.2 + diff --git a/queue-5.4/series b/queue-5.4/series index b948d92ec3d..62c15a57da3 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -29,3 +29,16 @@ scsi-qla2xxx-array-index-may-go-out-of-bound.patch uapi-general-notification-queue-definitions.patch keys-fix-linking-a-duplicate-key-to-a-keyring-s-asso.patch ext4-fix-to-check-return-value-of-freeze_bdev-in-ext.patch +i40e-fix-an-null-vs-is_err-bug-for-debugfs_create_di.patch +vxlan-calculate-correct-header-length-for-gpe.patch +phy-hisilicon-fix-an-out-of-bounds-check-in-hisi_inn.patch +ethernet-atheros-fix-return-value-check-in-atl1e_tso.patch +ipv6-addrconf-fix-bug-where-deleting-a-mngtmpaddr-ca.patch +tcp-reduce-chance-of-collisions-in-inet6_hashfn.patch +bonding-reset-bond-s-flags-when-down-link-is-p2p-dev.patch +team-reset-team-s-flags-when-down-link-is-p2p-device.patch +platform-x86-msi-laptop-fix-rfkill-out-of-sync-on-ms.patch +net-sched-mqprio-refactor-nlattr-parsing-to-a-separa.patch +net-sched-mqprio-add-extack-to-mqprio_parse_nlattr.patch +net-sched-mqprio-add-length-check-for-tca_mqprio_-ma.patch +benet-fix-return-value-check-in-be_lancer_xmit_worka.patch diff --git a/queue-5.4/tcp-reduce-chance-of-collisions-in-inet6_hashfn.patch b/queue-5.4/tcp-reduce-chance-of-collisions-in-inet6_hashfn.patch new file mode 100644 index 00000000000..39dcbb67558 --- /dev/null +++ b/queue-5.4/tcp-reduce-chance-of-collisions-in-inet6_hashfn.patch @@ -0,0 +1,75 @@ +From c06dfeca7a9b75758512603f5bc28e57eb405726 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jul 2023 15:24:10 -0700 +Subject: tcp: Reduce chance of collisions in inet6_hashfn(). + +From: Stewart Smith + +[ Upstream commit d11b0df7ddf1831f3e170972f43186dad520bfcc ] + +For both IPv4 and IPv6 incoming TCP connections are tracked in a hash +table with a hash over the source & destination addresses and ports. +However, the IPv6 hash is insufficient and can lead to a high rate of +collisions. + +The IPv6 hash used an XOR to fit everything into the 96 bits for the +fast jenkins hash, meaning it is possible for an external entity to +ensure the hash collides, thus falling back to a linear search in the +bucket, which is slow. + +We take the approach of hash the full length of IPv6 address in +__ipv6_addr_jhash() so that all users can benefit from a more secure +version. + +While this may look like it adds overhead, the reality of modern CPUs +means that this is unmeasurable in real world scenarios. + +In simulating with llvm-mca, the increase in cycles for the hashing +code was ~16 cycles on Skylake (from a base of ~155), and an extra ~9 +on Nehalem (base of ~173). + +In commit dd6d2910c5e0 ("netfilter: conntrack: switch to siphash") +netfilter switched from a jenkins hash to a siphash, but even the faster +hsiphash is a more significant overhead (~20-30%) in some preliminary +testing. So, in this patch, we keep to the more conservative approach to +ensure we don't add much overhead per SYN. + +In testing, this results in a consistently even spread across the +connection buckets. In both testing and real-world scenarios, we have +not found any measurable performance impact. + +Fixes: 08dcdbf6a7b9 ("ipv6: use a stronger hash for tcp") +Signed-off-by: Stewart Smith +Signed-off-by: Samuel Mendoza-Jonas +Suggested-by: Eric Dumazet +Signed-off-by: Kuniyuki Iwashima +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20230721222410.17914-1-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/ipv6.h | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +diff --git a/include/net/ipv6.h b/include/net/ipv6.h +index 0e031a4fef408..8c454509f299f 100644 +--- a/include/net/ipv6.h ++++ b/include/net/ipv6.h +@@ -660,12 +660,8 @@ static inline u32 ipv6_addr_hash(const struct in6_addr *a) + /* more secured version of ipv6_addr_hash() */ + static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 initval) + { +- u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1]; +- +- return jhash_3words(v, +- (__force u32)a->s6_addr32[2], +- (__force u32)a->s6_addr32[3], +- initval); ++ return jhash2((__force const u32 *)a->s6_addr32, ++ ARRAY_SIZE(a->s6_addr32), initval); + } + + static inline bool ipv6_addr_loopback(const struct in6_addr *a) +-- +2.39.2 + diff --git a/queue-5.4/team-reset-team-s-flags-when-down-link-is-p2p-device.patch b/queue-5.4/team-reset-team-s-flags-when-down-link-is-p2p-device.patch new file mode 100644 index 00000000000..3fc1b0052b3 --- /dev/null +++ b/queue-5.4/team-reset-team-s-flags-when-down-link-is-p2p-device.patch @@ -0,0 +1,52 @@ +From 80afbe8c0b2a439e0ef419a03711cfe70fc4900e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 21 Jul 2023 12:03:56 +0800 +Subject: team: reset team's flags when down link is P2P device + +From: Hangbin Liu + +[ Upstream commit fa532bee17d15acf8bba4bc8e2062b7a093ba801 ] + +When adding a point to point downlink to team device, we neglected to reset +the team's flags, which were still using flags like BROADCAST and +MULTICAST. Consequently, this would initiate ARP/DAD for P2P downlink +interfaces, such as when adding a GRE device to team device. Fix this by +remove multicast/broadcast flags and add p2p and noarp flags. + +After removing the none ethernet interface and adding an ethernet interface +to team, we need to reset team interface flags. Unlike bonding interface, +team do not need restore IFF_MASTER, IFF_SLAVE flags. + +Reported-by: Liang Li +Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2221438 +Fixes: 1d76efe1577b ("team: add support for non-ethernet devices") +Signed-off-by: Hangbin Liu +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/team/team.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c +index 227d97b4dc224..5c72e9ac4804d 100644 +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -2129,6 +2129,15 @@ static void team_setup_by_port(struct net_device *dev, + dev->mtu = port_dev->mtu; + memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len); + eth_hw_addr_inherit(dev, port_dev); ++ ++ if (port_dev->flags & IFF_POINTOPOINT) { ++ dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST); ++ dev->flags |= (IFF_POINTOPOINT | IFF_NOARP); ++ } else if ((port_dev->flags & (IFF_BROADCAST | IFF_MULTICAST)) == ++ (IFF_BROADCAST | IFF_MULTICAST)) { ++ dev->flags |= (IFF_BROADCAST | IFF_MULTICAST); ++ dev->flags &= ~(IFF_POINTOPOINT | IFF_NOARP); ++ } + } + + static int team_dev_type_check_change(struct net_device *dev, +-- +2.39.2 + diff --git a/queue-5.4/vxlan-calculate-correct-header-length-for-gpe.patch b/queue-5.4/vxlan-calculate-correct-header-length-for-gpe.patch new file mode 100644 index 00000000000..cd88b2507d0 --- /dev/null +++ b/queue-5.4/vxlan-calculate-correct-header-length-for-gpe.patch @@ -0,0 +1,163 @@ +From 88ab33b1bc4252164f70f897371328b77d76d3e8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 20 Jul 2023 11:05:56 +0200 +Subject: vxlan: calculate correct header length for GPE + +From: Jiri Benc + +[ Upstream commit 94d166c5318c6edd1e079df8552233443e909c33 ] + +VXLAN-GPE does not add an extra inner Ethernet header. Take that into +account when calculating header length. + +This causes problems in skb_tunnel_check_pmtu, where incorrect PMTU is +cached. + +In the collect_md mode (which is the only mode that VXLAN-GPE +supports), there's no magic auto-setting of the tunnel interface MTU. +It can't be, since the destination and thus the underlying interface +may be different for each packet. + +So, the administrator is responsible for setting the correct tunnel +interface MTU. Apparently, the administrators are capable enough to +calculate that the maximum MTU for VXLAN-GPE is (their_lower_MTU - 36). +They set the tunnel interface MTU to 1464. If you run a TCP stream over +such interface, it's then segmented according to the MTU 1464, i.e. +producing 1514 bytes frames. Which is okay, this still fits the lower +MTU. + +However, skb_tunnel_check_pmtu (called from vxlan_xmit_one) uses 50 as +the header size and thus incorrectly calculates the frame size to be +1528. This leads to ICMP too big message being generated (locally), +PMTU of 1450 to be cached and the TCP stream to be resegmented. + +The fix is to use the correct actual header size, especially for +skb_tunnel_check_pmtu calculation. + +Fixes: e1e5314de08ba ("vxlan: implement GPE") +Signed-off-by: Jiri Benc +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 +- + drivers/net/vxlan.c | 22 ++++++++----------- + include/net/vxlan.h | 13 +++++++---- + 3 files changed, 19 insertions(+), 18 deletions(-) + +diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +index a864b91065e33..567bb7792f8fe 100644 +--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c ++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +@@ -8423,7 +8423,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring, + struct ixgbe_adapter *adapter = q_vector->adapter; + + if (unlikely(skb_tail_pointer(skb) < hdr.network + +- VXLAN_HEADROOM)) ++ vxlan_headroom(0))) + return; + + /* verify the port is recognized as VXLAN */ +diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c +index f4869b1836f30..1e3e075454f33 100644 +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -2550,7 +2550,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + } + + ndst = &rt->dst; +- skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM); ++ skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE)); + + tos = ip_tunnel_ecn_encap(tos, old_iph, skb); + ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); +@@ -2590,7 +2590,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, + goto out_unlock; + } + +- skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM); ++ skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6)); + + tos = ip_tunnel_ecn_encap(tos, old_iph, skb); + ttl = ttl ? : ip6_dst_hoplimit(ndst); +@@ -2908,14 +2908,12 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu) + struct vxlan_rdst *dst = &vxlan->default_dst; + struct net_device *lowerdev = __dev_get_by_index(vxlan->net, + dst->remote_ifindex); +- bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6); + + /* This check is different than dev->max_mtu, because it looks at + * the lowerdev->mtu, rather than the static dev->max_mtu + */ + if (lowerdev) { +- int max_mtu = lowerdev->mtu - +- (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM); ++ int max_mtu = lowerdev->mtu - vxlan_headroom(vxlan->cfg.flags); + if (new_mtu > max_mtu) + return -EINVAL; + } +@@ -3514,11 +3512,11 @@ static void vxlan_config_apply(struct net_device *dev, + struct vxlan_dev *vxlan = netdev_priv(dev); + struct vxlan_rdst *dst = &vxlan->default_dst; + unsigned short needed_headroom = ETH_HLEN; +- bool use_ipv6 = !!(conf->flags & VXLAN_F_IPV6); + int max_mtu = ETH_MAX_MTU; ++ u32 flags = conf->flags; + + if (!changelink) { +- if (conf->flags & VXLAN_F_GPE) ++ if (flags & VXLAN_F_GPE) + vxlan_raw_setup(dev); + else + vxlan_ether_setup(dev); +@@ -3544,8 +3542,7 @@ static void vxlan_config_apply(struct net_device *dev, + + dev->needed_tailroom = lowerdev->needed_tailroom; + +- max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : +- VXLAN_HEADROOM); ++ max_mtu = lowerdev->mtu - vxlan_headroom(flags); + if (max_mtu < ETH_MIN_MTU) + max_mtu = ETH_MIN_MTU; + +@@ -3556,10 +3553,9 @@ static void vxlan_config_apply(struct net_device *dev, + if (dev->mtu > max_mtu) + dev->mtu = max_mtu; + +- if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA) +- needed_headroom += VXLAN6_HEADROOM; +- else +- needed_headroom += VXLAN_HEADROOM; ++ if (flags & VXLAN_F_COLLECT_METADATA) ++ flags |= VXLAN_F_IPV6; ++ needed_headroom += vxlan_headroom(flags); + dev->needed_headroom = needed_headroom; + + memcpy(&vxlan->cfg, conf, sizeof(*conf)); +diff --git a/include/net/vxlan.h b/include/net/vxlan.h +index 373aadcfea21d..d79ee21d7932a 100644 +--- a/include/net/vxlan.h ++++ b/include/net/vxlan.h +@@ -323,10 +323,15 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb, + return features; + } + +-/* IP header + UDP + VXLAN + Ethernet header */ +-#define VXLAN_HEADROOM (20 + 8 + 8 + 14) +-/* IPv6 header + UDP + VXLAN + Ethernet header */ +-#define VXLAN6_HEADROOM (40 + 8 + 8 + 14) ++static inline int vxlan_headroom(u32 flags) ++{ ++ /* VXLAN: IP4/6 header + UDP + VXLAN + Ethernet header */ ++ /* VXLAN-GPE: IP4/6 header + UDP + VXLAN */ ++ return (flags & VXLAN_F_IPV6 ? sizeof(struct ipv6hdr) : ++ sizeof(struct iphdr)) + ++ sizeof(struct udphdr) + sizeof(struct vxlanhdr) + ++ (flags & VXLAN_F_GPE ? 0 : ETH_HLEN); ++} + + static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb) + { +-- +2.39.2 + -- 2.47.3