From: Sasha Levin Date: Sun, 7 Jan 2024 01:58:54 +0000 (-0500) Subject: Fixes for 5.4 X-Git-Tag: v4.14.336~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=177b35b9c669ba1d303a35e1d539945a6dc57e1c;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/arm-sun9i-smp-fix-array-index-out-of-bounds-read-in-.patch b/queue-5.4/arm-sun9i-smp-fix-array-index-out-of-bounds-read-in-.patch new file mode 100644 index 00000000000..55bc9f892e5 --- /dev/null +++ b/queue-5.4/arm-sun9i-smp-fix-array-index-out-of-bounds-read-in-.patch @@ -0,0 +1,64 @@ +From 0ee4cf301c543492c01c39c5b44433dfe78c5468 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Dec 2023 20:39:02 +0100 +Subject: ARM: sun9i: smp: Fix array-index-out-of-bounds read in + sunxi_mc_smp_init + +From: Stefan Wahren + +[ Upstream commit 72ad3b772b6d393701df58ba1359b0bb346a19ed ] + +Running a multi-arch kernel (multi_v7_defconfig) on a Raspberry Pi 3B+ +with enabled CONFIG_UBSAN triggers the following warning: + + UBSAN: array-index-out-of-bounds in arch/arm/mach-sunxi/mc_smp.c:810:29 + index 2 is out of range for type 'sunxi_mc_smp_data [2]' + CPU: 0 PID: 1 Comm: swapper/0 Not tainted 6.7.0-rc6-00248-g5254c0cbc92d + Hardware name: BCM2835 + unwind_backtrace from show_stack+0x10/0x14 + show_stack from dump_stack_lvl+0x40/0x4c + dump_stack_lvl from ubsan_epilogue+0x8/0x34 + ubsan_epilogue from __ubsan_handle_out_of_bounds+0x78/0x80 + __ubsan_handle_out_of_bounds from sunxi_mc_smp_init+0xe4/0x4cc + sunxi_mc_smp_init from do_one_initcall+0xa0/0x2fc + do_one_initcall from kernel_init_freeable+0xf4/0x2f4 + kernel_init_freeable from kernel_init+0x18/0x158 + kernel_init from ret_from_fork+0x14/0x28 + +Since the enabled method couldn't match with any entry from +sunxi_mc_smp_data, the value of the index shouldn't be used right after +the loop. So move it after the check of ret in order to have a valid +index. + +Fixes: 1631090e34f5 ("ARM: sun9i: smp: Add is_a83t field") +Signed-off-by: Stefan Wahren +Link: https://lore.kernel.org/r/20231228193903.9078-1-wahrenst@gmx.net +Reviewed-by: Chen-Yu Tsai +Signed-off-by: Arnd Bergmann +Signed-off-by: Sasha Levin +--- + arch/arm/mach-sunxi/mc_smp.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/arch/arm/mach-sunxi/mc_smp.c b/arch/arm/mach-sunxi/mc_smp.c +index 26cbce1353387..b2f5f4f28705f 100644 +--- a/arch/arm/mach-sunxi/mc_smp.c ++++ b/arch/arm/mach-sunxi/mc_smp.c +@@ -808,12 +808,12 @@ static int __init sunxi_mc_smp_init(void) + break; + } + +- is_a83t = sunxi_mc_smp_data[i].is_a83t; +- + of_node_put(node); + if (ret) + return -ENODEV; + ++ is_a83t = sunxi_mc_smp_data[i].is_a83t; ++ + if (!sunxi_mc_smp_cpu_table_init()) + return -EINVAL; + +-- +2.43.0 + diff --git a/queue-5.4/asix-add-check-for-usbnet_get_endpoints.patch b/queue-5.4/asix-add-check-for-usbnet_get_endpoints.patch new file mode 100644 index 00000000000..3ffaabd09d3 --- /dev/null +++ b/queue-5.4/asix-add-check-for-usbnet_get_endpoints.patch @@ -0,0 +1,38 @@ +From fb6265e8f9403d8822dd36a8912e3f23e465957b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jan 2024 03:35:34 +0000 +Subject: asix: Add check for usbnet_get_endpoints + +From: Chen Ni + +[ Upstream commit eaac6a2d26b65511e164772bec6918fcbc61938e ] + +Add check for usbnet_get_endpoints() and return the error if it fails +in order to transfer the error. + +Fixes: 16626b0cc3d5 ("asix: Add a new driver for the AX88172A") +Signed-off-by: Chen Ni +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/usb/ax88172a.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c +index 6101d82102e79..bf65262e2256d 100644 +--- a/drivers/net/usb/ax88172a.c ++++ b/drivers/net/usb/ax88172a.c +@@ -186,7 +186,9 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf) + u8 buf[ETH_ALEN]; + struct ax88172a_private *priv; + +- usbnet_get_endpoints(dev, intf); ++ ret = usbnet_get_endpoints(dev, intf); ++ if (ret) ++ return ret; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) +-- +2.43.0 + diff --git a/queue-5.4/asoc-meson-g12a-extract-codec-to-codec-utils.patch b/queue-5.4/asoc-meson-g12a-extract-codec-to-codec-utils.patch new file mode 100644 index 00000000000..b3ad8fda8e0 --- /dev/null +++ b/queue-5.4/asoc-meson-g12a-extract-codec-to-codec-utils.patch @@ -0,0 +1,573 @@ +From 51aa6d37a344fca4c0bc043f6e7002bd1ef99833 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 13 Feb 2020 16:51:52 +0100 +Subject: ASoC: meson: g12a: extract codec-to-codec utils + +From: Jerome Brunet + +[ Upstream commit 9c29fd9bdf92900dc0cc5c2d8f58951a7bdc0f41 ] + +The hdmi routing mechanism used on g12a hdmi is also used: +* other Amlogic SoC types +* for the internal DAC path + +Each of these codec glues are slightly different but the idea +behind it remains the same. This change extract some helper functions +from the g12a-tohdmitx driver to make them available for other Amlogic +codecs. + +Signed-off-by: Jerome Brunet +Link: https://lore.kernel.org/r/20200213155159.3235792-3-jbrunet@baylibre.com +Signed-off-by: Mark Brown +Stable-dep-of: 1e001206804b ("ASoC: meson: g12a-tohdmitx: Validate written enum values") +Signed-off-by: Sasha Levin +--- + sound/soc/meson/Kconfig | 4 + + sound/soc/meson/Makefile | 2 + + sound/soc/meson/g12a-tohdmitx.c | 219 ++++++----------------------- + sound/soc/meson/meson-codec-glue.c | 149 ++++++++++++++++++++ + sound/soc/meson/meson-codec-glue.h | 32 +++++ + 5 files changed, 230 insertions(+), 176 deletions(-) + create mode 100644 sound/soc/meson/meson-codec-glue.c + create mode 100644 sound/soc/meson/meson-codec-glue.h + +diff --git a/sound/soc/meson/Kconfig b/sound/soc/meson/Kconfig +index e0d24592ebd70..f9188274f6b0f 100644 +--- a/sound/soc/meson/Kconfig ++++ b/sound/soc/meson/Kconfig +@@ -85,9 +85,13 @@ config SND_MESON_AXG_PDM + Select Y or M to add support for PDM input embedded + in the Amlogic AXG SoC family + ++config SND_MESON_CODEC_GLUE ++ tristate ++ + config SND_MESON_G12A_TOHDMITX + tristate "Amlogic G12A To HDMI TX Control Support" + select REGMAP_MMIO ++ select SND_MESON_CODEC_GLUE + imply SND_SOC_HDMI_CODEC + help + Select Y or M to add support for HDMI audio on the g12a SoC +diff --git a/sound/soc/meson/Makefile b/sound/soc/meson/Makefile +index 1a8b1470ed843..529a807b3f376 100644 +--- a/sound/soc/meson/Makefile ++++ b/sound/soc/meson/Makefile +@@ -11,6 +11,7 @@ snd-soc-meson-axg-sound-card-objs := axg-card.o + snd-soc-meson-axg-spdifin-objs := axg-spdifin.o + snd-soc-meson-axg-spdifout-objs := axg-spdifout.o + snd-soc-meson-axg-pdm-objs := axg-pdm.o ++snd-soc-meson-codec-glue-objs := meson-codec-glue.o + snd-soc-meson-g12a-tohdmitx-objs := g12a-tohdmitx.o + + obj-$(CONFIG_SND_MESON_AXG_FIFO) += snd-soc-meson-axg-fifo.o +@@ -24,4 +25,5 @@ obj-$(CONFIG_SND_MESON_AXG_SOUND_CARD) += snd-soc-meson-axg-sound-card.o + obj-$(CONFIG_SND_MESON_AXG_SPDIFIN) += snd-soc-meson-axg-spdifin.o + obj-$(CONFIG_SND_MESON_AXG_SPDIFOUT) += snd-soc-meson-axg-spdifout.o + obj-$(CONFIG_SND_MESON_AXG_PDM) += snd-soc-meson-axg-pdm.o ++obj-$(CONFIG_SND_MESON_CODEC_GLUE) += snd-soc-meson-codec-glue.o + obj-$(CONFIG_SND_MESON_G12A_TOHDMITX) += snd-soc-meson-g12a-tohdmitx.o +diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c +index cbe47e0cae426..d02825669484a 100644 +--- a/sound/soc/meson/g12a-tohdmitx.c ++++ b/sound/soc/meson/g12a-tohdmitx.c +@@ -12,112 +12,51 @@ + #include + + #include ++#include "meson-codec-glue.h" + + #define G12A_TOHDMITX_DRV_NAME "g12a-tohdmitx" + + #define TOHDMITX_CTRL0 0x0 + #define CTRL0_ENABLE_SHIFT 31 +-#define CTRL0_I2S_DAT_SEL GENMASK(13, 12) ++#define CTRL0_I2S_DAT_SEL_SHIFT 12 ++#define CTRL0_I2S_DAT_SEL (0x3 << CTRL0_I2S_DAT_SEL_SHIFT) + #define CTRL0_I2S_LRCLK_SEL GENMASK(9, 8) + #define CTRL0_I2S_BLK_CAP_INV BIT(7) + #define CTRL0_I2S_BCLK_O_INV BIT(6) + #define CTRL0_I2S_BCLK_SEL GENMASK(5, 4) + #define CTRL0_SPDIF_CLK_CAP_INV BIT(3) + #define CTRL0_SPDIF_CLK_O_INV BIT(2) +-#define CTRL0_SPDIF_SEL BIT(1) ++#define CTRL0_SPDIF_SEL_SHIFT 1 ++#define CTRL0_SPDIF_SEL (0x1 << CTRL0_SPDIF_SEL_SHIFT) + #define CTRL0_SPDIF_CLK_SEL BIT(0) + +-struct g12a_tohdmitx_input { +- struct snd_soc_pcm_stream params; +- unsigned int fmt; +-}; +- +-static struct snd_soc_dapm_widget * +-g12a_tohdmitx_get_input(struct snd_soc_dapm_widget *w) +-{ +- struct snd_soc_dapm_path *p = NULL; +- struct snd_soc_dapm_widget *in; +- +- snd_soc_dapm_widget_for_each_source_path(w, p) { +- if (!p->connect) +- continue; +- +- /* Check that we still are in the same component */ +- if (snd_soc_dapm_to_component(w->dapm) != +- snd_soc_dapm_to_component(p->source->dapm)) +- continue; +- +- if (p->source->id == snd_soc_dapm_dai_in) +- return p->source; +- +- in = g12a_tohdmitx_get_input(p->source); +- if (in) +- return in; +- } +- +- return NULL; +-} +- +-static struct g12a_tohdmitx_input * +-g12a_tohdmitx_get_input_data(struct snd_soc_dapm_widget *w) +-{ +- struct snd_soc_dapm_widget *in = +- g12a_tohdmitx_get_input(w); +- struct snd_soc_dai *dai; +- +- if (WARN_ON(!in)) +- return NULL; +- +- dai = in->priv; +- +- return dai->playback_dma_data; +-} +- + static const char * const g12a_tohdmitx_i2s_mux_texts[] = { + "I2S A", "I2S B", "I2S C", + }; + +-static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_i2s_mux_enum, +- g12a_tohdmitx_i2s_mux_texts); +- +-static int g12a_tohdmitx_get_input_val(struct snd_soc_component *component, +- unsigned int mask) +-{ +- unsigned int val; +- +- snd_soc_component_read(component, TOHDMITX_CTRL0, &val); +- return (val & mask) >> __ffs(mask); +-} +- +-static int g12a_tohdmitx_i2s_mux_get_enum(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- struct snd_soc_component *component = +- snd_soc_dapm_kcontrol_component(kcontrol); +- +- ucontrol->value.enumerated.item[0] = +- g12a_tohdmitx_get_input_val(component, CTRL0_I2S_DAT_SEL); +- +- return 0; +-} +- + static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) ++ struct snd_ctl_elem_value *ucontrol) + { + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; +- unsigned int mux = ucontrol->value.enumerated.item[0]; +- unsigned int val = g12a_tohdmitx_get_input_val(component, +- CTRL0_I2S_DAT_SEL); ++ unsigned int mux, changed; ++ ++ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); ++ changed = snd_soc_component_test_bits(component, e->reg, ++ CTRL0_I2S_DAT_SEL, ++ FIELD_PREP(CTRL0_I2S_DAT_SEL, ++ mux)); ++ ++ if (!changed) ++ return 0; + + /* Force disconnect of the mux while updating */ +- if (val != mux) +- snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); ++ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + +- snd_soc_component_update_bits(component, TOHDMITX_CTRL0, ++ snd_soc_component_update_bits(component, e->reg, + CTRL0_I2S_DAT_SEL | + CTRL0_I2S_LRCLK_SEL | + CTRL0_I2S_BCLK_SEL, +@@ -130,30 +69,19 @@ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol, + return 1; + } + ++static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_i2s_mux_enum, TOHDMITX_CTRL0, ++ CTRL0_I2S_DAT_SEL_SHIFT, ++ g12a_tohdmitx_i2s_mux_texts); ++ + static const struct snd_kcontrol_new g12a_tohdmitx_i2s_mux = + SOC_DAPM_ENUM_EXT("I2S Source", g12a_tohdmitx_i2s_mux_enum, +- g12a_tohdmitx_i2s_mux_get_enum, ++ snd_soc_dapm_get_enum_double, + g12a_tohdmitx_i2s_mux_put_enum); + + static const char * const g12a_tohdmitx_spdif_mux_texts[] = { + "SPDIF A", "SPDIF B", + }; + +-static SOC_ENUM_SINGLE_EXT_DECL(g12a_tohdmitx_spdif_mux_enum, +- g12a_tohdmitx_spdif_mux_texts); +- +-static int g12a_tohdmitx_spdif_mux_get_enum(struct snd_kcontrol *kcontrol, +- struct snd_ctl_elem_value *ucontrol) +-{ +- struct snd_soc_component *component = +- snd_soc_dapm_kcontrol_component(kcontrol); +- +- ucontrol->value.enumerated.item[0] = +- g12a_tohdmitx_get_input_val(component, CTRL0_SPDIF_SEL); +- +- return 0; +-} +- + static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) + { +@@ -162,13 +90,18 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; +- unsigned int mux = ucontrol->value.enumerated.item[0]; +- unsigned int val = g12a_tohdmitx_get_input_val(component, +- CTRL0_SPDIF_SEL); ++ unsigned int mux, changed; ++ ++ mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); ++ changed = snd_soc_component_test_bits(component, TOHDMITX_CTRL0, ++ CTRL0_SPDIF_SEL, ++ FIELD_PREP(CTRL0_SPDIF_SEL, mux)); ++ ++ if (!changed) ++ return 0; + + /* Force disconnect of the mux while updating */ +- if (val != mux) +- snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); ++ snd_soc_dapm_mux_update_power(dapm, kcontrol, 0, NULL, NULL); + + snd_soc_component_update_bits(component, TOHDMITX_CTRL0, + CTRL0_SPDIF_SEL | +@@ -181,9 +114,13 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, + return 0; + } + ++static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_spdif_mux_enum, TOHDMITX_CTRL0, ++ CTRL0_SPDIF_SEL_SHIFT, ++ g12a_tohdmitx_spdif_mux_texts); ++ + static const struct snd_kcontrol_new g12a_tohdmitx_spdif_mux = + SOC_DAPM_ENUM_EXT("SPDIF Source", g12a_tohdmitx_spdif_mux_enum, +- g12a_tohdmitx_spdif_mux_get_enum, ++ snd_soc_dapm_get_enum_double, + g12a_tohdmitx_spdif_mux_put_enum); + + static const struct snd_kcontrol_new g12a_tohdmitx_out_enable = +@@ -201,83 +138,13 @@ static const struct snd_soc_dapm_widget g12a_tohdmitx_widgets[] = { + &g12a_tohdmitx_out_enable), + }; + +-static int g12a_tohdmitx_input_probe(struct snd_soc_dai *dai) +-{ +- struct g12a_tohdmitx_input *data; +- +- data = kzalloc(sizeof(*data), GFP_KERNEL); +- if (!data) +- return -ENOMEM; +- +- dai->playback_dma_data = data; +- return 0; +-} +- +-static int g12a_tohdmitx_input_remove(struct snd_soc_dai *dai) +-{ +- kfree(dai->playback_dma_data); +- return 0; +-} +- +-static int g12a_tohdmitx_input_hw_params(struct snd_pcm_substream *substream, +- struct snd_pcm_hw_params *params, +- struct snd_soc_dai *dai) +-{ +- struct g12a_tohdmitx_input *data = dai->playback_dma_data; +- +- data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params)); +- data->params.rate_min = params_rate(params); +- data->params.rate_max = params_rate(params); +- data->params.formats = 1 << params_format(params); +- data->params.channels_min = params_channels(params); +- data->params.channels_max = params_channels(params); +- data->params.sig_bits = dai->driver->playback.sig_bits; +- +- return 0; +-} +- +- +-static int g12a_tohdmitx_input_set_fmt(struct snd_soc_dai *dai, +- unsigned int fmt) +-{ +- struct g12a_tohdmitx_input *data = dai->playback_dma_data; +- +- /* Save the source stream format for the downstream link */ +- data->fmt = fmt; +- return 0; +-} +- +-static int g12a_tohdmitx_output_startup(struct snd_pcm_substream *substream, +- struct snd_soc_dai *dai) +-{ +- struct snd_soc_pcm_runtime *rtd = substream->private_data; +- struct g12a_tohdmitx_input *in_data = +- g12a_tohdmitx_get_input_data(dai->capture_widget); +- +- if (!in_data) +- return -ENODEV; +- +- if (WARN_ON(!rtd->dai_link->params)) { +- dev_warn(dai->dev, "codec2codec link expected\n"); +- return -EINVAL; +- } +- +- /* Replace link params with the input params */ +- rtd->dai_link->params = &in_data->params; +- +- if (!in_data->fmt) +- return 0; +- +- return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt); +-} +- + static const struct snd_soc_dai_ops g12a_tohdmitx_input_ops = { +- .hw_params = g12a_tohdmitx_input_hw_params, +- .set_fmt = g12a_tohdmitx_input_set_fmt, ++ .hw_params = meson_codec_glue_input_hw_params, ++ .set_fmt = meson_codec_glue_input_set_fmt, + }; + + static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { +- .startup = g12a_tohdmitx_output_startup, ++ .startup = meson_codec_glue_output_startup, + }; + + #define TOHDMITX_SPDIF_FORMATS \ +@@ -304,8 +171,8 @@ static const struct snd_soc_dai_ops g12a_tohdmitx_output_ops = { + .id = (xid), \ + .playback = TOHDMITX_STREAM(xname, "Playback", xfmt, xchmax), \ + .ops = &g12a_tohdmitx_input_ops, \ +- .probe = g12a_tohdmitx_input_probe, \ +- .remove = g12a_tohdmitx_input_remove, \ ++ .probe = meson_codec_glue_input_dai_probe, \ ++ .remove = meson_codec_glue_input_dai_remove, \ + } + + #define TOHDMITX_OUT(xname, xid, xfmt, xchmax) { \ +diff --git a/sound/soc/meson/meson-codec-glue.c b/sound/soc/meson/meson-codec-glue.c +new file mode 100644 +index 0000000000000..97bbc967e1769 +--- /dev/null ++++ b/sound/soc/meson/meson-codec-glue.c +@@ -0,0 +1,149 @@ ++// SPDX-License-Identifier: GPL-2.0 ++// ++// Copyright (c) 2019 BayLibre, SAS. ++// Author: Jerome Brunet ++ ++#include ++#include ++#include ++#include ++ ++#include "meson-codec-glue.h" ++ ++static struct snd_soc_dapm_widget * ++meson_codec_glue_get_input(struct snd_soc_dapm_widget *w) ++{ ++ struct snd_soc_dapm_path *p = NULL; ++ struct snd_soc_dapm_widget *in; ++ ++ snd_soc_dapm_widget_for_each_source_path(w, p) { ++ if (!p->connect) ++ continue; ++ ++ /* Check that we still are in the same component */ ++ if (snd_soc_dapm_to_component(w->dapm) != ++ snd_soc_dapm_to_component(p->source->dapm)) ++ continue; ++ ++ if (p->source->id == snd_soc_dapm_dai_in) ++ return p->source; ++ ++ in = meson_codec_glue_get_input(p->source); ++ if (in) ++ return in; ++ } ++ ++ return NULL; ++} ++ ++static void meson_codec_glue_input_set_data(struct snd_soc_dai *dai, ++ struct meson_codec_glue_input *data) ++{ ++ dai->playback_dma_data = data; ++} ++ ++struct meson_codec_glue_input * ++meson_codec_glue_input_get_data(struct snd_soc_dai *dai) ++{ ++ return dai->playback_dma_data; ++} ++EXPORT_SYMBOL_GPL(meson_codec_glue_input_get_data); ++ ++static struct meson_codec_glue_input * ++meson_codec_glue_output_get_input_data(struct snd_soc_dapm_widget *w) ++{ ++ struct snd_soc_dapm_widget *in = ++ meson_codec_glue_get_input(w); ++ struct snd_soc_dai *dai; ++ ++ if (WARN_ON(!in)) ++ return NULL; ++ ++ dai = in->priv; ++ ++ return meson_codec_glue_input_get_data(dai); ++} ++ ++int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai) ++{ ++ struct meson_codec_glue_input *data = ++ meson_codec_glue_input_get_data(dai); ++ ++ data->params.rates = snd_pcm_rate_to_rate_bit(params_rate(params)); ++ data->params.rate_min = params_rate(params); ++ data->params.rate_max = params_rate(params); ++ data->params.formats = 1 << params_format(params); ++ data->params.channels_min = params_channels(params); ++ data->params.channels_max = params_channels(params); ++ data->params.sig_bits = dai->driver->playback.sig_bits; ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(meson_codec_glue_input_hw_params); ++ ++int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai, ++ unsigned int fmt) ++{ ++ struct meson_codec_glue_input *data = ++ meson_codec_glue_input_get_data(dai); ++ ++ /* Save the source stream format for the downstream link */ ++ data->fmt = fmt; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(meson_codec_glue_input_set_fmt); ++ ++int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct meson_codec_glue_input *in_data = ++ meson_codec_glue_output_get_input_data(dai->capture_widget); ++ ++ if (!in_data) ++ return -ENODEV; ++ ++ if (WARN_ON(!rtd->dai_link->params)) { ++ dev_warn(dai->dev, "codec2codec link expected\n"); ++ return -EINVAL; ++ } ++ ++ /* Replace link params with the input params */ ++ rtd->dai_link->params = &in_data->params; ++ ++ if (!in_data->fmt) ++ return 0; ++ ++ return snd_soc_runtime_set_dai_fmt(rtd, in_data->fmt); ++} ++EXPORT_SYMBOL_GPL(meson_codec_glue_output_startup); ++ ++int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai) ++{ ++ struct meson_codec_glue_input *data; ++ ++ data = kzalloc(sizeof(*data), GFP_KERNEL); ++ if (!data) ++ return -ENOMEM; ++ ++ meson_codec_glue_input_set_data(dai, data); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_probe); ++ ++int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai) ++{ ++ struct meson_codec_glue_input *data = ++ meson_codec_glue_input_get_data(dai); ++ ++ kfree(data); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(meson_codec_glue_input_dai_remove); ++ ++MODULE_AUTHOR("Jerome Brunet "); ++MODULE_DESCRIPTION("Amlogic Codec Glue Helpers"); ++MODULE_LICENSE("GPL v2"); ++ +diff --git a/sound/soc/meson/meson-codec-glue.h b/sound/soc/meson/meson-codec-glue.h +new file mode 100644 +index 0000000000000..07f99446c0c6b +--- /dev/null ++++ b/sound/soc/meson/meson-codec-glue.h +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: GPL-2.0 ++ * ++ * Copyright (c) 2018 Baylibre SAS. ++ * Author: Jerome Brunet ++ */ ++ ++#ifndef _MESON_CODEC_GLUE_H ++#define _MESON_CODEC_GLUE_H ++ ++#include ++ ++struct meson_codec_glue_input { ++ struct snd_soc_pcm_stream params; ++ unsigned int fmt; ++}; ++ ++/* Input helpers */ ++struct meson_codec_glue_input * ++meson_codec_glue_input_get_data(struct snd_soc_dai *dai); ++int meson_codec_glue_input_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params, ++ struct snd_soc_dai *dai); ++int meson_codec_glue_input_set_fmt(struct snd_soc_dai *dai, ++ unsigned int fmt); ++int meson_codec_glue_input_dai_probe(struct snd_soc_dai *dai); ++int meson_codec_glue_input_dai_remove(struct snd_soc_dai *dai); ++ ++/* Output helpers */ ++int meson_codec_glue_output_startup(struct snd_pcm_substream *substream, ++ struct snd_soc_dai *dai); ++ ++#endif /* _MESON_CODEC_GLUE_H */ +-- +2.43.0 + diff --git a/queue-5.4/asoc-meson-g12a-tohdmitx-fix-event-generation-for-s-.patch b/queue-5.4/asoc-meson-g12a-tohdmitx-fix-event-generation-for-s-.patch new file mode 100644 index 00000000000..07055c1a713 --- /dev/null +++ b/queue-5.4/asoc-meson-g12a-tohdmitx-fix-event-generation-for-s-.patch @@ -0,0 +1,39 @@ +From e9203e3757f19216c844168885d6c09acf92153d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jan 2024 18:34:04 +0000 +Subject: ASoC: meson: g12a-tohdmitx: Fix event generation for S/PDIF mux + +From: Mark Brown + +[ Upstream commit b036d8ef3120b996751495ce25994eea58032a98 ] + +When a control changes value the return value from _put() should be 1 so +we get events generated to userspace notifying applications of the change. +While the I2S mux gets this right the S/PDIF mux does not, fix the return +value. + +Fixes: c8609f3870f7 ("ASoC: meson: add g12a tohdmitx control") +Signed-off-by: Mark Brown +Link: https://lore.kernel.org/r/20240103-meson-enum-val-v1-4-424af7a8fb91@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/g12a-tohdmitx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c +index 2f44c138e1dee..c875c350be070 100644 +--- a/sound/soc/meson/g12a-tohdmitx.c ++++ b/sound/soc/meson/g12a-tohdmitx.c +@@ -117,7 +117,7 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, + + snd_soc_dapm_mux_update_power(dapm, kcontrol, mux, e, NULL); + +- return 0; ++ return 1; + } + + static SOC_ENUM_SINGLE_DECL(g12a_tohdmitx_spdif_mux_enum, TOHDMITX_CTRL0, +-- +2.43.0 + diff --git a/queue-5.4/asoc-meson-g12a-tohdmitx-validate-written-enum-value.patch b/queue-5.4/asoc-meson-g12a-tohdmitx-validate-written-enum-value.patch new file mode 100644 index 00000000000..7ef20aa1322 --- /dev/null +++ b/queue-5.4/asoc-meson-g12a-tohdmitx-validate-written-enum-value.patch @@ -0,0 +1,50 @@ +From 76e63129f04341bd4637686b28f19775a460e601 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jan 2024 18:34:02 +0000 +Subject: ASoC: meson: g12a-tohdmitx: Validate written enum values + +From: Mark Brown + +[ Upstream commit 1e001206804be3f3d21f4a1cf16e5d059d75643f ] + +When writing to an enum we need to verify that the value written is valid +for the enumeration, the helper function snd_soc_item_enum_to_val() doesn't +do it since it needs to return an unsigned (and in any case we'd need to +check the return value). + +Fixes: c8609f3870f7 ("ASoC: meson: add g12a tohdmitx control") +Signed-off-by: Mark Brown +Link: https://lore.kernel.org/r/20240103-meson-enum-val-v1-2-424af7a8fb91@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/meson/g12a-tohdmitx.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sound/soc/meson/g12a-tohdmitx.c b/sound/soc/meson/g12a-tohdmitx.c +index d02825669484a..2f44c138e1dee 100644 +--- a/sound/soc/meson/g12a-tohdmitx.c ++++ b/sound/soc/meson/g12a-tohdmitx.c +@@ -44,6 +44,9 @@ static int g12a_tohdmitx_i2s_mux_put_enum(struct snd_kcontrol *kcontrol, + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, changed; + ++ if (ucontrol->value.enumerated.item[0] >= e->items) ++ return -EINVAL; ++ + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); + changed = snd_soc_component_test_bits(component, e->reg, + CTRL0_I2S_DAT_SEL, +@@ -92,6 +95,9 @@ static int g12a_tohdmitx_spdif_mux_put_enum(struct snd_kcontrol *kcontrol, + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int mux, changed; + ++ if (ucontrol->value.enumerated.item[0] >= e->items) ++ return -EINVAL; ++ + mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]); + changed = snd_soc_component_test_bits(component, TOHDMITX_CTRL0, + CTRL0_SPDIF_SEL, +-- +2.43.0 + diff --git a/queue-5.4/bnxt_en-remove-mis-applied-code-from-bnxt_cfg_ntp_fi.patch b/queue-5.4/bnxt_en-remove-mis-applied-code-from-bnxt_cfg_ntp_fi.patch new file mode 100644 index 00000000000..eee69f85af6 --- /dev/null +++ b/queue-5.4/bnxt_en-remove-mis-applied-code-from-bnxt_cfg_ntp_fi.patch @@ -0,0 +1,47 @@ +From 261b36212f4dcc4227a3960fe3f8b0caa7a582d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Jan 2024 16:59:24 -0800 +Subject: bnxt_en: Remove mis-applied code from bnxt_cfg_ntp_filters() + +From: Michael Chan + +[ Upstream commit e009b2efb7a8850498796b360043ac25c8d3d28f ] + +The 2 lines to check for the BNXT_HWRM_PF_UNLOAD_SP_EVENT bit was +mis-applied to bnxt_cfg_ntp_filters() and should have been applied to +bnxt_sp_task(). + +Fixes: 19241368443f ("bnxt_en: Send PF driver unload notification to all VFs.") +Reviewed-by: Andy Gospodarek +Signed-off-by: Michael Chan +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 7f85315744009..2a12a41442611 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -10340,6 +10340,8 @@ static void bnxt_sp_task(struct work_struct *work) + bnxt_cfg_ntp_filters(bp); + if (test_and_clear_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event)) + bnxt_hwrm_exec_fwd_req(bp); ++ if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event)) ++ netdev_info(bp->dev, "Receive PF driver unload event!\n"); + if (test_and_clear_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event)) { + bnxt_hwrm_tunnel_dst_port_alloc( + bp, bp->vxlan_port, +@@ -11266,8 +11268,6 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp) + } + } + } +- if (test_and_clear_bit(BNXT_HWRM_PF_UNLOAD_SP_EVENT, &bp->sp_event)) +- netdev_info(bp->dev, "Receive PF driver unload event!"); + } + + #else +-- +2.43.0 + diff --git a/queue-5.4/can-raw-add-support-for-so_mark.patch b/queue-5.4/can-raw-add-support-for-so_mark.patch new file mode 100644 index 00000000000..6aa516d2496 --- /dev/null +++ b/queue-5.4/can-raw-add-support-for-so_mark.patch @@ -0,0 +1,36 @@ +From f5a70e0c671d9daf9c8a5dfc7a1ffb2e59cb5cbe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Dec 2022 10:10:08 +0100 +Subject: can: raw: add support for SO_MARK + +From: Marc Kleine-Budde + +[ Upstream commit 0826e82b8a32e646b7b32ba8b68ba30812028e47 ] + +Add support for SO_MARK to the CAN_RAW protocol. This makes it +possible to add traffic control filters based on the fwmark. + +Link: https://lore.kernel.org/all/20221210113653.170346-1-mkl@pengutronix.de +Acked-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Stable-dep-of: 7f6ca95d16b9 ("net: Implement missing getsockopt(SO_TIMESTAMPING_NEW)") +Signed-off-by: Sasha Levin +--- + net/can/raw.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/can/raw.c b/net/can/raw.c +index 2700153262771..2f500d8a0af24 100644 +--- a/net/can/raw.c ++++ b/net/can/raw.c +@@ -826,6 +826,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + skb->dev = dev; + skb->sk = sk; + skb->priority = sk->sk_priority; ++ skb->mark = sk->sk_mark; + skb->tstamp = sockc.transmit_time; + + skb_setup_tx_timestamp(skb, sockc.tsflags); +-- +2.43.0 + diff --git a/queue-5.4/can-raw-add-support-for-so_txtime-scm_txtime.patch b/queue-5.4/can-raw-add-support-for-so_txtime-scm_txtime.patch new file mode 100644 index 00000000000..d8e023e356f --- /dev/null +++ b/queue-5.4/can-raw-add-support-for-so_txtime-scm_txtime.patch @@ -0,0 +1,63 @@ +From 441f593b2aca37ef5de4096f16b22b2e27761fa9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Apr 2022 12:31:52 +0200 +Subject: can: raw: add support for SO_TXTIME/SCM_TXTIME + +From: Marc Kleine-Budde + +[ Upstream commit 51a0d5e51178fcd147c1b8fdab2ed16b561326db ] + +This patch calls into sock_cmsg_send() to parse the user supplied +control information into a struct sockcm_cookie. Then assign the +requested transmit time to the skb. + +This makes it possible to use the Earliest TXTIME First (ETF) packet +scheduler with the CAN_RAW protocol. The user can send a CAN_RAW frame +with a TXTIME and the kernel (with the ETF scheduler) will take care +of sending it to the network interface. + +Link: https://lore.kernel.org/all/20220502091946.1916211-3-mkl@pengutronix.de +Acked-by: Oliver Hartkopp +Signed-off-by: Marc Kleine-Budde +Stable-dep-of: 7f6ca95d16b9 ("net: Implement missing getsockopt(SO_TIMESTAMPING_NEW)") +Signed-off-by: Sasha Levin +--- + net/can/raw.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/net/can/raw.c b/net/can/raw.c +index bb837019d1724..2700153262771 100644 +--- a/net/can/raw.c ++++ b/net/can/raw.c +@@ -770,6 +770,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + { + struct sock *sk = sock->sk; + struct raw_sock *ro = raw_sk(sk); ++ struct sockcm_cookie sockc; + struct sk_buff *skb; + struct net_device *dev; + int ifindex; +@@ -815,11 +816,19 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) + if (err < 0) + goto free_skb; + +- skb_setup_tx_timestamp(skb, sk->sk_tsflags); ++ sockcm_init(&sockc, sk); ++ if (msg->msg_controllen) { ++ err = sock_cmsg_send(sk, msg, &sockc); ++ if (unlikely(err)) ++ goto free_skb; ++ } + + skb->dev = dev; + skb->sk = sk; + skb->priority = sk->sk_priority; ++ skb->tstamp = sockc.transmit_time; ++ ++ skb_setup_tx_timestamp(skb, sockc.tsflags); + + err = can_send(skb, ro->loopback); + +-- +2.43.0 + diff --git a/queue-5.4/i40e-fix-filter-input-checks-to-prevent-config-with-.patch b/queue-5.4/i40e-fix-filter-input-checks-to-prevent-config-with-.patch new file mode 100644 index 00000000000..ce5c79f8114 --- /dev/null +++ b/queue-5.4/i40e-fix-filter-input-checks-to-prevent-config-with-.patch @@ -0,0 +1,53 @@ +From faa4d14fabcef705e8648878e038617a0ceff4c2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 11:23:11 +0100 +Subject: i40e: Fix filter input checks to prevent config with invalid values + +From: Sudheer Mogilappagari + +[ Upstream commit 3e48041d9820c17e0a51599d12e66c6e12a8d08d ] + +Prevent VF from configuring filters with unsupported actions or use +REDIRECT action with invalid tc number. Current checks could cause +out of bounds access on PF side. + +Fixes: e284fc280473 ("i40e: Add and delete cloud filter") +Reviewed-by: Andrii Staikov +Signed-off-by: Sudheer Mogilappagari +Signed-off-by: Aleksandr Loktionov +Reviewed-by: Simon Horman +Tested-by: Bharathi Sreenivas +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +index 37ce764ed3730..d53e535a447d6 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +@@ -3332,16 +3332,16 @@ static int i40e_validate_cloud_filter(struct i40e_vf *vf, + bool found = false; + int bkt; + +- if (!tc_filter->action) { ++ if (tc_filter->action != VIRTCHNL_ACTION_TC_REDIRECT) { + dev_info(&pf->pdev->dev, +- "VF %d: Currently ADq doesn't support Drop Action\n", +- vf->vf_id); ++ "VF %d: ADQ doesn't support this action (%d)\n", ++ vf->vf_id, tc_filter->action); + goto err; + } + + /* action_meta is TC number here to which the filter is applied */ + if (!tc_filter->action_meta || +- tc_filter->action_meta > I40E_MAX_VF_VSI) { ++ tc_filter->action_meta > vf->num_tc) { + dev_info(&pf->pdev->dev, "VF %d: Invalid TC number %u\n", + vf->vf_id, tc_filter->action_meta); + goto err; +-- +2.43.0 + diff --git a/queue-5.4/i40e-fix-use-after-free-in-i40e_aqc_add_filters.patch b/queue-5.4/i40e-fix-use-after-free-in-i40e_aqc_add_filters.patch new file mode 100644 index 00000000000..c08334696f4 --- /dev/null +++ b/queue-5.4/i40e-fix-use-after-free-in-i40e_aqc_add_filters.patch @@ -0,0 +1,120 @@ +From 2c9bb1cbe44e9d6c27f97c554cf8214d40f1f345 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Dec 2023 15:08:50 +0800 +Subject: i40e: fix use-after-free in i40e_aqc_add_filters() + +From: Ke Xiao + +[ Upstream commit 6a15584e99db8918b60e507539c7446375dcf366 ] + +Commit 3116f59c12bd ("i40e: fix use-after-free in +i40e_sync_filters_subtask()") avoided use-after-free issues, +by increasing refcount during update the VSI filter list to +the HW. However, it missed the unicast situation. + +When deleting an unicast FDB entry, the i40e driver will release +the mac_filter, and i40e_service_task will concurrently request +firmware to add the mac_filter, which will lead to the following +use-after-free issue. + +Fix again for both netdev->uc and netdev->mc. + +BUG: KASAN: use-after-free in i40e_aqc_add_filters+0x55c/0x5b0 [i40e] +Read of size 2 at addr ffff888eb3452d60 by task kworker/8:7/6379 + +CPU: 8 PID: 6379 Comm: kworker/8:7 Kdump: loaded Tainted: G +Workqueue: i40e i40e_service_task [i40e] +Call Trace: + dump_stack+0x71/0xab + print_address_description+0x6b/0x290 + kasan_report+0x14a/0x2b0 + i40e_aqc_add_filters+0x55c/0x5b0 [i40e] + i40e_sync_vsi_filters+0x1676/0x39c0 [i40e] + i40e_service_task+0x1397/0x2bb0 [i40e] + process_one_work+0x56a/0x11f0 + worker_thread+0x8f/0xf40 + kthread+0x2a0/0x390 + ret_from_fork+0x1f/0x40 + +Allocated by task 21948: + kasan_kmalloc+0xa6/0xd0 + kmem_cache_alloc_trace+0xdb/0x1c0 + i40e_add_filter+0x11e/0x520 [i40e] + i40e_addr_sync+0x37/0x60 [i40e] + __hw_addr_sync_dev+0x1f5/0x2f0 + i40e_set_rx_mode+0x61/0x1e0 [i40e] + dev_uc_add_excl+0x137/0x190 + i40e_ndo_fdb_add+0x161/0x260 [i40e] + rtnl_fdb_add+0x567/0x950 + rtnetlink_rcv_msg+0x5db/0x880 + netlink_rcv_skb+0x254/0x380 + netlink_unicast+0x454/0x610 + netlink_sendmsg+0x747/0xb00 + sock_sendmsg+0xe2/0x120 + __sys_sendto+0x1ae/0x290 + __x64_sys_sendto+0xdd/0x1b0 + do_syscall_64+0xa0/0x370 + entry_SYSCALL_64_after_hwframe+0x65/0xca + +Freed by task 21948: + __kasan_slab_free+0x137/0x190 + kfree+0x8b/0x1b0 + __i40e_del_filter+0x116/0x1e0 [i40e] + i40e_del_mac_filter+0x16c/0x300 [i40e] + i40e_addr_unsync+0x134/0x1b0 [i40e] + __hw_addr_sync_dev+0xff/0x2f0 + i40e_set_rx_mode+0x61/0x1e0 [i40e] + dev_uc_del+0x77/0x90 + rtnl_fdb_del+0x6a5/0x860 + rtnetlink_rcv_msg+0x5db/0x880 + netlink_rcv_skb+0x254/0x380 + netlink_unicast+0x454/0x610 + netlink_sendmsg+0x747/0xb00 + sock_sendmsg+0xe2/0x120 + __sys_sendto+0x1ae/0x290 + __x64_sys_sendto+0xdd/0x1b0 + do_syscall_64+0xa0/0x370 + entry_SYSCALL_64_after_hwframe+0x65/0xca + +Fixes: 3116f59c12bd ("i40e: fix use-after-free in i40e_sync_filters_subtask()") +Fixes: 41c445ff0f48 ("i40e: main driver core") +Signed-off-by: Ke Xiao +Signed-off-by: Ding Hui +Cc: Di Zhu +Reviewed-by: Jan Sokolowski +Reviewed-by: Simon Horman +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index 3ccc248b1a8a7..b44ba73414831 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -110,12 +110,18 @@ static struct workqueue_struct *i40e_wq; + static void netdev_hw_addr_refcnt(struct i40e_mac_filter *f, + struct net_device *netdev, int delta) + { ++ struct netdev_hw_addr_list *ha_list; + struct netdev_hw_addr *ha; + + if (!f || !netdev) + return; + +- netdev_for_each_mc_addr(ha, netdev) { ++ if (is_unicast_ether_addr(f->macaddr) || is_link_local_ether_addr(f->macaddr)) ++ ha_list = &netdev->uc; ++ else ++ ha_list = &netdev->mc; ++ ++ netdev_hw_addr_list_for_each(ha, ha_list) { + if (ether_addr_equal(ha->addr, f->macaddr)) { + ha->refcount += delta; + if (ha->refcount <= 0) +-- +2.43.0 + diff --git a/queue-5.4/i40e-restore-vf-msi-x-state-during-pci-reset.patch b/queue-5.4/i40e-restore-vf-msi-x-state-during-pci-reset.patch new file mode 100644 index 00000000000..461c981b3fa --- /dev/null +++ b/queue-5.4/i40e-restore-vf-msi-x-state-during-pci-reset.patch @@ -0,0 +1,103 @@ +From 41f8897d0779f4bb7243d35fed836de51600902e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Dec 2023 14:27:35 +0100 +Subject: i40e: Restore VF MSI-X state during PCI reset + +From: Andrii Staikov + +[ Upstream commit 371e576ff3e8580d91d49026e5d5faebf5565558 ] + +During a PCI FLR the MSI-X Enable flag in the VF PCI MSI-X capability +register will be cleared. This can lead to issues when a VF is +assigned to a VM because in these cases the VF driver receives no +indication of the PF PCI error/reset and additionally it is incapable +of restoring the cleared flag in the hypervisor configuration space +without fully reinitializing the driver interrupt functionality. + +Since the VF driver is unable to easily resolve this condition on its own, +restore the VF MSI-X flag during the PF PCI reset handling. + +Fixes: 19b7960b2da1 ("i40e: implement split PCI error reset handler") +Co-developed-by: Karen Ostrowska +Signed-off-by: Karen Ostrowska +Co-developed-by: Mateusz Palczewski +Signed-off-by: Mateusz Palczewski +Reviewed-by: Wojciech Drewek +Reviewed-by: Przemek Kitszel +Signed-off-by: Andrii Staikov +Tested-by: Rafal Romanowski +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +++ + .../ethernet/intel/i40e/i40e_virtchnl_pf.c | 26 +++++++++++++++++++ + .../ethernet/intel/i40e/i40e_virtchnl_pf.h | 3 +++ + 3 files changed, 32 insertions(+) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index b44ba73414831..fa938281281a4 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -15716,6 +15716,9 @@ static void i40e_pci_error_reset_done(struct pci_dev *pdev) + struct i40e_pf *pf = pci_get_drvdata(pdev); + + i40e_reset_and_rebuild(pf, false, false); ++#ifdef CONFIG_PCI_IOV ++ i40e_restore_all_vfs_msi_state(pdev); ++#endif /* CONFIG_PCI_IOV */ + } + + /** +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +index d53e535a447d6..e79b8dc5c2a5e 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +@@ -99,6 +99,32 @@ void i40e_vc_notify_reset(struct i40e_pf *pf) + (u8 *)&pfe, sizeof(struct virtchnl_pf_event)); + } + ++#ifdef CONFIG_PCI_IOV ++void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev) ++{ ++ u16 vf_id; ++ u16 pos; ++ ++ /* Continue only if this is a PF */ ++ if (!pdev->is_physfn) ++ return; ++ ++ if (!pci_num_vf(pdev)) ++ return; ++ ++ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_SRIOV); ++ if (pos) { ++ struct pci_dev *vf_dev = NULL; ++ ++ pci_read_config_word(pdev, pos + PCI_SRIOV_VF_DID, &vf_id); ++ while ((vf_dev = pci_get_device(pdev->vendor, vf_id, vf_dev))) { ++ if (vf_dev->is_virtfn && vf_dev->physfn == pdev) ++ pci_restore_msi_state(vf_dev); ++ } ++ } ++} ++#endif /* CONFIG_PCI_IOV */ ++ + /** + * i40e_vc_notify_vf_reset + * @vf: pointer to the VF structure +diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +index 23182731a73d0..75d916714ad8a 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h ++++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h +@@ -141,5 +141,8 @@ int i40e_ndo_set_vf_spoofchk(struct net_device *netdev, int vf_id, bool enable); + + void i40e_vc_notify_link_state(struct i40e_pf *pf); + void i40e_vc_notify_reset(struct i40e_pf *pf); ++#ifdef CONFIG_PCI_IOV ++void i40e_restore_all_vfs_msi_state(struct pci_dev *pdev); ++#endif /* CONFIG_PCI_IOV */ + + #endif /* _I40E_VIRTCHNL_PF_H_ */ +-- +2.43.0 + diff --git a/queue-5.4/mm-memory-failure-check-the-mapcount-of-the-precise-.patch b/queue-5.4/mm-memory-failure-check-the-mapcount-of-the-precise-.patch new file mode 100644 index 00000000000..5ff1ed68851 --- /dev/null +++ b/queue-5.4/mm-memory-failure-check-the-mapcount-of-the-precise-.patch @@ -0,0 +1,54 @@ +From d913c79b96102a56cc4f7a330309eb8f0166791d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Dec 2023 13:58:36 +0000 +Subject: mm/memory-failure: check the mapcount of the precise page + +From: Matthew Wilcox (Oracle) + +[ Upstream commit c79c5a0a00a9457718056b588f312baadf44e471 ] + +A process may map only some of the pages in a folio, and might be missed +if it maps the poisoned page but not the head page. Or it might be +unnecessarily hit if it maps the head page, but not the poisoned page. + +Link: https://lkml.kernel.org/r/20231218135837.3310403-3-willy@infradead.org +Fixes: 7af446a841a2 ("HWPOISON, hugetlb: enable error handling path for hugepage") +Signed-off-by: Matthew Wilcox (Oracle) +Cc: Dan Williams +Cc: Naoya Horiguchi +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + mm/memory-failure.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/mm/memory-failure.c b/mm/memory-failure.c +index 9030ab0d9d975..c6453f9ffd4d9 100644 +--- a/mm/memory-failure.c ++++ b/mm/memory-failure.c +@@ -986,7 +986,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, + * This check implies we don't kill processes if their pages + * are in the swap cache early. Those are always late kills. + */ +- if (!page_mapped(hpage)) ++ if (!page_mapped(p)) + return true; + + if (PageKsm(p)) { +@@ -1030,10 +1030,10 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, + if (kill) + collect_procs(hpage, &tokill, flags & MF_ACTION_REQUIRED); + +- unmap_success = try_to_unmap(hpage, ttu); ++ unmap_success = try_to_unmap(p, ttu); + if (!unmap_success) + pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n", +- pfn, page_mapcount(hpage)); ++ pfn, page_mapcount(p)); + + /* + * try_to_unmap() might put mlocked page in lru cache, so call +-- +2.43.0 + diff --git a/queue-5.4/net-bcmgenet-fix-fcs-generation-for-fragmented-skbuf.patch b/queue-5.4/net-bcmgenet-fix-fcs-generation-for-fragmented-skbuf.patch new file mode 100644 index 00000000000..6831a4205cb --- /dev/null +++ b/queue-5.4/net-bcmgenet-fix-fcs-generation-for-fragmented-skbuf.patch @@ -0,0 +1,46 @@ +From 71959784908d9b9b24f945b2df35b25bc6fac9ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Dec 2023 14:56:38 +0100 +Subject: net: bcmgenet: Fix FCS generation for fragmented skbuffs + +From: Adrian Cinal + +[ Upstream commit e584f2ff1e6cc9b1d99e8a6b0f3415940d1b3eb3 ] + +The flag DMA_TX_APPEND_CRC was only written to the first DMA descriptor +in the TX path, where each descriptor corresponds to a single skbuff +fragment (or the skbuff head). This led to packets with no FCS appearing +on the wire if the kernel allocated the packet in fragments, which would +always happen when using PACKET_MMAP/TPACKET (cf. tpacket_fill_skb() in +net/af_packet.c). + +Fixes: 1c1008c793fa ("net: bcmgenet: add main driver file") +Signed-off-by: Adrian Cinal +Acked-by: Doug Berger +Acked-by: Florian Fainelli +Link: https://lore.kernel.org/r/20231228135638.1339245-1-adriancinal1@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +index 750acbf294640..eeadeeec17bab 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +@@ -1648,8 +1648,10 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) + /* Note: if we ever change from DMA_TX_APPEND_CRC below we + * will need to restore software padding of "runt" packets + */ ++ len_stat |= DMA_TX_APPEND_CRC; ++ + if (!i) { +- len_stat |= DMA_TX_APPEND_CRC | DMA_SOP; ++ len_stat |= DMA_SOP; + if (skb->ip_summed == CHECKSUM_PARTIAL) + len_stat |= DMA_TX_DO_CSUM; + } +-- +2.43.0 + diff --git a/queue-5.4/net-implement-missing-getsockopt-so_timestamping_new.patch b/queue-5.4/net-implement-missing-getsockopt-so_timestamping_new.patch new file mode 100644 index 00000000000..8caf0f8b953 --- /dev/null +++ b/queue-5.4/net-implement-missing-getsockopt-so_timestamping_new.patch @@ -0,0 +1,60 @@ +From 55f187e0dfd93dc016c60cef248642274ab0d255 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Dec 2023 00:19:01 +0100 +Subject: net: Implement missing getsockopt(SO_TIMESTAMPING_NEW) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jörn-Thorben Hinz + +[ Upstream commit 7f6ca95d16b96567ce4cf458a2790ff17fa620c3 ] + +Commit 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW") added the new +socket option SO_TIMESTAMPING_NEW. Setting the option is handled in +sk_setsockopt(), querying it was not handled in sk_getsockopt(), though. + +Following remarks on an earlier submission of this patch, keep the old +behavior of getsockopt(SO_TIMESTAMPING_OLD) which returns the active +flags even if they actually have been set through SO_TIMESTAMPING_NEW. + +The new getsockopt(SO_TIMESTAMPING_NEW) is stricter, returning flags +only if they have been set through the same option. + +Fixes: 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW") +Link: https://lore.kernel.org/lkml/20230703175048.151683-1-jthinz@mailbox.tu-berlin.de/ +Link: https://lore.kernel.org/netdev/0d7cddc9-03fa-43db-a579-14f3e822615b@app.fastmail.com/ +Signed-off-by: Jörn-Thorben Hinz +Reviewed-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/core/sock.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/net/core/sock.c b/net/core/sock.c +index 2c3c5df139345..a3ca522434a6e 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -1309,9 +1309,16 @@ int sock_getsockopt(struct socket *sock, int level, int optname, + break; + + case SO_LINGER: ++ case SO_TIMESTAMPING_NEW: + lv = sizeof(v.ling); +- v.ling.l_onoff = sock_flag(sk, SOCK_LINGER); +- v.ling.l_linger = sk->sk_lingertime / HZ; ++ /* For the later-added case SO_TIMESTAMPING_NEW: Be strict about only ++ * returning the flags when they were set through the same option. ++ * Don't change the beviour for the old case SO_TIMESTAMPING_OLD. ++ */ ++ if (optname == SO_TIMESTAMPING_OLD || sock_flag(sk, SOCK_TSTAMP_NEW)) { ++ v.ling.l_onoff = sock_flag(sk, SOCK_LINGER); ++ v.ling.l_linger = sk->sk_lingertime / HZ; ++ } + break; + + case SO_BSDCOMPAT: +-- +2.43.0 + diff --git a/queue-5.4/net-implement-missing-so_timestamping_new-cmsg-suppo.patch b/queue-5.4/net-implement-missing-so_timestamping_new-cmsg-suppo.patch new file mode 100644 index 00000000000..d3949d36e4c --- /dev/null +++ b/queue-5.4/net-implement-missing-so_timestamping_new-cmsg-suppo.patch @@ -0,0 +1,40 @@ +From 0af316372dd6fb4069a2aed54f46e4fcfed359f1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Jan 2024 09:57:44 +0100 +Subject: net: Implement missing SO_TIMESTAMPING_NEW cmsg support + +From: Thomas Lange + +[ Upstream commit 382a32018b74f407008615e0e831d05ed28e81cd ] + +Commit 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW") added the new +socket option SO_TIMESTAMPING_NEW. However, it was never implemented in +__sock_cmsg_send thus breaking SO_TIMESTAMPING cmsg for platforms using +SO_TIMESTAMPING_NEW. + +Fixes: 9718475e6908 ("socket: Add SO_TIMESTAMPING_NEW") +Link: https://lore.kernel.org/netdev/6a7281bf-bc4a-4f75-bb88-7011908ae471@app.fastmail.com/ +Signed-off-by: Thomas Lange +Reviewed-by: Willem de Bruijn +Link: https://lore.kernel.org/r/20240104085744.49164-1-thomas@corelatus.se +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/sock.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/core/sock.c b/net/core/sock.c +index a3ca522434a6e..42076a3e12c3c 100644 +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2310,6 +2310,7 @@ int __sock_cmsg_send(struct sock *sk, struct msghdr *msg, struct cmsghdr *cmsg, + sockc->mark = *(u32 *)CMSG_DATA(cmsg); + break; + case SO_TIMESTAMPING_OLD: ++ case SO_TIMESTAMPING_NEW: + if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32))) + return -EINVAL; + +-- +2.43.0 + diff --git a/queue-5.4/net-qla3xxx-fix-potential-memleak-in-ql_alloc_buffer.patch b/queue-5.4/net-qla3xxx-fix-potential-memleak-in-ql_alloc_buffer.patch new file mode 100644 index 00000000000..0b7b218aaf2 --- /dev/null +++ b/queue-5.4/net-qla3xxx-fix-potential-memleak-in-ql_alloc_buffer.patch @@ -0,0 +1,44 @@ +From d0e8b2dc79f2badceaf9f4307b2c8e634a7ef3c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Dec 2023 15:02:27 +0800 +Subject: net/qla3xxx: fix potential memleak in ql_alloc_buffer_queues + +From: Dinghao Liu + +[ Upstream commit 89f45c30172c80e55c887f32f1af8e184124577b ] + +When dma_alloc_coherent() fails, we should free qdev->lrg_buf +to prevent potential memleak. + +Fixes: 1357bfcf7106 ("qla3xxx: Dynamically size the rx buffer queue based on the MTU.") +Signed-off-by: Dinghao Liu +Link: https://lore.kernel.org/r/20231227070227.10527-1-dinghao.liu@zju.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/qlogic/qla3xxx.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c +index 65cdf1bfbddb8..5d0e65a3b6a83 100644 +--- a/drivers/net/ethernet/qlogic/qla3xxx.c ++++ b/drivers/net/ethernet/qlogic/qla3xxx.c +@@ -2590,6 +2590,7 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) + + if (qdev->lrg_buf_q_alloc_virt_addr == NULL) { + netdev_err(qdev->ndev, "lBufQ failed\n"); ++ kfree(qdev->lrg_buf); + return -ENOMEM; + } + qdev->lrg_buf_q_virt_addr = qdev->lrg_buf_q_alloc_virt_addr; +@@ -2614,6 +2615,7 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) + qdev->lrg_buf_q_alloc_size, + qdev->lrg_buf_q_alloc_virt_addr, + qdev->lrg_buf_q_alloc_phy_addr); ++ kfree(qdev->lrg_buf); + return -ENOMEM; + } + +-- +2.43.0 + diff --git a/queue-5.4/net-qla3xxx-switch-from-pci_-to-dma_-api.patch b/queue-5.4/net-qla3xxx-switch-from-pci_-to-dma_-api.patch new file mode 100644 index 00000000000..f7a1209b1f0 --- /dev/null +++ b/queue-5.4/net-qla3xxx-switch-from-pci_-to-dma_-api.patch @@ -0,0 +1,564 @@ +From ea2fbddcfdf85d30cfb860c12f04955dcc3c02a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Jan 2021 09:15:42 +0100 +Subject: net/qla3xxx: switch from 'pci_' to 'dma_' API + +From: Christophe JAILLET + +[ Upstream commit 41fb4c1ba7478fe34c7e094e124e4ee4513b9763 ] + +The wrappers in include/linux/pci-dma-compat.h should go away. + +The patch has been generated with the coccinelle script below and has been +hand modified to replace GFP_ with a correct flag. +It has been compile tested. + +When memory is allocated in 'ql_alloc_net_req_rsp_queues()' GFP_KERNEL can +be used because it is only called from 'ql_alloc_mem_resources()' which +already calls 'ql_alloc_buffer_queues()' which uses GFP_KERNEL. (see below) + +When memory is allocated in 'ql_alloc_buffer_queues()' GFP_KERNEL can be +used because this flag is already used just a few line above. + +When memory is allocated in 'ql_alloc_small_buffers()' GFP_KERNEL can +be used because it is only called from 'ql_alloc_mem_resources()' which +already calls 'ql_alloc_buffer_queues()' which uses GFP_KERNEL. (see above) + +When memory is allocated in 'ql_alloc_mem_resources()' GFP_KERNEL can be +used because this function already calls 'ql_alloc_buffer_queues()' which +uses GFP_KERNEL. (see above) + +While at it, use 'dma_set_mask_and_coherent()' instead of 'dma_set_mask()/ +dma_set_coherent_mask()' in order to slightly simplify code. + +@@ +@@ +- PCI_DMA_BIDIRECTIONAL ++ DMA_BIDIRECTIONAL + +@@ +@@ +- PCI_DMA_TODEVICE ++ DMA_TO_DEVICE + +@@ +@@ +- PCI_DMA_FROMDEVICE ++ DMA_FROM_DEVICE + +@@ +@@ +- PCI_DMA_NONE ++ DMA_NONE + +@@ +expression e1, e2, e3; +@@ +- pci_alloc_consistent(e1, e2, e3) ++ dma_alloc_coherent(&e1->dev, e2, e3, GFP_) + +@@ +expression e1, e2, e3; +@@ +- pci_zalloc_consistent(e1, e2, e3) ++ dma_alloc_coherent(&e1->dev, e2, e3, GFP_) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_free_consistent(e1, e2, e3, e4) ++ dma_free_coherent(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_map_single(e1, e2, e3, e4) ++ dma_map_single(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_unmap_single(e1, e2, e3, e4) ++ dma_unmap_single(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4, e5; +@@ +- pci_map_page(e1, e2, e3, e4, e5) ++ dma_map_page(&e1->dev, e2, e3, e4, e5) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_unmap_page(e1, e2, e3, e4) ++ dma_unmap_page(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_map_sg(e1, e2, e3, e4) ++ dma_map_sg(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_unmap_sg(e1, e2, e3, e4) ++ dma_unmap_sg(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_dma_sync_single_for_cpu(e1, e2, e3, e4) ++ dma_sync_single_for_cpu(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_dma_sync_single_for_device(e1, e2, e3, e4) ++ dma_sync_single_for_device(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_dma_sync_sg_for_cpu(e1, e2, e3, e4) ++ dma_sync_sg_for_cpu(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2, e3, e4; +@@ +- pci_dma_sync_sg_for_device(e1, e2, e3, e4) ++ dma_sync_sg_for_device(&e1->dev, e2, e3, e4) + +@@ +expression e1, e2; +@@ +- pci_dma_mapping_error(e1, e2) ++ dma_mapping_error(&e1->dev, e2) + +@@ +expression e1, e2; +@@ +- pci_set_dma_mask(e1, e2) ++ dma_set_mask(&e1->dev, e2) + +@@ +expression e1, e2; +@@ +- pci_set_consistent_dma_mask(e1, e2) ++ dma_set_coherent_mask(&e1->dev, e2) + +Signed-off-by: Christophe JAILLET +Link: https://lore.kernel.org/r/20210117081542.560021-1-christophe.jaillet@wanadoo.fr +Signed-off-by: Jakub Kicinski +Stable-dep-of: 89f45c30172c ("net/qla3xxx: fix potential memleak in ql_alloc_buffer_queues") +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/qlogic/qla3xxx.c | 196 ++++++++++++-------------- + 1 file changed, 87 insertions(+), 109 deletions(-) + +diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c +index 2fa68592210d7..65cdf1bfbddb8 100644 +--- a/drivers/net/ethernet/qlogic/qla3xxx.c ++++ b/drivers/net/ethernet/qlogic/qla3xxx.c +@@ -316,12 +316,11 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev, + * buffer + */ + skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE); +- map = pci_map_single(qdev->pdev, ++ map = dma_map_single(&qdev->pdev->dev, + lrg_buf_cb->skb->data, +- qdev->lrg_buffer_len - +- QL_HEADER_SPACE, +- PCI_DMA_FROMDEVICE); +- err = pci_dma_mapping_error(qdev->pdev, map); ++ qdev->lrg_buffer_len - QL_HEADER_SPACE, ++ DMA_FROM_DEVICE); ++ err = dma_mapping_error(&qdev->pdev->dev, map); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping failed with error: %d\n", +@@ -1803,13 +1802,12 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev) + * first buffer + */ + skb_reserve(lrg_buf_cb->skb, QL_HEADER_SPACE); +- map = pci_map_single(qdev->pdev, ++ map = dma_map_single(&qdev->pdev->dev, + lrg_buf_cb->skb->data, +- qdev->lrg_buffer_len - +- QL_HEADER_SPACE, +- PCI_DMA_FROMDEVICE); ++ qdev->lrg_buffer_len - QL_HEADER_SPACE, ++ DMA_FROM_DEVICE); + +- err = pci_dma_mapping_error(qdev->pdev, map); ++ err = dma_mapping_error(&qdev->pdev->dev, map); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping failed with error: %d\n", +@@ -1944,18 +1942,16 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev, + goto invalid_seg_count; + } + +- pci_unmap_single(qdev->pdev, ++ dma_unmap_single(&qdev->pdev->dev, + dma_unmap_addr(&tx_cb->map[0], mapaddr), +- dma_unmap_len(&tx_cb->map[0], maplen), +- PCI_DMA_TODEVICE); ++ dma_unmap_len(&tx_cb->map[0], maplen), DMA_TO_DEVICE); + tx_cb->seg_count--; + if (tx_cb->seg_count) { + for (i = 1; i < tx_cb->seg_count; i++) { +- pci_unmap_page(qdev->pdev, +- dma_unmap_addr(&tx_cb->map[i], +- mapaddr), ++ dma_unmap_page(&qdev->pdev->dev, ++ dma_unmap_addr(&tx_cb->map[i], mapaddr), + dma_unmap_len(&tx_cb->map[i], maplen), +- PCI_DMA_TODEVICE); ++ DMA_TO_DEVICE); + } + } + qdev->ndev->stats.tx_packets++; +@@ -2022,10 +2018,9 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev, + qdev->ndev->stats.rx_bytes += length; + + skb_put(skb, length); +- pci_unmap_single(qdev->pdev, ++ dma_unmap_single(&qdev->pdev->dev, + dma_unmap_addr(lrg_buf_cb2, mapaddr), +- dma_unmap_len(lrg_buf_cb2, maplen), +- PCI_DMA_FROMDEVICE); ++ dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE); + prefetch(skb->data); + skb_checksum_none_assert(skb); + skb->protocol = eth_type_trans(skb, qdev->ndev); +@@ -2068,10 +2063,9 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev, + skb2 = lrg_buf_cb2->skb; + + skb_put(skb2, length); /* Just the second buffer length here. */ +- pci_unmap_single(qdev->pdev, ++ dma_unmap_single(&qdev->pdev->dev, + dma_unmap_addr(lrg_buf_cb2, mapaddr), +- dma_unmap_len(lrg_buf_cb2, maplen), +- PCI_DMA_FROMDEVICE); ++ dma_unmap_len(lrg_buf_cb2, maplen), DMA_FROM_DEVICE); + prefetch(skb2->data); + + skb_checksum_none_assert(skb2); +@@ -2320,9 +2314,9 @@ static int ql_send_map(struct ql3_adapter *qdev, + /* + * Map the skb buffer first. + */ +- map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE); ++ map = dma_map_single(&qdev->pdev->dev, skb->data, len, DMA_TO_DEVICE); + +- err = pci_dma_mapping_error(qdev->pdev, map); ++ err = dma_mapping_error(&qdev->pdev->dev, map); + if (err) { + netdev_err(qdev->ndev, "PCI mapping failed with error: %d\n", + err); +@@ -2358,11 +2352,11 @@ static int ql_send_map(struct ql3_adapter *qdev, + (seg == 7 && seg_cnt > 8) || + (seg == 12 && seg_cnt > 13) || + (seg == 17 && seg_cnt > 18)) { +- map = pci_map_single(qdev->pdev, oal, ++ map = dma_map_single(&qdev->pdev->dev, oal, + sizeof(struct oal), +- PCI_DMA_TODEVICE); ++ DMA_TO_DEVICE); + +- err = pci_dma_mapping_error(qdev->pdev, map); ++ err = dma_mapping_error(&qdev->pdev->dev, map); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping outbound address list with error: %d\n", +@@ -2424,24 +2418,24 @@ static int ql_send_map(struct ql3_adapter *qdev, + (seg == 7 && seg_cnt > 8) || + (seg == 12 && seg_cnt > 13) || + (seg == 17 && seg_cnt > 18)) { +- pci_unmap_single(qdev->pdev, +- dma_unmap_addr(&tx_cb->map[seg], mapaddr), +- dma_unmap_len(&tx_cb->map[seg], maplen), +- PCI_DMA_TODEVICE); ++ dma_unmap_single(&qdev->pdev->dev, ++ dma_unmap_addr(&tx_cb->map[seg], mapaddr), ++ dma_unmap_len(&tx_cb->map[seg], maplen), ++ DMA_TO_DEVICE); + oal++; + seg++; + } + +- pci_unmap_page(qdev->pdev, ++ dma_unmap_page(&qdev->pdev->dev, + dma_unmap_addr(&tx_cb->map[seg], mapaddr), + dma_unmap_len(&tx_cb->map[seg], maplen), +- PCI_DMA_TODEVICE); ++ DMA_TO_DEVICE); + } + +- pci_unmap_single(qdev->pdev, ++ dma_unmap_single(&qdev->pdev->dev, + dma_unmap_addr(&tx_cb->map[0], mapaddr), + dma_unmap_addr(&tx_cb->map[0], maplen), +- PCI_DMA_TODEVICE); ++ DMA_TO_DEVICE); + + return NETDEV_TX_BUSY; + +@@ -2527,9 +2521,8 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) + wmb(); + + qdev->req_q_virt_addr = +- pci_alloc_consistent(qdev->pdev, +- (size_t) qdev->req_q_size, +- &qdev->req_q_phy_addr); ++ dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size, ++ &qdev->req_q_phy_addr, GFP_KERNEL); + + if ((qdev->req_q_virt_addr == NULL) || + LS_64BITS(qdev->req_q_phy_addr) & (qdev->req_q_size - 1)) { +@@ -2538,16 +2531,14 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev) + } + + qdev->rsp_q_virt_addr = +- pci_alloc_consistent(qdev->pdev, +- (size_t) qdev->rsp_q_size, +- &qdev->rsp_q_phy_addr); ++ dma_alloc_coherent(&qdev->pdev->dev, (size_t)qdev->rsp_q_size, ++ &qdev->rsp_q_phy_addr, GFP_KERNEL); + + if ((qdev->rsp_q_virt_addr == NULL) || + LS_64BITS(qdev->rsp_q_phy_addr) & (qdev->rsp_q_size - 1)) { + netdev_err(qdev->ndev, "rspQ allocation failed\n"); +- pci_free_consistent(qdev->pdev, (size_t) qdev->req_q_size, +- qdev->req_q_virt_addr, +- qdev->req_q_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, (size_t)qdev->req_q_size, ++ qdev->req_q_virt_addr, qdev->req_q_phy_addr); + return -ENOMEM; + } + +@@ -2563,15 +2554,13 @@ static void ql_free_net_req_rsp_queues(struct ql3_adapter *qdev) + return; + } + +- pci_free_consistent(qdev->pdev, +- qdev->req_q_size, +- qdev->req_q_virt_addr, qdev->req_q_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, qdev->req_q_size, ++ qdev->req_q_virt_addr, qdev->req_q_phy_addr); + + qdev->req_q_virt_addr = NULL; + +- pci_free_consistent(qdev->pdev, +- qdev->rsp_q_size, +- qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, qdev->rsp_q_size, ++ qdev->rsp_q_virt_addr, qdev->rsp_q_phy_addr); + + qdev->rsp_q_virt_addr = NULL; + +@@ -2595,9 +2584,9 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) + return -ENOMEM; + + qdev->lrg_buf_q_alloc_virt_addr = +- pci_alloc_consistent(qdev->pdev, +- qdev->lrg_buf_q_alloc_size, +- &qdev->lrg_buf_q_alloc_phy_addr); ++ dma_alloc_coherent(&qdev->pdev->dev, ++ qdev->lrg_buf_q_alloc_size, ++ &qdev->lrg_buf_q_alloc_phy_addr, GFP_KERNEL); + + if (qdev->lrg_buf_q_alloc_virt_addr == NULL) { + netdev_err(qdev->ndev, "lBufQ failed\n"); +@@ -2615,15 +2604,16 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) + qdev->small_buf_q_alloc_size = qdev->small_buf_q_size * 2; + + qdev->small_buf_q_alloc_virt_addr = +- pci_alloc_consistent(qdev->pdev, +- qdev->small_buf_q_alloc_size, +- &qdev->small_buf_q_alloc_phy_addr); ++ dma_alloc_coherent(&qdev->pdev->dev, ++ qdev->small_buf_q_alloc_size, ++ &qdev->small_buf_q_alloc_phy_addr, GFP_KERNEL); + + if (qdev->small_buf_q_alloc_virt_addr == NULL) { + netdev_err(qdev->ndev, "Small Buffer Queue allocation failed\n"); +- pci_free_consistent(qdev->pdev, qdev->lrg_buf_q_alloc_size, +- qdev->lrg_buf_q_alloc_virt_addr, +- qdev->lrg_buf_q_alloc_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, ++ qdev->lrg_buf_q_alloc_size, ++ qdev->lrg_buf_q_alloc_virt_addr, ++ qdev->lrg_buf_q_alloc_phy_addr); + return -ENOMEM; + } + +@@ -2640,17 +2630,15 @@ static void ql_free_buffer_queues(struct ql3_adapter *qdev) + return; + } + kfree(qdev->lrg_buf); +- pci_free_consistent(qdev->pdev, +- qdev->lrg_buf_q_alloc_size, +- qdev->lrg_buf_q_alloc_virt_addr, +- qdev->lrg_buf_q_alloc_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, qdev->lrg_buf_q_alloc_size, ++ qdev->lrg_buf_q_alloc_virt_addr, ++ qdev->lrg_buf_q_alloc_phy_addr); + + qdev->lrg_buf_q_virt_addr = NULL; + +- pci_free_consistent(qdev->pdev, +- qdev->small_buf_q_alloc_size, +- qdev->small_buf_q_alloc_virt_addr, +- qdev->small_buf_q_alloc_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, qdev->small_buf_q_alloc_size, ++ qdev->small_buf_q_alloc_virt_addr, ++ qdev->small_buf_q_alloc_phy_addr); + + qdev->small_buf_q_virt_addr = NULL; + +@@ -2668,9 +2656,9 @@ static int ql_alloc_small_buffers(struct ql3_adapter *qdev) + QL_SMALL_BUFFER_SIZE); + + qdev->small_buf_virt_addr = +- pci_alloc_consistent(qdev->pdev, +- qdev->small_buf_total_size, +- &qdev->small_buf_phy_addr); ++ dma_alloc_coherent(&qdev->pdev->dev, ++ qdev->small_buf_total_size, ++ &qdev->small_buf_phy_addr, GFP_KERNEL); + + if (qdev->small_buf_virt_addr == NULL) { + netdev_err(qdev->ndev, "Failed to get small buffer memory\n"); +@@ -2703,10 +2691,10 @@ static void ql_free_small_buffers(struct ql3_adapter *qdev) + return; + } + if (qdev->small_buf_virt_addr != NULL) { +- pci_free_consistent(qdev->pdev, +- qdev->small_buf_total_size, +- qdev->small_buf_virt_addr, +- qdev->small_buf_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, ++ qdev->small_buf_total_size, ++ qdev->small_buf_virt_addr, ++ qdev->small_buf_phy_addr); + + qdev->small_buf_virt_addr = NULL; + } +@@ -2721,10 +2709,10 @@ static void ql_free_large_buffers(struct ql3_adapter *qdev) + lrg_buf_cb = &qdev->lrg_buf[i]; + if (lrg_buf_cb->skb) { + dev_kfree_skb(lrg_buf_cb->skb); +- pci_unmap_single(qdev->pdev, ++ dma_unmap_single(&qdev->pdev->dev, + dma_unmap_addr(lrg_buf_cb, mapaddr), + dma_unmap_len(lrg_buf_cb, maplen), +- PCI_DMA_FROMDEVICE); ++ DMA_FROM_DEVICE); + memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb)); + } else { + break; +@@ -2776,13 +2764,11 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev) + * buffer + */ + skb_reserve(skb, QL_HEADER_SPACE); +- map = pci_map_single(qdev->pdev, +- skb->data, +- qdev->lrg_buffer_len - +- QL_HEADER_SPACE, +- PCI_DMA_FROMDEVICE); ++ map = dma_map_single(&qdev->pdev->dev, skb->data, ++ qdev->lrg_buffer_len - QL_HEADER_SPACE, ++ DMA_FROM_DEVICE); + +- err = pci_dma_mapping_error(qdev->pdev, map); ++ err = dma_mapping_error(&qdev->pdev->dev, map); + if (err) { + netdev_err(qdev->ndev, + "PCI mapping failed with error: %d\n", +@@ -2867,8 +2853,8 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev) + * Network Completion Queue Producer Index Register + */ + qdev->shadow_reg_virt_addr = +- pci_alloc_consistent(qdev->pdev, +- PAGE_SIZE, &qdev->shadow_reg_phy_addr); ++ dma_alloc_coherent(&qdev->pdev->dev, PAGE_SIZE, ++ &qdev->shadow_reg_phy_addr, GFP_KERNEL); + + if (qdev->shadow_reg_virt_addr != NULL) { + qdev->preq_consumer_index = qdev->shadow_reg_virt_addr; +@@ -2923,10 +2909,9 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev) + err_buffer_queues: + ql_free_net_req_rsp_queues(qdev); + err_req_rsp: +- pci_free_consistent(qdev->pdev, +- PAGE_SIZE, +- qdev->shadow_reg_virt_addr, +- qdev->shadow_reg_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE, ++ qdev->shadow_reg_virt_addr, ++ qdev->shadow_reg_phy_addr); + + return -ENOMEM; + } +@@ -2939,10 +2924,9 @@ static void ql_free_mem_resources(struct ql3_adapter *qdev) + ql_free_buffer_queues(qdev); + ql_free_net_req_rsp_queues(qdev); + if (qdev->shadow_reg_virt_addr != NULL) { +- pci_free_consistent(qdev->pdev, +- PAGE_SIZE, +- qdev->shadow_reg_virt_addr, +- qdev->shadow_reg_phy_addr); ++ dma_free_coherent(&qdev->pdev->dev, PAGE_SIZE, ++ qdev->shadow_reg_virt_addr, ++ qdev->shadow_reg_phy_addr); + qdev->shadow_reg_virt_addr = NULL; + } + } +@@ -3643,18 +3627,15 @@ static void ql_reset_work(struct work_struct *work) + if (tx_cb->skb) { + netdev_printk(KERN_DEBUG, ndev, + "Freeing lost SKB\n"); +- pci_unmap_single(qdev->pdev, +- dma_unmap_addr(&tx_cb->map[0], +- mapaddr), +- dma_unmap_len(&tx_cb->map[0], maplen), +- PCI_DMA_TODEVICE); ++ dma_unmap_single(&qdev->pdev->dev, ++ dma_unmap_addr(&tx_cb->map[0], mapaddr), ++ dma_unmap_len(&tx_cb->map[0], maplen), ++ DMA_TO_DEVICE); + for (j = 1; j < tx_cb->seg_count; j++) { +- pci_unmap_page(qdev->pdev, +- dma_unmap_addr(&tx_cb->map[j], +- mapaddr), +- dma_unmap_len(&tx_cb->map[j], +- maplen), +- PCI_DMA_TODEVICE); ++ dma_unmap_page(&qdev->pdev->dev, ++ dma_unmap_addr(&tx_cb->map[j], mapaddr), ++ dma_unmap_len(&tx_cb->map[j], maplen), ++ DMA_TO_DEVICE); + } + dev_kfree_skb(tx_cb->skb); + tx_cb->skb = NULL; +@@ -3786,13 +3767,10 @@ static int ql3xxx_probe(struct pci_dev *pdev, + + pci_set_master(pdev); + +- if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { ++ if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) + pci_using_dac = 1; +- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); +- } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { ++ else if (!(err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)))) + pci_using_dac = 0; +- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); +- } + + if (err) { + pr_err("%s no usable DMA configuration\n", pci_name(pdev)); +-- +2.43.0 + diff --git a/queue-5.4/net-save-and-restore-msg_namelen-in-sock_sendmsg.patch b/queue-5.4/net-save-and-restore-msg_namelen-in-sock_sendmsg.patch new file mode 100644 index 00000000000..8341ab4e778 --- /dev/null +++ b/queue-5.4/net-save-and-restore-msg_namelen-in-sock_sendmsg.patch @@ -0,0 +1,55 @@ +From d1cbbf3db417201a8d257cb065aa556ebe802fcb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Dec 2023 09:12:30 -0400 +Subject: net: Save and restore msg_namelen in sock_sendmsg + +From: Marc Dionne + +[ Upstream commit 01b2885d9415152bcb12ff1f7788f500a74ea0ed ] + +Commit 86a7e0b69bd5 ("net: prevent rewrite of msg_name in +sock_sendmsg()") made sock_sendmsg save the incoming msg_name pointer +and restore it before returning, to insulate the caller against +msg_name being changed by the called code. If the address length +was also changed however, we may return with an inconsistent structure +where the length doesn't match the address, and attempts to reuse it may +lead to lost packets. + +For example, a kernel that doesn't have commit 1c5950fc6fe9 ("udp6: fix +potential access to stale information") will replace a v4 mapped address +with its ipv4 equivalent, and shorten namelen accordingly from 28 to 16. +If the caller attempts to reuse the resulting msg structure, it will have +the original ipv6 (v4 mapped) address but an incorrect v4 length. + +Fixes: 86a7e0b69bd5 ("net: prevent rewrite of msg_name in sock_sendmsg()") +Signed-off-by: Marc Dionne +Reviewed-by: Willem de Bruijn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/socket.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/socket.c b/net/socket.c +index 38c26e20511d7..e3a50f107d64d 100644 +--- a/net/socket.c ++++ b/net/socket.c +@@ -661,6 +661,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg) + { + struct sockaddr_storage *save_addr = (struct sockaddr_storage *)msg->msg_name; + struct sockaddr_storage address; ++ int save_len = msg->msg_namelen; + int ret; + + if (msg->msg_name) { +@@ -670,6 +671,7 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg) + + ret = __sock_sendmsg(sock, msg); + msg->msg_name = save_addr; ++ msg->msg_namelen = save_len; + + return ret; + } +-- +2.43.0 + diff --git a/queue-5.4/net-sched-em_text-fix-possible-memory-leak-in-em_tex.patch b/queue-5.4/net-sched-em_text-fix-possible-memory-leak-in-em_tex.patch new file mode 100644 index 00000000000..28ac646803a --- /dev/null +++ b/queue-5.4/net-sched-em_text-fix-possible-memory-leak-in-em_tex.patch @@ -0,0 +1,40 @@ +From b41009cf4f2057c500dedc997efbbb0c27d29d8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Dec 2023 10:25:31 +0800 +Subject: net: sched: em_text: fix possible memory leak in em_text_destroy() + +From: Hangyu Hua + +[ Upstream commit 8fcb0382af6f1ef50936f1be05b8149eb2f88496 ] + +m->data needs to be freed when em_text_destroy is called. + +Fixes: d675c989ed2d ("[PKT_SCHED]: Packet classification based on textsearch (ematch)") +Acked-by: Jamal Hadi Salim +Signed-off-by: Hangyu Hua +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/sched/em_text.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/sched/em_text.c b/net/sched/em_text.c +index 6f3c1fb2fb44c..f176afb70559e 100644 +--- a/net/sched/em_text.c ++++ b/net/sched/em_text.c +@@ -97,8 +97,10 @@ static int em_text_change(struct net *net, void *data, int len, + + static void em_text_destroy(struct tcf_ematch *m) + { +- if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config) ++ if (EM_TEXT_PRIV(m) && EM_TEXT_PRIV(m)->config) { + textsearch_destroy(EM_TEXT_PRIV(m)->config); ++ kfree(EM_TEXT_PRIV(m)); ++ } + } + + static int em_text_dump(struct sk_buff *skb, struct tcf_ematch *m) +-- +2.43.0 + diff --git a/queue-5.4/net-timestamp-extend-sof_timestamping_opt_id-to-hw-t.patch b/queue-5.4/net-timestamp-extend-sof_timestamping_opt_id-to-hw-t.patch new file mode 100644 index 00000000000..d53740e33d8 --- /dev/null +++ b/queue-5.4/net-timestamp-extend-sof_timestamping_opt_id-to-hw-t.patch @@ -0,0 +1,52 @@ +From f5752280b642e9f3dc6c4d30a318371cba6f4c0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 6 Mar 2023 08:07:38 -0800 +Subject: net-timestamp: extend SOF_TIMESTAMPING_OPT_ID to HW timestamps + +From: Vadim Fedorenko + +[ Upstream commit 8ca5a5790b9a1ce147484d2a2c4e66d2553f3d6c ] + +When the feature was added it was enabled for SW timestamps only but +with current hardware the same out-of-order timestamps can be seen. +Let's expand the area for the feature to all types of timestamps. + +Signed-off-by: Vadim Fedorenko +Reviewed-by: Willem de Bruijn +Signed-off-by: David S. Miller +Stable-dep-of: 7f6ca95d16b9 ("net: Implement missing getsockopt(SO_TIMESTAMPING_NEW)") +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_output.c | 2 +- + net/ipv6/ip6_output.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index bf7c2333bc236..0f70c2dbbe5bb 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -993,7 +993,7 @@ static int __ip_append_data(struct sock *sk, + mtu = cork->gso_size ? IP_MAX_MTU : cork->fragsize; + paged = !!cork->gso_size; + +- if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP && ++ if (cork->tx_flags & SKBTX_ANY_TSTAMP && + sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) + tskey = sk->sk_tskey++; + +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index d3455585e6a8c..c67d634dccd47 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1425,7 +1425,7 @@ static int __ip6_append_data(struct sock *sk, + mtu = cork->gso_size ? IP6_MAX_MTU : cork->fragsize; + orig_mtu = mtu; + +- if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP && ++ if (cork->tx_flags & SKBTX_ANY_TSTAMP && + sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) + tskey = sk->sk_tskey++; + +-- +2.43.0 + diff --git a/queue-5.4/nfc-llcp_core-hold-a-ref-to-llcp_local-dev-when-hold.patch b/queue-5.4/nfc-llcp_core-hold-a-ref-to-llcp_local-dev-when-hold.patch new file mode 100644 index 00000000000..e14d3d1c54b --- /dev/null +++ b/queue-5.4/nfc-llcp_core-hold-a-ref-to-llcp_local-dev-when-hold.patch @@ -0,0 +1,128 @@ +From ca4a3af8c76a69f4405024d141d9857b16090aa2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Dec 2023 23:19:43 +0530 +Subject: nfc: llcp_core: Hold a ref to llcp_local->dev when holding a ref to + llcp_local + +From: Siddh Raman Pant + +[ Upstream commit c95f919567d6f1914f13350af61a1b044ac85014 ] + +llcp_sock_sendmsg() calls nfc_llcp_send_ui_frame() which in turn calls +nfc_alloc_send_skb(), which accesses the nfc_dev from the llcp_sock for +getting the headroom and tailroom needed for skb allocation. + +Parallelly the nfc_dev can be freed, as the refcount is decreased via +nfc_free_device(), leading to a UAF reported by Syzkaller, which can +be summarized as follows: + +(1) llcp_sock_sendmsg() -> nfc_llcp_send_ui_frame() + -> nfc_alloc_send_skb() -> Dereference *nfc_dev +(2) virtual_ncidev_close() -> nci_free_device() -> nfc_free_device() + -> put_device() -> nfc_release() -> Free *nfc_dev + +When a reference to llcp_local is acquired, we do not acquire the same +for the nfc_dev. This leads to freeing even when the llcp_local is in +use, and this is the case with the UAF described above too. + +Thus, when we acquire a reference to llcp_local, we should acquire a +reference to nfc_dev, and release the references appropriately later. + +References for llcp_local is initialized in nfc_llcp_register_device() +(which is called by nfc_register_device()). Thus, we should acquire a +reference to nfc_dev there. + +nfc_unregister_device() calls nfc_llcp_unregister_device() which in +turn calls nfc_llcp_local_put(). Thus, the reference to nfc_dev is +appropriately released later. + +Reported-and-tested-by: syzbot+bbe84a4010eeea00982d@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=bbe84a4010eeea00982d +Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket") +Reviewed-by: Suman Ghosh +Signed-off-by: Siddh Raman Pant +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/nfc/llcp_core.c | 39 ++++++++++++++++++++++++++++++++++++--- + 1 file changed, 36 insertions(+), 3 deletions(-) + +diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c +index 92f70686bee0a..da3cb0d29b972 100644 +--- a/net/nfc/llcp_core.c ++++ b/net/nfc/llcp_core.c +@@ -147,6 +147,13 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device, + + static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local) + { ++ /* Since using nfc_llcp_local may result in usage of nfc_dev, whenever ++ * we hold a reference to local, we also need to hold a reference to ++ * the device to avoid UAF. ++ */ ++ if (!nfc_get_device(local->dev->idx)) ++ return NULL; ++ + kref_get(&local->ref); + + return local; +@@ -179,10 +186,18 @@ static void local_release(struct kref *ref) + + int nfc_llcp_local_put(struct nfc_llcp_local *local) + { ++ struct nfc_dev *dev; ++ int ret; ++ + if (local == NULL) + return 0; + +- return kref_put(&local->ref, local_release); ++ dev = local->dev; ++ ++ ret = kref_put(&local->ref, local_release); ++ nfc_put_device(dev); ++ ++ return ret; + } + + static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, +@@ -968,8 +983,17 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, + } + + new_sock = nfc_llcp_sock(new_sk); +- new_sock->dev = local->dev; ++ + new_sock->local = nfc_llcp_local_get(local); ++ if (!new_sock->local) { ++ reason = LLCP_DM_REJ; ++ sock_put(&new_sock->sk); ++ release_sock(&sock->sk); ++ sock_put(&sock->sk); ++ goto fail; ++ } ++ ++ new_sock->dev = local->dev; + new_sock->rw = sock->rw; + new_sock->miux = sock->miux; + new_sock->nfc_protocol = sock->nfc_protocol; +@@ -1607,7 +1631,16 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) + if (local == NULL) + return -ENOMEM; + +- local->dev = ndev; ++ /* As we are going to initialize local's refcount, we need to get the ++ * nfc_dev to avoid UAF, otherwise there is no point in continuing. ++ * See nfc_llcp_local_get(). ++ */ ++ local->dev = nfc_get_device(ndev->idx); ++ if (!local->dev) { ++ kfree(local); ++ return -ENODEV; ++ } ++ + INIT_LIST_HEAD(&local->list); + kref_init(&local->ref); + mutex_init(&local->sdp_lock); +-- +2.43.0 + diff --git a/queue-5.4/series b/queue-5.4/series index f97ece4d239..3e0fdd30953 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -43,3 +43,24 @@ usb-fotg210-hcd-delete-an-incorrect-bounds-test.patch smb-client-fix-oob-in-smbcalcsize.patch ring-buffer-fix-wake-ups-when-buffer_percent-is-set-to-100.patch block-don-t-invalidate-pagecache-for-invalid-falloc-modes.patch +nfc-llcp_core-hold-a-ref-to-llcp_local-dev-when-hold.patch +i40e-fix-filter-input-checks-to-prevent-config-with-.patch +net-sched-em_text-fix-possible-memory-leak-in-em_tex.patch +net-implement-missing-getsockopt-so_timestamping_new.patch +can-raw-add-support-for-so_txtime-scm_txtime.patch +can-raw-add-support-for-so_mark.patch +net-timestamp-extend-sof_timestamping_opt_id-to-hw-t.patch +arm-sun9i-smp-fix-array-index-out-of-bounds-read-in-.patch +net-bcmgenet-fix-fcs-generation-for-fragmented-skbuf.patch +net-save-and-restore-msg_namelen-in-sock_sendmsg.patch +i40e-fix-use-after-free-in-i40e_aqc_add_filters.patch +asoc-meson-g12a-extract-codec-to-codec-utils.patch +asoc-meson-g12a-tohdmitx-validate-written-enum-value.patch +asoc-meson-g12a-tohdmitx-fix-event-generation-for-s-.patch +i40e-restore-vf-msi-x-state-during-pci-reset.patch +net-qla3xxx-switch-from-pci_-to-dma_-api.patch +net-qla3xxx-fix-potential-memleak-in-ql_alloc_buffer.patch +asix-add-check-for-usbnet_get_endpoints.patch +bnxt_en-remove-mis-applied-code-from-bnxt_cfg_ntp_fi.patch +net-implement-missing-so_timestamping_new-cmsg-suppo.patch +mm-memory-failure-check-the-mapcount-of-the-precise-.patch