From d512f357ff01b0ad7a42c4076ad9689d89d9a7ca Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sun, 2 Jan 2022 16:57:06 -0500 Subject: [PATCH] Fixes for 4.19 Signed-off-by: Sasha Levin --- ...sing-put_device-call-in-fman_port_pr.patch | 82 ++++++ ...ong-features-assignment-in-case-of-e.patch | 87 ++++++ ...sus-do-not-drop-long-ethernet-frames.patch | 63 ++++ ...-memory-leak-in-device-probe-and-rem.patch | 101 +++++++ ...ate-string-in-lpfc_debugfs_nvmeio_tr.patch | 40 +++ .../sctp-use-call_rcu-to-free-endpoint.patch | 277 ++++++++++++++++++ ...ate-udpgso-segment-count-without-hea.patch | 70 +++++ ...-udpgso_bench_tx-fix-dst-ip-argument.patch | 63 ++++ queue-4.19/series | 9 + ...len-to-cap-ipv6-udp-max-gso-segments.patch | 44 +++ 10 files changed, 836 insertions(+) create mode 100644 queue-4.19/fsl-fman-fix-missing-put_device-call-in-fman_port_pr.patch create mode 100644 queue-4.19/net-mlx5e-fix-wrong-features-assignment-in-case-of-e.patch create mode 100644 queue-4.19/net-usb-pegasus-do-not-drop-long-ethernet-frames.patch create mode 100644 queue-4.19/nfc-st21nfca-fix-memory-leak-in-device-probe-and-rem.patch create mode 100644 queue-4.19/scsi-lpfc-terminate-string-in-lpfc_debugfs_nvmeio_tr.patch create mode 100644 queue-4.19/sctp-use-call_rcu-to-free-endpoint.patch create mode 100644 queue-4.19/selftests-calculate-udpgso-segment-count-without-hea.patch create mode 100644 queue-4.19/selftests-net-udpgso_bench_tx-fix-dst-ip-argument.patch create mode 100644 queue-4.19/udp-using-datalen-to-cap-ipv6-udp-max-gso-segments.patch diff --git a/queue-4.19/fsl-fman-fix-missing-put_device-call-in-fman_port_pr.patch b/queue-4.19/fsl-fman-fix-missing-put_device-call-in-fman_port_pr.patch new file mode 100644 index 00000000000..f8373f274e9 --- /dev/null +++ b/queue-4.19/fsl-fman-fix-missing-put_device-call-in-fman_port_pr.patch @@ -0,0 +1,82 @@ +From a4cce9a251627ea8bb82c684273f073dfadc5204 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Dec 2021 12:26:27 +0000 +Subject: fsl/fman: Fix missing put_device() call in fman_port_probe + +From: Miaoqian Lin + +[ Upstream commit bf2b09fedc17248b315f80fb249087b7d28a69a6 ] + +The reference taken by 'of_find_device_by_node()' must be released when +not needed anymore. +Add the corresponding 'put_device()' in the and error handling paths. + +Fixes: 18a6c85fcc78 ("fsl/fman: Add FMan Port Support") +Signed-off-by: Miaoqian Lin +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/freescale/fman/fman_port.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c +index 47f6fee1f3964..1812434cda847 100644 +--- a/drivers/net/ethernet/freescale/fman/fman_port.c ++++ b/drivers/net/ethernet/freescale/fman/fman_port.c +@@ -1791,7 +1791,7 @@ static int fman_port_probe(struct platform_device *of_dev) + fman = dev_get_drvdata(&fm_pdev->dev); + if (!fman) { + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + + err = of_property_read_u32(port_node, "cell-index", &val); +@@ -1799,7 +1799,7 @@ static int fman_port_probe(struct platform_device *of_dev) + dev_err(port->dev, "%s: reading cell-index for %pOF failed\n", + __func__, port_node); + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + port_id = (u8)val; + port->dts_params.id = port_id; +@@ -1833,7 +1833,7 @@ static int fman_port_probe(struct platform_device *of_dev) + } else { + dev_err(port->dev, "%s: Illegal port type\n", __func__); + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + + port->dts_params.type = port_type; +@@ -1847,7 +1847,7 @@ static int fman_port_probe(struct platform_device *of_dev) + dev_err(port->dev, "%s: incorrect qman-channel-id\n", + __func__); + err = -EINVAL; +- goto return_err; ++ goto put_device; + } + port->dts_params.qman_channel_id = qman_channel_id; + } +@@ -1857,7 +1857,7 @@ static int fman_port_probe(struct platform_device *of_dev) + dev_err(port->dev, "%s: of_address_to_resource() failed\n", + __func__); + err = -ENOMEM; +- goto return_err; ++ goto put_device; + } + + port->dts_params.fman = fman; +@@ -1882,6 +1882,8 @@ static int fman_port_probe(struct platform_device *of_dev) + + return 0; + ++put_device: ++ put_device(&fm_pdev->dev); + return_err: + of_node_put(port_node); + free_port: +-- +2.34.1 + diff --git a/queue-4.19/net-mlx5e-fix-wrong-features-assignment-in-case-of-e.patch b/queue-4.19/net-mlx5e-fix-wrong-features-assignment-in-case-of-e.patch new file mode 100644 index 00000000000..a6a76093fff --- /dev/null +++ b/queue-4.19/net-mlx5e-fix-wrong-features-assignment-in-case-of-e.patch @@ -0,0 +1,87 @@ +From 7f07d5dc7d2ab24c98be569c880615dd45cfc53c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 29 Nov 2021 11:08:41 +0200 +Subject: net/mlx5e: Fix wrong features assignment in case of error + +From: Gal Pressman + +[ Upstream commit 992d8a4e38f0527f24e273ce3a9cd6dea1a6a436 ] + +In case of an error in mlx5e_set_features(), 'netdev->features' must be +updated with the correct state of the device to indicate which features +were updated successfully. +To do that we maintain a copy of 'netdev->features' and update it after +successful feature changes, so we can assign it to back to +'netdev->features' if needed. + +However, since not all netdev features are handled by the driver (e.g. +GRO/TSO/etc), some features may not be updated correctly in case of an +error updating another feature. + +For example, while requesting to disable TSO (feature which is not +handled by the driver) and enable HW-GRO, if an error occurs during +HW-GRO enable, 'oper_features' will be assigned with 'netdev->features' +and HW-GRO turned off. TSO will remain enabled in such case, which is a +bug. + +To solve that, instead of using 'netdev->features' as the baseline of +'oper_features' and changing it on set feature success, use 'features' +instead and update it in case of errors. + +Fixes: 75b81ce719b7 ("net/mlx5e: Don't override netdev features field unless in error flow") +Signed-off-by: Gal Pressman +Signed-off-by: Saeed Mahameed +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 9003702892cda..5979fcf124bb4 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -3666,12 +3666,11 @@ static int set_feature_arfs(struct net_device *netdev, bool enable) + + static int mlx5e_handle_feature(struct net_device *netdev, + netdev_features_t *features, +- netdev_features_t wanted_features, + netdev_features_t feature, + mlx5e_feature_handler feature_handler) + { +- netdev_features_t changes = wanted_features ^ netdev->features; +- bool enable = !!(wanted_features & feature); ++ netdev_features_t changes = *features ^ netdev->features; ++ bool enable = !!(*features & feature); + int err; + + if (!(changes & feature)) +@@ -3679,23 +3678,23 @@ static int mlx5e_handle_feature(struct net_device *netdev, + + err = feature_handler(netdev, enable); + if (err) { ++ MLX5E_SET_FEATURE(features, feature, !enable); + netdev_err(netdev, "%s feature %pNF failed, err %d\n", + enable ? "Enable" : "Disable", &feature, err); + return err; + } + +- MLX5E_SET_FEATURE(features, feature, enable); + return 0; + } + + static int mlx5e_set_features(struct net_device *netdev, + netdev_features_t features) + { +- netdev_features_t oper_features = netdev->features; ++ netdev_features_t oper_features = features; + int err = 0; + + #define MLX5E_HANDLE_FEATURE(feature, handler) \ +- mlx5e_handle_feature(netdev, &oper_features, features, feature, handler) ++ mlx5e_handle_feature(netdev, &oper_features, feature, handler) + + err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro); + err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER, +-- +2.34.1 + diff --git a/queue-4.19/net-usb-pegasus-do-not-drop-long-ethernet-frames.patch b/queue-4.19/net-usb-pegasus-do-not-drop-long-ethernet-frames.patch new file mode 100644 index 00000000000..167a6966434 --- /dev/null +++ b/queue-4.19/net-usb-pegasus-do-not-drop-long-ethernet-frames.patch @@ -0,0 +1,63 @@ +From 4354ed54862b8af5a74b0aaffced0324f61fd6b0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Dec 2021 23:12:08 +0100 +Subject: net: usb: pegasus: Do not drop long Ethernet frames + +From: Matthias-Christian Ott + +[ Upstream commit ca506fca461b260ab32952b610c3d4aadc6c11fd ] + +The D-Link DSB-650TX (2001:4002) is unable to receive Ethernet frames +that are longer than 1518 octets, for example, Ethernet frames that +contain 802.1Q VLAN tags. + +The frames are sent to the pegasus driver via USB but the driver +discards them because they have the Long_pkt field set to 1 in the +received status report. The function read_bulk_callback of the pegasus +driver treats such received "packets" (in the terminology of the +hardware) as errors but the field simply does just indicate that the +Ethernet frame (MAC destination to FCS) is longer than 1518 octets. + +It seems that in the 1990s there was a distinction between +"giant" (> 1518) and "runt" (< 64) frames and the hardware includes +flags to indicate this distinction. It seems that the purpose of the +distinction "giant" frames was to not allow infinitely long frames due +to transmission errors and to allow hardware to have an upper limit of +the frame size. However, the hardware already has such limit with its +2048 octet receive buffer and, therefore, Long_pkt is merely a +convention and should not be treated as a receive error. + +Actually, the hardware is even able to receive Ethernet frames with 2048 +octets which exceeds the claimed limit frame size limit of the driver of +1536 octets (PEGASUS_MTU). + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Matthias-Christian Ott +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/usb/pegasus.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c +index 9f1777e56d7db..881468ff02bfa 100644 +--- a/drivers/net/usb/pegasus.c ++++ b/drivers/net/usb/pegasus.c +@@ -498,11 +498,11 @@ static void read_bulk_callback(struct urb *urb) + goto goon; + + rx_status = buf[count - 2]; +- if (rx_status & 0x1e) { ++ if (rx_status & 0x1c) { + netif_dbg(pegasus, rx_err, net, + "RX packet error %x\n", rx_status); + net->stats.rx_errors++; +- if (rx_status & 0x06) /* long or runt */ ++ if (rx_status & 0x04) /* runt */ + net->stats.rx_length_errors++; + if (rx_status & 0x08) + net->stats.rx_crc_errors++; +-- +2.34.1 + diff --git a/queue-4.19/nfc-st21nfca-fix-memory-leak-in-device-probe-and-rem.patch b/queue-4.19/nfc-st21nfca-fix-memory-leak-in-device-probe-and-rem.patch new file mode 100644 index 00000000000..a740d4fb09b --- /dev/null +++ b/queue-4.19/nfc-st21nfca-fix-memory-leak-in-device-probe-and-rem.patch @@ -0,0 +1,101 @@ +From 686172725d417e546285eab305814a6378a67050 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Dec 2021 12:48:11 +0000 +Subject: NFC: st21nfca: Fix memory leak in device probe and remove + +From: Wei Yongjun + +[ Upstream commit 1b9dadba502234eea7244879b8d5d126bfaf9f0c ] + +'phy->pending_skb' is alloced when device probe, but forgot to free +in the error handling path and remove path, this cause memory leak +as follows: + +unreferenced object 0xffff88800bc06800 (size 512): + comm "8", pid 11775, jiffies 4295159829 (age 9.032s) + hex dump (first 32 bytes): + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + backtrace: + [<00000000d66c09ce>] __kmalloc_node_track_caller+0x1ed/0x450 + [<00000000c93382b3>] kmalloc_reserve+0x37/0xd0 + [<000000005fea522c>] __alloc_skb+0x124/0x380 + [<0000000019f29f9a>] st21nfca_hci_i2c_probe+0x170/0x8f2 + +Fix it by freeing 'pending_skb' in error and remove. + +Fixes: 68957303f44a ("NFC: ST21NFCA: Add driver for STMicroelectronics ST21NFCA NFC Chip") +Reported-by: Hulk Robot +Signed-off-by: Wei Yongjun +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/nfc/st21nfca/i2c.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c +index 1b347096422ff..ebea3b4dd8e1b 100644 +--- a/drivers/nfc/st21nfca/i2c.c ++++ b/drivers/nfc/st21nfca/i2c.c +@@ -544,7 +544,8 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, + phy->gpiod_ena = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); + if (IS_ERR(phy->gpiod_ena)) { + nfc_err(dev, "Unable to get ENABLE GPIO\n"); +- return PTR_ERR(phy->gpiod_ena); ++ r = PTR_ERR(phy->gpiod_ena); ++ goto out_free; + } + + phy->se_status.is_ese_present = +@@ -555,7 +556,7 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, + r = st21nfca_hci_platform_init(phy); + if (r < 0) { + nfc_err(&client->dev, "Unable to reboot st21nfca\n"); +- return r; ++ goto out_free; + } + + r = devm_request_threaded_irq(&client->dev, client->irq, NULL, +@@ -564,15 +565,23 @@ static int st21nfca_hci_i2c_probe(struct i2c_client *client, + ST21NFCA_HCI_DRIVER_NAME, phy); + if (r < 0) { + nfc_err(&client->dev, "Unable to register IRQ handler\n"); +- return r; ++ goto out_free; + } + +- return st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, +- ST21NFCA_FRAME_HEADROOM, +- ST21NFCA_FRAME_TAILROOM, +- ST21NFCA_HCI_LLC_MAX_PAYLOAD, +- &phy->hdev, +- &phy->se_status); ++ r = st21nfca_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, ++ ST21NFCA_FRAME_HEADROOM, ++ ST21NFCA_FRAME_TAILROOM, ++ ST21NFCA_HCI_LLC_MAX_PAYLOAD, ++ &phy->hdev, ++ &phy->se_status); ++ if (r) ++ goto out_free; ++ ++ return 0; ++ ++out_free: ++ kfree_skb(phy->pending_skb); ++ return r; + } + + static int st21nfca_hci_i2c_remove(struct i2c_client *client) +@@ -585,6 +594,8 @@ static int st21nfca_hci_i2c_remove(struct i2c_client *client) + + if (phy->powered) + st21nfca_hci_i2c_disable(phy); ++ if (phy->pending_skb) ++ kfree_skb(phy->pending_skb); + + return 0; + } +-- +2.34.1 + diff --git a/queue-4.19/scsi-lpfc-terminate-string-in-lpfc_debugfs_nvmeio_tr.patch b/queue-4.19/scsi-lpfc-terminate-string-in-lpfc_debugfs_nvmeio_tr.patch new file mode 100644 index 00000000000..a3705d01b0e --- /dev/null +++ b/queue-4.19/scsi-lpfc-terminate-string-in-lpfc_debugfs_nvmeio_tr.patch @@ -0,0 +1,40 @@ +From 8f25569625c3d92e9a6e9dd73faaa30f8b5580f6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Dec 2021 10:05:27 +0300 +Subject: scsi: lpfc: Terminate string in lpfc_debugfs_nvmeio_trc_write() + +From: Dan Carpenter + +[ Upstream commit 9020be114a47bf7ff33e179b3bb0016b91a098e6 ] + +The "mybuf" string comes from the user, so we need to ensure that it is NUL +terminated. + +Link: https://lore.kernel.org/r/20211214070527.GA27934@kili +Fixes: bd2cdd5e400f ("scsi: lpfc: NVME Initiator: Add debugfs support") +Reviewed-by: James Smart +Signed-off-by: Dan Carpenter +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/scsi/lpfc/lpfc_debugfs.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c +index 2c70e311943ac..0a908d1cc494a 100644 +--- a/drivers/scsi/lpfc/lpfc_debugfs.c ++++ b/drivers/scsi/lpfc/lpfc_debugfs.c +@@ -2267,8 +2267,8 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf, + char mybuf[64]; + char *pbuf; + +- if (nbytes > 64) +- nbytes = 64; ++ if (nbytes > 63) ++ nbytes = 63; + + memset(mybuf, 0, sizeof(mybuf)); + +-- +2.34.1 + diff --git a/queue-4.19/sctp-use-call_rcu-to-free-endpoint.patch b/queue-4.19/sctp-use-call_rcu-to-free-endpoint.patch new file mode 100644 index 00000000000..9f0951caf3c --- /dev/null +++ b/queue-4.19/sctp-use-call_rcu-to-free-endpoint.patch @@ -0,0 +1,277 @@ +From 5d5053842d54b0f8fbe5c650d1ec7447681b25ca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Dec 2021 13:04:30 -0500 +Subject: sctp: use call_rcu to free endpoint + +From: Xin Long + +[ Upstream commit 5ec7d18d1813a5bead0b495045606c93873aecbb ] + +This patch is to delay the endpoint free by calling call_rcu() to fix +another use-after-free issue in sctp_sock_dump(): + + BUG: KASAN: use-after-free in __lock_acquire+0x36d9/0x4c20 + Call Trace: + __lock_acquire+0x36d9/0x4c20 kernel/locking/lockdep.c:3218 + lock_acquire+0x1ed/0x520 kernel/locking/lockdep.c:3844 + __raw_spin_lock_bh include/linux/spinlock_api_smp.h:135 [inline] + _raw_spin_lock_bh+0x31/0x40 kernel/locking/spinlock.c:168 + spin_lock_bh include/linux/spinlock.h:334 [inline] + __lock_sock+0x203/0x350 net/core/sock.c:2253 + lock_sock_nested+0xfe/0x120 net/core/sock.c:2774 + lock_sock include/net/sock.h:1492 [inline] + sctp_sock_dump+0x122/0xb20 net/sctp/diag.c:324 + sctp_for_each_transport+0x2b5/0x370 net/sctp/socket.c:5091 + sctp_diag_dump+0x3ac/0x660 net/sctp/diag.c:527 + __inet_diag_dump+0xa8/0x140 net/ipv4/inet_diag.c:1049 + inet_diag_dump+0x9b/0x110 net/ipv4/inet_diag.c:1065 + netlink_dump+0x606/0x1080 net/netlink/af_netlink.c:2244 + __netlink_dump_start+0x59a/0x7c0 net/netlink/af_netlink.c:2352 + netlink_dump_start include/linux/netlink.h:216 [inline] + inet_diag_handler_cmd+0x2ce/0x3f0 net/ipv4/inet_diag.c:1170 + __sock_diag_cmd net/core/sock_diag.c:232 [inline] + sock_diag_rcv_msg+0x31d/0x410 net/core/sock_diag.c:263 + netlink_rcv_skb+0x172/0x440 net/netlink/af_netlink.c:2477 + sock_diag_rcv+0x2a/0x40 net/core/sock_diag.c:274 + +This issue occurs when asoc is peeled off and the old sk is freed after +getting it by asoc->base.sk and before calling lock_sock(sk). + +To prevent the sk free, as a holder of the sk, ep should be alive when +calling lock_sock(). This patch uses call_rcu() and moves sock_put and +ep free into sctp_endpoint_destroy_rcu(), so that it's safe to try to +hold the ep under rcu_read_lock in sctp_transport_traverse_process(). + +If sctp_endpoint_hold() returns true, it means this ep is still alive +and we have held it and can continue to dump it; If it returns false, +it means this ep is dead and can be freed after rcu_read_unlock, and +we should skip it. + +In sctp_sock_dump(), after locking the sk, if this ep is different from +tsp->asoc->ep, it means during this dumping, this asoc was peeled off +before calling lock_sock(), and the sk should be skipped; If this ep is +the same with tsp->asoc->ep, it means no peeloff happens on this asoc, +and due to lock_sock, no peeloff will happen either until release_sock. + +Note that delaying endpoint free won't delay the port release, as the +port release happens in sctp_endpoint_destroy() before calling call_rcu(). +Also, freeing endpoint by call_rcu() makes it safe to access the sk by +asoc->base.sk in sctp_assocs_seq_show() and sctp_rcv(). + +Thanks Jones to bring this issue up. + +v1->v2: + - improve the changelog. + - add kfree(ep) into sctp_endpoint_destroy_rcu(), as Jakub noticed. + +Reported-by: syzbot+9276d76e83e3bcde6c99@syzkaller.appspotmail.com +Reported-by: Lee Jones +Fixes: d25adbeb0cdb ("sctp: fix an use-after-free issue in sctp_sock_dump") +Signed-off-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/sctp/sctp.h | 6 +++--- + include/net/sctp/structs.h | 3 ++- + net/sctp/diag.c | 12 ++++++------ + net/sctp/endpointola.c | 23 +++++++++++++++-------- + net/sctp/socket.c | 23 +++++++++++++++-------- + 5 files changed, 41 insertions(+), 26 deletions(-) + +diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h +index 2c6570e6fcfec..903b2ddde1b43 100644 +--- a/include/net/sctp/sctp.h ++++ b/include/net/sctp/sctp.h +@@ -118,6 +118,7 @@ extern struct percpu_counter sctp_sockets_allocated; + int sctp_asconf_mgmt(struct sctp_sock *, struct sctp_sockaddr_entry *); + struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); + ++typedef int (*sctp_callback_t)(struct sctp_endpoint *, struct sctp_transport *, void *); + void sctp_transport_walk_start(struct rhashtable_iter *iter); + void sctp_transport_walk_stop(struct rhashtable_iter *iter); + struct sctp_transport *sctp_transport_get_next(struct net *net, +@@ -128,9 +129,8 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), + struct net *net, + const union sctp_addr *laddr, + const union sctp_addr *paddr, void *p); +-int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), +- int (*cb_done)(struct sctp_transport *, void *), +- struct net *net, int *pos, void *p); ++int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done, ++ struct net *net, int *pos, void *p); + int sctp_for_each_endpoint(int (*cb)(struct sctp_endpoint *, void *), void *p); + int sctp_get_sctp_info(struct sock *sk, struct sctp_association *asoc, + struct sctp_info *info); +diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h +index 2882bc7a5b4b8..18f9924aa2507 100644 +--- a/include/net/sctp/structs.h ++++ b/include/net/sctp/structs.h +@@ -1348,6 +1348,7 @@ struct sctp_endpoint { + + u32 secid; + u32 peer_secid; ++ struct rcu_head rcu; + }; + + /* Recover the outter endpoint structure. */ +@@ -1363,7 +1364,7 @@ static inline struct sctp_endpoint *sctp_ep(struct sctp_ep_common *base) + struct sctp_endpoint *sctp_endpoint_new(struct sock *, gfp_t); + void sctp_endpoint_free(struct sctp_endpoint *); + void sctp_endpoint_put(struct sctp_endpoint *); +-void sctp_endpoint_hold(struct sctp_endpoint *); ++int sctp_endpoint_hold(struct sctp_endpoint *ep); + void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *); + struct sctp_association *sctp_endpoint_lookup_assoc( + const struct sctp_endpoint *ep, +diff --git a/net/sctp/diag.c b/net/sctp/diag.c +index 8767405de9fa4..0a9db0a7f4234 100644 +--- a/net/sctp/diag.c ++++ b/net/sctp/diag.c +@@ -307,9 +307,8 @@ out: + return err; + } + +-static int sctp_sock_dump(struct sctp_transport *tsp, void *p) ++static int sctp_sock_dump(struct sctp_endpoint *ep, struct sctp_transport *tsp, void *p) + { +- struct sctp_endpoint *ep = tsp->asoc->ep; + struct sctp_comm_param *commp = p; + struct sock *sk = ep->base.sk; + struct sk_buff *skb = commp->skb; +@@ -319,6 +318,8 @@ static int sctp_sock_dump(struct sctp_transport *tsp, void *p) + int err = 0; + + lock_sock(sk); ++ if (ep != tsp->asoc->ep) ++ goto release; + list_for_each_entry(assoc, &ep->asocs, asocs) { + if (cb->args[4] < cb->args[1]) + goto next; +@@ -361,9 +362,8 @@ release: + return err; + } + +-static int sctp_sock_filter(struct sctp_transport *tsp, void *p) ++static int sctp_sock_filter(struct sctp_endpoint *ep, struct sctp_transport *tsp, void *p) + { +- struct sctp_endpoint *ep = tsp->asoc->ep; + struct sctp_comm_param *commp = p; + struct sock *sk = ep->base.sk; + const struct inet_diag_req_v2 *r = commp->r; +@@ -521,8 +521,8 @@ skip: + if (!(idiag_states & ~(TCPF_LISTEN | TCPF_CLOSE))) + goto done; + +- sctp_for_each_transport(sctp_sock_filter, sctp_sock_dump, +- net, &pos, &commp); ++ sctp_transport_traverse_process(sctp_sock_filter, sctp_sock_dump, ++ net, &pos, &commp); + cb->args[2] = pos; + + done: +diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c +index 8640dedcf64f1..c4068451b9c76 100644 +--- a/net/sctp/endpointola.c ++++ b/net/sctp/endpointola.c +@@ -242,6 +242,18 @@ void sctp_endpoint_free(struct sctp_endpoint *ep) + } + + /* Final destructor for endpoint. */ ++static void sctp_endpoint_destroy_rcu(struct rcu_head *head) ++{ ++ struct sctp_endpoint *ep = container_of(head, struct sctp_endpoint, rcu); ++ struct sock *sk = ep->base.sk; ++ ++ sctp_sk(sk)->ep = NULL; ++ sock_put(sk); ++ ++ kfree(ep); ++ SCTP_DBG_OBJCNT_DEC(ep); ++} ++ + static void sctp_endpoint_destroy(struct sctp_endpoint *ep) + { + struct sock *sk; +@@ -275,18 +287,13 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) + if (sctp_sk(sk)->bind_hash) + sctp_put_port(sk); + +- sctp_sk(sk)->ep = NULL; +- /* Give up our hold on the sock */ +- sock_put(sk); +- +- kfree(ep); +- SCTP_DBG_OBJCNT_DEC(ep); ++ call_rcu(&ep->rcu, sctp_endpoint_destroy_rcu); + } + + /* Hold a reference to an endpoint. */ +-void sctp_endpoint_hold(struct sctp_endpoint *ep) ++int sctp_endpoint_hold(struct sctp_endpoint *ep) + { +- refcount_inc(&ep->base.refcnt); ++ return refcount_inc_not_zero(&ep->base.refcnt); + } + + /* Release a reference to an endpoint and clean up if there are +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 1148f66917079..d429d59228041 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -5056,11 +5056,12 @@ int sctp_transport_lookup_process(int (*cb)(struct sctp_transport *, void *), + } + EXPORT_SYMBOL_GPL(sctp_transport_lookup_process); + +-int sctp_for_each_transport(int (*cb)(struct sctp_transport *, void *), +- int (*cb_done)(struct sctp_transport *, void *), +- struct net *net, int *pos, void *p) { ++int sctp_transport_traverse_process(sctp_callback_t cb, sctp_callback_t cb_done, ++ struct net *net, int *pos, void *p) ++{ + struct rhashtable_iter hti; + struct sctp_transport *tsp; ++ struct sctp_endpoint *ep; + int ret; + + again: +@@ -5069,26 +5070,32 @@ again: + + tsp = sctp_transport_get_idx(net, &hti, *pos + 1); + for (; !IS_ERR_OR_NULL(tsp); tsp = sctp_transport_get_next(net, &hti)) { +- ret = cb(tsp, p); +- if (ret) +- break; ++ ep = tsp->asoc->ep; ++ if (sctp_endpoint_hold(ep)) { /* asoc can be peeled off */ ++ ret = cb(ep, tsp, p); ++ if (ret) ++ break; ++ sctp_endpoint_put(ep); ++ } + (*pos)++; + sctp_transport_put(tsp); + } + sctp_transport_walk_stop(&hti); + + if (ret) { +- if (cb_done && !cb_done(tsp, p)) { ++ if (cb_done && !cb_done(ep, tsp, p)) { + (*pos)++; ++ sctp_endpoint_put(ep); + sctp_transport_put(tsp); + goto again; + } ++ sctp_endpoint_put(ep); + sctp_transport_put(tsp); + } + + return ret; + } +-EXPORT_SYMBOL_GPL(sctp_for_each_transport); ++EXPORT_SYMBOL_GPL(sctp_transport_traverse_process); + + /* 7.2.1 Association Status (SCTP_STATUS) + +-- +2.34.1 + diff --git a/queue-4.19/selftests-calculate-udpgso-segment-count-without-hea.patch b/queue-4.19/selftests-calculate-udpgso-segment-count-without-hea.patch new file mode 100644 index 00000000000..c00175f5719 --- /dev/null +++ b/queue-4.19/selftests-calculate-udpgso-segment-count-without-hea.patch @@ -0,0 +1,70 @@ +From 3cb7341d2e748ffa04a1ebf9e1350866f74e3fdb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Dec 2021 22:24:41 +0000 +Subject: selftests: Calculate udpgso segment count without header adjustment + +From: Coco Li + +[ Upstream commit 5471d5226c3b39b3d2f7011c082d5715795bd65c ] + +The below referenced commit correctly updated the computation of number +of segments (gso_size) by using only the gso payload size and +removing the header lengths. + +With this change the regression test started failing. Update +the tests to match this new behavior. + +Both IPv4 and IPv6 tests are updated, as a separate patch in this series +will update udp_v6_send_skb to match this change in udp_send_skb. + +Fixes: 158390e45612 ("udp: using datalen to cap max gso segments") +Signed-off-by: Coco Li +Reviewed-by: Willem de Bruijn +Link: https://lore.kernel.org/r/20211223222441.2975883-2-lixiaoyan@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/udpgso.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/tools/testing/selftests/net/udpgso.c b/tools/testing/selftests/net/udpgso.c +index 270c17ab071e4..23177b6436067 100644 +--- a/tools/testing/selftests/net/udpgso.c ++++ b/tools/testing/selftests/net/udpgso.c +@@ -157,13 +157,13 @@ struct testcase testcases_v4[] = { + }, + { + /* send max number of min sized segments */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V4, ++ .tlen = UDP_MAX_SEGMENTS, + .gso_len = 1, +- .r_num_mss = UDP_MAX_SEGMENTS - CONST_HDRLEN_V4, ++ .r_num_mss = UDP_MAX_SEGMENTS, + }, + { + /* send max number + 1 of min sized segments: fail */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V4 + 1, ++ .tlen = UDP_MAX_SEGMENTS + 1, + .gso_len = 1, + .tfail = true, + }, +@@ -260,13 +260,13 @@ struct testcase testcases_v6[] = { + }, + { + /* send max number of min sized segments */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V6, ++ .tlen = UDP_MAX_SEGMENTS, + .gso_len = 1, +- .r_num_mss = UDP_MAX_SEGMENTS - CONST_HDRLEN_V6, ++ .r_num_mss = UDP_MAX_SEGMENTS, + }, + { + /* send max number + 1 of min sized segments: fail */ +- .tlen = UDP_MAX_SEGMENTS - CONST_HDRLEN_V6 + 1, ++ .tlen = UDP_MAX_SEGMENTS + 1, + .gso_len = 1, + .tfail = true, + }, +-- +2.34.1 + diff --git a/queue-4.19/selftests-net-udpgso_bench_tx-fix-dst-ip-argument.patch b/queue-4.19/selftests-net-udpgso_bench_tx-fix-dst-ip-argument.patch new file mode 100644 index 00000000000..5ae1503c524 --- /dev/null +++ b/queue-4.19/selftests-net-udpgso_bench_tx-fix-dst-ip-argument.patch @@ -0,0 +1,63 @@ +From 6a97350858affb4547cbad2f7ec8540c77979fe1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Dec 2021 18:58:10 +0800 +Subject: selftests/net: udpgso_bench_tx: fix dst ip argument + +From: wujianguo + +[ Upstream commit 9c1952aeaa98b3cfc49e2a79cb2c7d6a674213e9 ] + +udpgso_bench_tx call setup_sockaddr() for dest address before +parsing all arguments, if we specify "-p ${dst_port}" after "-D ${dst_ip}", +then ${dst_port} will be ignored, and using default cfg_port 8000. + +This will cause test case "multiple GRO socks" failed in udpgro.sh. + +Setup sockaddr after parsing all arguments. + +Fixes: 3a687bef148d ("selftests: udp gso benchmark") +Signed-off-by: Jianguo Wu +Reviewed-by: Willem de Bruijn +Link: https://lore.kernel.org/r/ff620d9f-5b52-06ab-5286-44b945453002@163.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/net/udpgso_bench_tx.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/tools/testing/selftests/net/udpgso_bench_tx.c b/tools/testing/selftests/net/udpgso_bench_tx.c +index e821564053cfb..463a2cbd0261a 100644 +--- a/tools/testing/selftests/net/udpgso_bench_tx.c ++++ b/tools/testing/selftests/net/udpgso_bench_tx.c +@@ -247,6 +247,7 @@ static void usage(const char *filepath) + + static void parse_opts(int argc, char **argv) + { ++ const char *bind_addr = NULL; + int max_len, hdrlen; + int c; + +@@ -271,7 +272,7 @@ static void parse_opts(int argc, char **argv) + cfg_cpu = strtol(optarg, NULL, 0); + break; + case 'D': +- setup_sockaddr(cfg_family, optarg, &cfg_dst_addr); ++ bind_addr = optarg; + break; + case 'l': + cfg_runtime_ms = strtoul(optarg, NULL, 10) * 1000; +@@ -300,6 +301,11 @@ static void parse_opts(int argc, char **argv) + } + } + ++ if (!bind_addr) ++ bind_addr = cfg_family == PF_INET6 ? "::" : "0.0.0.0"; ++ ++ setup_sockaddr(cfg_family, bind_addr, &cfg_dst_addr); ++ + if (optind != argc) + usage(argv[0]); + +-- +2.34.1 + diff --git a/queue-4.19/series b/queue-4.19/series index 934a2bc52e8..8f2e36544d6 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -5,3 +5,12 @@ input-i8042-enable-deferred-probe-quirk-for-asus-um3.patch platform-x86-apple-gmux-use-resource_size-with-res.patch recordmcount.pl-fix-typo-in-s390-mcount-regex.patch selinux-initialize-proto-variable-in-selinux_ip_postroute_compat.patch +scsi-lpfc-terminate-string-in-lpfc_debugfs_nvmeio_tr.patch +udp-using-datalen-to-cap-ipv6-udp-max-gso-segments.patch +selftests-calculate-udpgso-segment-count-without-hea.patch +sctp-use-call_rcu-to-free-endpoint.patch +net-usb-pegasus-do-not-drop-long-ethernet-frames.patch +nfc-st21nfca-fix-memory-leak-in-device-probe-and-rem.patch +net-mlx5e-fix-wrong-features-assignment-in-case-of-e.patch +selftests-net-udpgso_bench_tx-fix-dst-ip-argument.patch +fsl-fman-fix-missing-put_device-call-in-fman_port_pr.patch diff --git a/queue-4.19/udp-using-datalen-to-cap-ipv6-udp-max-gso-segments.patch b/queue-4.19/udp-using-datalen-to-cap-ipv6-udp-max-gso-segments.patch new file mode 100644 index 00000000000..3635f3cec18 --- /dev/null +++ b/queue-4.19/udp-using-datalen-to-cap-ipv6-udp-max-gso-segments.patch @@ -0,0 +1,44 @@ +From 470ed62ae1ac8baa185701d597a8315a98ca6353 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Dec 2021 22:24:40 +0000 +Subject: udp: using datalen to cap ipv6 udp max gso segments + +From: Coco Li + +[ Upstream commit 736ef37fd9a44f5966e25319d08ff7ea99ac79e8 ] + +The max number of UDP gso segments is intended to cap to +UDP_MAX_SEGMENTS, this is checked in udp_send_skb(). + +skb->len contains network and transport header len here, we should use +only data len instead. + +This is the ipv6 counterpart to the below referenced commit, +which missed the ipv6 change + +Fixes: 158390e45612 ("udp: using datalen to cap max gso segments") +Signed-off-by: Coco Li +Reviewed-by: Willem de Bruijn +Link: https://lore.kernel.org/r/20211223222441.2975883-1-lixiaoyan@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/udp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c +index 0198910c2bf27..7d3caafdf2059 100644 +--- a/net/ipv6/udp.c ++++ b/net/ipv6/udp.c +@@ -1069,7 +1069,7 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6, + kfree_skb(skb); + return -EINVAL; + } +- if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) { ++ if (datalen > cork->gso_size * UDP_MAX_SEGMENTS) { + kfree_skb(skb); + return -EINVAL; + } +-- +2.34.1 + -- 2.47.3