--- /dev/null
+From a65752a6372cfe2f82366306ffe39165b8f9c361 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 14:39:03 +0000
+Subject: afs: Increase buffer size in afs_update_volume_status()
+
+From: Daniil Dulov <d.dulov@aladdin.ru>
+
+[ Upstream commit 6ea38e2aeb72349cad50e38899b0ba6fbcb2af3d ]
+
+The max length of volume->vid value is 20 characters.
+So increase idbuf[] size up to 24 to avoid overflow.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+[DH: Actually, it's 20 + NUL, so increase it to 24 and use snprintf()]
+
+Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation")
+Signed-off-by: Daniil Dulov <d.dulov@aladdin.ru>
+Signed-off-by: David Howells <dhowells@redhat.com>
+Link: https://lore.kernel.org/r/20240211150442.3416-1-d.dulov@aladdin.ru/ # v1
+Link: https://lore.kernel.org/r/20240212083347.10742-1-d.dulov@aladdin.ru/ # v2
+Link: https://lore.kernel.org/r/20240219143906.138346-3-dhowells@redhat.com
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/afs/volume.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/afs/volume.c b/fs/afs/volume.c
+index 1c9144e3e83ac..a146d70efa650 100644
+--- a/fs/afs/volume.c
++++ b/fs/afs/volume.c
+@@ -341,7 +341,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
+ {
+ struct afs_server_list *new, *old, *discard;
+ struct afs_vldb_entry *vldb;
+- char idbuf[16];
++ char idbuf[24];
+ int ret, idsz;
+
+ _enter("");
+@@ -349,7 +349,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key)
+ /* We look up an ID by passing it as a decimal string in the
+ * operation's name parameter.
+ */
+- idsz = sprintf(idbuf, "%llu", volume->vid);
++ idsz = snprintf(idbuf, sizeof(idbuf), "%llu", volume->vid);
+
+ vldb = afs_vl_lookup_vldb(volume->cell, key, idbuf, idsz);
+ if (IS_ERR(vldb)) {
+--
+2.43.0
+
--- /dev/null
+From 0fde352f5cd32e52437427f3f3afd3c7e20b4792 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jan 2024 11:16:56 +0100
+Subject: arm64: dts: rockchip: set num-cs property for spi on px30
+
+From: Heiko Stuebner <heiko.stuebner@cherry.de>
+
+[ Upstream commit 334bf0710c98d391f4067b72f535d6c4c84dfb6f ]
+
+The px30 has two spi controllers with two chip-selects each.
+The num-cs property is specified as the total number of chip
+selects a controllers has and is used since 2020 to find uses
+of chipselects outside that range in the Rockchip spi driver.
+
+Without the property set, the default is 1, so spi devices
+using the second chipselect will not be created.
+
+Fixes: eb1262e3cc8b ("spi: spi-rockchip: use num-cs property and ctlr->enable_gpiods")
+Signed-off-by: Heiko Stuebner <heiko.stuebner@cherry.de>
+Reviewed-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
+Link: https://lore.kernel.org/r/20240119101656.965744-1-heiko@sntech.de
+Signed-off-by: Heiko Stuebner <heiko@sntech.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/rockchip/px30.dtsi | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi b/arch/arm64/boot/dts/rockchip/px30.dtsi
+index bfa3580429d10..61f0186447dad 100644
+--- a/arch/arm64/boot/dts/rockchip/px30.dtsi
++++ b/arch/arm64/boot/dts/rockchip/px30.dtsi
+@@ -607,6 +607,7 @@
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac 12>, <&dmac 13>;
+ dma-names = "tx", "rx";
++ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_clk &spi0_csn &spi0_miso &spi0_mosi>;
+ #address-cells = <1>;
+@@ -622,6 +623,7 @@
+ clock-names = "spiclk", "apb_pclk";
+ dmas = <&dmac 14>, <&dmac 15>;
+ dma-names = "tx", "rx";
++ num-cs = <2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_clk &spi1_csn0 &spi1_csn1 &spi1_miso &spi1_mosi>;
+ #address-cells = <1>;
+--
+2.43.0
+
--- /dev/null
+From d9397ef594bd26a946745e7f94e350618f180d2f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 23:06:32 +0000
+Subject: arm64/sme: Restore SME registers on exit from suspend
+
+From: Mark Brown <broonie@kernel.org>
+
+[ Upstream commit 9533864816fb4a6207c63b7a98396351ce1a9fae ]
+
+The fields in SMCR_EL1 and SMPRI_EL1 reset to an architecturally UNKNOWN
+value. Since we do not otherwise manage the traps configured in this
+register at runtime we need to reconfigure them after a suspend in case
+nothing else was kind enough to preserve them for us.
+
+The vector length will be restored as part of restoring the SME state for
+the next SME using task.
+
+Fixes: a1f4ccd25cc2 ("arm64/sme: Provide Kconfig for SME")
+Reported-by: Jackson Cooper-Driver <Jackson.Cooper-Driver@arm.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/20240213-arm64-sme-resume-v3-1-17e05e493471@kernel.org
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/include/asm/fpsimd.h | 2 ++
+ arch/arm64/kernel/fpsimd.c | 14 ++++++++++++++
+ arch/arm64/kernel/suspend.c | 3 +++
+ 3 files changed, 19 insertions(+)
+
+diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
+index d720b6f7e5f9c..da18413712c04 100644
+--- a/arch/arm64/include/asm/fpsimd.h
++++ b/arch/arm64/include/asm/fpsimd.h
+@@ -343,6 +343,7 @@ extern void sme_alloc(struct task_struct *task, bool flush);
+ extern unsigned int sme_get_vl(void);
+ extern int sme_set_current_vl(unsigned long arg);
+ extern int sme_get_current_vl(void);
++extern void sme_suspend_exit(void);
+
+ /*
+ * Return how many bytes of memory are required to store the full SME
+@@ -372,6 +373,7 @@ static inline int sme_max_vl(void) { return 0; }
+ static inline int sme_max_virtualisable_vl(void) { return 0; }
+ static inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; }
+ static inline int sme_get_current_vl(void) { return -EINVAL; }
++static inline void sme_suspend_exit(void) { }
+
+ static inline size_t za_state_size(struct task_struct const *task)
+ {
+diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
+index 8c226d79abdfc..59b5a16bab5d6 100644
+--- a/arch/arm64/kernel/fpsimd.c
++++ b/arch/arm64/kernel/fpsimd.c
+@@ -1347,6 +1347,20 @@ void __init sme_setup(void)
+ get_sme_default_vl());
+ }
+
++void sme_suspend_exit(void)
++{
++ u64 smcr = 0;
++
++ if (!system_supports_sme())
++ return;
++
++ if (system_supports_fa64())
++ smcr |= SMCR_ELx_FA64;
++
++ write_sysreg_s(smcr, SYS_SMCR_EL1);
++ write_sysreg_s(0, SYS_SMPRI_EL1);
++}
++
+ #endif /* CONFIG_ARM64_SME */
+
+ static void sve_init_regs(void)
+diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
+index 8b02d310838f9..064d996cc55b2 100644
+--- a/arch/arm64/kernel/suspend.c
++++ b/arch/arm64/kernel/suspend.c
+@@ -11,6 +11,7 @@
+ #include <asm/daifflags.h>
+ #include <asm/debug-monitors.h>
+ #include <asm/exec.h>
++#include <asm/fpsimd.h>
+ #include <asm/mte.h>
+ #include <asm/memory.h>
+ #include <asm/mmu_context.h>
+@@ -77,6 +78,8 @@ void notrace __cpu_suspend_exit(void)
+ */
+ spectre_v4_enable_mitigation(NULL);
+
++ sme_suspend_exit();
++
+ /* Restore additional feature-specific configuration */
+ ptrauth_suspend_exit();
+ }
+--
+2.43.0
+
--- /dev/null
+From f3c32de86f769a5d6ee79bc5ddc66e2b1b939948 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Feb 2024 23:44:57 +0530
+Subject: ata: ahci_ceva: fix error handling for Xilinx GT PHY support
+
+From: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+
+[ Upstream commit 26c8404e162b43dddcb037ba2d0cb58c0ed60aab ]
+
+Platform clock and phy error resources are not cleaned up in Xilinx GT PHY
+error path.
+
+To fix introduce the function ceva_ahci_platform_enable_resources() which
+is a customized version of ahci_platform_enable_resources() and inline with
+SATA IP programming sequence it does:
+
+- Assert SATA reset
+- Program PS GTR phy
+- Bring SATA by de-asserting the reset
+- Wait for GT lane PLL to be locked
+
+ceva_ahci_platform_enable_resources() is also used in the resume path
+as the same SATA programming sequence (as in probe) should be followed.
+Also cleanup the mixed usage of ahci_platform_enable_resources() and custom
+implementation in the probe function as both are not required.
+
+Fixes: 9a9d3abe24bb ("ata: ahci: ceva: Update the driver to support xilinx GT phy")
+Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
+Signed-off-by: Niklas Cassel <cassel@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/ahci_ceva.c | 125 +++++++++++++++++++++++++---------------
+ 1 file changed, 79 insertions(+), 46 deletions(-)
+
+diff --git a/drivers/ata/ahci_ceva.c b/drivers/ata/ahci_ceva.c
+index cb24ecf36fafe..50e07ea60e45c 100644
+--- a/drivers/ata/ahci_ceva.c
++++ b/drivers/ata/ahci_ceva.c
+@@ -88,7 +88,6 @@ struct ceva_ahci_priv {
+ u32 axicc;
+ bool is_cci_enabled;
+ int flags;
+- struct reset_control *rst;
+ };
+
+ static unsigned int ceva_ahci_read_id(struct ata_device *dev,
+@@ -189,6 +188,60 @@ static struct scsi_host_template ahci_platform_sht = {
+ AHCI_SHT(DRV_NAME),
+ };
+
++static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)
++{
++ int rc, i;
++
++ rc = ahci_platform_enable_regulators(hpriv);
++ if (rc)
++ return rc;
++
++ rc = ahci_platform_enable_clks(hpriv);
++ if (rc)
++ goto disable_regulator;
++
++ /* Assert the controller reset */
++ rc = ahci_platform_assert_rsts(hpriv);
++ if (rc)
++ goto disable_clks;
++
++ for (i = 0; i < hpriv->nports; i++) {
++ rc = phy_init(hpriv->phys[i]);
++ if (rc)
++ goto disable_rsts;
++ }
++
++ /* De-assert the controller reset */
++ ahci_platform_deassert_rsts(hpriv);
++
++ for (i = 0; i < hpriv->nports; i++) {
++ rc = phy_power_on(hpriv->phys[i]);
++ if (rc) {
++ phy_exit(hpriv->phys[i]);
++ goto disable_phys;
++ }
++ }
++
++ return 0;
++
++disable_rsts:
++ ahci_platform_deassert_rsts(hpriv);
++
++disable_phys:
++ while (--i >= 0) {
++ phy_power_off(hpriv->phys[i]);
++ phy_exit(hpriv->phys[i]);
++ }
++
++disable_clks:
++ ahci_platform_disable_clks(hpriv);
++
++disable_regulator:
++ ahci_platform_disable_regulators(hpriv);
++
++ return rc;
++}
++
+ static int ceva_ahci_probe(struct platform_device *pdev)
+ {
+ struct device_node *np = pdev->dev.of_node;
+@@ -203,47 +256,19 @@ static int ceva_ahci_probe(struct platform_device *pdev)
+ return -ENOMEM;
+
+ cevapriv->ahci_pdev = pdev;
+-
+- cevapriv->rst = devm_reset_control_get_optional_exclusive(&pdev->dev,
+- NULL);
+- if (IS_ERR(cevapriv->rst))
+- dev_err_probe(&pdev->dev, PTR_ERR(cevapriv->rst),
+- "failed to get reset\n");
+-
+ hpriv = ahci_platform_get_resources(pdev, 0);
+ if (IS_ERR(hpriv))
+ return PTR_ERR(hpriv);
+
+- if (!cevapriv->rst) {
+- rc = ahci_platform_enable_resources(hpriv);
+- if (rc)
+- return rc;
+- } else {
+- int i;
++ hpriv->rsts = devm_reset_control_get_optional_exclusive(&pdev->dev,
++ NULL);
++ if (IS_ERR(hpriv->rsts))
++ return dev_err_probe(&pdev->dev, PTR_ERR(hpriv->rsts),
++ "failed to get reset\n");
+
+- rc = ahci_platform_enable_clks(hpriv);
+- if (rc)
+- return rc;
+- /* Assert the controller reset */
+- reset_control_assert(cevapriv->rst);
+-
+- for (i = 0; i < hpriv->nports; i++) {
+- rc = phy_init(hpriv->phys[i]);
+- if (rc)
+- return rc;
+- }
+-
+- /* De-assert the controller reset */
+- reset_control_deassert(cevapriv->rst);
+-
+- for (i = 0; i < hpriv->nports; i++) {
+- rc = phy_power_on(hpriv->phys[i]);
+- if (rc) {
+- phy_exit(hpriv->phys[i]);
+- return rc;
+- }
+- }
+- }
++ rc = ceva_ahci_platform_enable_resources(hpriv);
++ if (rc)
++ return rc;
+
+ if (of_property_read_bool(np, "ceva,broken-gen2"))
+ cevapriv->flags = CEVA_FLAG_BROKEN_GEN2;
+@@ -252,52 +277,60 @@ static int ceva_ahci_probe(struct platform_device *pdev)
+ if (of_property_read_u8_array(np, "ceva,p0-cominit-params",
+ (u8 *)&cevapriv->pp2c[0], 4) < 0) {
+ dev_warn(dev, "ceva,p0-cominit-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ if (of_property_read_u8_array(np, "ceva,p1-cominit-params",
+ (u8 *)&cevapriv->pp2c[1], 4) < 0) {
+ dev_warn(dev, "ceva,p1-cominit-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ /* Read OOB timing value for COMWAKE from device-tree*/
+ if (of_property_read_u8_array(np, "ceva,p0-comwake-params",
+ (u8 *)&cevapriv->pp3c[0], 4) < 0) {
+ dev_warn(dev, "ceva,p0-comwake-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ if (of_property_read_u8_array(np, "ceva,p1-comwake-params",
+ (u8 *)&cevapriv->pp3c[1], 4) < 0) {
+ dev_warn(dev, "ceva,p1-comwake-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ /* Read phy BURST timing value from device-tree */
+ if (of_property_read_u8_array(np, "ceva,p0-burst-params",
+ (u8 *)&cevapriv->pp4c[0], 4) < 0) {
+ dev_warn(dev, "ceva,p0-burst-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ if (of_property_read_u8_array(np, "ceva,p1-burst-params",
+ (u8 *)&cevapriv->pp4c[1], 4) < 0) {
+ dev_warn(dev, "ceva,p1-burst-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ /* Read phy RETRY interval timing value from device-tree */
+ if (of_property_read_u16_array(np, "ceva,p0-retry-params",
+ (u16 *)&cevapriv->pp5c[0], 2) < 0) {
+ dev_warn(dev, "ceva,p0-retry-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ if (of_property_read_u16_array(np, "ceva,p1-retry-params",
+ (u16 *)&cevapriv->pp5c[1], 2) < 0) {
+ dev_warn(dev, "ceva,p1-retry-params property not defined\n");
+- return -EINVAL;
++ rc = -EINVAL;
++ goto disable_resources;
+ }
+
+ /*
+@@ -335,7 +368,7 @@ static int __maybe_unused ceva_ahci_resume(struct device *dev)
+ struct ahci_host_priv *hpriv = host->private_data;
+ int rc;
+
+- rc = ahci_platform_enable_resources(hpriv);
++ rc = ceva_ahci_platform_enable_resources(hpriv);
+ if (rc)
+ return rc;
+
+--
+2.43.0
+
--- /dev/null
+From b40a1d11ef5753f5ad57c0f6c6fd13daef0a1ad4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 13:12:17 -0800
+Subject: bpf: Fix racing between bpf_timer_cancel_and_free and
+ bpf_timer_cancel
+
+From: Martin KaFai Lau <martin.lau@kernel.org>
+
+[ Upstream commit 0281b919e175bb9c3128bd3872ac2903e9436e3f ]
+
+The following race is possible between bpf_timer_cancel_and_free
+and bpf_timer_cancel. It will lead a UAF on the timer->timer.
+
+bpf_timer_cancel();
+ spin_lock();
+ t = timer->time;
+ spin_unlock();
+
+ bpf_timer_cancel_and_free();
+ spin_lock();
+ t = timer->timer;
+ timer->timer = NULL;
+ spin_unlock();
+ hrtimer_cancel(&t->timer);
+ kfree(t);
+
+ /* UAF on t */
+ hrtimer_cancel(&t->timer);
+
+In bpf_timer_cancel_and_free, this patch frees the timer->timer
+after a rcu grace period. This requires a rcu_head addition
+to the "struct bpf_hrtimer". Another kfree(t) happens in bpf_timer_init,
+this does not need a kfree_rcu because it is still under the
+spin_lock and timer->timer has not been visible by others yet.
+
+In bpf_timer_cancel, rcu_read_lock() is added because this helper
+can be used in a non rcu critical section context (e.g. from
+a sleepable bpf prog). Other timer->timer usages in helpers.c
+have been audited, bpf_timer_cancel() is the only place where
+timer->timer is used outside of the spin_lock.
+
+Another solution considered is to mark a t->flag in bpf_timer_cancel
+and clear it after hrtimer_cancel() is done. In bpf_timer_cancel_and_free,
+it busy waits for the flag to be cleared before kfree(t). This patch
+goes with a straight forward solution and frees timer->timer after
+a rcu grace period.
+
+Fixes: b00628b1c7d5 ("bpf: Introduce bpf timers.")
+Suggested-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Hou Tao <houtao1@huawei.com>
+Link: https://lore.kernel.org/bpf/20240215211218.990808-1-martin.lau@linux.dev
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/helpers.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
+index 6a61a98d602cd..83f8f67e933df 100644
+--- a/kernel/bpf/helpers.c
++++ b/kernel/bpf/helpers.c
+@@ -1091,6 +1091,7 @@ struct bpf_hrtimer {
+ struct bpf_prog *prog;
+ void __rcu *callback_fn;
+ void *value;
++ struct rcu_head rcu;
+ };
+
+ /* the actual struct hidden inside uapi struct bpf_timer */
+@@ -1312,6 +1313,7 @@ BPF_CALL_1(bpf_timer_cancel, struct bpf_timer_kern *, timer)
+
+ if (in_nmi())
+ return -EOPNOTSUPP;
++ rcu_read_lock();
+ __bpf_spin_lock_irqsave(&timer->lock);
+ t = timer->timer;
+ if (!t) {
+@@ -1333,6 +1335,7 @@ BPF_CALL_1(bpf_timer_cancel, struct bpf_timer_kern *, timer)
+ * if it was running.
+ */
+ ret = ret ?: hrtimer_cancel(&t->timer);
++ rcu_read_unlock();
+ return ret;
+ }
+
+@@ -1387,7 +1390,7 @@ void bpf_timer_cancel_and_free(void *val)
+ */
+ if (this_cpu_read(hrtimer_running) != t)
+ hrtimer_cancel(&t->timer);
+- kfree(t);
++ kfree_rcu(t, rcu);
+ }
+
+ BPF_CALL_2(bpf_kptr_xchg, void *, map_value, void *, ptr)
+--
+2.43.0
+
--- /dev/null
+From 9927185100ea7644df6d3daa30f9300cfbcdd86a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 23:05:46 +0000
+Subject: bpf, scripts: Correct GPL license name
+
+From: Gianmarco Lusvardi <glusvardi@posteo.net>
+
+[ Upstream commit e37243b65d528a8a9f8b9a57a43885f8e8dfc15c ]
+
+The bpf_doc script refers to the GPL as the "GNU Privacy License".
+I strongly suspect that the author wanted to refer to the GNU General
+Public License, under which the Linux kernel is released, as, to the
+best of my knowledge, there is no license named "GNU Privacy License".
+This patch corrects the license name in the script accordingly.
+
+Fixes: 56a092c89505 ("bpf: add script and prepare bpf.h for new helpers documentation")
+Signed-off-by: Gianmarco Lusvardi <glusvardi@posteo.net>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Reviewed-by: Quentin Monnet <quentin@isovalent.com>
+Link: https://lore.kernel.org/bpf/20240213230544.930018-3-glusvardi@posteo.net
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ scripts/bpf_doc.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py
+index d5c389df6045e..4de98b7bbea95 100755
+--- a/scripts/bpf_doc.py
++++ b/scripts/bpf_doc.py
+@@ -495,7 +495,7 @@ eBPF programs can have an associated license, passed along with the bytecode
+ instructions to the kernel when the programs are loaded. The format for that
+ string is identical to the one in use for kernel modules (Dual licenses, such
+ as "Dual BSD/GPL", may be used). Some helper functions are only accessible to
+-programs that are compatible with the GNU Privacy License (GPL).
++programs that are compatible with the GNU General Public License (GNU GPL).
+
+ In order to use such helpers, the eBPF program must be loaded with the correct
+ license string passed (via **attr**) to the **bpf**\ () system call, and this
+--
+2.43.0
+
--- /dev/null
+From 2bdda0d2f8d6d6a45074bcc1d06a26f6f8158438 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 00:09:33 +0900
+Subject: bpf, sockmap: Fix NULL pointer dereference in
+ sk_psock_verdict_data_ready()
+
+From: Shigeru Yoshida <syoshida@redhat.com>
+
+[ Upstream commit 4cd12c6065dfcdeba10f49949bffcf383b3952d8 ]
+
+syzbot reported the following NULL pointer dereference issue [1]:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000000
+ [...]
+ RIP: 0010:0x0
+ [...]
+ Call Trace:
+ <TASK>
+ sk_psock_verdict_data_ready+0x232/0x340 net/core/skmsg.c:1230
+ unix_stream_sendmsg+0x9b4/0x1230 net/unix/af_unix.c:2293
+ sock_sendmsg_nosec net/socket.c:730 [inline]
+ __sock_sendmsg+0x221/0x270 net/socket.c:745
+ ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584
+ ___sys_sendmsg net/socket.c:2638 [inline]
+ __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667
+ do_syscall_64+0xf9/0x240
+ entry_SYSCALL_64_after_hwframe+0x6f/0x77
+
+If sk_psock_verdict_data_ready() and sk_psock_stop_verdict() are called
+concurrently, psock->saved_data_ready can be NULL, causing the above issue.
+
+This patch fixes this issue by calling the appropriate data ready function
+using the sk_psock_data_ready() helper and protecting it from concurrency
+with sk->sk_callback_lock.
+
+Fixes: 6df7f764cd3c ("bpf, sockmap: Wake up polling after data copy")
+Reported-by: syzbot+fd7b34375c1c8ce29c93@syzkaller.appspotmail.com
+Signed-off-by: Shigeru Yoshida <syoshida@redhat.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Tested-by: syzbot+fd7b34375c1c8ce29c93@syzkaller.appspotmail.com
+Acked-by: John Fastabend <john.fastabend@gmail.com>
+Closes: https://syzkaller.appspot.com/bug?extid=fd7b34375c1c8ce29c93 [1]
+Link: https://lore.kernel.org/bpf/20240218150933.6004-1-syoshida@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/skmsg.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/skmsg.c b/net/core/skmsg.c
+index 3818035ea0021..39643f78cf782 100644
+--- a/net/core/skmsg.c
++++ b/net/core/skmsg.c
+@@ -1217,8 +1217,11 @@ static void sk_psock_verdict_data_ready(struct sock *sk)
+
+ rcu_read_lock();
+ psock = sk_psock(sk);
+- if (psock)
+- psock->saved_data_ready(sk);
++ if (psock) {
++ read_lock_bh(&sk->sk_callback_lock);
++ sk_psock_data_ready(sk, psock);
++ read_unlock_bh(&sk->sk_callback_lock);
++ }
+ rcu_read_unlock();
+ }
+ }
+--
+2.43.0
+
--- /dev/null
+From 7d0af6406456ee500c384154aea5ac25a7e2afae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Feb 2024 11:13:08 -0800
+Subject: dccp/tcp: Unhash sk from ehash for tb2 alloc failure after
+ check_estalblished().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 66b60b0c8c4a163b022a9f0ad6769b0fd3dc662f ]
+
+syzkaller reported a warning [0] in inet_csk_destroy_sock() with no
+repro.
+
+ WARN_ON(inet_sk(sk)->inet_num && !inet_csk(sk)->icsk_bind_hash);
+
+However, the syzkaller's log hinted that connect() failed just before
+the warning due to FAULT_INJECTION. [1]
+
+When connect() is called for an unbound socket, we search for an
+available ephemeral port. If a bhash bucket exists for the port, we
+call __inet_check_established() or __inet6_check_established() to check
+if the bucket is reusable.
+
+If reusable, we add the socket into ehash and set inet_sk(sk)->inet_num.
+
+Later, we look up the corresponding bhash2 bucket and try to allocate
+it if it does not exist.
+
+Although it rarely occurs in real use, if the allocation fails, we must
+revert the changes by check_established(). Otherwise, an unconnected
+socket could illegally occupy an ehash entry.
+
+Note that we do not put tw back into ehash because sk might have
+already responded to a packet for tw and it would be better to free
+tw earlier under such memory presure.
+
+[0]:
+WARNING: CPU: 0 PID: 350830 at net/ipv4/inet_connection_sock.c:1193 inet_csk_destroy_sock (net/ipv4/inet_connection_sock.c:1193)
+Modules linked in:
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014
+RIP: 0010:inet_csk_destroy_sock (net/ipv4/inet_connection_sock.c:1193)
+Code: 41 5c 41 5d 41 5e e9 2d 4a 3d fd e8 28 4a 3d fd 48 89 ef e8 f0 cd 7d ff 5b 5d 41 5c 41 5d 41 5e e9 13 4a 3d fd e8 0e 4a 3d fd <0f> 0b e9 61 fe ff ff e8 02 4a 3d fd 4c 89 e7 be 03 00 00 00 e8 05
+RSP: 0018:ffffc9000b21fd38 EFLAGS: 00010293
+RAX: 0000000000000000 RBX: 0000000000009e78 RCX: ffffffff840bae40
+RDX: ffff88806e46c600 RSI: ffffffff840bb012 RDI: ffff88811755cca8
+RBP: ffff88811755c880 R08: 0000000000000003 R09: 0000000000000000
+R10: 0000000000009e78 R11: 0000000000000000 R12: ffff88811755c8e0
+R13: ffff88811755c892 R14: ffff88811755c918 R15: 0000000000000000
+FS: 00007f03e5243800(0000) GS:ffff88811ae00000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000001b32f21000 CR3: 0000000112ffe001 CR4: 0000000000770ef0
+PKRU: 55555554
+Call Trace:
+ <TASK>
+ ? inet_csk_destroy_sock (net/ipv4/inet_connection_sock.c:1193)
+ dccp_close (net/dccp/proto.c:1078)
+ inet_release (net/ipv4/af_inet.c:434)
+ __sock_release (net/socket.c:660)
+ sock_close (net/socket.c:1423)
+ __fput (fs/file_table.c:377)
+ __fput_sync (fs/file_table.c:462)
+ __x64_sys_close (fs/open.c:1557 fs/open.c:1539 fs/open.c:1539)
+ do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83)
+ entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:129)
+RIP: 0033:0x7f03e53852bb
+Code: 03 00 00 00 0f 05 48 3d 00 f0 ff ff 77 41 c3 48 83 ec 18 89 7c 24 0c e8 43 c9 f5 ff 8b 7c 24 0c 41 89 c0 b8 03 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 35 44 89 c7 89 44 24 0c e8 a1 c9 f5 ff 8b 44
+RSP: 002b:00000000005dfba0 EFLAGS: 00000293 ORIG_RAX: 0000000000000003
+RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007f03e53852bb
+RDX: 0000000000000002 RSI: 0000000000000002 RDI: 0000000000000003
+RBP: 0000000000000000 R08: 0000000000000000 R09: 000000000000167c
+R10: 0000000008a79680 R11: 0000000000000293 R12: 00007f03e4e43000
+R13: 00007f03e4e43170 R14: 00007f03e4e43178 R15: 00007f03e4e43170
+ </TASK>
+
+[1]:
+FAULT_INJECTION: forcing a failure.
+name failslab, interval 1, probability 0, space 0, times 0
+CPU: 0 PID: 350833 Comm: syz-executor.1 Not tainted 6.7.0-12272-g2121c43f88f5 #9
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014
+Call Trace:
+ <TASK>
+ dump_stack_lvl (lib/dump_stack.c:107 (discriminator 1))
+ should_fail_ex (lib/fault-inject.c:52 lib/fault-inject.c:153)
+ should_failslab (mm/slub.c:3748)
+ kmem_cache_alloc (mm/slub.c:3763 mm/slub.c:3842 mm/slub.c:3867)
+ inet_bind2_bucket_create (net/ipv4/inet_hashtables.c:135)
+ __inet_hash_connect (net/ipv4/inet_hashtables.c:1100)
+ dccp_v4_connect (net/dccp/ipv4.c:116)
+ __inet_stream_connect (net/ipv4/af_inet.c:676)
+ inet_stream_connect (net/ipv4/af_inet.c:747)
+ __sys_connect_file (net/socket.c:2048 (discriminator 2))
+ __sys_connect (net/socket.c:2065)
+ __x64_sys_connect (net/socket.c:2072)
+ do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83)
+ entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:129)
+RIP: 0033:0x7f03e5284e5d
+Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 73 9f 1b 00 f7 d8 64 89 01 48
+RSP: 002b:00007f03e4641cc8 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
+RAX: ffffffffffffffda RBX: 00000000004bbf80 RCX: 00007f03e5284e5d
+RDX: 0000000000000010 RSI: 0000000020000000 RDI: 0000000000000003
+RBP: 00000000004bbf80 R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
+R13: 000000000000000b R14: 00007f03e52e5530 R15: 0000000000000000
+ </TASK>
+
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Fixes: 28044fc1d495 ("net: Add a bhash2 table hashed by port and address")
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_hashtables.c | 25 ++++++++++++++++++++++++-
+ 1 file changed, 24 insertions(+), 1 deletion(-)
+
+diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
+index f2ed2aed08ab3..56776e1b1de52 100644
+--- a/net/ipv4/inet_hashtables.c
++++ b/net/ipv4/inet_hashtables.c
+@@ -1111,10 +1111,33 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
+ return 0;
+
+ error:
++ if (sk_hashed(sk)) {
++ spinlock_t *lock = inet_ehash_lockp(hinfo, sk->sk_hash);
++
++ sock_prot_inuse_add(net, sk->sk_prot, -1);
++
++ spin_lock(lock);
++ sk_nulls_del_node_init_rcu(sk);
++ spin_unlock(lock);
++
++ sk->sk_hash = 0;
++ inet_sk(sk)->inet_sport = 0;
++ inet_sk(sk)->inet_num = 0;
++
++ if (tw)
++ inet_twsk_bind_unhash(tw, hinfo);
++ }
++
+ spin_unlock(&head2->lock);
+ if (tb_created)
+ inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb);
+- spin_unlock_bh(&head->lock);
++ spin_unlock(&head->lock);
++
++ if (tw)
++ inet_twsk_deschedule_put(tw);
++
++ local_bh_enable();
++
+ return -ENOMEM;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 55f59837c7ffbd5e784366e4e70f4f08e752056c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 01:50:50 +0100
+Subject: drm/amd/display: Fix memory leak in dm_sw_fini()
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+[ Upstream commit bae67893578d608e35691dcdfa90c4957debf1d3 ]
+
+After destroying dmub_srv, the memory associated with it is
+not freed, causing a memory leak:
+
+unreferenced object 0xffff896302b45800 (size 1024):
+ comm "(udev-worker)", pid 222, jiffies 4294894636
+ 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 (crc 6265fd77):
+ [<ffffffff993495ed>] kmalloc_trace+0x29d/0x340
+ [<ffffffffc0ea4a94>] dm_dmub_sw_init+0xb4/0x450 [amdgpu]
+ [<ffffffffc0ea4e55>] dm_sw_init+0x15/0x2b0 [amdgpu]
+ [<ffffffffc0ba8557>] amdgpu_device_init+0x1417/0x24e0 [amdgpu]
+ [<ffffffffc0bab285>] amdgpu_driver_load_kms+0x15/0x190 [amdgpu]
+ [<ffffffffc0ba09c7>] amdgpu_pci_probe+0x187/0x4e0 [amdgpu]
+ [<ffffffff9968fd1e>] local_pci_probe+0x3e/0x90
+ [<ffffffff996918a3>] pci_device_probe+0xc3/0x230
+ [<ffffffff99805872>] really_probe+0xe2/0x480
+ [<ffffffff99805c98>] __driver_probe_device+0x78/0x160
+ [<ffffffff99805daf>] driver_probe_device+0x1f/0x90
+ [<ffffffff9980601e>] __driver_attach+0xce/0x1c0
+ [<ffffffff99803170>] bus_for_each_dev+0x70/0xc0
+ [<ffffffff99804822>] bus_add_driver+0x112/0x210
+ [<ffffffff99807245>] driver_register+0x55/0x100
+ [<ffffffff990012d1>] do_one_initcall+0x41/0x300
+
+Fix this by freeing dmub_srv after destroying it.
+
+Fixes: 743b9786b14a ("drm/amd/display: Hook up the DMUB service in DM")
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index a826c92933199..da16048bf1004 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2255,6 +2255,7 @@ static int dm_sw_fini(void *handle)
+
+ if (adev->dm.dmub_srv) {
+ dmub_srv_destroy(adev->dm.dmub_srv);
++ kfree(adev->dm.dmub_srv);
+ adev->dm.dmub_srv = NULL;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 69fbeb6ad5938362c0c75b25b5d16f858260b813 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 19 Jan 2024 08:32:06 -0800
+Subject: drm/syncobj: call drm_syncobj_fence_add_wait when WAIT_AVAILABLE flag
+ is set
+
+From: Erik Kurzinger <ekurzinger@nvidia.com>
+
+[ Upstream commit 3c43177ffb54ea5be97505eb8e2690e99ac96bc9 ]
+
+When waiting for a syncobj timeline point whose fence has not yet been
+submitted with the WAIT_FOR_SUBMIT flag, a callback is registered using
+drm_syncobj_fence_add_wait and the thread is put to sleep until the
+timeout expires. If the fence is submitted before then,
+drm_syncobj_add_point will wake up the sleeping thread immediately which
+will proceed to wait for the fence to be signaled.
+
+However, if the WAIT_AVAILABLE flag is used instead,
+drm_syncobj_fence_add_wait won't get called, meaning the waiting thread
+will always sleep for the full timeout duration, even if the fence gets
+submitted earlier. If it turns out that the fence *has* been submitted
+by the time it eventually wakes up, it will still indicate to userspace
+that the wait completed successfully (it won't return -ETIME), but it
+will have taken much longer than it should have.
+
+To fix this, we must call drm_syncobj_fence_add_wait if *either* the
+WAIT_FOR_SUBMIT flag or the WAIT_AVAILABLE flag is set. The only
+difference being that with WAIT_FOR_SUBMIT we will also wait for the
+fence to be signaled after it has been submitted while with
+WAIT_AVAILABLE we will return immediately.
+
+IGT test patch: https://lists.freedesktop.org/archives/igt-dev/2024-January/067537.html
+
+v1 -> v2: adjust lockdep_assert_none_held_once condition
+
+(cherry picked from commit 8c44ea81634a4a337df70a32621a5f3791be23df)
+
+Fixes: 01d6c3578379 ("drm/syncobj: add support for timeline point wait v8")
+Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
+Signed-off-by: Simon Ser <contact@emersion.fr>
+Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
+Reviewed-by: Simon Ser <contact@emersion.fr>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240119163208.3723457-1-ekurzinger@nvidia.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/drm_syncobj.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
+index da0145bc104a8..8f2737075dc2f 100644
+--- a/drivers/gpu/drm/drm_syncobj.c
++++ b/drivers/gpu/drm/drm_syncobj.c
+@@ -980,7 +980,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
+ uint64_t *points;
+ uint32_t signaled_count, i;
+
+- if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT)
++ if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
++ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE))
+ lockdep_assert_none_held_once();
+
+ points = kmalloc_array(count, sizeof(*points), GFP_KERNEL);
+@@ -1049,7 +1050,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
+ * fallthough and try a 0 timeout wait!
+ */
+
+- if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
++ if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT |
++ DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) {
+ for (i = 0; i < count; ++i)
+ drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]);
+ }
+--
+2.43.0
+
--- /dev/null
+From d5f33c4846b7832dd4325b5e021c8c101ae4bee7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 14:52:54 +0100
+Subject: Fix write to cloned skb in ipv6_hop_ioam()
+
+From: Justin Iurman <justin.iurman@uliege.be>
+
+[ Upstream commit f198d933c2e4f8f89e0620fbaf1ea7eac384a0eb ]
+
+ioam6_fill_trace_data() writes inside the skb payload without ensuring
+it's writeable (e.g., not cloned). This function is called both from the
+input and output path. The output path (ioam6_iptunnel) already does the
+check. This commit provides a fix for the input path, inside
+ipv6_hop_ioam(). It also updates ip6_parse_tlv() to refresh the network
+header pointer ("nh") when returning from ipv6_hop_ioam().
+
+Fixes: 9ee11f0fff20 ("ipv6: ioam: Data plane support for Pre-allocated Trace")
+Reported-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/exthdrs.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c
+index 5fa0e37305d9d..1cfdd9d950123 100644
+--- a/net/ipv6/exthdrs.c
++++ b/net/ipv6/exthdrs.c
+@@ -180,6 +180,8 @@ static bool ip6_parse_tlv(bool hopbyhop,
+ case IPV6_TLV_IOAM:
+ if (!ipv6_hop_ioam(skb, off))
+ return false;
++
++ nh = skb_network_header(skb);
+ break;
+ case IPV6_TLV_JUMBO:
+ if (!ipv6_hop_jumbo(skb, off))
+@@ -974,6 +976,14 @@ static bool ipv6_hop_ioam(struct sk_buff *skb, int optoff)
+ if (!skb_valid_dst(skb))
+ ip6_route_input(skb);
+
++ /* About to mangle packet header */
++ if (skb_ensure_writable(skb, optoff + 2 + hdr->opt_len))
++ goto drop;
++
++ /* Trace pointer may have changed */
++ trace = (struct ioam6_trace_hdr *)(skb_network_header(skb)
++ + optoff + sizeof(*hdr));
++
+ ioam6_fill_trace_data(skb, ns, trace, true);
+ break;
+ default:
+--
+2.43.0
+
--- /dev/null
+From 6bf36e7eb78ca226b2f1e51e83cc3bd107aec4d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Feb 2024 20:27:13 +0100
+Subject: i2c: imx: when being a target, mark the last read as processed
+
+From: Corey Minyard <minyard@acm.org>
+
+[ Upstream commit 87aec499368d488c20292952d6d4be7cb9e49c5e ]
+
+When being a target, NAK from the controller means that all bytes have
+been transferred. So, the last byte needs also to be marked as
+'processed'. Otherwise index registers of backends may not increase.
+
+Fixes: f7414cd6923f ("i2c: imx: support slave mode for imx I2C driver")
+Signed-off-by: Corey Minyard <minyard@acm.org>
+Tested-by: Andrew Manley <andrew.manley@sealingtech.com>
+Reviewed-by: Andrew Manley <andrew.manley@sealingtech.com>
+Reviewed-by: Oleksij Rempel <o.rempel@pengutronix.de>
+[wsa: fixed comment and commit message to properly describe the case]
+Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
+Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/i2c/busses/i2c-imx.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
+index fc70920c4ddab..0c203c614197c 100644
+--- a/drivers/i2c/busses/i2c-imx.c
++++ b/drivers/i2c/busses/i2c-imx.c
+@@ -804,6 +804,11 @@ static irqreturn_t i2c_imx_slave_handle(struct imx_i2c_struct *i2c_imx,
+ ctl &= ~I2CR_MTX;
+ imx_i2c_write_reg(ctl, i2c_imx, IMX_I2C_I2CR);
+ imx_i2c_read_reg(i2c_imx, IMX_I2C_I2DR);
++
++ /* flag the last byte as processed */
++ i2c_imx_slave_event(i2c_imx,
++ I2C_SLAVE_READ_PROCESSED, &value);
++
+ i2c_imx_slave_finish_op(i2c_imx);
+ return IRQ_HANDLED;
+ }
+--
+2.43.0
+
--- /dev/null
+From 700de167e0f662ff0bebb86d5667a690c808b492 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Jan 2024 16:55:23 +0800
+Subject: IB/hfi1: Fix a memleak in init_credit_return
+
+From: Zhipeng Lu <alexious@zju.edu.cn>
+
+[ Upstream commit 809aa64ebff51eb170ee31a95f83b2d21efa32e2 ]
+
+When dma_alloc_coherent fails to allocate dd->cr_base[i].va,
+init_credit_return should deallocate dd->cr_base and
+dd->cr_base[i] that allocated before. Or those resources
+would be never freed and a memleak is triggered.
+
+Fixes: 7724105686e7 ("IB/hfi1: add driver files")
+Signed-off-by: Zhipeng Lu <alexious@zju.edu.cn>
+Link: https://lore.kernel.org/r/20240112085523.3731720-1-alexious@zju.edu.cn
+Acked-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/hfi1/pio.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
+index 51ae58c02b15c..802b0e5801a7d 100644
+--- a/drivers/infiniband/hw/hfi1/pio.c
++++ b/drivers/infiniband/hw/hfi1/pio.c
+@@ -2089,7 +2089,7 @@ int init_credit_return(struct hfi1_devdata *dd)
+ "Unable to allocate credit return DMA range for NUMA %d\n",
+ i);
+ ret = -ENOMEM;
+- goto done;
++ goto free_cr_base;
+ }
+ }
+ set_dev_node(&dd->pcidev->dev, dd->node);
+@@ -2097,6 +2097,10 @@ int init_credit_return(struct hfi1_devdata *dd)
+ ret = 0;
+ done:
+ return ret;
++
++free_cr_base:
++ free_credit_return(dd);
++ goto done;
+ }
+
+ void free_credit_return(struct hfi1_devdata *dd)
+--
+2.43.0
+
--- /dev/null
+From 7bba0b52763dad2f32cf509dc2182a28561504d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Feb 2024 13:34:07 +0000
+Subject: iommufd/iova_bitmap: Bounds check mapped::pages access
+
+From: Joao Martins <joao.m.martins@oracle.com>
+
+[ Upstream commit a4ab7dedaee0e39b15653c5fd0367e420739f7ef ]
+
+Dirty IOMMU hugepages reported on a base page page-size granularity can
+lead to an attempt to set dirty pages in the bitmap beyond the limits that
+are pinned.
+
+Bounds check the page index of the array we are trying to access is within
+the limits before we kmap() and return otherwise.
+
+While it is also a defensive check, this is also in preparation to defer
+setting bits (outside the mapped range) to the next iteration(s) when the
+pages become available.
+
+Fixes: b058ea3ab5af ("vfio/iova_bitmap: refactor iova_bitmap_set() to better handle page boundaries")
+Link: https://lore.kernel.org/r/20240202133415.23819-2-joao.m.martins@oracle.com
+Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
+Tested-by: Avihai Horon <avihaih@nvidia.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/iova_bitmap.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/vfio/iova_bitmap.c b/drivers/vfio/iova_bitmap.c
+index 0f19d502f351b..5b540a164c98f 100644
+--- a/drivers/vfio/iova_bitmap.c
++++ b/drivers/vfio/iova_bitmap.c
+@@ -405,6 +405,7 @@ void iova_bitmap_set(struct iova_bitmap *bitmap,
+ mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE;
+ unsigned long last_bit = (((iova + length - 1) - mapped->iova) >>
+ mapped->pgshift) + mapped->pgoff * BITS_PER_BYTE;
++ unsigned long last_page_idx = mapped->npages - 1;
+
+ do {
+ unsigned int page_idx = cur_bit / BITS_PER_PAGE;
+@@ -413,6 +414,9 @@ void iova_bitmap_set(struct iova_bitmap *bitmap,
+ last_bit - cur_bit + 1);
+ void *kaddr;
+
++ if (unlikely(page_idx > last_page_idx))
++ break;
++
+ kaddr = kmap_local_page(mapped->pages[page_idx]);
+ bitmap_set(kaddr, offset, nbits);
+ kunmap_local(kaddr);
+--
+2.43.0
+
--- /dev/null
+From 004a1804da6246f4cc50987a96f35a5a51e5f679 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Feb 2024 13:34:15 +0000
+Subject: iommufd/iova_bitmap: Consider page offset for the pages to be pinned
+
+From: Joao Martins <joao.m.martins@oracle.com>
+
+[ Upstream commit 4bbcbc6ea2fa379632a24c14cfb47aa603816ac6 ]
+
+For small bitmaps that aren't PAGE_SIZE aligned *and* that are less than
+512 pages in bitmap length, use an extra page to be able to cover the
+entire range e.g. [1M..3G] which would be iterated more efficiently in a
+single iteration, rather than two.
+
+Fixes: b058ea3ab5af ("vfio/iova_bitmap: refactor iova_bitmap_set() to better handle page boundaries")
+Link: https://lore.kernel.org/r/20240202133415.23819-10-joao.m.martins@oracle.com
+Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
+Tested-by: Avihai Horon <avihaih@nvidia.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/iova_bitmap.c | 13 +++++++------
+ 1 file changed, 7 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/vfio/iova_bitmap.c b/drivers/vfio/iova_bitmap.c
+index c748a1e3ba53a..dfab5b742191a 100644
+--- a/drivers/vfio/iova_bitmap.c
++++ b/drivers/vfio/iova_bitmap.c
+@@ -174,18 +174,19 @@ static int iova_bitmap_get(struct iova_bitmap *bitmap)
+ bitmap->mapped_base_index) *
+ sizeof(*bitmap->bitmap), PAGE_SIZE);
+
+- /*
+- * We always cap at max number of 'struct page' a base page can fit.
+- * This is, for example, on x86 means 2M of bitmap data max.
+- */
+- npages = min(npages, PAGE_SIZE / sizeof(struct page *));
+-
+ /*
+ * Bitmap address to be pinned is calculated via pointer arithmetic
+ * with bitmap u64 word index.
+ */
+ addr = bitmap->bitmap + bitmap->mapped_base_index;
+
++ /*
++ * We always cap at max number of 'struct page' a base page can fit.
++ * This is, for example, on x86 means 2M of bitmap data max.
++ */
++ npages = min(npages + !!offset_in_page(addr),
++ PAGE_SIZE / sizeof(struct page *));
++
+ ret = pin_user_pages_fast((unsigned long)addr, npages,
+ FOLL_WRITE, mapped->pages);
+ if (ret <= 0)
+--
+2.43.0
+
--- /dev/null
+From 14456a14353a37a04f39a8871b2cd65a35d84cdc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Feb 2024 13:34:08 +0000
+Subject: iommufd/iova_bitmap: Switch iova_bitmap::bitmap to an u8 array
+
+From: Joao Martins <joao.m.martins@oracle.com>
+
+[ Upstream commit d18411ec305728c6371806c4fb09be07016aad0b ]
+
+iova_bitmap_mapped_length() don't deal correctly with the small bitmaps
+(< 2M bitmaps) when the starting address isn't u64 aligned, leading to
+skipping a tiny part of the IOVA range. This is materialized as not
+marking data dirty that should otherwise have been.
+
+Fix that by using a u8 * in the internal state of IOVA bitmap. Most of the
+data structures use the type of the bitmap to adjust its indexes, thus
+changing the type of the bitmap decreases the granularity of the bitmap
+indexes.
+
+Fixes: b058ea3ab5af ("vfio/iova_bitmap: refactor iova_bitmap_set() to better handle page boundaries")
+Link: https://lore.kernel.org/r/20240202133415.23819-3-joao.m.martins@oracle.com
+Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
+Tested-by: Avihai Horon <avihaih@nvidia.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/vfio/iova_bitmap.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/vfio/iova_bitmap.c b/drivers/vfio/iova_bitmap.c
+index 5b540a164c98f..c748a1e3ba53a 100644
+--- a/drivers/vfio/iova_bitmap.c
++++ b/drivers/vfio/iova_bitmap.c
+@@ -99,7 +99,7 @@ struct iova_bitmap {
+ struct iova_bitmap_map mapped;
+
+ /* userspace address of the bitmap */
+- u64 __user *bitmap;
++ u8 __user *bitmap;
+
+ /* u64 index that @mapped points to */
+ unsigned long mapped_base_index;
+@@ -161,7 +161,7 @@ static int iova_bitmap_get(struct iova_bitmap *bitmap)
+ {
+ struct iova_bitmap_map *mapped = &bitmap->mapped;
+ unsigned long npages;
+- u64 __user *addr;
++ u8 __user *addr;
+ long ret;
+
+ /*
+@@ -246,7 +246,7 @@ struct iova_bitmap *iova_bitmap_alloc(unsigned long iova, size_t length,
+
+ mapped = &bitmap->mapped;
+ mapped->pgshift = __ffs(page_size);
+- bitmap->bitmap = data;
++ bitmap->bitmap = (u8 __user *)data;
+ bitmap->mapped_total_index =
+ iova_bitmap_offset_to_index(bitmap, length - 1) + 1;
+ bitmap->iova = iova;
+@@ -301,7 +301,7 @@ static unsigned long iova_bitmap_mapped_remaining(struct iova_bitmap *bitmap)
+
+ remaining = bitmap->mapped_total_index - bitmap->mapped_base_index;
+ remaining = min_t(unsigned long, remaining,
+- bytes / sizeof(*bitmap->bitmap));
++ DIV_ROUND_UP(bytes, sizeof(*bitmap->bitmap)));
+
+ return remaining;
+ }
+--
+2.43.0
+
--- /dev/null
+From 750d26da67e860ecb33259e352815c3094a5b39b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 17:21:06 +0000
+Subject: ipv4: properly combine dev_base_seq and ipv4.dev_addr_genid
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 081a0e3b0d4c061419d3f4679dec9f68725b17e4 ]
+
+net->dev_base_seq and ipv4.dev_addr_genid are monotonically increasing.
+
+If we XOR their values, we could miss to detect if both values
+were changed with the same amount.
+
+Fixes: 0465277f6b3f ("ipv4: provide addr and netconf dump consistency info")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/devinet.c | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
+index 35d6e74be8406..bb0d1252cad86 100644
+--- a/net/ipv4/devinet.c
++++ b/net/ipv4/devinet.c
+@@ -1804,6 +1804,21 @@ static int in_dev_dump_addr(struct in_device *in_dev, struct sk_buff *skb,
+ return err;
+ }
+
++/* Combine dev_addr_genid and dev_base_seq to detect changes.
++ */
++static u32 inet_base_seq(const struct net *net)
++{
++ u32 res = atomic_read(&net->ipv4.dev_addr_genid) +
++ net->dev_base_seq;
++
++ /* Must not return 0 (see nl_dump_check_consistent()).
++ * Chose a value far away from 0.
++ */
++ if (!res)
++ res = 0x80000000;
++ return res;
++}
++
+ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ {
+ const struct nlmsghdr *nlh = cb->nlh;
+@@ -1855,8 +1870,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+ idx = 0;
+ head = &tgt_net->dev_index_head[h];
+ rcu_read_lock();
+- cb->seq = atomic_read(&tgt_net->ipv4.dev_addr_genid) ^
+- tgt_net->dev_base_seq;
++ cb->seq = inet_base_seq(tgt_net);
+ hlist_for_each_entry_rcu(dev, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+@@ -2257,8 +2271,7 @@ static int inet_netconf_dump_devconf(struct sk_buff *skb,
+ idx = 0;
+ head = &net->dev_index_head[h];
+ rcu_read_lock();
+- cb->seq = atomic_read(&net->ipv4.dev_addr_genid) ^
+- net->dev_base_seq;
++ cb->seq = inet_base_seq(net);
+ hlist_for_each_entry_rcu(dev, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+--
+2.43.0
+
--- /dev/null
+From f7da708e69d9514808bbbbb16d619d6054f75118 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 17:21:07 +0000
+Subject: ipv6: properly combine dev_base_seq and ipv6.dev_addr_genid
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit e898e4cd1aab271ca414f9ac6e08e4c761f6913c ]
+
+net->dev_base_seq and ipv6.dev_addr_genid are monotonically increasing.
+
+If we XOR their values, we could miss to detect if both values
+were changed with the same amount.
+
+Fixes: 63998ac24f83 ("ipv6: provide addr and netconf dump consistency info")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/addrconf.c | 21 ++++++++++++++++++---
+ 1 file changed, 18 insertions(+), 3 deletions(-)
+
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index b8dc20fe7a4e2..46527b5cc8f0c 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -706,6 +706,22 @@ static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
+ return err;
+ }
+
++/* Combine dev_addr_genid and dev_base_seq to detect changes.
++ */
++static u32 inet6_base_seq(const struct net *net)
++{
++ u32 res = atomic_read(&net->ipv6.dev_addr_genid) +
++ net->dev_base_seq;
++
++ /* Must not return 0 (see nl_dump_check_consistent()).
++ * Chose a value far away from 0.
++ */
++ if (!res)
++ res = 0x80000000;
++ return res;
++}
++
++
+ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
+ struct netlink_callback *cb)
+ {
+@@ -739,8 +755,7 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb,
+ idx = 0;
+ head = &net->dev_index_head[h];
+ rcu_read_lock();
+- cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^
+- net->dev_base_seq;
++ cb->seq = inet6_base_seq(net);
+ hlist_for_each_entry_rcu(dev, head, index_hlist) {
+ if (idx < s_idx)
+ goto cont;
+@@ -5326,7 +5341,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
+ }
+
+ rcu_read_lock();
+- cb->seq = atomic_read(&tgt_net->ipv6.dev_addr_genid) ^ tgt_net->dev_base_seq;
++ cb->seq = inet6_base_seq(tgt_net);
+ for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
+ idx = 0;
+ head = &tgt_net->dev_index_head[h];
+--
+2.43.0
+
--- /dev/null
+From 4b4260b4f2e796090c2ac011fab7dbc7d303c84f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 23:27:17 +0300
+Subject: ipv6: sr: fix possible use-after-free and null-ptr-deref
+
+From: Vasiliy Kovalev <kovalev@altlinux.org>
+
+[ Upstream commit 5559cea2d5aa3018a5f00dd2aca3427ba09b386b ]
+
+The pernet operations structure for the subsystem must be registered
+before registering the generic netlink family.
+
+Fixes: 915d7e5e5930 ("ipv6: sr: add code base for control plane support of SR-IPv6")
+Signed-off-by: Vasiliy Kovalev <kovalev@altlinux.org>
+Link: https://lore.kernel.org/r/20240215202717.29815-1-kovalev@altlinux.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/seg6.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
+index 29346a6eec9ff..35508abd76f43 100644
+--- a/net/ipv6/seg6.c
++++ b/net/ipv6/seg6.c
+@@ -512,22 +512,24 @@ int __init seg6_init(void)
+ {
+ int err;
+
+- err = genl_register_family(&seg6_genl_family);
++ err = register_pernet_subsys(&ip6_segments_ops);
+ if (err)
+ goto out;
+
+- err = register_pernet_subsys(&ip6_segments_ops);
++ err = genl_register_family(&seg6_genl_family);
+ if (err)
+- goto out_unregister_genl;
++ goto out_unregister_pernet;
+
+ #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+ err = seg6_iptunnel_init();
+ if (err)
+- goto out_unregister_pernet;
++ goto out_unregister_genl;
+
+ err = seg6_local_init();
+- if (err)
+- goto out_unregister_pernet;
++ if (err) {
++ seg6_iptunnel_exit();
++ goto out_unregister_genl;
++ }
+ #endif
+
+ #ifdef CONFIG_IPV6_SEG6_HMAC
+@@ -548,11 +550,11 @@ int __init seg6_init(void)
+ #endif
+ #endif
+ #ifdef CONFIG_IPV6_SEG6_LWTUNNEL
+-out_unregister_pernet:
+- unregister_pernet_subsys(&ip6_segments_ops);
+-#endif
+ out_unregister_genl:
+ genl_unregister_family(&seg6_genl_family);
++#endif
++out_unregister_pernet:
++ unregister_pernet_subsys(&ip6_segments_ops);
+ goto out;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From f896fa41ab0e1d43e09769ca8c0717a437c23ba0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Feb 2024 22:40:04 +0100
+Subject: net: bridge: switchdev: Ensure deferred event delivery on unoffload
+
+From: Tobias Waldekranz <tobias@waldekranz.com>
+
+[ Upstream commit f7a70d650b0b6b0134ccba763d672c8439d9f09b ]
+
+When unoffloading a device, it is important to ensure that all
+relevant deferred events are delivered to it before it disassociates
+itself from the bridge.
+
+Before this change, this was true for the normal case when a device
+maps 1:1 to a net_bridge_port, i.e.
+
+ br0
+ /
+swp0
+
+When swp0 leaves br0, the call to switchdev_deferred_process() in
+del_nbp() makes sure to process any outstanding events while the
+device is still associated with the bridge.
+
+In the case when the association is indirect though, i.e. when the
+device is attached to the bridge via an intermediate device, like a
+LAG...
+
+ br0
+ /
+ lag0
+ /
+swp0
+
+...then detaching swp0 from lag0 does not cause any net_bridge_port to
+be deleted, so there was no guarantee that all events had been
+processed before the device disassociated itself from the bridge.
+
+Fix this by always synchronously processing all deferred events before
+signaling completion of unoffloading back to the driver.
+
+Fixes: 4e51bf44a03a ("net: bridge: move the switchdev object replay helpers to "push" mode")
+Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bridge/br_switchdev.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
+index 65567d1c8b853..b61ef2dff7a4b 100644
+--- a/net/bridge/br_switchdev.c
++++ b/net/bridge/br_switchdev.c
+@@ -798,6 +798,16 @@ static void nbp_switchdev_unsync_objs(struct net_bridge_port *p,
+ br_switchdev_mdb_replay(br_dev, dev, ctx, false, blocking_nb, NULL);
+
+ br_switchdev_vlan_replay(br_dev, ctx, false, blocking_nb, NULL);
++
++ /* Make sure that the device leaving this bridge has seen all
++ * relevant events before it is disassociated. In the normal
++ * case, when the device is directly attached to the bridge,
++ * this is covered by del_nbp(). If the association was indirect
++ * however, e.g. via a team or bond, and the device is leaving
++ * that intermediate device, then the bridge port remains in
++ * place.
++ */
++ switchdev_deferred_process();
+ }
+
+ /* Let the bridge know that this port is offloaded, so that it can assign a
+--
+2.43.0
+
--- /dev/null
+From 2e7af85b7ffd41521e3ec638faded487ec08488e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Feb 2024 22:40:03 +0100
+Subject: net: bridge: switchdev: Skip MDB replays of deferred events on
+ offload
+
+From: Tobias Waldekranz <tobias@waldekranz.com>
+
+[ Upstream commit dc489f86257cab5056e747344f17a164f63bff4b ]
+
+Before this change, generation of the list of MDB events to replay
+would race against the creation of new group memberships, either from
+the IGMP/MLD snooping logic or from user configuration.
+
+While new memberships are immediately visible to walkers of
+br->mdb_list, the notification of their existence to switchdev event
+subscribers is deferred until a later point in time. So if a replay
+list was generated during a time that overlapped with such a window,
+it would also contain a replay of the not-yet-delivered event.
+
+The driver would thus receive two copies of what the bridge internally
+considered to be one single event. On destruction of the bridge, only
+a single membership deletion event was therefore sent. As a
+consequence of this, drivers which reference count memberships (at
+least DSA), would be left with orphan groups in their hardware
+database when the bridge was destroyed.
+
+This is only an issue when replaying additions. While deletion events
+may still be pending on the deferred queue, they will already have
+been removed from br->mdb_list, so no duplicates can be generated in
+that scenario.
+
+To a user this meant that old group memberships, from a bridge in
+which a port was previously attached, could be reanimated (in
+hardware) when the port joined a new bridge, without the new bridge's
+knowledge.
+
+For example, on an mv88e6xxx system, create a snooping bridge and
+immediately add a port to it:
+
+ root@infix-06-0b-00:~$ ip link add dev br0 up type bridge mcast_snooping 1 && \
+ > ip link set dev x3 up master br0
+
+And then destroy the bridge:
+
+ root@infix-06-0b-00:~$ ip link del dev br0
+ root@infix-06-0b-00:~$ mvls atu
+ ADDRESS FID STATE Q F 0 1 2 3 4 5 6 7 8 9 a
+ DEV:0 Marvell 88E6393X
+ 33:33:00:00:00:6a 1 static - - 0 . . . . . . . . . .
+ 33:33:ff:87:e4:3f 1 static - - 0 . . . . . . . . . .
+ ff:ff:ff:ff:ff:ff 1 static - - 0 1 2 3 4 5 6 7 8 9 a
+ root@infix-06-0b-00:~$
+
+The two IPv6 groups remain in the hardware database because the
+port (x3) is notified of the host's membership twice: once via the
+original event and once via a replay. Since only a single delete
+notification is sent, the count remains at 1 when the bridge is
+destroyed.
+
+Then add the same port (or another port belonging to the same hardware
+domain) to a new bridge, this time with snooping disabled:
+
+ root@infix-06-0b-00:~$ ip link add dev br1 up type bridge mcast_snooping 0 && \
+ > ip link set dev x3 up master br1
+
+All multicast, including the two IPv6 groups from br0, should now be
+flooded, according to the policy of br1. But instead the old
+memberships are still active in the hardware database, causing the
+switch to only forward traffic to those groups towards the CPU (port
+0).
+
+Eliminate the race in two steps:
+
+1. Grab the write-side lock of the MDB while generating the replay
+ list.
+
+This prevents new memberships from showing up while we are generating
+the replay list. But it leaves the scenario in which a deferred event
+was already generated, but not delivered, before we grabbed the
+lock. Therefore:
+
+2. Make sure that no deferred version of a replay event is already
+ enqueued to the switchdev deferred queue, before adding it to the
+ replay list, when replaying additions.
+
+Fixes: 4f2673b3a2b6 ("net: bridge: add helper to replay port and host-joined mdb entries")
+Signed-off-by: Tobias Waldekranz <tobias@waldekranz.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/switchdev.h | 3 ++
+ net/bridge/br_switchdev.c | 74 ++++++++++++++++++++++++---------------
+ net/switchdev/switchdev.c | 73 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 122 insertions(+), 28 deletions(-)
+
+diff --git a/include/net/switchdev.h b/include/net/switchdev.h
+index 7dcdc97c0bc33..a3d8f013adcd5 100644
+--- a/include/net/switchdev.h
++++ b/include/net/switchdev.h
+@@ -303,6 +303,9 @@ void switchdev_deferred_process(void);
+ int switchdev_port_attr_set(struct net_device *dev,
+ const struct switchdev_attr *attr,
+ struct netlink_ext_ack *extack);
++bool switchdev_port_obj_act_is_deferred(struct net_device *dev,
++ enum switchdev_notifier_type nt,
++ const struct switchdev_obj *obj);
+ int switchdev_port_obj_add(struct net_device *dev,
+ const struct switchdev_obj *obj,
+ struct netlink_ext_ack *extack);
+diff --git a/net/bridge/br_switchdev.c b/net/bridge/br_switchdev.c
+index 4b3982c368b35..65567d1c8b853 100644
+--- a/net/bridge/br_switchdev.c
++++ b/net/bridge/br_switchdev.c
+@@ -593,21 +593,40 @@ br_switchdev_mdb_replay_one(struct notifier_block *nb, struct net_device *dev,
+ }
+
+ static int br_switchdev_mdb_queue_one(struct list_head *mdb_list,
++ struct net_device *dev,
++ unsigned long action,
+ enum switchdev_obj_id id,
+ const struct net_bridge_mdb_entry *mp,
+ struct net_device *orig_dev)
+ {
+- struct switchdev_obj_port_mdb *mdb;
++ struct switchdev_obj_port_mdb mdb = {
++ .obj = {
++ .id = id,
++ .orig_dev = orig_dev,
++ },
++ };
++ struct switchdev_obj_port_mdb *pmdb;
+
+- mdb = kzalloc(sizeof(*mdb), GFP_ATOMIC);
+- if (!mdb)
+- return -ENOMEM;
++ br_switchdev_mdb_populate(&mdb, mp);
+
+- mdb->obj.id = id;
+- mdb->obj.orig_dev = orig_dev;
+- br_switchdev_mdb_populate(mdb, mp);
+- list_add_tail(&mdb->obj.list, mdb_list);
++ if (action == SWITCHDEV_PORT_OBJ_ADD &&
++ switchdev_port_obj_act_is_deferred(dev, action, &mdb.obj)) {
++ /* This event is already in the deferred queue of
++ * events, so this replay must be elided, lest the
++ * driver receives duplicate events for it. This can
++ * only happen when replaying additions, since
++ * modifications are always immediately visible in
++ * br->mdb_list, whereas actual event delivery may be
++ * delayed.
++ */
++ return 0;
++ }
++
++ pmdb = kmemdup(&mdb, sizeof(mdb), GFP_ATOMIC);
++ if (!pmdb)
++ return -ENOMEM;
+
++ list_add_tail(&pmdb->obj.list, mdb_list);
+ return 0;
+ }
+
+@@ -675,51 +694,50 @@ br_switchdev_mdb_replay(struct net_device *br_dev, struct net_device *dev,
+ if (!br_opt_get(br, BROPT_MULTICAST_ENABLED))
+ return 0;
+
+- /* We cannot walk over br->mdb_list protected just by the rtnl_mutex,
+- * because the write-side protection is br->multicast_lock. But we
+- * need to emulate the [ blocking ] calling context of a regular
+- * switchdev event, so since both br->multicast_lock and RCU read side
+- * critical sections are atomic, we have no choice but to pick the RCU
+- * read side lock, queue up all our events, leave the critical section
+- * and notify switchdev from blocking context.
++ if (adding)
++ action = SWITCHDEV_PORT_OBJ_ADD;
++ else
++ action = SWITCHDEV_PORT_OBJ_DEL;
++
++ /* br_switchdev_mdb_queue_one() will take care to not queue a
++ * replay of an event that is already pending in the switchdev
++ * deferred queue. In order to safely determine that, there
++ * must be no new deferred MDB notifications enqueued for the
++ * duration of the MDB scan. Therefore, grab the write-side
++ * lock to avoid racing with any concurrent IGMP/MLD snooping.
+ */
+- rcu_read_lock();
++ spin_lock_bh(&br->multicast_lock);
+
+- hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) {
++ hlist_for_each_entry(mp, &br->mdb_list, mdb_node) {
+ struct net_bridge_port_group __rcu * const *pp;
+ const struct net_bridge_port_group *p;
+
+ if (mp->host_joined) {
+- err = br_switchdev_mdb_queue_one(&mdb_list,
++ err = br_switchdev_mdb_queue_one(&mdb_list, dev, action,
+ SWITCHDEV_OBJ_ID_HOST_MDB,
+ mp, br_dev);
+ if (err) {
+- rcu_read_unlock();
++ spin_unlock_bh(&br->multicast_lock);
+ goto out_free_mdb;
+ }
+ }
+
+- for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL;
++ for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL;
+ pp = &p->next) {
+ if (p->key.port->dev != dev)
+ continue;
+
+- err = br_switchdev_mdb_queue_one(&mdb_list,
++ err = br_switchdev_mdb_queue_one(&mdb_list, dev, action,
+ SWITCHDEV_OBJ_ID_PORT_MDB,
+ mp, dev);
+ if (err) {
+- rcu_read_unlock();
++ spin_unlock_bh(&br->multicast_lock);
+ goto out_free_mdb;
+ }
+ }
+ }
+
+- rcu_read_unlock();
+-
+- if (adding)
+- action = SWITCHDEV_PORT_OBJ_ADD;
+- else
+- action = SWITCHDEV_PORT_OBJ_DEL;
++ spin_unlock_bh(&br->multicast_lock);
+
+ list_for_each_entry(obj, &mdb_list, list) {
+ err = br_switchdev_mdb_replay_one(nb, dev,
+diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
+index 8cc42aea19c7e..2e14d4c37e2dc 100644
+--- a/net/switchdev/switchdev.c
++++ b/net/switchdev/switchdev.c
+@@ -19,6 +19,35 @@
+ #include <linux/rtnetlink.h>
+ #include <net/switchdev.h>
+
++static bool switchdev_obj_eq(const struct switchdev_obj *a,
++ const struct switchdev_obj *b)
++{
++ const struct switchdev_obj_port_vlan *va, *vb;
++ const struct switchdev_obj_port_mdb *ma, *mb;
++
++ if (a->id != b->id || a->orig_dev != b->orig_dev)
++ return false;
++
++ switch (a->id) {
++ case SWITCHDEV_OBJ_ID_PORT_VLAN:
++ va = SWITCHDEV_OBJ_PORT_VLAN(a);
++ vb = SWITCHDEV_OBJ_PORT_VLAN(b);
++ return va->flags == vb->flags &&
++ va->vid == vb->vid &&
++ va->changed == vb->changed;
++ case SWITCHDEV_OBJ_ID_PORT_MDB:
++ case SWITCHDEV_OBJ_ID_HOST_MDB:
++ ma = SWITCHDEV_OBJ_PORT_MDB(a);
++ mb = SWITCHDEV_OBJ_PORT_MDB(b);
++ return ma->vid == mb->vid &&
++ ether_addr_equal(ma->addr, mb->addr);
++ default:
++ break;
++ }
++
++ BUG();
++}
++
+ static LIST_HEAD(deferred);
+ static DEFINE_SPINLOCK(deferred_lock);
+
+@@ -307,6 +336,50 @@ int switchdev_port_obj_del(struct net_device *dev,
+ }
+ EXPORT_SYMBOL_GPL(switchdev_port_obj_del);
+
++/**
++ * switchdev_port_obj_act_is_deferred - Is object action pending?
++ *
++ * @dev: port device
++ * @nt: type of action; add or delete
++ * @obj: object to test
++ *
++ * Returns true if a deferred item is pending, which is
++ * equivalent to the action @nt on an object @obj.
++ *
++ * rtnl_lock must be held.
++ */
++bool switchdev_port_obj_act_is_deferred(struct net_device *dev,
++ enum switchdev_notifier_type nt,
++ const struct switchdev_obj *obj)
++{
++ struct switchdev_deferred_item *dfitem;
++ bool found = false;
++
++ ASSERT_RTNL();
++
++ spin_lock_bh(&deferred_lock);
++
++ list_for_each_entry(dfitem, &deferred, list) {
++ if (dfitem->dev != dev)
++ continue;
++
++ if ((dfitem->func == switchdev_port_obj_add_deferred &&
++ nt == SWITCHDEV_PORT_OBJ_ADD) ||
++ (dfitem->func == switchdev_port_obj_del_deferred &&
++ nt == SWITCHDEV_PORT_OBJ_DEL)) {
++ if (switchdev_obj_eq((const void *)dfitem->data, obj)) {
++ found = true;
++ break;
++ }
++ }
++ }
++
++ spin_unlock_bh(&deferred_lock);
++
++ return found;
++}
++EXPORT_SYMBOL_GPL(switchdev_port_obj_act_is_deferred);
++
+ static ATOMIC_NOTIFIER_HEAD(switchdev_notif_chain);
+ static BLOCKING_NOTIFIER_HEAD(switchdev_blocking_notif_chain);
+
+--
+2.43.0
+
--- /dev/null
+From b612f045d7213f210e1bfc3ce9ba04fb7a0812b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Oct 2022 02:56:03 -0700
+Subject: net: dev: Convert sa_data to flexible array in struct sockaddr
+
+From: Kees Cook <keescook@chromium.org>
+
+[ Upstream commit b5f0de6df6dce8d641ef58ef7012f3304dffb9a1 ]
+
+One of the worst offenders of "fake flexible arrays" is struct sockaddr,
+as it is the classic example of why GCC and Clang have been traditionally
+forced to treat all trailing arrays as fake flexible arrays: in the
+distant misty past, sa_data became too small, and code started just
+treating it as a flexible array, even though it was fixed-size. The
+special case by the compiler is specifically that sizeof(sa->sa_data)
+and FORTIFY_SOURCE (which uses __builtin_object_size(sa->sa_data, 1))
+do not agree (14 and -1 respectively), which makes FORTIFY_SOURCE treat
+it as a flexible array.
+
+However, the coming -fstrict-flex-arrays compiler flag will remove
+these special cases so that FORTIFY_SOURCE can gain coverage over all
+the trailing arrays in the kernel that are _not_ supposed to be treated
+as a flexible array. To deal with this change, convert sa_data to a true
+flexible array. To keep the structure size the same, move sa_data into
+a union with a newly introduced sa_data_min with the original size. The
+result is that FORTIFY_SOURCE can continue to have no idea how large
+sa_data may actually be, but anything using sizeof(sa->sa_data) must
+switch to sizeof(sa->sa_data_min).
+
+Cc: Jens Axboe <axboe@kernel.dk>
+Cc: Pavel Begunkov <asml.silence@gmail.com>
+Cc: David Ahern <dsahern@kernel.org>
+Cc: Dylan Yudaken <dylany@fb.com>
+Cc: Yajun Deng <yajun.deng@linux.dev>
+Cc: Petr Machata <petrm@nvidia.com>
+Cc: Hangbin Liu <liuhangbin@gmail.com>
+Cc: Leon Romanovsky <leon@kernel.org>
+Cc: syzbot <syzkaller@googlegroups.com>
+Cc: Willem de Bruijn <willemb@google.com>
+Cc: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Link: https://lore.kernel.org/r/20221018095503.never.671-kees@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: a7d6027790ac ("arp: Prevent overflow in arp_req_get().")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/socket.h | 5 ++++-
+ net/core/dev.c | 2 +-
+ net/core/dev_ioctl.c | 2 +-
+ net/packet/af_packet.c | 10 +++++-----
+ 4 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/include/linux/socket.h b/include/linux/socket.h
+index b3c58042bd254..d79efd0268809 100644
+--- a/include/linux/socket.h
++++ b/include/linux/socket.h
+@@ -33,7 +33,10 @@ typedef __kernel_sa_family_t sa_family_t;
+
+ struct sockaddr {
+ sa_family_t sa_family; /* address family, AF_xxx */
+- char sa_data[14]; /* 14 bytes of protocol address */
++ union {
++ char sa_data_min[14]; /* Minimum 14 bytes of protocol address */
++ DECLARE_FLEX_ARRAY(char, sa_data);
++ };
+ };
+
+ struct linger {
+diff --git a/net/core/dev.c b/net/core/dev.c
+index 1ba3662faf0aa..60619fe8af5fc 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -8861,7 +8861,7 @@ EXPORT_SYMBOL(dev_set_mac_address_user);
+
+ int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name)
+ {
+- size_t size = sizeof(sa->sa_data);
++ size_t size = sizeof(sa->sa_data_min);
+ struct net_device *dev;
+ int ret = 0;
+
+diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
+index 7674bb9f3076c..5cdbfbf9a7dcf 100644
+--- a/net/core/dev_ioctl.c
++++ b/net/core/dev_ioctl.c
+@@ -342,7 +342,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
+ if (ifr->ifr_hwaddr.sa_family != dev->type)
+ return -EINVAL;
+ memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
+- min(sizeof(ifr->ifr_hwaddr.sa_data),
++ min(sizeof(ifr->ifr_hwaddr.sa_data_min),
+ (size_t)dev->addr_len));
+ call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+ return 0;
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index 51882f07ef70c..c3117350f5fbb 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -3284,7 +3284,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
+ int addr_len)
+ {
+ struct sock *sk = sock->sk;
+- char name[sizeof(uaddr->sa_data) + 1];
++ char name[sizeof(uaddr->sa_data_min) + 1];
+
+ /*
+ * Check legality
+@@ -3295,8 +3295,8 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
+ /* uaddr->sa_data comes from the userspace, it's not guaranteed to be
+ * zero-terminated.
+ */
+- memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data));
+- name[sizeof(uaddr->sa_data)] = 0;
++ memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data_min));
++ name[sizeof(uaddr->sa_data_min)] = 0;
+
+ return packet_do_bind(sk, name, 0, 0);
+ }
+@@ -3566,11 +3566,11 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
+ return -EOPNOTSUPP;
+
+ uaddr->sa_family = AF_PACKET;
+- memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data));
++ memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data_min));
+ rcu_read_lock();
+ dev = dev_get_by_index_rcu(sock_net(sk), READ_ONCE(pkt_sk(sk)->ifindex));
+ if (dev)
+- strscpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
++ strscpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data_min));
+ rcu_read_unlock();
+
+ return sizeof(*uaddr);
+--
+2.43.0
+
--- /dev/null
+From 7c3bab1514e02cefe9ce458103a053030f09ef07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Feb 2024 23:00:50 -0800
+Subject: net: ethernet: adi: requires PHYLIB support
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit a9f80df4f51440303d063b55bb98720857693821 ]
+
+This driver uses functions that are supplied by the Kconfig symbol
+PHYLIB, so select it to ensure that they are built as needed.
+
+When CONFIG_ADIN1110=y and CONFIG_PHYLIB=m, there are multiple build
+(linker) errors that are resolved by this Kconfig change:
+
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_net_open':
+ drivers/net/ethernet/adi/adin1110.c:933: undefined reference to `phy_start'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_probe_netdevs':
+ drivers/net/ethernet/adi/adin1110.c:1603: undefined reference to `get_phy_device'
+ ld: drivers/net/ethernet/adi/adin1110.c:1609: undefined reference to `phy_connect'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_disconnect_phy':
+ drivers/net/ethernet/adi/adin1110.c:1226: undefined reference to `phy_disconnect'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `devm_mdiobus_alloc':
+ include/linux/phy.h:455: undefined reference to `devm_mdiobus_alloc_size'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_register_mdiobus':
+ drivers/net/ethernet/adi/adin1110.c:529: undefined reference to `__devm_mdiobus_register'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_net_stop':
+ drivers/net/ethernet/adi/adin1110.c:958: undefined reference to `phy_stop'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_disconnect_phy':
+ drivers/net/ethernet/adi/adin1110.c:1226: undefined reference to `phy_disconnect'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_adjust_link':
+ drivers/net/ethernet/adi/adin1110.c:1077: undefined reference to `phy_print_status'
+ ld: drivers/net/ethernet/adi/adin1110.o: in function `adin1110_ioctl':
+ drivers/net/ethernet/adi/adin1110.c:790: undefined reference to `phy_do_ioctl'
+ ld: drivers/net/ethernet/adi/adin1110.o:(.rodata+0xf60): undefined reference to `phy_ethtool_get_link_ksettings'
+ ld: drivers/net/ethernet/adi/adin1110.o:(.rodata+0xf68): undefined reference to `phy_ethtool_set_link_ksettings'
+
+Fixes: bc93e19d088b ("net: ethernet: adi: Add ADIN1110 support")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202402070626.eZsfVHG5-lkp@intel.com/
+Cc: Lennart Franzen <lennart@lfdomain.com>
+Cc: Alexandru Tachici <alexandru.tachici@analog.com>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Eric Dumazet <edumazet@google.com>
+Cc: Jakub Kicinski <kuba@kernel.org>
+Cc: Paolo Abeni <pabeni@redhat.com>
+Cc: netdev@vger.kernel.org
+Reviewed-by: Nuno Sa <nuno.sa@analog.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/adi/Kconfig | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
+index da3bdd3025022..c91b4dcef4ec2 100644
+--- a/drivers/net/ethernet/adi/Kconfig
++++ b/drivers/net/ethernet/adi/Kconfig
+@@ -7,6 +7,7 @@ config NET_VENDOR_ADI
+ bool "Analog Devices devices"
+ default y
+ depends on SPI
++ select PHYLIB
+ help
+ If you have a network (Ethernet) card belonging to this class, say Y.
+
+--
+2.43.0
+
--- /dev/null
+From 411791fe82c0b08a8c4ee827713133f47c2e890d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jun 2023 08:27:42 -0700
+Subject: net: ioctl: Use kernel memory on protocol ioctl callbacks
+
+From: Breno Leitao <leitao@debian.org>
+
+[ Upstream commit e1d001fa5b477c4da46a29be1fcece91db7c7c6f ]
+
+Most of the ioctls to net protocols operates directly on userspace
+argument (arg). Usually doing get_user()/put_user() directly in the
+ioctl callback. This is not flexible, because it is hard to reuse these
+functions without passing userspace buffers.
+
+Change the "struct proto" ioctls to avoid touching userspace memory and
+operate on kernel buffers, i.e., all protocol's ioctl callbacks is
+adapted to operate on a kernel memory other than on userspace (so, no
+more {put,get}_user() and friends being called in the ioctl callback).
+
+This changes the "struct proto" ioctl format in the following way:
+
+ int (*ioctl)(struct sock *sk, int cmd,
+- unsigned long arg);
++ int *karg);
+
+(Important to say that this patch does not touch the "struct proto_ops"
+protocols)
+
+So, the "karg" argument, which is passed to the ioctl callback, is a
+pointer allocated to kernel space memory (inside a function wrapper).
+This buffer (karg) may contain input argument (copied from userspace in
+a prep function) and it might return a value/buffer, which is copied
+back to userspace if necessary. There is not one-size-fits-all format
+(that is I am using 'may' above), but basically, there are three type of
+ioctls:
+
+1) Do not read from userspace, returns a result to userspace
+2) Read an input parameter from userspace, and does not return anything
+ to userspace
+3) Read an input from userspace, and return a buffer to userspace.
+
+The default case (1) (where no input parameter is given, and an "int" is
+returned to userspace) encompasses more than 90% of the cases, but there
+are two other exceptions. Here is a list of exceptions:
+
+* Protocol RAW:
+ * cmd = SIOCGETVIFCNT:
+ * input and output = struct sioc_vif_req
+ * cmd = SIOCGETSGCNT
+ * input and output = struct sioc_sg_req
+ * Explanation: for the SIOCGETVIFCNT case, userspace passes the input
+ argument, which is struct sioc_vif_req. Then the callback populates
+ the struct, which is copied back to userspace.
+
+* Protocol RAW6:
+ * cmd = SIOCGETMIFCNT_IN6
+ * input and output = struct sioc_mif_req6
+ * cmd = SIOCGETSGCNT_IN6
+ * input and output = struct sioc_sg_req6
+
+* Protocol PHONET:
+ * cmd == SIOCPNADDRESOURCE | SIOCPNDELRESOURCE
+ * input int (4 bytes)
+ * Nothing is copied back to userspace.
+
+For the exception cases, functions sock_sk_ioctl_inout() will
+copy the userspace input, and copy it back to kernel space.
+
+The wrapper that prepare the buffer and put the buffer back to user is
+sk_ioctl(), so, instead of calling sk->sk_prot->ioctl(), the callee now
+calls sk_ioctl(), which will handle all cases.
+
+Signed-off-by: Breno Leitao <leitao@debian.org>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://lore.kernel.org/r/20230609152800.830401-1-leitao@debian.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 3b2d9bc4d4ac ("phonet: take correct lock to peek at the RX queue")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/icmpv6.h | 6 ++++
+ include/linux/mroute.h | 22 +++++++++++--
+ include/linux/mroute6.h | 31 ++++++++++++++++--
+ include/net/phonet/phonet.h | 21 ++++++++++++
+ include/net/sock.h | 5 ++-
+ include/net/tcp.h | 2 +-
+ include/net/udp.h | 2 +-
+ net/core/sock.c | 64 +++++++++++++++++++++++++++++++++++++
+ net/dccp/dccp.h | 2 +-
+ net/dccp/proto.c | 12 +++----
+ net/ieee802154/socket.c | 15 ++++-----
+ net/ipv4/af_inet.c | 2 +-
+ net/ipv4/ipmr.c | 63 ++++++++++++++++++++++--------------
+ net/ipv4/raw.c | 16 +++++-----
+ net/ipv4/tcp.c | 5 +--
+ net/ipv4/udp.c | 12 +++----
+ net/ipv6/af_inet6.c | 2 +-
+ net/ipv6/ip6mr.c | 44 +++++++++++--------------
+ net/ipv6/raw.c | 16 +++++-----
+ net/l2tp/l2tp_core.h | 2 +-
+ net/l2tp/l2tp_ip.c | 9 +++---
+ net/mptcp/protocol.c | 11 +++----
+ net/phonet/datagram.c | 11 +++----
+ net/phonet/pep.c | 11 +++----
+ net/phonet/socket.c | 2 +-
+ net/sctp/socket.c | 8 ++---
+ 26 files changed, 267 insertions(+), 129 deletions(-)
+
+diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h
+index db0f4fcfdaf4f..1fe33e6741cca 100644
+--- a/include/linux/icmpv6.h
++++ b/include/linux/icmpv6.h
+@@ -111,4 +111,10 @@ static inline bool icmpv6_is_err(int type)
+ return false;
+ }
+
++static inline int sk_is_icmpv6(struct sock *sk)
++{
++ return sk->sk_family == AF_INET6 &&
++ inet_sk(sk)->inet_num == IPPROTO_ICMPV6;
++}
++
+ #endif
+diff --git a/include/linux/mroute.h b/include/linux/mroute.h
+index 80b8400ab8b24..94c6e6f549f0a 100644
+--- a/include/linux/mroute.h
++++ b/include/linux/mroute.h
+@@ -16,12 +16,19 @@ static inline int ip_mroute_opt(int opt)
+ return opt >= MRT_BASE && opt <= MRT_MAX;
+ }
+
++static inline int sk_is_ipmr(struct sock *sk)
++{
++ return sk->sk_family == AF_INET &&
++ inet_sk(sk)->inet_num == IPPROTO_IGMP;
++}
++
+ int ip_mroute_setsockopt(struct sock *, int, sockptr_t, unsigned int);
+ int ip_mroute_getsockopt(struct sock *, int, sockptr_t, sockptr_t);
+-int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg);
++int ipmr_ioctl(struct sock *sk, int cmd, void *arg);
+ int ipmr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+ int ip_mr_init(void);
+ bool ipmr_rule_default(const struct fib_rule *rule);
++int ipmr_sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+ #else
+ static inline int ip_mroute_setsockopt(struct sock *sock, int optname,
+ sockptr_t optval, unsigned int optlen)
+@@ -35,7 +42,7 @@ static inline int ip_mroute_getsockopt(struct sock *sk, int optname,
+ return -ENOPROTOOPT;
+ }
+
+-static inline int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
++static inline int ipmr_ioctl(struct sock *sk, int cmd, void *arg)
+ {
+ return -ENOIOCTLCMD;
+ }
+@@ -50,10 +57,21 @@ static inline int ip_mroute_opt(int opt)
+ return 0;
+ }
+
++static inline int sk_is_ipmr(struct sock *sk)
++{
++ return 0;
++}
++
+ static inline bool ipmr_rule_default(const struct fib_rule *rule)
+ {
+ return true;
+ }
++
++static inline int ipmr_sk_ioctl(struct sock *sk, unsigned int cmd,
++ void __user *arg)
++{
++ return 1;
++}
+ #endif
+
+ #define VIFF_STATIC 0x8000
+diff --git a/include/linux/mroute6.h b/include/linux/mroute6.h
+index 8f2b307fb1241..2f95d5b4e47af 100644
+--- a/include/linux/mroute6.h
++++ b/include/linux/mroute6.h
+@@ -29,10 +29,10 @@ struct sock;
+ extern int ip6_mroute_setsockopt(struct sock *, int, sockptr_t, unsigned int);
+ extern int ip6_mroute_getsockopt(struct sock *, int, sockptr_t, sockptr_t);
+ extern int ip6_mr_input(struct sk_buff *skb);
+-extern int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg);
+ extern int ip6mr_compat_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+ extern int ip6_mr_init(void);
+ extern void ip6_mr_cleanup(void);
++int ip6mr_ioctl(struct sock *sk, int cmd, void *arg);
+ #else
+ static inline int ip6_mroute_setsockopt(struct sock *sock, int optname,
+ sockptr_t optval, unsigned int optlen)
+@@ -48,7 +48,7 @@ int ip6_mroute_getsockopt(struct sock *sock,
+ }
+
+ static inline
+-int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
++int ip6mr_ioctl(struct sock *sk, int cmd, void *arg)
+ {
+ return -ENOIOCTLCMD;
+ }
+@@ -100,6 +100,27 @@ extern int ip6mr_get_route(struct net *net, struct sk_buff *skb,
+ #ifdef CONFIG_IPV6_MROUTE
+ bool mroute6_is_socket(struct net *net, struct sk_buff *skb);
+ extern int ip6mr_sk_done(struct sock *sk);
++static inline int ip6mr_sk_ioctl(struct sock *sk, unsigned int cmd,
++ void __user *arg)
++{
++ switch (cmd) {
++ /* These userspace buffers will be consumed by ip6mr_ioctl() */
++ case SIOCGETMIFCNT_IN6: {
++ struct sioc_mif_req6 buffer;
++
++ return sock_ioctl_inout(sk, cmd, arg, &buffer,
++ sizeof(buffer));
++ }
++ case SIOCGETSGCNT_IN6: {
++ struct sioc_mif_req6 buffer;
++
++ return sock_ioctl_inout(sk, cmd, arg, &buffer,
++ sizeof(buffer));
++ }
++ }
++
++ return 1;
++}
+ #else
+ static inline bool mroute6_is_socket(struct net *net, struct sk_buff *skb)
+ {
+@@ -109,5 +130,11 @@ static inline int ip6mr_sk_done(struct sock *sk)
+ {
+ return 0;
+ }
++
++static inline int ip6mr_sk_ioctl(struct sock *sk, unsigned int cmd,
++ void __user *arg)
++{
++ return 1;
++}
+ #endif
+ #endif
+diff --git a/include/net/phonet/phonet.h b/include/net/phonet/phonet.h
+index 862f1719b5230..cf5ecae4a2fcd 100644
+--- a/include/net/phonet/phonet.h
++++ b/include/net/phonet/phonet.h
+@@ -109,4 +109,25 @@ void phonet_sysctl_exit(void);
+ int isi_register(void);
+ void isi_unregister(void);
+
++static inline bool sk_is_phonet(struct sock *sk)
++{
++ return sk->sk_family == PF_PHONET;
++}
++
++static inline int phonet_sk_ioctl(struct sock *sk, unsigned int cmd,
++ void __user *arg)
++{
++ int karg;
++
++ switch (cmd) {
++ case SIOCPNADDRESOURCE:
++ case SIOCPNDELRESOURCE:
++ if (get_user(karg, (int __user *)arg))
++ return -EFAULT;
++
++ return sk->sk_prot->ioctl(sk, cmd, &karg);
++ }
++ /* A positive return value means that the ioctl was not processed */
++ return 1;
++}
+ #endif
+diff --git a/include/net/sock.h b/include/net/sock.h
+index 579732d47dfc4..6ea961ee257d2 100644
+--- a/include/net/sock.h
++++ b/include/net/sock.h
+@@ -1258,7 +1258,7 @@ struct proto {
+ bool kern);
+
+ int (*ioctl)(struct sock *sk, int cmd,
+- unsigned long arg);
++ int *karg);
+ int (*init)(struct sock *sk);
+ void (*destroy)(struct sock *sk);
+ void (*shutdown)(struct sock *sk, int how);
+@@ -3048,6 +3048,9 @@ int sock_get_timeout(long timeo, void *optval, bool old_timeval);
+ int sock_copy_user_timeval(struct __kernel_sock_timeval *tv,
+ sockptr_t optval, int optlen, bool old_timeval);
+
++int sock_ioctl_inout(struct sock *sk, unsigned int cmd,
++ void __user *arg, void *karg, size_t size);
++int sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg);
+ static inline bool sk_is_readable(struct sock *sk)
+ {
+ if (sk->sk_prot->sock_is_readable)
+diff --git a/include/net/tcp.h b/include/net/tcp.h
+index 8ea1fba84eff9..8d3777e476e0e 100644
+--- a/include/net/tcp.h
++++ b/include/net/tcp.h
+@@ -346,7 +346,7 @@ void tcp_release_cb(struct sock *sk);
+ void tcp_wfree(struct sk_buff *skb);
+ void tcp_write_timer_handler(struct sock *sk);
+ void tcp_delack_timer_handler(struct sock *sk);
+-int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg);
++int tcp_ioctl(struct sock *sk, int cmd, int *karg);
+ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb);
+ void tcp_rcv_established(struct sock *sk, struct sk_buff *skb);
+ void tcp_rcv_space_adjust(struct sock *sk);
+diff --git a/include/net/udp.h b/include/net/udp.h
+index fa4cdbe55552c..b5e5d5e2b4e1b 100644
+--- a/include/net/udp.h
++++ b/include/net/udp.h
+@@ -275,7 +275,7 @@ void udp_flush_pending_frames(struct sock *sk);
+ int udp_cmsg_send(struct sock *sk, struct msghdr *msg, u16 *gso_size);
+ void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst);
+ int udp_rcv(struct sk_buff *skb);
+-int udp_ioctl(struct sock *sk, int cmd, unsigned long arg);
++int udp_ioctl(struct sock *sk, int cmd, int *karg);
+ int udp_init_sock(struct sock *sk);
+ int udp_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
+ int __udp_disconnect(struct sock *sk, int flags);
+diff --git a/net/core/sock.c b/net/core/sock.c
+index c8803b95ea0da..e55220cc08640 100644
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -115,6 +115,9 @@
+ #include <linux/memcontrol.h>
+ #include <linux/prefetch.h>
+ #include <linux/compat.h>
++#include <linux/mroute.h>
++#include <linux/mroute6.h>
++#include <linux/icmpv6.h>
+
+ #include <linux/uaccess.h>
+
+@@ -139,6 +142,7 @@
+
+ #include <net/tcp.h>
+ #include <net/busy_poll.h>
++#include <net/phonet/phonet.h>
+
+ #include <linux/ethtool.h>
+
+@@ -4129,3 +4133,63 @@ int sock_bind_add(struct sock *sk, struct sockaddr *addr, int addr_len)
+ return sk->sk_prot->bind_add(sk, addr, addr_len);
+ }
+ EXPORT_SYMBOL(sock_bind_add);
++
++/* Copy 'size' bytes from userspace and return `size` back to userspace */
++int sock_ioctl_inout(struct sock *sk, unsigned int cmd,
++ void __user *arg, void *karg, size_t size)
++{
++ int ret;
++
++ if (copy_from_user(karg, arg, size))
++ return -EFAULT;
++
++ ret = READ_ONCE(sk->sk_prot)->ioctl(sk, cmd, karg);
++ if (ret)
++ return ret;
++
++ if (copy_to_user(arg, karg, size))
++ return -EFAULT;
++
++ return 0;
++}
++EXPORT_SYMBOL(sock_ioctl_inout);
++
++/* This is the most common ioctl prep function, where the result (4 bytes) is
++ * copied back to userspace if the ioctl() returns successfully. No input is
++ * copied from userspace as input argument.
++ */
++static int sock_ioctl_out(struct sock *sk, unsigned int cmd, void __user *arg)
++{
++ int ret, karg = 0;
++
++ ret = READ_ONCE(sk->sk_prot)->ioctl(sk, cmd, &karg);
++ if (ret)
++ return ret;
++
++ return put_user(karg, (int __user *)arg);
++}
++
++/* A wrapper around sock ioctls, which copies the data from userspace
++ * (depending on the protocol/ioctl), and copies back the result to userspace.
++ * The main motivation for this function is to pass kernel memory to the
++ * protocol ioctl callbacks, instead of userspace memory.
++ */
++int sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
++{
++ int rc = 1;
++
++ if (sk_is_ipmr(sk))
++ rc = ipmr_sk_ioctl(sk, cmd, arg);
++ else if (sk_is_icmpv6(sk))
++ rc = ip6mr_sk_ioctl(sk, cmd, arg);
++ else if (sk_is_phonet(sk))
++ rc = phonet_sk_ioctl(sk, cmd, arg);
++
++ /* If ioctl was processed, returns its value */
++ if (rc <= 0)
++ return rc;
++
++ /* Otherwise call the default handler */
++ return sock_ioctl_out(sk, cmd, arg);
++}
++EXPORT_SYMBOL(sk_ioctl);
+diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
+index 9ddc3a9e89e40..1f748ed1279d3 100644
+--- a/net/dccp/dccp.h
++++ b/net/dccp/dccp.h
+@@ -292,7 +292,7 @@ int dccp_getsockopt(struct sock *sk, int level, int optname,
+ char __user *optval, int __user *optlen);
+ int dccp_setsockopt(struct sock *sk, int level, int optname,
+ sockptr_t optval, unsigned int optlen);
+-int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg);
++int dccp_ioctl(struct sock *sk, int cmd, int *karg);
+ int dccp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
+ int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,
+ int *addr_len);
+diff --git a/net/dccp/proto.c b/net/dccp/proto.c
+index c522c76a9f89f..1d25cfcdbe5dc 100644
+--- a/net/dccp/proto.c
++++ b/net/dccp/proto.c
+@@ -363,7 +363,7 @@ __poll_t dccp_poll(struct file *file, struct socket *sock,
+ }
+ EXPORT_SYMBOL_GPL(dccp_poll);
+
+-int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++int dccp_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ int rc = -ENOTCONN;
+
+@@ -374,17 +374,17 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+
+ switch (cmd) {
+ case SIOCOUTQ: {
+- int amount = sk_wmem_alloc_get(sk);
++ *karg = sk_wmem_alloc_get(sk);
+ /* Using sk_wmem_alloc here because sk_wmem_queued is not used by DCCP and
+ * always 0, comparably to UDP.
+ */
+
+- rc = put_user(amount, (int __user *)arg);
++ rc = 0;
+ }
+ break;
+ case SIOCINQ: {
+ struct sk_buff *skb;
+- unsigned long amount = 0;
++ *karg = 0;
+
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb != NULL) {
+@@ -392,9 +392,9 @@ int dccp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ * We will only return the amount of this packet since
+ * that is all that will be read.
+ */
+- amount = skb->len;
++ *karg = skb->len;
+ }
+- rc = put_user(amount, (int __user *)arg);
++ rc = 0;
+ }
+ break;
+ default:
+diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c
+index 1fa2fe041ec03..9c124705120dd 100644
+--- a/net/ieee802154/socket.c
++++ b/net/ieee802154/socket.c
+@@ -162,7 +162,7 @@ static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd,
+ default:
+ if (!sk->sk_prot->ioctl)
+ return -ENOIOCTLCMD;
+- return sk->sk_prot->ioctl(sk, cmd, arg);
++ return sk_ioctl(sk, cmd, (void __user *)arg);
+ }
+ }
+
+@@ -531,22 +531,21 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
+ return err;
+ }
+
+-static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
++static int dgram_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ switch (cmd) {
+ case SIOCOUTQ:
+ {
+- int amount = sk_wmem_alloc_get(sk);
++ *karg = sk_wmem_alloc_get(sk);
+
+- return put_user(amount, (int __user *)arg);
++ return 0;
+ }
+
+ case SIOCINQ:
+ {
+ struct sk_buff *skb;
+- unsigned long amount;
+
+- amount = 0;
++ *karg = 0;
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb) {
+@@ -554,10 +553,10 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ * of this packet since that is all
+ * that will be read.
+ */
+- amount = skb->len - ieee802154_hdr_length(skb);
++ *karg = skb->len - ieee802154_hdr_length(skb);
+ }
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+- return put_user(amount, (int __user *)arg);
++ return 0;
+ }
+ }
+
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index 9408dc3bb42d3..eddedc2f8c5c9 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1007,7 +1007,7 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ break;
+ default:
+ if (sk->sk_prot->ioctl)
+- err = sk->sk_prot->ioctl(sk, cmd, arg);
++ err = sk_ioctl(sk, cmd, (void __user *)arg);
+ else
+ err = -ENOIOCTLCMD;
+ break;
+diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
+index d5421c38c2aae..e20f7ab8099ad 100644
+--- a/net/ipv4/ipmr.c
++++ b/net/ipv4/ipmr.c
+@@ -1546,6 +1546,28 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
+ return ret;
+ }
+
++/* Execute if this ioctl is a special mroute ioctl */
++int ipmr_sk_ioctl(struct sock *sk, unsigned int cmd, void __user *arg)
++{
++ switch (cmd) {
++ /* These userspace buffers will be consumed by ipmr_ioctl() */
++ case SIOCGETVIFCNT: {
++ struct sioc_vif_req buffer;
++
++ return sock_ioctl_inout(sk, cmd, arg, &buffer,
++ sizeof(buffer));
++ }
++ case SIOCGETSGCNT: {
++ struct sioc_sg_req buffer;
++
++ return sock_ioctl_inout(sk, cmd, arg, &buffer,
++ sizeof(buffer));
++ }
++ }
++ /* return code > 0 means that the ioctl was not executed */
++ return 1;
++}
++
+ /* Getsock opt support for the multicast routing system. */
+ int ip_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
+ sockptr_t optlen)
+@@ -1592,13 +1614,13 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
+ }
+
+ /* The IP multicast ioctl support routines. */
+-int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
++int ipmr_ioctl(struct sock *sk, int cmd, void *arg)
+ {
+- struct sioc_sg_req sr;
+- struct sioc_vif_req vr;
+ struct vif_device *vif;
+ struct mfc_cache *c;
+ struct net *net = sock_net(sk);
++ struct sioc_vif_req *vr;
++ struct sioc_sg_req *sr;
+ struct mr_table *mrt;
+
+ mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
+@@ -1607,40 +1629,33 @@ int ipmr_ioctl(struct sock *sk, int cmd, void __user *arg)
+
+ switch (cmd) {
+ case SIOCGETVIFCNT:
+- if (copy_from_user(&vr, arg, sizeof(vr)))
+- return -EFAULT;
+- if (vr.vifi >= mrt->maxvif)
++ vr = (struct sioc_vif_req *)arg;
++ if (vr->vifi >= mrt->maxvif)
+ return -EINVAL;
+- vr.vifi = array_index_nospec(vr.vifi, mrt->maxvif);
++ vr->vifi = array_index_nospec(vr->vifi, mrt->maxvif);
+ rcu_read_lock();
+- vif = &mrt->vif_table[vr.vifi];
+- if (VIF_EXISTS(mrt, vr.vifi)) {
+- vr.icount = READ_ONCE(vif->pkt_in);
+- vr.ocount = READ_ONCE(vif->pkt_out);
+- vr.ibytes = READ_ONCE(vif->bytes_in);
+- vr.obytes = READ_ONCE(vif->bytes_out);
++ vif = &mrt->vif_table[vr->vifi];
++ if (VIF_EXISTS(mrt, vr->vifi)) {
++ vr->icount = READ_ONCE(vif->pkt_in);
++ vr->ocount = READ_ONCE(vif->pkt_out);
++ vr->ibytes = READ_ONCE(vif->bytes_in);
++ vr->obytes = READ_ONCE(vif->bytes_out);
+ rcu_read_unlock();
+
+- if (copy_to_user(arg, &vr, sizeof(vr)))
+- return -EFAULT;
+ return 0;
+ }
+ rcu_read_unlock();
+ return -EADDRNOTAVAIL;
+ case SIOCGETSGCNT:
+- if (copy_from_user(&sr, arg, sizeof(sr)))
+- return -EFAULT;
++ sr = (struct sioc_sg_req *)arg;
+
+ rcu_read_lock();
+- c = ipmr_cache_find(mrt, sr.src.s_addr, sr.grp.s_addr);
++ c = ipmr_cache_find(mrt, sr->src.s_addr, sr->grp.s_addr);
+ if (c) {
+- sr.pktcnt = c->_c.mfc_un.res.pkt;
+- sr.bytecnt = c->_c.mfc_un.res.bytes;
+- sr.wrong_if = c->_c.mfc_un.res.wrong_if;
++ sr->pktcnt = c->_c.mfc_un.res.pkt;
++ sr->bytecnt = c->_c.mfc_un.res.bytes;
++ sr->wrong_if = c->_c.mfc_un.res.wrong_if;
+ rcu_read_unlock();
+-
+- if (copy_to_user(arg, &sr, sizeof(sr)))
+- return -EFAULT;
+ return 0;
+ }
+ rcu_read_unlock();
+diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
+index 7c63b91edbf7a..a2d1f1ee7df59 100644
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -858,29 +858,29 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
+ return do_raw_getsockopt(sk, level, optname, optval, optlen);
+ }
+
+-static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
++static int raw_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ switch (cmd) {
+ case SIOCOUTQ: {
+- int amount = sk_wmem_alloc_get(sk);
+-
+- return put_user(amount, (int __user *)arg);
++ *karg = sk_wmem_alloc_get(sk);
++ return 0;
+ }
+ case SIOCINQ: {
+ struct sk_buff *skb;
+- int amount = 0;
+
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb)
+- amount = skb->len;
++ *karg = skb->len;
++ else
++ *karg = 0;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+- return put_user(amount, (int __user *)arg);
++ return 0;
+ }
+
+ default:
+ #ifdef CONFIG_IP_MROUTE
+- return ipmr_ioctl(sk, cmd, (void __user *)arg);
++ return ipmr_ioctl(sk, cmd, karg);
+ #else
+ return -ENOIOCTLCMD;
+ #endif
+diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
+index 86e7695d91adf..dcbcf238bf3ab 100644
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -598,7 +598,7 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
+ }
+ EXPORT_SYMBOL(tcp_poll);
+
+-int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++int tcp_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ struct tcp_sock *tp = tcp_sk(sk);
+ int answ;
+@@ -640,7 +640,8 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ return -ENOIOCTLCMD;
+ }
+
+- return put_user(answ, (int __user *)arg);
++ *karg = answ;
++ return 0;
+ }
+ EXPORT_SYMBOL(tcp_ioctl);
+
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index 87d759bab0012..2a5748c246e24 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1694,21 +1694,19 @@ static int first_packet_length(struct sock *sk)
+ * IOCTL requests applicable to the UDP protocol
+ */
+
+-int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++int udp_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ switch (cmd) {
+ case SIOCOUTQ:
+ {
+- int amount = sk_wmem_alloc_get(sk);
+-
+- return put_user(amount, (int __user *)arg);
++ *karg = sk_wmem_alloc_get(sk);
++ return 0;
+ }
+
+ case SIOCINQ:
+ {
+- int amount = max_t(int, 0, first_packet_length(sk));
+-
+- return put_user(amount, (int __user *)arg);
++ *karg = max_t(int, 0, first_packet_length(sk));
++ return 0;
+ }
+
+ default:
+diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
+index 0b42eb8c55aaf..37190217d650c 100644
+--- a/net/ipv6/af_inet6.c
++++ b/net/ipv6/af_inet6.c
+@@ -598,7 +598,7 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+ prot = READ_ONCE(sk->sk_prot);
+ if (!prot->ioctl)
+ return -ENOIOCTLCMD;
+- return prot->ioctl(sk, cmd, arg);
++ return sk_ioctl(sk, cmd, (void __user *)arg);
+ }
+ /*NOTREACHED*/
+ return 0;
+diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
+index 27fb5479988af..76db80a7124c8 100644
+--- a/net/ipv6/ip6mr.c
++++ b/net/ipv6/ip6mr.c
+@@ -1879,11 +1879,10 @@ int ip6_mroute_getsockopt(struct sock *sk, int optname, sockptr_t optval,
+ /*
+ * The IP multicast ioctl support routines.
+ */
+-
+-int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
++int ip6mr_ioctl(struct sock *sk, int cmd, void *arg)
+ {
+- struct sioc_sg_req6 sr;
+- struct sioc_mif_req6 vr;
++ struct sioc_sg_req6 *sr;
++ struct sioc_mif_req6 *vr;
+ struct vif_device *vif;
+ struct mfc6_cache *c;
+ struct net *net = sock_net(sk);
+@@ -1895,40 +1894,33 @@ int ip6mr_ioctl(struct sock *sk, int cmd, void __user *arg)
+
+ switch (cmd) {
+ case SIOCGETMIFCNT_IN6:
+- if (copy_from_user(&vr, arg, sizeof(vr)))
+- return -EFAULT;
+- if (vr.mifi >= mrt->maxvif)
++ vr = (struct sioc_mif_req6 *)arg;
++ if (vr->mifi >= mrt->maxvif)
+ return -EINVAL;
+- vr.mifi = array_index_nospec(vr.mifi, mrt->maxvif);
++ vr->mifi = array_index_nospec(vr->mifi, mrt->maxvif);
+ rcu_read_lock();
+- vif = &mrt->vif_table[vr.mifi];
+- if (VIF_EXISTS(mrt, vr.mifi)) {
+- vr.icount = READ_ONCE(vif->pkt_in);
+- vr.ocount = READ_ONCE(vif->pkt_out);
+- vr.ibytes = READ_ONCE(vif->bytes_in);
+- vr.obytes = READ_ONCE(vif->bytes_out);
++ vif = &mrt->vif_table[vr->mifi];
++ if (VIF_EXISTS(mrt, vr->mifi)) {
++ vr->icount = READ_ONCE(vif->pkt_in);
++ vr->ocount = READ_ONCE(vif->pkt_out);
++ vr->ibytes = READ_ONCE(vif->bytes_in);
++ vr->obytes = READ_ONCE(vif->bytes_out);
+ rcu_read_unlock();
+-
+- if (copy_to_user(arg, &vr, sizeof(vr)))
+- return -EFAULT;
+ return 0;
+ }
+ rcu_read_unlock();
+ return -EADDRNOTAVAIL;
+ case SIOCGETSGCNT_IN6:
+- if (copy_from_user(&sr, arg, sizeof(sr)))
+- return -EFAULT;
++ sr = (struct sioc_sg_req6 *)arg;
+
+ rcu_read_lock();
+- c = ip6mr_cache_find(mrt, &sr.src.sin6_addr, &sr.grp.sin6_addr);
++ c = ip6mr_cache_find(mrt, &sr->src.sin6_addr,
++ &sr->grp.sin6_addr);
+ if (c) {
+- sr.pktcnt = c->_c.mfc_un.res.pkt;
+- sr.bytecnt = c->_c.mfc_un.res.bytes;
+- sr.wrong_if = c->_c.mfc_un.res.wrong_if;
++ sr->pktcnt = c->_c.mfc_un.res.pkt;
++ sr->bytecnt = c->_c.mfc_un.res.bytes;
++ sr->wrong_if = c->_c.mfc_un.res.wrong_if;
+ rcu_read_unlock();
+-
+- if (copy_to_user(arg, &sr, sizeof(sr)))
+- return -EFAULT;
+ return 0;
+ }
+ rcu_read_unlock();
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index dc31752a7edcc..e361953ca7f45 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -1116,29 +1116,29 @@ static int rawv6_getsockopt(struct sock *sk, int level, int optname,
+ return do_rawv6_getsockopt(sk, level, optname, optval, optlen);
+ }
+
+-static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
++static int rawv6_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ switch (cmd) {
+ case SIOCOUTQ: {
+- int amount = sk_wmem_alloc_get(sk);
+-
+- return put_user(amount, (int __user *)arg);
++ *karg = sk_wmem_alloc_get(sk);
++ return 0;
+ }
+ case SIOCINQ: {
+ struct sk_buff *skb;
+- int amount = 0;
+
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb)
+- amount = skb->len;
++ *karg = skb->len;
++ else
++ *karg = 0;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+- return put_user(amount, (int __user *)arg);
++ return 0;
+ }
+
+ default:
+ #ifdef CONFIG_IPV6_MROUTE
+- return ip6mr_ioctl(sk, cmd, (void __user *)arg);
++ return ip6mr_ioctl(sk, cmd, karg);
+ #else
+ return -ENOIOCTLCMD;
+ #endif
+diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
+index a88e070b431d8..91ebf0a3f4997 100644
+--- a/net/l2tp/l2tp_core.h
++++ b/net/l2tp/l2tp_core.h
+@@ -272,7 +272,7 @@ int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops
+ void l2tp_nl_unregister_ops(enum l2tp_pwtype pw_type);
+
+ /* IOCTL helper for IP encap modules. */
+-int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg);
++int l2tp_ioctl(struct sock *sk, int cmd, int *karg);
+
+ /* Extract the tunnel structure from a socket's sk_user_data pointer,
+ * validating the tunnel magic feather.
+diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
+index 41a74fc84ca13..2b795c1064f5c 100644
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -562,19 +562,18 @@ static int l2tp_ip_recvmsg(struct sock *sk, struct msghdr *msg,
+ return err ? err : copied;
+ }
+
+-int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++int l2tp_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ struct sk_buff *skb;
+- int amount;
+
+ switch (cmd) {
+ case SIOCOUTQ:
+- amount = sk_wmem_alloc_get(sk);
++ *karg = sk_wmem_alloc_get(sk);
+ break;
+ case SIOCINQ:
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+- amount = skb ? skb->len : 0;
++ *karg = skb ? skb->len : 0;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ break;
+
+@@ -582,7 +581,7 @@ int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ return -ENOIOCTLCMD;
+ }
+
+- return put_user(amount, (int __user *)arg);
++ return 0;
+ }
+ EXPORT_SYMBOL_GPL(l2tp_ioctl);
+
+diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
+index 859b18cb8e4f6..7ea10d7aec961 100644
+--- a/net/mptcp/protocol.c
++++ b/net/mptcp/protocol.c
+@@ -3640,11 +3640,10 @@ static int mptcp_ioctl_outq(const struct mptcp_sock *msk, u64 v)
+ return (int)delta;
+ }
+
+-static int mptcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++static int mptcp_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ struct mptcp_sock *msk = mptcp_sk(sk);
+ bool slow;
+- int answ;
+
+ switch (cmd) {
+ case SIOCINQ:
+@@ -3653,24 +3652,24 @@ static int mptcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+
+ lock_sock(sk);
+ __mptcp_move_skbs(msk);
+- answ = mptcp_inq_hint(sk);
++ *karg = mptcp_inq_hint(sk);
+ release_sock(sk);
+ break;
+ case SIOCOUTQ:
+ slow = lock_sock_fast(sk);
+- answ = mptcp_ioctl_outq(msk, READ_ONCE(msk->snd_una));
++ *karg = mptcp_ioctl_outq(msk, READ_ONCE(msk->snd_una));
+ unlock_sock_fast(sk, slow);
+ break;
+ case SIOCOUTQNSD:
+ slow = lock_sock_fast(sk);
+- answ = mptcp_ioctl_outq(msk, msk->snd_nxt);
++ *karg = mptcp_ioctl_outq(msk, msk->snd_nxt);
+ unlock_sock_fast(sk, slow);
+ break;
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+- return put_user(answ, (int __user *)arg);
++ return 0;
+ }
+
+ static void mptcp_subflow_early_fallback(struct mptcp_sock *msk,
+diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
+index ff5f49ab236ed..3aa50dc7535b7 100644
+--- a/net/phonet/datagram.c
++++ b/net/phonet/datagram.c
+@@ -28,24 +28,21 @@ static void pn_sock_close(struct sock *sk, long timeout)
+ sk_common_release(sk);
+ }
+
+-static int pn_ioctl(struct sock *sk, int cmd, unsigned long arg)
++static int pn_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ struct sk_buff *skb;
+- int answ;
+
+ switch (cmd) {
+ case SIOCINQ:
+ lock_sock(sk);
+ skb = skb_peek(&sk->sk_receive_queue);
+- answ = skb ? skb->len : 0;
++ *karg = skb ? skb->len : 0;
+ release_sock(sk);
+- return put_user(answ, (int __user *)arg);
++ return 0;
+
+ case SIOCPNADDRESOURCE:
+ case SIOCPNDELRESOURCE: {
+- u32 res;
+- if (get_user(res, (u32 __user *)arg))
+- return -EFAULT;
++ u32 res = *karg;
+ if (res >= 256)
+ return -EINVAL;
+ if (cmd == SIOCPNADDRESOURCE)
+diff --git a/net/phonet/pep.c b/net/phonet/pep.c
+index 83ea13a50690b..faba31f2eff29 100644
+--- a/net/phonet/pep.c
++++ b/net/phonet/pep.c
+@@ -917,10 +917,9 @@ static int pep_sock_enable(struct sock *sk, struct sockaddr *addr, int len)
+ return 0;
+ }
+
+-static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
++static int pep_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ struct pep_sock *pn = pep_sk(sk);
+- int answ;
+ int ret = -ENOIOCTLCMD;
+
+ switch (cmd) {
+@@ -933,13 +932,13 @@ static int pep_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ lock_sock(sk);
+ if (sock_flag(sk, SOCK_URGINLINE) &&
+ !skb_queue_empty(&pn->ctrlreq_queue))
+- answ = skb_peek(&pn->ctrlreq_queue)->len;
++ *karg = skb_peek(&pn->ctrlreq_queue)->len;
+ else if (!skb_queue_empty(&sk->sk_receive_queue))
+- answ = skb_peek(&sk->sk_receive_queue)->len;
++ *karg = skb_peek(&sk->sk_receive_queue)->len;
+ else
+- answ = 0;
++ *karg = 0;
+ release_sock(sk);
+- ret = put_user(answ, (int __user *)arg);
++ ret = 0;
+ break;
+
+ case SIOCPNENABLEPIPE:
+diff --git a/net/phonet/socket.c b/net/phonet/socket.c
+index 71e2caf6ab859..967f9b4dc0265 100644
+--- a/net/phonet/socket.c
++++ b/net/phonet/socket.c
+@@ -387,7 +387,7 @@ static int pn_socket_ioctl(struct socket *sock, unsigned int cmd,
+ return put_user(handle, (__u16 __user *)arg);
+ }
+
+- return sk->sk_prot->ioctl(sk, cmd, arg);
++ return sk_ioctl(sk, cmd, (void __user *)arg);
+ }
+
+ static int pn_socket_listen(struct socket *sock, int backlog)
+diff --git a/net/sctp/socket.c b/net/sctp/socket.c
+index 237a6b04adf6f..9c29bff647a11 100644
+--- a/net/sctp/socket.c
++++ b/net/sctp/socket.c
+@@ -4902,7 +4902,7 @@ static struct sock *sctp_accept(struct sock *sk, int flags, int *err, bool kern)
+ }
+
+ /* The SCTP ioctl handler. */
+-static int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
++static int sctp_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ int rc = -ENOTCONN;
+
+@@ -4918,7 +4918,7 @@ static int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ switch (cmd) {
+ case SIOCINQ: {
+ struct sk_buff *skb;
+- unsigned int amount = 0;
++ *karg = 0;
+
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb != NULL) {
+@@ -4926,9 +4926,9 @@ static int sctp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+ * We will only return the amount of this packet since
+ * that is all that will be read.
+ */
+- amount = skb->len;
++ *karg = skb->len;
+ }
+- rc = put_user(amount, (int __user *)arg);
++ rc = 0;
+ break;
+ }
+ default:
+--
+2.43.0
+
--- /dev/null
+From f806cb6e3a4b66b68257cefbadf0a8b5e11f2f79 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 15:53:08 +0800
+Subject: net: mctp: put sock on tag allocation failure
+
+From: Jeremy Kerr <jk@codeconstruct.com.au>
+
+[ Upstream commit 9990889be14288d4f1743e4768222d5032a79c27 ]
+
+We may hold an extra reference on a socket if a tag allocation fails: we
+optimistically allocate the sk_key, and take a ref there, but do not
+drop if we end up not using the allocated key.
+
+Ensure we're dropping the sock on this failure by doing a proper unref
+rather than directly kfree()ing.
+
+Fixes: de8a6b15d965 ("net: mctp: add an explicit reference from a mctp_sk_key to sock")
+Signed-off-by: Jeremy Kerr <jk@codeconstruct.com.au>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/ce9b61e44d1cdae7797be0c5e3141baf582d23a0.1707983487.git.jk@codeconstruct.com.au
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mctp/route.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/mctp/route.c b/net/mctp/route.c
+index 68be8f2b622dd..256bf0b89e6ca 100644
+--- a/net/mctp/route.c
++++ b/net/mctp/route.c
+@@ -663,7 +663,7 @@ struct mctp_sk_key *mctp_alloc_local_tag(struct mctp_sock *msk,
+ spin_unlock_irqrestore(&mns->keys_lock, flags);
+
+ if (!tagbits) {
+- kfree(key);
++ mctp_key_unref(key);
+ return ERR_PTR(-EBUSY);
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 49b249c7a3d94e62196e307624d89b4212f923a0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Feb 2024 12:30:07 +0530
+Subject: net: phy: realtek: Fix rtl8211f_config_init() for
+ RTL8211F(D)(I)-VD-CG PHY
+
+From: Siddharth Vadapalli <s-vadapalli@ti.com>
+
+[ Upstream commit 3489182b11d35f1944c1245fc9c4867cf622c50f ]
+
+Commit bb726b753f75 ("net: phy: realtek: add support for
+RTL8211F(D)(I)-VD-CG") extended support of the driver from the existing
+support for RTL8211F(D)(I)-CG PHY to the newer RTL8211F(D)(I)-VD-CG PHY.
+
+While that commit indicated that the RTL8211F_PHYCR2 register is not
+supported by the "VD-CG" PHY model and therefore updated the corresponding
+section in rtl8211f_config_init() to be invoked conditionally, the call to
+"genphy_soft_reset()" was left as-is, when it should have also been invoked
+conditionally. This is because the call to "genphy_soft_reset()" was first
+introduced by the commit 0a4355c2b7f8 ("net: phy: realtek: add dt property
+to disable CLKOUT clock") since the RTL8211F guide indicates that a PHY
+reset should be issued after setting bits in the PHYCR2 register.
+
+As the PHYCR2 register is not applicable to the "VD-CG" PHY model, fix the
+rtl8211f_config_init() function by invoking "genphy_soft_reset()"
+conditionally based on the presence of the "PHYCR2" register.
+
+Fixes: bb726b753f75 ("net: phy: realtek: add support for RTL8211F(D)(I)-VD-CG")
+Signed-off-by: Siddharth Vadapalli <s-vadapalli@ti.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/20240220070007.968762-1-s-vadapalli@ti.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/realtek.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
+index 3d99fd6664d7a..70e52d27064ec 100644
+--- a/drivers/net/phy/realtek.c
++++ b/drivers/net/phy/realtek.c
+@@ -414,9 +414,11 @@ static int rtl8211f_config_init(struct phy_device *phydev)
+ ERR_PTR(ret));
+ return ret;
+ }
++
++ return genphy_soft_reset(phydev);
+ }
+
+- return genphy_soft_reset(phydev);
++ return 0;
+ }
+
+ static int rtl821x_resume(struct phy_device *phydev)
+--
+2.43.0
+
--- /dev/null
+From 5051d5e36fb20f1bedb77327b708977af28d1647 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 09:00:43 +0100
+Subject: net: sparx5: Add spinlock for frame transmission from CPU
+
+From: Horatiu Vultur <horatiu.vultur@microchip.com>
+
+[ Upstream commit 603ead96582d85903baec2d55f021b8dac5c25d2 ]
+
+Both registers used when doing manual injection or fdma injection are
+shared between all the net devices of the switch. It was noticed that
+when having two process which each of them trying to inject frames on
+different ethernet ports, that the HW started to behave strange, by
+sending out more frames then expected. When doing fdma injection it is
+required to set the frame in the DCB and then make sure that the next
+pointer of the last DCB is invalid. But because there is no locks for
+this, then easily this pointer between the DCB can be broken and then it
+would create a loop of DCBs. And that means that the HW will
+continuously transmit these frames in a loop. Until the SW will break
+this loop.
+Therefore to fix this issue, add a spin lock for when accessing the
+registers for manual or fdma injection.
+
+Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
+Reviewed-by: Daniel Machon <daniel.machon@microchip.com>
+Fixes: f3cad2611a77 ("net: sparx5: add hostmode with phylink support")
+Link: https://lore.kernel.org/r/20240219080043.1561014-1-horatiu.vultur@microchip.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/microchip/sparx5/sparx5_main.c | 1 +
+ drivers/net/ethernet/microchip/sparx5/sparx5_main.h | 1 +
+ drivers/net/ethernet/microchip/sparx5/sparx5_packet.c | 2 ++
+ 3 files changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+index 3423c95cc84ae..7031f41287e09 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+@@ -744,6 +744,7 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
+ platform_set_drvdata(pdev, sparx5);
+ sparx5->pdev = pdev;
+ sparx5->dev = &pdev->dev;
++ spin_lock_init(&sparx5->tx_lock);
+
+ /* Do switch core reset if available */
+ reset = devm_reset_control_get_optional_shared(&pdev->dev, "switch");
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
+index 7a83222caa737..cb3173d2b0e8d 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
+@@ -278,6 +278,7 @@ struct sparx5 {
+ int xtr_irq;
+ /* Frame DMA */
+ int fdma_irq;
++ spinlock_t tx_lock; /* lock for frame transmission */
+ struct sparx5_rx rx;
+ struct sparx5_tx tx;
+ /* PTP */
+diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
+index 6db6ac6a3bbc2..ac7e1cffbcecf 100644
+--- a/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
+@@ -244,10 +244,12 @@ netdev_tx_t sparx5_port_xmit_impl(struct sk_buff *skb, struct net_device *dev)
+ }
+
+ skb_tx_timestamp(skb);
++ spin_lock(&sparx5->tx_lock);
+ if (sparx5->fdma_irq > 0)
+ ret = sparx5_fdma_xmit(sparx5, ifh, skb);
+ else
+ ret = sparx5_inject(sparx5, ifh, skb, dev);
++ spin_unlock(&sparx5->tx_lock);
+
+ if (ret == -EBUSY)
+ goto busy;
+--
+2.43.0
+
--- /dev/null
+From f94bc64bb302393c14f3102fe0832a33b5d73756 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Feb 2024 12:27:17 +0300
+Subject: net: stmmac: Fix incorrect dereference in interrupt handlers
+
+From: Pavel Sakharov <p.sakharov@ispras.ru>
+
+[ Upstream commit 97dde84026339e4b4af9a6301f825d1828d7874b ]
+
+If 'dev' or 'data' is NULL, the 'priv' variable has an incorrect address
+when dereferencing calling netdev_err().
+
+Since we get as 'dev_id' or 'data' what was passed as the 'dev' argument
+to request_irq() during interrupt initialization (that is, the net_device
+and rx/tx queue pointers initialized at the time of the call) and since
+there are usually no checks for the 'dev_id' argument in such handlers
+in other drivers, remove these checks from the handlers in stmmac driver.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 8532f613bc78 ("net: stmmac: introduce MSI Interrupt routines for mac, safety, RX & TX")
+Signed-off-by: Pavel Sakharov <p.sakharov@ispras.ru>
+Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 20 -------------------
+ 1 file changed, 20 deletions(-)
+
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+index 66178ce6d000e..91b2aa81914ba 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+@@ -5823,11 +5823,6 @@ static irqreturn_t stmmac_mac_interrupt(int irq, void *dev_id)
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+- if (unlikely(!dev)) {
+- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
+- return IRQ_NONE;
+- }
+-
+ /* Check if adapter is up */
+ if (test_bit(STMMAC_DOWN, &priv->state))
+ return IRQ_HANDLED;
+@@ -5843,11 +5838,6 @@ static irqreturn_t stmmac_safety_interrupt(int irq, void *dev_id)
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct stmmac_priv *priv = netdev_priv(dev);
+
+- if (unlikely(!dev)) {
+- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
+- return IRQ_NONE;
+- }
+-
+ /* Check if adapter is up */
+ if (test_bit(STMMAC_DOWN, &priv->state))
+ return IRQ_HANDLED;
+@@ -5869,11 +5859,6 @@ static irqreturn_t stmmac_msi_intr_tx(int irq, void *data)
+ dma_conf = container_of(tx_q, struct stmmac_dma_conf, tx_queue[chan]);
+ priv = container_of(dma_conf, struct stmmac_priv, dma_conf);
+
+- if (unlikely(!data)) {
+- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
+- return IRQ_NONE;
+- }
+-
+ /* Check if adapter is up */
+ if (test_bit(STMMAC_DOWN, &priv->state))
+ return IRQ_HANDLED;
+@@ -5900,11 +5885,6 @@ static irqreturn_t stmmac_msi_intr_rx(int irq, void *data)
+ dma_conf = container_of(rx_q, struct stmmac_dma_conf, rx_queue[chan]);
+ priv = container_of(dma_conf, struct stmmac_priv, dma_conf);
+
+- if (unlikely(!data)) {
+- netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
+- return IRQ_NONE;
+- }
+-
+ /* Check if adapter is up */
+ if (test_bit(STMMAC_DOWN, &priv->state))
+ return IRQ_HANDLED;
+--
+2.43.0
+
--- /dev/null
+From 4149f11f589a89e2246d7845a6c61e87d9430340 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 May 2023 07:35:33 +0200
+Subject: netfilter: flowtable: simplify route logic
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit fa502c86566680ac62bc28ec883a069bf7a2aa5e ]
+
+Grab reference to dst from skbuff earlier to simplify route caching.
+
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Stable-dep-of: 9e0f0430389b ("netfilter: nft_flow_offload: reset dst in route object after setting up flow")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_flow_table.h | 4 ++--
+ net/netfilter/nf_flow_table_core.c | 24 +++---------------------
+ net/netfilter/nft_flow_offload.c | 12 ++++++++----
+ 3 files changed, 13 insertions(+), 27 deletions(-)
+
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index dde4dd9c4012c..692d5955911c7 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -274,8 +274,8 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
+ flow_table->type->put(flow_table);
+ }
+
+-int flow_offload_route_init(struct flow_offload *flow,
+- const struct nf_flow_route *route);
++void flow_offload_route_init(struct flow_offload *flow,
++ const struct nf_flow_route *route);
+
+ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);
+ void flow_offload_refresh(struct nf_flowtable *flow_table,
+diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
+index c1d99cb370b44..78e4aba52b22a 100644
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -125,9 +125,6 @@ static int flow_offload_fill_route(struct flow_offload *flow,
+ break;
+ case FLOW_OFFLOAD_XMIT_XFRM:
+ case FLOW_OFFLOAD_XMIT_NEIGH:
+- if (!dst_hold_safe(route->tuple[dir].dst))
+- return -1;
+-
+ flow_tuple->dst_cache = dst;
+ flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple);
+ break;
+@@ -148,27 +145,12 @@ static void nft_flow_dst_release(struct flow_offload *flow,
+ dst_release(flow->tuplehash[dir].tuple.dst_cache);
+ }
+
+-int flow_offload_route_init(struct flow_offload *flow,
++void flow_offload_route_init(struct flow_offload *flow,
+ const struct nf_flow_route *route)
+ {
+- int err;
+-
+- err = flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_ORIGINAL);
+- if (err < 0)
+- return err;
+-
+- err = flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_REPLY);
+- if (err < 0)
+- goto err_route_reply;
+-
++ flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_ORIGINAL);
++ flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_REPLY);
+ flow->type = NF_FLOW_OFFLOAD_ROUTE;
+-
+- return 0;
+-
+-err_route_reply:
+- nft_flow_dst_release(flow, FLOW_OFFLOAD_DIR_ORIGINAL);
+-
+- return err;
+ }
+ EXPORT_SYMBOL_GPL(flow_offload_route_init);
+
+diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c
+index 3d9f6dda5aeb2..7a8707632a815 100644
+--- a/net/netfilter/nft_flow_offload.c
++++ b/net/netfilter/nft_flow_offload.c
+@@ -250,9 +250,14 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
+ break;
+ }
+
++ if (!dst_hold_safe(this_dst))
++ return -ENOENT;
++
+ nf_route(nft_net(pkt), &other_dst, &fl, false, nft_pf(pkt));
+- if (!other_dst)
++ if (!other_dst) {
++ dst_release(this_dst);
+ return -ENOENT;
++ }
+
+ nft_default_forward_path(route, this_dst, dir);
+ nft_default_forward_path(route, other_dst, !dir);
+@@ -349,8 +354,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
+ if (!flow)
+ goto err_flow_alloc;
+
+- if (flow_offload_route_init(flow, &route) < 0)
+- goto err_flow_add;
++ flow_offload_route_init(flow, &route);
+
+ if (tcph) {
+ ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL;
+@@ -361,12 +365,12 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
+ if (ret < 0)
+ goto err_flow_add;
+
+- dst_release(route.tuple[!dir].dst);
+ return;
+
+ err_flow_add:
+ flow_offload_free(flow);
+ err_flow_alloc:
++ dst_release(route.tuple[dir].dst);
+ dst_release(route.tuple[!dir].dst);
+ err_flow_route:
+ clear_bit(IPS_OFFLOAD_BIT, &ct->status);
+--
+2.43.0
+
--- /dev/null
+From 795b8c0ab65fa3ae4ce101196d3793ded8052961 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 19:43:53 +0100
+Subject: netfilter: nf_tables: register hooks last when adding new
+ chain/flowtable
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit d472e9853d7b46a6b094224d131d09ccd3a03daf ]
+
+Register hooks last when adding chain/flowtable to ensure that packets do
+not walk over datastructure that is being released in the error path
+without waiting for the rcu grace period.
+
+Fixes: 91c7b38dc9f0 ("netfilter: nf_tables: use new transaction infrastructure to handle chain")
+Fixes: 3b49e2e94e6e ("netfilter: nf_tables: add flow table netlink frontend")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 78 ++++++++++++++++++-----------------
+ 1 file changed, 40 insertions(+), 38 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index c7b543d1a0516..a29313e0aaa4d 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -686,15 +686,16 @@ static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj)
+ return err;
+ }
+
+-static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type,
+- struct nft_flowtable *flowtable)
++static struct nft_trans *
++nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type,
++ struct nft_flowtable *flowtable)
+ {
+ struct nft_trans *trans;
+
+ trans = nft_trans_alloc(ctx, msg_type,
+ sizeof(struct nft_trans_flowtable));
+ if (trans == NULL)
+- return -ENOMEM;
++ return ERR_PTR(-ENOMEM);
+
+ if (msg_type == NFT_MSG_NEWFLOWTABLE)
+ nft_activate_next(ctx->net, flowtable);
+@@ -703,22 +704,22 @@ static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type,
+ nft_trans_flowtable(trans) = flowtable;
+ nft_trans_commit_list_add_tail(ctx->net, trans);
+
+- return 0;
++ return trans;
+ }
+
+ static int nft_delflowtable(struct nft_ctx *ctx,
+ struct nft_flowtable *flowtable)
+ {
+- int err;
++ struct nft_trans *trans;
+
+- err = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable);
+- if (err < 0)
+- return err;
++ trans = nft_trans_flowtable_add(ctx, NFT_MSG_DELFLOWTABLE, flowtable);
++ if (IS_ERR(trans))
++ return PTR_ERR(trans);
+
+ nft_deactivate_next(ctx->net, flowtable);
+ nft_use_dec(&ctx->table->use);
+
+- return err;
++ return 0;
+ }
+
+ static void __nft_reg_track_clobber(struct nft_regs_track *track, u8 dreg)
+@@ -2459,19 +2460,15 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
+ RCU_INIT_POINTER(chain->blob_gen_0, blob);
+ RCU_INIT_POINTER(chain->blob_gen_1, blob);
+
+- err = nf_tables_register_hook(net, table, chain);
+- if (err < 0)
+- goto err_destroy_chain;
+-
+ if (!nft_use_inc(&table->use)) {
+ err = -EMFILE;
+- goto err_use;
++ goto err_destroy_chain;
+ }
+
+ trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
+ if (IS_ERR(trans)) {
+ err = PTR_ERR(trans);
+- goto err_unregister_hook;
++ goto err_trans;
+ }
+
+ nft_trans_chain_policy(trans) = NFT_CHAIN_POLICY_UNSET;
+@@ -2479,17 +2476,22 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
+ nft_trans_chain_policy(trans) = policy;
+
+ err = nft_chain_add(table, chain);
+- if (err < 0) {
+- nft_trans_destroy(trans);
+- goto err_unregister_hook;
+- }
++ if (err < 0)
++ goto err_chain_add;
++
++ /* This must be LAST to ensure no packets are walking over this chain. */
++ err = nf_tables_register_hook(net, table, chain);
++ if (err < 0)
++ goto err_register_hook;
+
+ return 0;
+
+-err_unregister_hook:
++err_register_hook:
++ nft_chain_del(chain);
++err_chain_add:
++ nft_trans_destroy(trans);
++err_trans:
+ nft_use_dec_restore(&table->use);
+-err_use:
+- nf_tables_unregister_hook(net, table, chain);
+ err_destroy_chain:
+ nf_tables_chain_destroy(ctx);
+
+@@ -8031,9 +8033,9 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
+ u8 family = info->nfmsg->nfgen_family;
+ const struct nf_flowtable_type *type;
+ struct nft_flowtable *flowtable;
+- struct nft_hook *hook, *next;
+ struct net *net = info->net;
+ struct nft_table *table;
++ struct nft_trans *trans;
+ struct nft_ctx ctx;
+ int err;
+
+@@ -8113,34 +8115,34 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
+ err = nft_flowtable_parse_hook(&ctx, nla[NFTA_FLOWTABLE_HOOK],
+ &flowtable_hook, flowtable, true);
+ if (err < 0)
+- goto err4;
++ goto err_flowtable_parse_hooks;
+
+ list_splice(&flowtable_hook.list, &flowtable->hook_list);
+ flowtable->data.priority = flowtable_hook.priority;
+ flowtable->hooknum = flowtable_hook.num;
+
++ trans = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable);
++ if (IS_ERR(trans)) {
++ err = PTR_ERR(trans);
++ goto err_flowtable_trans;
++ }
++
++ /* This must be LAST to ensure no packets are walking over this flowtable. */
+ err = nft_register_flowtable_net_hooks(ctx.net, table,
+ &flowtable->hook_list,
+ flowtable);
+- if (err < 0) {
+- nft_hooks_destroy(&flowtable->hook_list);
+- goto err4;
+- }
+-
+- err = nft_trans_flowtable_add(&ctx, NFT_MSG_NEWFLOWTABLE, flowtable);
+ if (err < 0)
+- goto err5;
++ goto err_flowtable_hooks;
+
+ list_add_tail_rcu(&flowtable->list, &table->flowtables);
+
+ return 0;
+-err5:
+- list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
+- nft_unregister_flowtable_hook(net, flowtable, hook);
+- list_del_rcu(&hook->list);
+- kfree_rcu(hook, rcu);
+- }
+-err4:
++
++err_flowtable_hooks:
++ nft_trans_destroy(trans);
++err_flowtable_trans:
++ nft_hooks_destroy(&flowtable->hook_list);
++err_flowtable_parse_hooks:
+ flowtable->data.type->free(&flowtable->data);
+ err3:
+ module_put(type->owner);
+--
+2.43.0
+
--- /dev/null
+From 1593cc918dde81d0111c2f4395641d8906524a2c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Apr 2023 00:34:30 +0200
+Subject: netfilter: nf_tables: rename function to destroy hook list
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit cdc32546632354305afdcf399a5431138a31c9e0 ]
+
+Rename nft_flowtable_hooks_destroy() by nft_hooks_destroy() to prepare
+for netdev chain device updates.
+
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Stable-dep-of: d472e9853d7b ("netfilter: nf_tables: register hooks last when adding new chain/flowtable")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index f1a74b0949999..c7b543d1a0516 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -7938,7 +7938,7 @@ static int nft_register_flowtable_net_hooks(struct net *net,
+ return err;
+ }
+
+-static void nft_flowtable_hooks_destroy(struct list_head *hook_list)
++static void nft_hooks_destroy(struct list_head *hook_list)
+ {
+ struct nft_hook *hook, *next;
+
+@@ -8123,7 +8123,7 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
+ &flowtable->hook_list,
+ flowtable);
+ if (err < 0) {
+- nft_flowtable_hooks_destroy(&flowtable->hook_list);
++ nft_hooks_destroy(&flowtable->hook_list);
+ goto err4;
+ }
+
+@@ -8893,7 +8893,7 @@ static void nft_commit_release(struct nft_trans *trans)
+ break;
+ case NFT_MSG_DELFLOWTABLE:
+ if (nft_trans_flowtable_update(trans))
+- nft_flowtable_hooks_destroy(&nft_trans_flowtable_hooks(trans));
++ nft_hooks_destroy(&nft_trans_flowtable_hooks(trans));
+ else
+ nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
+ break;
+@@ -9850,7 +9850,7 @@ static void nf_tables_abort_release(struct nft_trans *trans)
+ break;
+ case NFT_MSG_NEWFLOWTABLE:
+ if (nft_trans_flowtable_update(trans))
+- nft_flowtable_hooks_destroy(&nft_trans_flowtable_hooks(trans));
++ nft_hooks_destroy(&nft_trans_flowtable_hooks(trans));
+ else
+ nf_tables_flowtable_destroy(nft_trans_flowtable(trans));
+ break;
+--
+2.43.0
+
--- /dev/null
+From 09be199d01a383d0b60fa2e30a2f9b853c97f9f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 16:58:04 +0100
+Subject: netfilter: nf_tables: set dormant flag on hook register failure
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit bccebf64701735533c8db37773eeacc6566cc8ec ]
+
+We need to set the dormant flag again if we fail to register
+the hooks.
+
+During memory pressure hook registration can fail and we end up
+with a table marked as active but no registered hooks.
+
+On table/base chain deletion, nf_tables will attempt to unregister
+the hook again which yields a warn splat from the nftables core.
+
+Reported-and-tested-by: syzbot+de4025c006ec68ac56fc@syzkaller.appspotmail.com
+Fixes: 179d9ba5559a ("netfilter: nf_tables: fix table flag updates")
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 49acb89ba9c56..f1a74b0949999 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -1245,6 +1245,7 @@ static int nf_tables_updtable(struct nft_ctx *ctx)
+ return 0;
+
+ err_register_hooks:
++ ctx->table->flags |= NFT_TABLE_F_DORMANT;
+ nft_trans_destroy(trans);
+ return ret;
+ }
+--
+2.43.0
+
--- /dev/null
+From 33db609121871f789aa7af3574b7b5f132508b9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Feb 2024 18:38:45 +0100
+Subject: netfilter: nf_tables: use kzalloc for hook allocation
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 195e5f88c2e48330ba5483e0bad2de3b3fad484f ]
+
+KMSAN reports unitialized variable when registering the hook,
+ reg->hook_ops_type == NF_HOOK_OP_BPF)
+ ~~~~~~~~~~~ undefined
+
+This is a small structure, just use kzalloc to make sure this
+won't happen again when new fields get added to nf_hook_ops.
+
+Fixes: 7b4b2fa37587 ("netfilter: annotate nf_tables base hook ops")
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index a29313e0aaa4d..e21ec3ad80939 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -2059,7 +2059,7 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
+ struct nft_hook *hook;
+ int err;
+
+- hook = kmalloc(sizeof(struct nft_hook), GFP_KERNEL_ACCOUNT);
++ hook = kzalloc(sizeof(struct nft_hook), GFP_KERNEL_ACCOUNT);
+ if (!hook) {
+ err = -ENOMEM;
+ goto err_hook_alloc;
+--
+2.43.0
+
--- /dev/null
+From 48a0ad02aa81bbb1f08891b8f2b873a3b954fa47 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Feb 2024 21:36:39 +0100
+Subject: netfilter: nft_flow_offload: release dst in case direct xmit path is
+ used
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 8762785f459be1cfe6fcf7285c123aad6a3703f0 ]
+
+Direct xmit does not use it since it calls dev_queue_xmit() to send
+packets, hence it calls dst_release().
+
+kmemleak reports:
+
+unreferenced object 0xffff88814f440900 (size 184):
+ comm "softirq", pid 0, jiffies 4294951896
+ hex dump (first 32 bytes):
+ 00 60 5b 04 81 88 ff ff 00 e6 e8 82 ff ff ff ff .`[.............
+ 21 0b 50 82 ff ff ff ff 00 00 00 00 00 00 00 00 !.P.............
+ backtrace (crc cb2bf5d6):
+ [<000000003ee17107>] kmem_cache_alloc+0x286/0x340
+ [<0000000021a5de2c>] dst_alloc+0x43/0xb0
+ [<00000000f0671159>] rt_dst_alloc+0x2e/0x190
+ [<00000000fe5092c9>] __mkroute_output+0x244/0x980
+ [<000000005fb96fb0>] ip_route_output_flow+0xc0/0x160
+ [<0000000045367433>] nf_ip_route+0xf/0x30
+ [<0000000085da1d8e>] nf_route+0x2d/0x60
+ [<00000000d1ecd1cb>] nft_flow_route+0x171/0x6a0 [nft_flow_offload]
+ [<00000000d9b2fb60>] nft_flow_offload_eval+0x4e8/0x700 [nft_flow_offload]
+ [<000000009f447dbb>] expr_call_ops_eval+0x53/0x330 [nf_tables]
+ [<00000000072e1be6>] nft_do_chain+0x17c/0x840 [nf_tables]
+ [<00000000d0551029>] nft_do_chain_inet+0xa1/0x210 [nf_tables]
+ [<0000000097c9d5c6>] nf_hook_slow+0x5b/0x160
+ [<0000000005eccab1>] ip_forward+0x8b6/0x9b0
+ [<00000000553a269b>] ip_rcv+0x221/0x230
+ [<00000000412872e5>] __netif_receive_skb_one_core+0xfe/0x110
+
+Fixes: fa502c865666 ("netfilter: flowtable: simplify route logic")
+Reported-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_flow_table_core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
+index 2036c7a27075b..99195cf6b2657 100644
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -132,6 +132,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
+ ETH_ALEN);
+ flow_tuple->out.ifidx = route->tuple[dir].out.ifindex;
+ flow_tuple->out.hw_ifidx = route->tuple[dir].out.hw_ifindex;
++ dst_release(dst);
+ break;
+ case FLOW_OFFLOAD_XMIT_XFRM:
+ case FLOW_OFFLOAD_XMIT_NEIGH:
+--
+2.43.0
+
--- /dev/null
+From 0fd162379ba0c91a4dcf5e1309a208acb894043d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Feb 2024 12:32:58 +0100
+Subject: netfilter: nft_flow_offload: reset dst in route object after setting
+ up flow
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 9e0f0430389be7696396c62f037be4bf72cf93e3 ]
+
+dst is transferred to the flow object, route object does not own it
+anymore. Reset dst in route object, otherwise if flow_offload_add()
+fails, error path releases dst twice, leading to a refcount underflow.
+
+Fixes: a3c90f7a2323 ("netfilter: nf_tables: flow offload expression")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_flow_table.h | 2 +-
+ net/netfilter/nf_flow_table_core.c | 16 +++++++++++++---
+ 2 files changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/netfilter/nf_flow_table.h b/include/net/netfilter/nf_flow_table.h
+index 692d5955911c7..4a767b3d20b9d 100644
+--- a/include/net/netfilter/nf_flow_table.h
++++ b/include/net/netfilter/nf_flow_table.h
+@@ -275,7 +275,7 @@ nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table,
+ }
+
+ void flow_offload_route_init(struct flow_offload *flow,
+- const struct nf_flow_route *route);
++ struct nf_flow_route *route);
+
+ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);
+ void flow_offload_refresh(struct nf_flowtable *flow_table,
+diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c
+index 78e4aba52b22a..2036c7a27075b 100644
+--- a/net/netfilter/nf_flow_table_core.c
++++ b/net/netfilter/nf_flow_table_core.c
+@@ -87,12 +87,22 @@ static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple)
+ return 0;
+ }
+
++static struct dst_entry *nft_route_dst_fetch(struct nf_flow_route *route,
++ enum flow_offload_tuple_dir dir)
++{
++ struct dst_entry *dst = route->tuple[dir].dst;
++
++ route->tuple[dir].dst = NULL;
++
++ return dst;
++}
++
+ static int flow_offload_fill_route(struct flow_offload *flow,
+- const struct nf_flow_route *route,
++ struct nf_flow_route *route,
+ enum flow_offload_tuple_dir dir)
+ {
+ struct flow_offload_tuple *flow_tuple = &flow->tuplehash[dir].tuple;
+- struct dst_entry *dst = route->tuple[dir].dst;
++ struct dst_entry *dst = nft_route_dst_fetch(route, dir);
+ int i, j = 0;
+
+ switch (flow_tuple->l3proto) {
+@@ -146,7 +156,7 @@ static void nft_flow_dst_release(struct flow_offload *flow,
+ }
+
+ void flow_offload_route_init(struct flow_offload *flow,
+- const struct nf_flow_route *route)
++ struct nf_flow_route *route)
+ {
+ flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_ORIGINAL);
+ flow_offload_fill_route(flow, route, FLOW_OFFLOAD_DIR_REPLY);
+--
+2.43.0
+
--- /dev/null
+From 40e6df1db011eb416bcabb72f9532b60557db2c2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 10:57:37 +0100
+Subject: nouveau: fix function cast warnings
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 0affdba22aca5573f9d989bcb1d71d32a6a03efe ]
+
+clang-16 warns about casting between incompatible function types:
+
+drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c:161:10: error: cast from 'void (*)(const struct firmware *)' to 'void (*)(void *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict]
+ 161 | .fini = (void(*)(void *))release_firmware,
+
+This one was done to use the generic shadow_fw_release() function as a
+callback for struct nvbios_source. Change it to use the same prototype
+as the other five instances, with a trivial helper function that actually
+calls release_firmware.
+
+Fixes: 70c0f263cc2e ("drm/nouveau/bios: pull in basic vbios subdev, more to come later")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Danilo Krummrich <dakr@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240213095753.455062-1-arnd@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+index 19188683c8fca..8c2bf1c16f2a9 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadow.c
+@@ -154,11 +154,17 @@ shadow_fw_init(struct nvkm_bios *bios, const char *name)
+ return (void *)fw;
+ }
+
++static void
++shadow_fw_release(void *fw)
++{
++ release_firmware(fw);
++}
++
+ static const struct nvbios_source
+ shadow_fw = {
+ .name = "firmware",
+ .init = shadow_fw_init,
+- .fini = (void(*)(void *))release_firmware,
++ .fini = shadow_fw_release,
+ .read = shadow_fw_read,
+ .rw = false,
+ };
+--
+2.43.0
+
--- /dev/null
+From 9071c7009209488722f5da4de852c83908097fa0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 19 Feb 2024 18:25:14 +0530
+Subject: octeontx2-af: Consider the action set by PF
+
+From: Subbaraya Sundeep <sbhatta@marvell.com>
+
+[ Upstream commit 3b1ae9b71c2a97f848b00fb085a2bd29bddbe8d9 ]
+
+AF reserves MCAM entries for each PF, VF present in the
+system and populates the entry with DMAC and action with
+default RSS so that basic packet I/O works. Since PF/VF is
+not aware of the RSS action installed by AF, AF only fixup
+the actions of the rules installed by PF/VF with corresponding
+default RSS action. This worked well for rules installed by
+PF/VF for features like RX VLAN offload and DMAC filters but
+rules involving action like drop/forward to queue are also
+getting modified by AF. Hence fix it by setting the default
+RSS action only if requested by PF/VF.
+
+Fixes: 967db3529eca ("octeontx2-af: add support for multicast/promisc packet replication feature")
+Signed-off-by: Subbaraya Sundeep <sbhatta@marvell.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+index 3784347b6fd88..55639c133dd02 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+@@ -437,6 +437,10 @@ static void npc_fixup_vf_rule(struct rvu *rvu, struct npc_mcam *mcam,
+ return;
+ }
+
++ /* AF modifies given action iff PF/VF has requested for it */
++ if ((entry->action & 0xFULL) != NIX_RX_ACTION_DEFAULT)
++ return;
++
+ /* copy VF default entry action to the VF mcam entry */
+ rx_action = npc_get_default_entry_action(rvu, mcam, blkaddr,
+ target_func);
+--
+2.43.0
+
--- /dev/null
+From 6dc94850c4e644c3186f1b1dbd8b577769ea3b4a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Feb 2024 10:12:14 +0200
+Subject: phonet/pep: fix racy skb_queue_empty() use
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rémi Denis-Courmont <courmisch@gmail.com>
+
+[ Upstream commit 7d2a894d7f487dcb894df023e9d3014cf5b93fe5 ]
+
+The receive queues are protected by their respective spin-lock, not
+the socket lock. This could lead to skb_peek() unexpectedly
+returning NULL or a pointer to an already dequeued socket buffer.
+
+Fixes: 9641458d3ec4 ("Phonet: Pipe End Point for Phonet Pipes protocol")
+Signed-off-by: Rémi Denis-Courmont <courmisch@gmail.com>
+Link: https://lore.kernel.org/r/20240218081214.4806-2-remi@remlab.net
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/phonet/pep.c | 41 ++++++++++++++++++++++++++++++++---------
+ 1 file changed, 32 insertions(+), 9 deletions(-)
+
+diff --git a/net/phonet/pep.c b/net/phonet/pep.c
+index faba31f2eff29..3dd5f52bc1b58 100644
+--- a/net/phonet/pep.c
++++ b/net/phonet/pep.c
+@@ -917,6 +917,37 @@ static int pep_sock_enable(struct sock *sk, struct sockaddr *addr, int len)
+ return 0;
+ }
+
++static unsigned int pep_first_packet_length(struct sock *sk)
++{
++ struct pep_sock *pn = pep_sk(sk);
++ struct sk_buff_head *q;
++ struct sk_buff *skb;
++ unsigned int len = 0;
++ bool found = false;
++
++ if (sock_flag(sk, SOCK_URGINLINE)) {
++ q = &pn->ctrlreq_queue;
++ spin_lock_bh(&q->lock);
++ skb = skb_peek(q);
++ if (skb) {
++ len = skb->len;
++ found = true;
++ }
++ spin_unlock_bh(&q->lock);
++ }
++
++ if (likely(!found)) {
++ q = &sk->sk_receive_queue;
++ spin_lock_bh(&q->lock);
++ skb = skb_peek(q);
++ if (skb)
++ len = skb->len;
++ spin_unlock_bh(&q->lock);
++ }
++
++ return len;
++}
++
+ static int pep_ioctl(struct sock *sk, int cmd, int *karg)
+ {
+ struct pep_sock *pn = pep_sk(sk);
+@@ -929,15 +960,7 @@ static int pep_ioctl(struct sock *sk, int cmd, int *karg)
+ break;
+ }
+
+- lock_sock(sk);
+- if (sock_flag(sk, SOCK_URGINLINE) &&
+- !skb_queue_empty(&pn->ctrlreq_queue))
+- *karg = skb_peek(&pn->ctrlreq_queue)->len;
+- else if (!skb_queue_empty(&sk->sk_receive_queue))
+- *karg = skb_peek(&sk->sk_receive_queue)->len;
+- else
+- *karg = 0;
+- release_sock(sk);
++ *karg = pep_first_packet_length(sk);
+ ret = 0;
+ break;
+
+--
+2.43.0
+
--- /dev/null
+From 1f5a44d59b1b5de08871b7c222043aa6fe0c382a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Feb 2024 10:12:13 +0200
+Subject: phonet: take correct lock to peek at the RX queue
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Rémi Denis-Courmont <courmisch@gmail.com>
+
+[ Upstream commit 3b2d9bc4d4acdf15a876eae2c0d83149250e85ba ]
+
+The receive queue is protected by its embedded spin-lock, not the
+socket lock, so we need the former lock here (and only that one).
+
+Fixes: 107d0d9b8d9a ("Phonet: Phonet datagram transport protocol")
+Reported-by: Luosili <rootlab@huawei.com>
+Signed-off-by: Rémi Denis-Courmont <courmisch@gmail.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/20240218081214.4806-1-remi@remlab.net
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/phonet/datagram.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c
+index 3aa50dc7535b7..976fe250b5095 100644
+--- a/net/phonet/datagram.c
++++ b/net/phonet/datagram.c
+@@ -34,10 +34,10 @@ static int pn_ioctl(struct sock *sk, int cmd, int *karg)
+
+ switch (cmd) {
+ case SIOCINQ:
+- lock_sock(sk);
++ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ *karg = skb ? skb->len : 0;
+- release_sock(sk);
++ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ return 0;
+
+ case SIOCPNADDRESOURCE:
+--
+2.43.0
+
--- /dev/null
+From 3bc92822a99dc339035146d658250db282eb2243 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Feb 2024 20:23:11 -0600
+Subject: platform/x86: thinkpad_acpi: Only update profile if successfully
+ converted
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 427c70dec738318b7f71e1b9d829ff0e9771d493 ]
+
+Randomly a Lenovo Z13 will trigger a kernel warning traceback from this
+condition:
+
+```
+if (WARN_ON((profile < 0) || (profile >= ARRAY_SIZE(profile_names))))
+```
+
+This happens because thinkpad-acpi always assumes that
+convert_dytc_to_profile() successfully updated the profile. On the
+contrary a condition can occur that when dytc_profile_refresh() is called
+the profile doesn't get updated as there is a -EOPNOTSUPP branch.
+
+Catch this situation and avoid updating the profile. Also log this into
+dynamic debugging in case any other modes should be added in the future.
+
+Fixes: c3bfcd4c6762 ("platform/x86: thinkpad_acpi: Add platform profile support")
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Link: https://lore.kernel.org/r/20240217022311.113879-1-mario.limonciello@amd.com
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/platform/x86/thinkpad_acpi.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
+index 6edd2e294750e..c2fb19af10705 100644
+--- a/drivers/platform/x86/thinkpad_acpi.c
++++ b/drivers/platform/x86/thinkpad_acpi.c
+@@ -10511,6 +10511,7 @@ static int convert_dytc_to_profile(int funcmode, int dytcmode,
+ return 0;
+ default:
+ /* Unknown function */
++ pr_debug("unknown function 0x%x\n", funcmode);
+ return -EOPNOTSUPP;
+ }
+ return 0;
+@@ -10696,8 +10697,8 @@ static void dytc_profile_refresh(void)
+ return;
+
+ perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
+- convert_dytc_to_profile(funcmode, perfmode, &profile);
+- if (profile != dytc_current_profile) {
++ err = convert_dytc_to_profile(funcmode, perfmode, &profile);
++ if (!err && profile != dytc_current_profile) {
+ dytc_current_profile = profile;
+ platform_profile_notify();
+ }
+--
+2.43.0
+
--- /dev/null
+From 20828f272a533db4970c971e51edf00cb49835c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 Jan 2024 20:54:36 -0800
+Subject: RDMA/bnxt_re: Return error for SRQ resize
+
+From: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+
+[ Upstream commit 3687b450c5f32e80f179ce4b09e0454da1449eac ]
+
+SRQ resize is not supported in the driver. But driver is not
+returning error from bnxt_re_modify_srq() for SRQ resize.
+
+Fixes: 37cb11acf1f7 ("RDMA/bnxt_re: Add SRQ support for Broadcom adapters")
+Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Signed-off-by: Selvin Xavier <selvin.xavier@broadcom.com>
+Link: https://lore.kernel.org/r/1705985677-15551-5-git-send-email-selvin.xavier@broadcom.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/bnxt_re/ib_verbs.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+index 4ed8814efde6f..6ed0568747eaa 100644
+--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
++++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+@@ -1710,7 +1710,7 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr,
+ switch (srq_attr_mask) {
+ case IB_SRQ_MAX_WR:
+ /* SRQ resize is not supported */
+- break;
++ return -EINVAL;
+ case IB_SRQ_LIMIT:
+ /* Change the SRQ threshold */
+ if (srq_attr->srq_limit > srq->qplib_srq.max_wqe)
+@@ -1725,13 +1725,12 @@ int bnxt_re_modify_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr,
+ /* On success, update the shadow */
+ srq->srq_limit = srq_attr->srq_limit;
+ /* No need to Build and send response back to udata */
+- break;
++ return 0;
+ default:
+ ibdev_err(&rdev->ibdev,
+ "Unsupported srq_attr_mask 0x%x", srq_attr_mask);
+ return -EINVAL;
+ }
+- return 0;
+ }
+
+ int bnxt_re_query_srq(struct ib_srq *ib_srq, struct ib_srq_attr *srq_attr)
+--
+2.43.0
+
--- /dev/null
+From 8b2aab68d1c40b38beed9264faaea1564d210dfd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 17:38:49 -0600
+Subject: RDMA/irdma: Add AE for too many RNRS
+
+From: Mustafa Ismail <mustafa.ismail@intel.com>
+
+[ Upstream commit 630bdb6f28ca9e5ff79e244030170ac788478332 ]
+
+Add IRDMA_AE_LLP_TOO_MANY_RNRS to the list of AE's processed as an
+abnormal asyncronous event.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Mustafa Ismail <mustafa.ismail@intel.com>
+Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
+Signed-off-by: Sindhu Devale <sindhu.devale@gmail.com>
+Link: https://lore.kernel.org/r/20240131233849.400285-5-sindhu.devale@intel.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/defs.h | 1 +
+ drivers/infiniband/hw/irdma/hw.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/defs.h b/drivers/infiniband/hw/irdma/defs.h
+index ad54260cb58c9..ebe98fa2b1cd2 100644
+--- a/drivers/infiniband/hw/irdma/defs.h
++++ b/drivers/infiniband/hw/irdma/defs.h
+@@ -345,6 +345,7 @@ enum irdma_cqp_op_type {
+ #define IRDMA_AE_LLP_TOO_MANY_KEEPALIVE_RETRIES 0x050b
+ #define IRDMA_AE_LLP_DOUBT_REACHABILITY 0x050c
+ #define IRDMA_AE_LLP_CONNECTION_ESTABLISHED 0x050e
++#define IRDMA_AE_LLP_TOO_MANY_RNRS 0x050f
+ #define IRDMA_AE_RESOURCE_EXHAUSTION 0x0520
+ #define IRDMA_AE_RESET_SENT 0x0601
+ #define IRDMA_AE_TERMINATE_SENT 0x0602
+diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c
+index 12bd38b1e2c15..918a2d783141f 100644
+--- a/drivers/infiniband/hw/irdma/hw.c
++++ b/drivers/infiniband/hw/irdma/hw.c
+@@ -379,6 +379,7 @@ static void irdma_process_aeq(struct irdma_pci_f *rf)
+ case IRDMA_AE_LLP_TOO_MANY_RETRIES:
+ case IRDMA_AE_LCE_QP_CATASTROPHIC:
+ case IRDMA_AE_LCE_FUNCTION_CATASTROPHIC:
++ case IRDMA_AE_LLP_TOO_MANY_RNRS:
+ case IRDMA_AE_LCE_CQ_CATASTROPHIC:
+ case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG:
+ default:
+--
+2.43.0
+
--- /dev/null
+From 9268c24bff8072ca5744676c05748cc60903e33d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 17:38:46 -0600
+Subject: RDMA/irdma: Fix KASAN issue with tasklet
+
+From: Mike Marciniszyn <mike.marciniszyn@intel.com>
+
+[ Upstream commit bd97cea7b18a0a553773af806dfbfac27a7c4acb ]
+
+KASAN testing revealed the following issue assocated with freeing an IRQ.
+
+[50006.466686] Call Trace:
+[50006.466691] <IRQ>
+[50006.489538] dump_stack+0x5c/0x80
+[50006.493475] print_address_description.constprop.6+0x1a/0x150
+[50006.499872] ? irdma_sc_process_ceq+0x483/0x790 [irdma]
+[50006.505742] ? irdma_sc_process_ceq+0x483/0x790 [irdma]
+[50006.511644] kasan_report.cold.11+0x7f/0x118
+[50006.516572] ? irdma_sc_process_ceq+0x483/0x790 [irdma]
+[50006.522473] irdma_sc_process_ceq+0x483/0x790 [irdma]
+[50006.528232] irdma_process_ceq+0xb2/0x400 [irdma]
+[50006.533601] ? irdma_hw_flush_wqes_callback+0x370/0x370 [irdma]
+[50006.540298] irdma_ceq_dpc+0x44/0x100 [irdma]
+[50006.545306] tasklet_action_common.isra.14+0x148/0x2c0
+[50006.551096] __do_softirq+0x1d0/0xaf8
+[50006.555396] irq_exit_rcu+0x219/0x260
+[50006.559670] irq_exit+0xa/0x20
+[50006.563320] smp_apic_timer_interrupt+0x1bf/0x690
+[50006.568645] apic_timer_interrupt+0xf/0x20
+[50006.573341] </IRQ>
+
+The issue is that a tasklet could be pending on another core racing
+the delete of the irq.
+
+Fix by insuring any scheduled tasklet is killed after deleting the
+irq.
+
+Fixes: 44d9e52977a1 ("RDMA/irdma: Implement device initialization definitions")
+Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
+Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
+Signed-off-by: Sindhu Devale <sindhu.devale@intel.com>
+Link: https://lore.kernel.org/r/20240131233849.400285-2-sindhu.devale@intel.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/hw.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c
+index 311a1138e838d..12bd38b1e2c15 100644
+--- a/drivers/infiniband/hw/irdma/hw.c
++++ b/drivers/infiniband/hw/irdma/hw.c
+@@ -562,6 +562,13 @@ static void irdma_destroy_irq(struct irdma_pci_f *rf,
+ dev->irq_ops->irdma_dis_irq(dev, msix_vec->idx);
+ irq_update_affinity_hint(msix_vec->irq, NULL);
+ free_irq(msix_vec->irq, dev_id);
++ if (rf == dev_id) {
++ tasklet_kill(&rf->dpc_tasklet);
++ } else {
++ struct irdma_ceq *iwceq = (struct irdma_ceq *)dev_id;
++
++ tasklet_kill(&iwceq->dpc_tasklet);
++ }
+ }
+
+ /**
+--
+2.43.0
+
--- /dev/null
+From d3ee42ec947f951c1040ccb91859f08ec9641923 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 17:38:48 -0600
+Subject: RDMA/irdma: Set the CQ read threshold for GEN 1
+
+From: Mustafa Ismail <mustafa.ismail@intel.com>
+
+[ Upstream commit 666047f3ece9f991774c1fe9b223139a9ef8908d ]
+
+The CQ shadow read threshold is currently not set for GEN 2. This could
+cause an invalid CQ overflow condition, so remove the GEN check that
+exclused GEN 1.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Signed-off-by: Mustafa Ismail <mustafa.ismail@intel.com>
+Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
+Signed-off-by: Sindhu Devale <sindhu.devale@intel.com>
+Link: https://lore.kernel.org/r/20240131233849.400285-4-sindhu.devale@intel.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 0fbc39df1e7d4..42c671f209233 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -2121,9 +2121,8 @@ static int irdma_create_cq(struct ib_cq *ibcq,
+ info.cq_base_pa = iwcq->kmem.pa;
+ }
+
+- if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
+- info.shadow_read_threshold = min(info.cq_uk_init_info.cq_size / 2,
+- (u32)IRDMA_MAX_CQ_READ_THRESH);
++ info.shadow_read_threshold = min(info.cq_uk_init_info.cq_size / 2,
++ (u32)IRDMA_MAX_CQ_READ_THRESH);
+
+ if (irdma_sc_cq_init(cq, &info)) {
+ ibdev_dbg(&iwdev->ibdev, "VERBS: init cq fail\n");
+--
+2.43.0
+
--- /dev/null
+From e2785e1bca91ac0b4f3bc17258c3f8bb2bbb9566 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 17:38:47 -0600
+Subject: RDMA/irdma: Validate max_send_wr and max_recv_wr
+
+From: Shiraz Saleem <shiraz.saleem@intel.com>
+
+[ Upstream commit ee107186bcfd25d7873258f3f75440e20f5e6416 ]
+
+Validate that max_send_wr and max_recv_wr is within the
+supported range.
+
+Fixes: b48c24c2d710 ("RDMA/irdma: Implement device supported verb APIs")
+Change-Id: I2fc8b10292b641fddd20b36986a9dae90a93f4be
+Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com>
+Signed-off-by: Sindhu Devale <sindhu.devale@intel.com>
+Link: https://lore.kernel.org/r/20240131233849.400285-3-sindhu.devale@intel.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/irdma/verbs.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
+index 01faec6ea5285..0fbc39df1e7d4 100644
+--- a/drivers/infiniband/hw/irdma/verbs.c
++++ b/drivers/infiniband/hw/irdma/verbs.c
+@@ -762,7 +762,9 @@ static int irdma_validate_qp_attrs(struct ib_qp_init_attr *init_attr,
+
+ if (init_attr->cap.max_inline_data > uk_attrs->max_hw_inline ||
+ init_attr->cap.max_send_sge > uk_attrs->max_hw_wq_frags ||
+- init_attr->cap.max_recv_sge > uk_attrs->max_hw_wq_frags)
++ init_attr->cap.max_recv_sge > uk_attrs->max_hw_wq_frags ||
++ init_attr->cap.max_send_wr > uk_attrs->max_hw_wq_quanta ||
++ init_attr->cap.max_recv_wr > uk_attrs->max_hw_rq_quanta)
+ return -EINVAL;
+
+ if (rdma_protocol_roce(&iwdev->ibdev, 1)) {
+--
+2.43.0
+
--- /dev/null
+From 973c9a2e9a723a8e8f7eb8454f67b124325686c0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Feb 2024 17:36:28 -0500
+Subject: RDMA/qedr: Fix qedr_create_user_qp error flow
+
+From: Kamal Heib <kheib@redhat.com>
+
+[ Upstream commit 5ba4e6d5863c53e937f49932dee0ecb004c65928 ]
+
+Avoid the following warning by making sure to free the allocated
+resources in case that qedr_init_user_queue() fail.
+
+-----------[ cut here ]-----------
+WARNING: CPU: 0 PID: 143192 at drivers/infiniband/core/rdma_core.c:874 uverbs_destroy_ufile_hw+0xcf/0xf0 [ib_uverbs]
+Modules linked in: tls target_core_user uio target_core_pscsi target_core_file target_core_iblock ib_srpt ib_srp scsi_transport_srp nfsd nfs_acl rpcsec_gss_krb5 auth_rpcgss nfsv4 dns_resolver nfs lockd grace fscache netfs 8021q garp mrp stp llc ext4 mbcache jbd2 opa_vnic ib_umad ib_ipoib sunrpc rdma_ucm ib_isert iscsi_target_mod target_core_mod ib_iser libiscsi scsi_transport_iscsi rdma_cm iw_cm ib_cm hfi1 intel_rapl_msr intel_rapl_common mgag200 qedr sb_edac drm_shmem_helper rdmavt x86_pkg_temp_thermal drm_kms_helper intel_powerclamp ib_uverbs coretemp i2c_algo_bit kvm_intel dell_wmi_descriptor ipmi_ssif sparse_keymap kvm ib_core rfkill syscopyarea sysfillrect video sysimgblt irqbypass ipmi_si ipmi_devintf fb_sys_fops rapl iTCO_wdt mxm_wmi iTCO_vendor_support intel_cstate pcspkr dcdbas intel_uncore ipmi_msghandler lpc_ich acpi_power_meter mei_me mei fuse drm xfs libcrc32c qede sd_mod ahci libahci t10_pi sg crct10dif_pclmul crc32_pclmul crc32c_intel qed libata tg3
+ghash_clmulni_intel megaraid_sas crc8 wmi [last unloaded: ib_srpt]
+CPU: 0 PID: 143192 Comm: fi_rdm_tagged_p Kdump: loaded Not tainted 5.14.0-408.el9.x86_64 #1
+Hardware name: Dell Inc. PowerEdge R430/03XKDV, BIOS 2.14.0 01/25/2022
+RIP: 0010:uverbs_destroy_ufile_hw+0xcf/0xf0 [ib_uverbs]
+Code: 5d 41 5c 41 5d 41 5e e9 0f 26 1b dd 48 89 df e8 67 6a ff ff 49 8b 86 10 01 00 00 48 85 c0 74 9c 4c 89 e7 e8 83 c0 cb dd eb 92 <0f> 0b eb be 0f 0b be 04 00 00 00 48 89 df e8 8e f5 ff ff e9 6d ff
+RSP: 0018:ffffb7c6cadfbc60 EFLAGS: 00010286
+RAX: ffff8f0889ee3f60 RBX: ffff8f088c1a5200 RCX: 00000000802a0016
+RDX: 00000000802a0017 RSI: 0000000000000001 RDI: ffff8f0880042600
+RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000000
+R10: ffff8f11fffd5000 R11: 0000000000039000 R12: ffff8f0d5b36cd80
+R13: ffff8f088c1a5250 R14: ffff8f1206d91000 R15: 0000000000000000
+FS: 0000000000000000(0000) GS:ffff8f11d7c00000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 0000147069200e20 CR3: 00000001c7210002 CR4: 00000000001706f0
+Call Trace:
+<TASK>
+? show_trace_log_lvl+0x1c4/0x2df
+? show_trace_log_lvl+0x1c4/0x2df
+? ib_uverbs_close+0x1f/0xb0 [ib_uverbs]
+? uverbs_destroy_ufile_hw+0xcf/0xf0 [ib_uverbs]
+? __warn+0x81/0x110
+? uverbs_destroy_ufile_hw+0xcf/0xf0 [ib_uverbs]
+? report_bug+0x10a/0x140
+? handle_bug+0x3c/0x70
+? exc_invalid_op+0x14/0x70
+? asm_exc_invalid_op+0x16/0x20
+? uverbs_destroy_ufile_hw+0xcf/0xf0 [ib_uverbs]
+ib_uverbs_close+0x1f/0xb0 [ib_uverbs]
+__fput+0x94/0x250
+task_work_run+0x5c/0x90
+do_exit+0x270/0x4a0
+do_group_exit+0x2d/0x90
+get_signal+0x87c/0x8c0
+arch_do_signal_or_restart+0x25/0x100
+? ib_uverbs_ioctl+0xc2/0x110 [ib_uverbs]
+exit_to_user_mode_loop+0x9c/0x130
+exit_to_user_mode_prepare+0xb6/0x100
+syscall_exit_to_user_mode+0x12/0x40
+do_syscall_64+0x69/0x90
+? syscall_exit_work+0x103/0x130
+? syscall_exit_to_user_mode+0x22/0x40
+? do_syscall_64+0x69/0x90
+? syscall_exit_work+0x103/0x130
+? syscall_exit_to_user_mode+0x22/0x40
+? do_syscall_64+0x69/0x90
+? do_syscall_64+0x69/0x90
+? common_interrupt+0x43/0xa0
+entry_SYSCALL_64_after_hwframe+0x72/0xdc
+RIP: 0033:0x1470abe3ec6b
+Code: Unable to access opcode bytes at RIP 0x1470abe3ec41.
+RSP: 002b:00007fff13ce9108 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
+RAX: fffffffffffffffc RBX: 00007fff13ce9218 RCX: 00001470abe3ec6b
+RDX: 00007fff13ce9200 RSI: 00000000c0181b01 RDI: 0000000000000004
+RBP: 00007fff13ce91e0 R08: 0000558d9655da10 R09: 0000558d9655dd00
+R10: 00007fff13ce95c0 R11: 0000000000000246 R12: 00007fff13ce9358
+R13: 0000000000000013 R14: 0000558d9655db50 R15: 00007fff13ce9470
+</TASK>
+--[ end trace 888a9b92e04c5c97 ]--
+
+Fixes: df15856132bc ("RDMA/qedr: restructure functions that create/destroy QPs")
+Signed-off-by: Kamal Heib <kheib@redhat.com>
+Link: https://lore.kernel.org/r/20240208223628.2040841-1-kheib@redhat.com
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/hw/qedr/verbs.c | 11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
+index d745ce9dc88aa..61755b5f3e20d 100644
+--- a/drivers/infiniband/hw/qedr/verbs.c
++++ b/drivers/infiniband/hw/qedr/verbs.c
+@@ -1879,8 +1879,17 @@ static int qedr_create_user_qp(struct qedr_dev *dev,
+ /* RQ - read access only (0) */
+ rc = qedr_init_user_queue(udata, dev, &qp->urq, ureq.rq_addr,
+ ureq.rq_len, true, 0, alloc_and_init);
+- if (rc)
++ if (rc) {
++ ib_umem_release(qp->usq.umem);
++ qp->usq.umem = NULL;
++ if (rdma_protocol_roce(&dev->ibdev, 1)) {
++ qedr_free_pbl(dev, &qp->usq.pbl_info,
++ qp->usq.pbl_tbl);
++ } else {
++ kfree(qp->usq.pbl_tbl);
++ }
+ return rc;
++ }
+ }
+
+ memset(&in_params, 0, sizeof(in_params));
+--
+2.43.0
+
--- /dev/null
+From debbee18717ce55815e8ec7468b35dd895670698 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 11:07:13 +0100
+Subject: RDMA/srpt: fix function pointer cast warnings
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit eb5c7465c3240151cd42a55c7ace9da0026308a1 ]
+
+clang-16 notices that srpt_qp_event() gets called through an incompatible
+pointer here:
+
+drivers/infiniband/ulp/srpt/ib_srpt.c:1815:5: error: cast from 'void (*)(struct ib_event *, struct srpt_rdma_ch *)' to 'void (*)(struct ib_event *, void *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict]
+ 1815 | = (void(*)(struct ib_event *, void*))srpt_qp_event;
+
+Change srpt_qp_event() to use the correct prototype and adjust the
+argument inside of it.
+
+Fixes: a42d985bd5b2 ("ib_srpt: Initial SRP Target merge for v3.3-rc1")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Link: https://lore.kernel.org/r/20240213100728.458348-1-arnd@kernel.org
+Reviewed-by: Bart Van Assche <bvanassche@acm.org>
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/ulp/srpt/ib_srpt.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
+index 4607d37b9224a..cffa93f114a73 100644
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -214,10 +214,12 @@ static const char *get_ch_state_name(enum rdma_ch_state s)
+ /**
+ * srpt_qp_event - QP event callback function
+ * @event: Description of the event that occurred.
+- * @ch: SRPT RDMA channel.
++ * @ptr: SRPT RDMA channel.
+ */
+-static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
++static void srpt_qp_event(struct ib_event *event, void *ptr)
+ {
++ struct srpt_rdma_ch *ch = ptr;
++
+ pr_debug("QP event %d on ch=%p sess_name=%s-%d state=%s\n",
+ event->event, ch, ch->sess_name, ch->qp->qp_num,
+ get_ch_state_name(ch->state));
+@@ -1811,8 +1813,7 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
+ ch->cq_size = ch->rq_size + sq_size;
+
+ qp_init->qp_context = (void *)ch;
+- qp_init->event_handler
+- = (void(*)(struct ib_event *, void*))srpt_qp_event;
++ qp_init->event_handler = srpt_qp_event;
+ qp_init->send_cq = ch->cq;
+ qp_init->recv_cq = ch->cq;
+ qp_init->sq_sig_type = IB_SIGNAL_REQ_WR;
+--
+2.43.0
+
--- /dev/null
+From c44742b7bfb555d7c7e8cb7a2bd3ed4e0c727d21 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 4 Feb 2024 16:42:07 -0800
+Subject: RDMA/srpt: Support specifying the srpt_service_guid parameter
+
+From: Bart Van Assche <bvanassche@acm.org>
+
+[ Upstream commit fdfa083549de5d50ebf7f6811f33757781e838c0 ]
+
+Make loading ib_srpt with this parameter set work. The current behavior is
+that setting that parameter while loading the ib_srpt kernel module
+triggers the following kernel crash:
+
+BUG: kernel NULL pointer dereference, address: 0000000000000000
+Call Trace:
+ <TASK>
+ parse_one+0x18c/0x1d0
+ parse_args+0xe1/0x230
+ load_module+0x8de/0xa60
+ init_module_from_file+0x8b/0xd0
+ idempotent_init_module+0x181/0x240
+ __x64_sys_finit_module+0x5a/0xb0
+ do_syscall_64+0x5f/0xe0
+ entry_SYSCALL_64_after_hwframe+0x6e/0x76
+
+Cc: LiHonggang <honggangli@163.com>
+Reported-by: LiHonggang <honggangli@163.com>
+Fixes: a42d985bd5b2 ("ib_srpt: Initial SRP Target merge for v3.3-rc1")
+Signed-off-by: Bart Van Assche <bvanassche@acm.org>
+Link: https://lore.kernel.org/r/20240205004207.17031-1-bvanassche@acm.org
+Signed-off-by: Leon Romanovsky <leon@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/infiniband/ulp/srpt/ib_srpt.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
+index 25e799dba999e..4607d37b9224a 100644
+--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
++++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
+@@ -79,12 +79,16 @@ module_param(srpt_srq_size, int, 0444);
+ MODULE_PARM_DESC(srpt_srq_size,
+ "Shared receive queue (SRQ) size.");
+
++static int srpt_set_u64_x(const char *buffer, const struct kernel_param *kp)
++{
++ return kstrtou64(buffer, 16, (u64 *)kp->arg);
++}
+ static int srpt_get_u64_x(char *buffer, const struct kernel_param *kp)
+ {
+ return sprintf(buffer, "0x%016llx\n", *(u64 *)kp->arg);
+ }
+-module_param_call(srpt_service_guid, NULL, srpt_get_u64_x, &srpt_service_guid,
+- 0444);
++module_param_call(srpt_service_guid, srpt_set_u64_x, srpt_get_u64_x,
++ &srpt_service_guid, 0444);
+ MODULE_PARM_DESC(srpt_service_guid,
+ "Using this value for ioc_guid, id_ext, and cm_listen_id instead of using the node_guid of the first HCA.");
+
+--
+2.43.0
+
--- /dev/null
+From 6b7cbe507c83dd22f5b5d6b314b67b796371115b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Feb 2024 20:48:14 -0400
+Subject: s390: use the correct count for __iowrite64_copy()
+
+From: Jason Gunthorpe <jgg@nvidia.com>
+
+[ Upstream commit 723a2cc8d69d4342b47dfddbfe6c19f1b135f09b ]
+
+The signature for __iowrite64_copy() requires the number of 64 bit
+quantities, not bytes. Multiple by 8 to get to a byte length before
+invoking zpci_memcpy_toio()
+
+Fixes: 87bc359b9822 ("s390/pci: speed up __iowrite64_copy by using pci store block insn")
+Acked-by: Niklas Schnelle <schnelle@linux.ibm.com>
+Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
+Link: https://lore.kernel.org/r/0-v1-9223d11a7662+1d7785-s390_iowrite64_jgg@nvidia.com
+Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/pci/pci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
+index 2c99f9552b2f5..394c69fda399e 100644
+--- a/arch/s390/pci/pci.c
++++ b/arch/s390/pci/pci.c
+@@ -241,7 +241,7 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+ /* combine single writes by using store-block insn */
+ void __iowrite64_copy(void __iomem *to, const void *from, size_t count)
+ {
+- zpci_memcpy_toio(to, from, count);
++ zpci_memcpy_toio(to, from, count * 8);
+ }
+
+ static void __iomem *__ioremap(phys_addr_t addr, size_t size, pgprot_t prot)
+--
+2.43.0
+
--- /dev/null
+From 9c870ca9d068c8a3fc17a1b7481646c2247abdb8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 21:59:53 -0800
+Subject: scsi: jazz_esp: Only build if SCSI core is builtin
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ Upstream commit 9ddf190a7df77b77817f955fdb9c2ae9d1c9c9a3 ]
+
+JAZZ_ESP is a bool kconfig symbol that selects SCSI_SPI_ATTRS. When
+CONFIG_SCSI=m, this results in SCSI_SPI_ATTRS=m while JAZZ_ESP=y, which
+causes many undefined symbol linker errors.
+
+Fix this by only offering to build this driver when CONFIG_SCSI=y.
+
+[mkp: JAZZ_ESP is unique in that it does not support being compiled as a
+module unlike the remaining SPI SCSI HBA drivers]
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
+Link: https://lore.kernel.org/r/20240214055953.9612-1-rdunlap@infradead.org
+Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Cc: linux-mips@vger.kernel.org
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Masahiro Yamada <masahiroy@kernel.org>
+Cc: Nicolas Schier <nicolas@fjasle.eu>
+Cc: James E.J. Bottomley <jejb@linux.ibm.com>
+Cc: Martin K. Petersen <martin.petersen@oracle.com>
+Cc: linux-scsi@vger.kernel.org
+Cc: Geert Uytterhoeven <geert@linux-m68k.org>
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202402112222.Gl0udKyU-lkp@intel.com/
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index 03e71e3d5e5b3..3b990cf2c1954 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -1285,7 +1285,7 @@ source "drivers/scsi/arm/Kconfig"
+
+ config JAZZ_ESP
+ bool "MIPS JAZZ FAS216 SCSI support"
+- depends on MACH_JAZZ && SCSI
++ depends on MACH_JAZZ && SCSI=y
+ select SCSI_SPI_ATTRS
+ help
+ This is the driver for the onboard SCSI host adapter of MIPS Magnum
+--
+2.43.0
+
--- /dev/null
+From 15c5fdea1f3548ffc1c5af0015f4dc8fb9be3cf0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Feb 2024 10:22:00 -0600
+Subject: scsi: smartpqi: Fix disable_managed_interrupts
+
+From: Don Brace <don.brace@microchip.com>
+
+[ Upstream commit 5761eb9761d2d5fe8248a9b719efc4d8baf1f24a ]
+
+Correct blk-mq registration issue with module parameter
+disable_managed_interrupts enabled.
+
+When we turn off the default PCI_IRQ_AFFINITY flag, the driver needs to
+register with blk-mq using blk_mq_map_queues(). The driver is currently
+calling blk_mq_pci_map_queues() which results in a stack trace and possibly
+undefined behavior.
+
+Stack Trace:
+[ 7.860089] scsi host2: smartpqi
+[ 7.871934] WARNING: CPU: 0 PID: 238 at block/blk-mq-pci.c:52 blk_mq_pci_map_queues+0xca/0xd0
+[ 7.889231] Modules linked in: sd_mod t10_pi sg uas smartpqi(+) crc32c_intel scsi_transport_sas usb_storage dm_mirror dm_region_hash dm_log dm_mod ipmi_devintf ipmi_msghandler fuse
+[ 7.924755] CPU: 0 PID: 238 Comm: kworker/0:3 Not tainted 4.18.0-372.88.1.el8_6_smartpqi_test.x86_64 #1
+[ 7.944336] Hardware name: HPE ProLiant DL380 Gen10/ProLiant DL380 Gen10, BIOS U30 03/08/2022
+[ 7.963026] Workqueue: events work_for_cpu_fn
+[ 7.978275] RIP: 0010:blk_mq_pci_map_queues+0xca/0xd0
+[ 7.978278] Code: 48 89 de 89 c7 e8 f6 0f 4f 00 3b 05 c4 b7 8e 01 72 e1 5b 31 c0 5d 41 5c 41 5d 41 5e 41 5f e9 7d df 73 00 31 c0 e9 76 df 73 00 <0f> 0b eb bc 90 90 0f 1f 44 00 00 41 57 49 89 ff 41 56 41 55 41 54
+[ 7.978280] RSP: 0018:ffffa95fc3707d50 EFLAGS: 00010216
+[ 7.978283] RAX: 00000000ffffffff RBX: 0000000000000000 RCX: 0000000000000010
+[ 7.978284] RDX: 0000000000000004 RSI: 0000000000000000 RDI: ffff9190c32d4310
+[ 7.978286] RBP: 0000000000000000 R08: ffffa95fc3707d38 R09: ffff91929b81ac00
+[ 7.978287] R10: 0000000000000001 R11: ffffa95fc3707ac0 R12: 0000000000000000
+[ 7.978288] R13: ffff9190c32d4000 R14: 00000000ffffffff R15: ffff9190c4c950a8
+[ 7.978290] FS: 0000000000000000(0000) GS:ffff9193efc00000(0000) knlGS:0000000000000000
+[ 7.978292] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 8.172814] CR2: 000055d11166c000 CR3: 00000002dae10002 CR4: 00000000007706f0
+[ 8.172816] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 8.172817] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 8.172818] PKRU: 55555554
+[ 8.172819] Call Trace:
+[ 8.172823] blk_mq_alloc_tag_set+0x12e/0x310
+[ 8.264339] scsi_add_host_with_dma.cold.9+0x30/0x245
+[ 8.279302] pqi_ctrl_init+0xacf/0xc8e [smartpqi]
+[ 8.294085] ? pqi_pci_probe+0x480/0x4c8 [smartpqi]
+[ 8.309015] pqi_pci_probe+0x480/0x4c8 [smartpqi]
+[ 8.323286] local_pci_probe+0x42/0x80
+[ 8.337855] work_for_cpu_fn+0x16/0x20
+[ 8.351193] process_one_work+0x1a7/0x360
+[ 8.364462] ? create_worker+0x1a0/0x1a0
+[ 8.379252] worker_thread+0x1ce/0x390
+[ 8.392623] ? create_worker+0x1a0/0x1a0
+[ 8.406295] kthread+0x10a/0x120
+[ 8.418428] ? set_kthread_struct+0x50/0x50
+[ 8.431532] ret_from_fork+0x1f/0x40
+[ 8.444137] ---[ end trace 1bf0173d39354506 ]---
+
+Fixes: cf15c3e734e8 ("scsi: smartpqi: Add module param to disable managed ints")
+Tested-by: Yogesh Chandra Pandey <YogeshChandra.Pandey@microchip.com>
+Reviewed-by: Scott Benesh <scott.benesh@microchip.com>
+Reviewed-by: Scott Teel <scott.teel@microchip.com>
+Reviewed-by: Mahesh Rajashekhara <mahesh.rajashekhara@microchip.com>
+Reviewed-by: Mike McGowen <mike.mcgowen@microchip.com>
+Reviewed-by: Kevin Barnett <kevin.barnett@microchip.com>
+Signed-off-by: Don Brace <don.brace@microchip.com>
+Link: https://lore.kernel.org/r/20240213162200.1875970-2-don.brace@microchip.com
+Reviewed-by: Tomas Henzl <thenzl@redhat.com>
+Reviewed-by: Ewan D. Milne <emilne@redhat.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/smartpqi/smartpqi_init.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
+index 47d487729635c..e44f6bb25a8ea 100644
+--- a/drivers/scsi/smartpqi/smartpqi_init.c
++++ b/drivers/scsi/smartpqi/smartpqi_init.c
+@@ -6449,8 +6449,11 @@ static void pqi_map_queues(struct Scsi_Host *shost)
+ {
+ struct pqi_ctrl_info *ctrl_info = shost_to_hba(shost);
+
+- blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
++ if (!ctrl_info->disable_managed_interrupts)
++ return blk_mq_pci_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT],
+ ctrl_info->pci_dev, 0);
++ else
++ return blk_mq_map_queues(&shost->tag_set.map[HCTX_TYPE_DEFAULT]);
+ }
+
+ static inline bool pqi_is_tape_changer_device(struct pqi_scsi_dev *device)
+--
+2.43.0
+
mptcp-add-needs_id-for-userspace-appending-addr.patch
mptcp-fix-lockless-access-in-subflow-ulp-diag.patch
revert-drm-amd-display-increased-min_dcfclk_mhz-and-min_fclk_mhz.patch
+ib-hfi1-fix-a-memleak-in-init_credit_return.patch
+rdma-bnxt_re-return-error-for-srq-resize.patch
+rdma-irdma-fix-kasan-issue-with-tasklet.patch
+rdma-irdma-validate-max_send_wr-and-max_recv_wr.patch
+rdma-irdma-set-the-cq-read-threshold-for-gen-1.patch
+rdma-irdma-add-ae-for-too-many-rnrs.patch
+rdma-srpt-support-specifying-the-srpt_service_guid-p.patch
+iommufd-iova_bitmap-bounds-check-mapped-pages-access.patch
+iommufd-iova_bitmap-switch-iova_bitmap-bitmap-to-an-.patch
+iommufd-iova_bitmap-consider-page-offset-for-the-pag.patch
+rdma-qedr-fix-qedr_create_user_qp-error-flow.patch
+arm64-dts-rockchip-set-num-cs-property-for-spi-on-px.patch
+rdma-srpt-fix-function-pointer-cast-warnings.patch
+bpf-scripts-correct-gpl-license-name.patch
+scsi-smartpqi-fix-disable_managed_interrupts.patch
+scsi-jazz_esp-only-build-if-scsi-core-is-builtin.patch
+net-bridge-switchdev-skip-mdb-replays-of-deferred-ev.patch
+net-bridge-switchdev-ensure-deferred-event-delivery-.patch
+dccp-tcp-unhash-sk-from-ehash-for-tb2-alloc-failure-.patch
+net-ethernet-adi-requires-phylib-support.patch
+nouveau-fix-function-cast-warnings.patch
+x86-numa-fix-the-address-overlap-check-in-numa_fill_.patch
+x86-numa-fix-the-sort-compare-func-used-in-numa_fill.patch
+net-stmmac-fix-incorrect-dereference-in-interrupt-ha.patch
+ipv4-properly-combine-dev_base_seq-and-ipv4.dev_addr.patch
+ipv6-properly-combine-dev_base_seq-and-ipv6.dev_addr.patch
+ata-ahci_ceva-fix-error-handling-for-xilinx-gt-phy-s.patch
+bpf-fix-racing-between-bpf_timer_cancel_and_free-and.patch
+afs-increase-buffer-size-in-afs_update_volume_status.patch
+ipv6-sr-fix-possible-use-after-free-and-null-ptr-der.patch
+net-dev-convert-sa_data-to-flexible-array-in-struct-.patch
+arm64-sme-restore-sme-registers-on-exit-from-suspend.patch
+platform-x86-thinkpad_acpi-only-update-profile-if-su.patch
+octeontx2-af-consider-the-action-set-by-pf.patch
+s390-use-the-correct-count-for-__iowrite64_copy.patch
+bpf-sockmap-fix-null-pointer-dereference-in-sk_psock.patch
+tls-break-out-of-main-loop-when-peek-gets-a-non-data.patch
+tls-stop-recv-if-initial-process_rx_list-gave-us-non.patch
+tls-don-t-skip-over-different-type-records-from-the-.patch
+netfilter-nf_tables-set-dormant-flag-on-hook-registe.patch
+netfilter-flowtable-simplify-route-logic.patch
+netfilter-nft_flow_offload-reset-dst-in-route-object.patch
+netfilter-nft_flow_offload-release-dst-in-case-direc.patch
+netfilter-nf_tables-rename-function-to-destroy-hook-.patch
+netfilter-nf_tables-register-hooks-last-when-adding-.patch
+netfilter-nf_tables-use-kzalloc-for-hook-allocation.patch
+net-mctp-put-sock-on-tag-allocation-failure.patch
+net-sparx5-add-spinlock-for-frame-transmission-from-.patch
+net-ioctl-use-kernel-memory-on-protocol-ioctl-callba.patch
+phonet-take-correct-lock-to-peek-at-the-rx-queue.patch
+phonet-pep-fix-racy-skb_queue_empty-use.patch
+fix-write-to-cloned-skb-in-ipv6_hop_ioam.patch
+net-phy-realtek-fix-rtl8211f_config_init-for-rtl8211.patch
+drm-syncobj-call-drm_syncobj_fence_add_wait-when-wai.patch
+drm-amd-display-fix-memory-leak-in-dm_sw_fini.patch
+i2c-imx-when-being-a-target-mark-the-last-read-as-pr.patch
--- /dev/null
+From 1aebbfe29d93e34d6de2bb7837a6e4566515a3b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 17:17:29 +0100
+Subject: tls: break out of main loop when PEEK gets a non-data record
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+[ Upstream commit 10f41d0710fc81b7af93fa6106678d57b1ff24a7 ]
+
+PEEK needs to leave decrypted records on the rx_list so that we can
+receive them later on, so it jumps back into the async code that
+queues the skb. Unfortunately that makes us skip the
+TLS_RECORD_TYPE_DATA check at the bottom of the main loop, so if two
+records of the same (non-DATA) type are queued, we end up merging
+them.
+
+Add the same record type check, and make it unlikely to not penalize
+the async fastpath. Async decrypt only applies to data record, so this
+check is only needed for PEEK.
+
+process_rx_list also has similar issues.
+
+Fixes: 692d7b5d1f91 ("tls: Fix recvmsg() to be able to peek across multiple records")
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Link: https://lore.kernel.org/r/3df2eef4fdae720c55e69472b5bea668772b45a2.1708007371.git.sd@queasysnail.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index c8cbdd02a784e..cd86c271c1348 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -2137,6 +2137,8 @@ int tls_sw_recvmsg(struct sock *sk,
+ decrypted += chunk;
+ len -= chunk;
+ __skb_queue_tail(&ctx->rx_list, skb);
++ if (unlikely(control != TLS_RECORD_TYPE_DATA))
++ break;
+ continue;
+ }
+
+--
+2.43.0
+
--- /dev/null
+From 521606a692335737ba2c321996295b106e2c16b3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 17:17:31 +0100
+Subject: tls: don't skip over different type records from the rx_list
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+[ Upstream commit ec823bf3a479d42c589dc0f28ef4951c49cd2d2a ]
+
+If we queue 3 records:
+ - record 1, type DATA
+ - record 2, some other type
+ - record 3, type DATA
+and do a recv(PEEK), the rx_list will contain the first two records.
+
+The next large recv will walk through the rx_list and copy data from
+record 1, then stop because record 2 is a different type. Since we
+haven't filled up our buffer, we will process the next available
+record. It's also DATA, so we can merge it with the current read.
+
+We shouldn't do that, since there was a record in between that we
+ignored.
+
+Add a flag to let process_rx_list inform tls_sw_recvmsg that it had
+more data available.
+
+Fixes: 692d7b5d1f91 ("tls: Fix recvmsg() to be able to peek across multiple records")
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Link: https://lore.kernel.org/r/f00c0c0afa080c60f016df1471158c1caf983c34.1708007371.git.sd@queasysnail.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index 20d2877bf22ad..93e1bfa72d791 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -1845,7 +1845,8 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
+ u8 *control,
+ size_t skip,
+ size_t len,
+- bool is_peek)
++ bool is_peek,
++ bool *more)
+ {
+ struct sk_buff *skb = skb_peek(&ctx->rx_list);
+ struct tls_msg *tlm;
+@@ -1858,7 +1859,7 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
+
+ err = tls_record_content_type(msg, tlm, control);
+ if (err <= 0)
+- goto out;
++ goto more;
+
+ if (skip < rxm->full_len)
+ break;
+@@ -1876,12 +1877,12 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
+
+ err = tls_record_content_type(msg, tlm, control);
+ if (err <= 0)
+- goto out;
++ goto more;
+
+ err = skb_copy_datagram_msg(skb, rxm->offset + skip,
+ msg, chunk);
+ if (err < 0)
+- goto out;
++ goto more;
+
+ len = len - chunk;
+ copied = copied + chunk;
+@@ -1917,6 +1918,10 @@ static int process_rx_list(struct tls_sw_context_rx *ctx,
+
+ out:
+ return copied ? : err;
++more:
++ if (more)
++ *more = true;
++ goto out;
+ }
+
+ static bool
+@@ -2020,6 +2025,7 @@ int tls_sw_recvmsg(struct sock *sk,
+ int target, err;
+ bool is_kvec = iov_iter_is_kvec(&msg->msg_iter);
+ bool is_peek = flags & MSG_PEEK;
++ bool rx_more = false;
+ bool released = true;
+ bool bpf_strp_enabled;
+ bool zc_capable;
+@@ -2039,12 +2045,12 @@ int tls_sw_recvmsg(struct sock *sk,
+ goto end;
+
+ /* Process pending decrypted records. It must be non-zero-copy */
+- err = process_rx_list(ctx, msg, &control, 0, len, is_peek);
++ err = process_rx_list(ctx, msg, &control, 0, len, is_peek, &rx_more);
+ if (err < 0)
+ goto end;
+
+ copied = err;
+- if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA))
++ if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA) || rx_more)
+ goto end;
+
+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
+@@ -2203,10 +2209,10 @@ int tls_sw_recvmsg(struct sock *sk,
+ /* Drain records from the rx_list & copy if required */
+ if (is_peek || is_kvec)
+ err = process_rx_list(ctx, msg, &control, copied,
+- decrypted, is_peek);
++ decrypted, is_peek, NULL);
+ else
+ err = process_rx_list(ctx, msg, &control, 0,
+- async_copy_bytes, is_peek);
++ async_copy_bytes, is_peek, NULL);
+ }
+
+ copied += decrypted;
+--
+2.43.0
+
--- /dev/null
+From ff5e02b70841c13a45978f83d5a44bcb69690ef1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Feb 2024 17:17:30 +0100
+Subject: tls: stop recv() if initial process_rx_list gave us non-DATA
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+[ Upstream commit fdfbaec5923d9359698cbb286bc0deadbb717504 ]
+
+If we have a non-DATA record on the rx_list and another record of the
+same type still on the queue, we will end up merging them:
+ - process_rx_list copies the non-DATA record
+ - we start the loop and process the first available record since it's
+ of the same type
+ - we break out of the loop since the record was not DATA
+
+Just check the record type and jump to the end in case process_rx_list
+did some work.
+
+Fixes: 692d7b5d1f91 ("tls: Fix recvmsg() to be able to peek across multiple records")
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Link: https://lore.kernel.org/r/bd31449e43bd4b6ff546f5c51cf958c31c511deb.1708007371.git.sd@queasysnail.net
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/tls/tls_sw.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
+index cd86c271c1348..20d2877bf22ad 100644
+--- a/net/tls/tls_sw.c
++++ b/net/tls/tls_sw.c
+@@ -2044,7 +2044,7 @@ int tls_sw_recvmsg(struct sock *sk,
+ goto end;
+
+ copied = err;
+- if (len <= copied)
++ if (len <= copied || (copied && control != TLS_RECORD_TYPE_DATA))
+ goto end;
+
+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
+--
+2.43.0
+
--- /dev/null
+From b0fe0fe31344c6a50e9d142051516d268a6e6501 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Jan 2024 12:09:50 -0800
+Subject: x86/numa: Fix the address overlap check in numa_fill_memblks()
+
+From: Alison Schofield <alison.schofield@intel.com>
+
+[ Upstream commit 9b99c17f7510bed2adbe17751fb8abddba5620bc ]
+
+numa_fill_memblks() fills in the gaps in numa_meminfo memblks over a
+physical address range. To do so, it first creates a list of existing
+memblks that overlap that address range. The issue is that it is off
+by one when comparing to the end of the address range, so memblks
+that do not overlap are selected.
+
+The impact of selecting a memblk that does not actually overlap is
+that an existing memblk may be filled when the expected action is to
+do nothing and return NUMA_NO_MEMBLK to the caller. The caller can
+then add a new NUMA node and memblk.
+
+Replace the broken open-coded search for address overlap with the
+memblock helper memblock_addrs_overlap(). Update the kernel doc
+and in code comments.
+
+Suggested by: "Huang, Ying" <ying.huang@intel.com>
+
+Fixes: 8f012db27c95 ("x86/numa: Introduce numa_fill_memblks()")
+Signed-off-by: Alison Schofield <alison.schofield@intel.com>
+Acked-by: Mike Rapoport (IBM) <rppt@kernel.org>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by: Dan Williams <dan.j.williams@intel.com>
+Link: https://lore.kernel.org/r/10a3e6109c34c21a8dd4c513cf63df63481a2b07.1705085543.git.alison.schofield@intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/numa.c | 19 +++++++------------
+ include/linux/memblock.h | 2 ++
+ mm/memblock.c | 5 +++--
+ 3 files changed, 12 insertions(+), 14 deletions(-)
+
+diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
+index aa39d678fe81d..e60c61b8bbc61 100644
+--- a/arch/x86/mm/numa.c
++++ b/arch/x86/mm/numa.c
+@@ -971,14 +971,12 @@ static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata;
+ * @start: address to begin fill
+ * @end: address to end fill
+ *
+- * Find and extend numa_meminfo memblks to cover the @start-@end
+- * physical address range, such that the first memblk includes
+- * @start, the last memblk includes @end, and any gaps in between
+- * are filled.
++ * Find and extend numa_meminfo memblks to cover the physical
++ * address range @start-@end
+ *
+ * RETURNS:
+ * 0 : Success
+- * NUMA_NO_MEMBLK : No memblk exists in @start-@end range
++ * NUMA_NO_MEMBLK : No memblks exist in address range @start-@end
+ */
+
+ int __init numa_fill_memblks(u64 start, u64 end)
+@@ -990,17 +988,14 @@ int __init numa_fill_memblks(u64 start, u64 end)
+
+ /*
+ * Create a list of pointers to numa_meminfo memblks that
+- * overlap start, end. Exclude (start == bi->end) since
+- * end addresses in both a CFMWS range and a memblk range
+- * are exclusive.
+- *
+- * This list of pointers is used to make in-place changes
+- * that fill out the numa_meminfo memblks.
++ * overlap start, end. The list is used to make in-place
++ * changes that fill out the numa_meminfo memblks.
+ */
+ for (int i = 0; i < mi->nr_blks; i++) {
+ struct numa_memblk *bi = &mi->blk[i];
+
+- if (start < bi->end && end >= bi->start) {
++ if (memblock_addrs_overlap(start, end - start, bi->start,
++ bi->end - bi->start)) {
+ blk[count] = &mi->blk[i];
+ count++;
+ }
+diff --git a/include/linux/memblock.h b/include/linux/memblock.h
+index 50ad19662a322..6790f08066b72 100644
+--- a/include/linux/memblock.h
++++ b/include/linux/memblock.h
+@@ -118,6 +118,8 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size);
+ int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
+ #endif
+ void memblock_trim_memory(phys_addr_t align);
++unsigned long memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
++ phys_addr_t base2, phys_addr_t size2);
+ bool memblock_overlaps_region(struct memblock_type *type,
+ phys_addr_t base, phys_addr_t size);
+ int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
+diff --git a/mm/memblock.c b/mm/memblock.c
+index 511d4783dcf1d..516efec80851a 100644
+--- a/mm/memblock.c
++++ b/mm/memblock.c
+@@ -175,8 +175,9 @@ static inline phys_addr_t memblock_cap_size(phys_addr_t base, phys_addr_t *size)
+ /*
+ * Address comparison utilities
+ */
+-static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
+- phys_addr_t base2, phys_addr_t size2)
++unsigned long __init_memblock
++memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1, phys_addr_t base2,
++ phys_addr_t size2)
+ {
+ return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
+ }
+--
+2.43.0
+
--- /dev/null
+From 84fc11188dd8675294a8592af9bd4a4d45642ff8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 Jan 2024 12:09:51 -0800
+Subject: x86/numa: Fix the sort compare func used in numa_fill_memblks()
+
+From: Alison Schofield <alison.schofield@intel.com>
+
+[ Upstream commit b626070ffc14acca5b87a2aa5f581db98617584c ]
+
+The compare function used to sort memblks into starting address
+order fails when the result of its u64 address subtraction gets
+truncated to an int upon return.
+
+The impact of the bad sort is that memblks will be filled out
+incorrectly. Depending on the set of memblks, a user may see no
+errors at all but still have a bad fill, or see messages reporting
+a node overlap that leads to numa init failure:
+
+[] node 0 [mem: ] overlaps with node 1 [mem: ]
+[] No NUMA configuration found
+
+Replace with a comparison that can only result in: 1, 0, -1.
+
+Fixes: 8f012db27c95 ("x86/numa: Introduce numa_fill_memblks()")
+Signed-off-by: Alison Schofield <alison.schofield@intel.com>
+Acked-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by: Dan Williams <dan.j.williams@intel.com>
+Link: https://lore.kernel.org/r/99dcb3ae87e04995e9f293f6158dc8fa0749a487.1705085543.git.alison.schofield@intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/mm/numa.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
+index e60c61b8bbc61..dae5c952735c7 100644
+--- a/arch/x86/mm/numa.c
++++ b/arch/x86/mm/numa.c
+@@ -961,7 +961,7 @@ static int __init cmp_memblk(const void *a, const void *b)
+ const struct numa_memblk *ma = *(const struct numa_memblk **)a;
+ const struct numa_memblk *mb = *(const struct numa_memblk **)b;
+
+- return ma->start - mb->start;
++ return (ma->start > mb->start) - (ma->start < mb->start);
+ }
+
+ static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata;
+--
+2.43.0
+