From: Greg Kroah-Hartman Date: Sat, 12 Aug 2023 16:58:17 +0000 (+0200) Subject: 6.4-stable patches X-Git-Tag: v4.14.323~49 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bf22d201b84af4a40b018306e33ad76ea3544ad6;p=thirdparty%2Fkernel%2Fstable-queue.git 6.4-stable patches added patches: binder-fix-memory-leak-in-binder_init.patch drm-nouveau-disp-revert-a-null-check-inside-nouveau_connector_get_modes.patch iio-adc-ad7192-fix-ac-excitation-feature.patch iio-adc-ina2xx-avoid-null-pointer-dereference-on-of-device-match.patch iio-adc-meson-fix-core-clock-enable-disable-moment.patch iio-core-prevent-invalid-memory-access-when-there-is-no-parent.patch iio-cros_ec-fix-the-allocation-size-for-cros_ec_command.patch iio-frequency-admv1013-propagate-errors-from-regulator_get_voltage.patch iio-imu-lsm6dsx-fix-mount-matrix-retrieval.patch iio-light-bu27034-fix-scale-format.patch misc-rtsx-judge-aspm-mode-to-set-petxcfg-reg.patch netfilter-nf_tables-adapt-set-backend-to-use-gc-transaction-api.patch netfilter-nf_tables-don-t-skip-expired-elements-during-walk.patch netfilter-nf_tables-gc-transaction-api-to-avoid-race-with-control-plane.patch netfilter-nft_set_hash-mark-set-element-as-dead-when-deleting-from-packet-path.patch revert-pci-mvebu-mark-driver-as-broken.patch thunderbolt-fix-memory-leak-in-tb_handle_dp_bandwidth_request.patch usb-common-usb-conn-gpio-prevent-bailing-out-if-initial-role-is-none.patch usb-dwc3-properly-handle-processing-of-pending-events.patch usb-gadget-core-help-prevent-panic-during-uvc-unconfigure.patch usb-storage-alauda-fix-uninit-value-in-alauda_check_media.patch usb-typec-altmodes-displayport-signal-hpd-when-configuring-pin-assignment.patch usb-typec-tcpm-fix-response-to-vsafe0v-event.patch x86-cpu-amd-enable-zenbleed-fix-for-amd-custom-apu-0405.patch x86-linkage-fix-typo-of-build_vdso-in-asm-linkage.h.patch x86-mm-fix-vdso-and-vvar-placement-on-5-level-paging-machines.patch x86-move-gds_ucode_mitigated-declaration-to-header.patch x86-sev-do-not-try-to-parse-for-the-cc-blob-on-non-amd-hardware.patch x86-speculation-add-cpu_show_gds-prototype.patch x86-srso-fix-build-breakage-with-the-llvm-linker.patch x86-vdso-choose-the-right-gdt_entry_cpunode-for-32-bit-getcpu-on-64-bit-kernel.patch --- diff --git a/queue-6.4/binder-fix-memory-leak-in-binder_init.patch b/queue-6.4/binder-fix-memory-leak-in-binder_init.patch new file mode 100644 index 00000000000..b76191e4e7e --- /dev/null +++ b/queue-6.4/binder-fix-memory-leak-in-binder_init.patch @@ -0,0 +1,61 @@ +From adb9743d6a08778b78d62d16b4230346d3508986 Mon Sep 17 00:00:00 2001 +From: Qi Zheng +Date: Sun, 25 Jun 2023 15:49:37 +0000 +Subject: binder: fix memory leak in binder_init() + +From: Qi Zheng + +commit adb9743d6a08778b78d62d16b4230346d3508986 upstream. + +In binder_init(), the destruction of binder_alloc_shrinker_init() is not +performed in the wrong path, which will cause memory leaks. So this commit +introduces binder_alloc_shrinker_exit() and calls it in the wrong path to +fix that. + +Signed-off-by: Qi Zheng +Acked-by: Carlos Llamas +Fixes: f2517eb76f1f ("android: binder: Add global lru shrinker to binder") +Cc: stable +Link: https://lore.kernel.org/r/20230625154937.64316-1-qi.zheng@linux.dev +Signed-off-by: Greg Kroah-Hartman +--- + drivers/android/binder.c | 1 + + drivers/android/binder_alloc.c | 6 ++++++ + drivers/android/binder_alloc.h | 1 + + 3 files changed, 8 insertions(+) + +--- a/drivers/android/binder.c ++++ b/drivers/android/binder.c +@@ -6610,6 +6610,7 @@ err_init_binder_device_failed: + + err_alloc_device_names_failed: + debugfs_remove_recursive(binder_debugfs_dir_entry_root); ++ binder_alloc_shrinker_exit(); + + return ret; + } +--- a/drivers/android/binder_alloc.c ++++ b/drivers/android/binder_alloc.c +@@ -1087,6 +1087,12 @@ int binder_alloc_shrinker_init(void) + return ret; + } + ++void binder_alloc_shrinker_exit(void) ++{ ++ unregister_shrinker(&binder_shrinker); ++ list_lru_destroy(&binder_alloc_lru); ++} ++ + /** + * check_buffer() - verify that buffer/offset is safe to access + * @alloc: binder_alloc for this proc +--- a/drivers/android/binder_alloc.h ++++ b/drivers/android/binder_alloc.h +@@ -129,6 +129,7 @@ extern struct binder_buffer *binder_allo + int pid); + extern void binder_alloc_init(struct binder_alloc *alloc); + extern int binder_alloc_shrinker_init(void); ++extern void binder_alloc_shrinker_exit(void); + extern void binder_alloc_vma_close(struct binder_alloc *alloc); + extern struct binder_buffer * + binder_alloc_prepare_to_free(struct binder_alloc *alloc, diff --git a/queue-6.4/drm-nouveau-disp-revert-a-null-check-inside-nouveau_connector_get_modes.patch b/queue-6.4/drm-nouveau-disp-revert-a-null-check-inside-nouveau_connector_get_modes.patch new file mode 100644 index 00000000000..7bd71855cf0 --- /dev/null +++ b/queue-6.4/drm-nouveau-disp-revert-a-null-check-inside-nouveau_connector_get_modes.patch @@ -0,0 +1,40 @@ +From d5712cd22b9cf109fded1b7f178f4c1888c8b84b Mon Sep 17 00:00:00 2001 +From: Karol Herbst +Date: Sat, 5 Aug 2023 12:18:13 +0200 +Subject: drm/nouveau/disp: Revert a NULL check inside nouveau_connector_get_modes + +From: Karol Herbst + +commit d5712cd22b9cf109fded1b7f178f4c1888c8b84b upstream. + +The original commit adding that check tried to protect the kenrel against +a potential invalid NULL pointer access. + +However we call nouveau_connector_detect_depth once without a native_mode +set on purpose for non LVDS connectors and this broke DP support in a few +cases. + +Cc: Olaf Skibbe +Cc: Lyude Paul +Closes: https://gitlab.freedesktop.org/drm/nouveau/-/issues/238 +Closes: https://gitlab.freedesktop.org/drm/nouveau/-/issues/245 +Fixes: 20a2ce87fbaf8 ("drm/nouveau/dp: check for NULL nv_connector->native_mode") +Signed-off-by: Karol Herbst +Reviewed-by: Lyude Paul +Link: https://patchwork.freedesktop.org/patch/msgid/20230805101813.2603989-1-kherbst@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/nouveau/nouveau_connector.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/nouveau/nouveau_connector.c ++++ b/drivers/gpu/drm/nouveau/nouveau_connector.c +@@ -967,7 +967,7 @@ nouveau_connector_get_modes(struct drm_c + /* Determine display colour depth for everything except LVDS now, + * DP requires this before mode_valid() is called. + */ +- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && nv_connector->native_mode) ++ if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) + nouveau_connector_detect_depth(connector); + + /* Find the native mode if this is a digital panel, if we didn't diff --git a/queue-6.4/iio-adc-ad7192-fix-ac-excitation-feature.patch b/queue-6.4/iio-adc-ad7192-fix-ac-excitation-feature.patch new file mode 100644 index 00000000000..da026fdfa39 --- /dev/null +++ b/queue-6.4/iio-adc-ad7192-fix-ac-excitation-feature.patch @@ -0,0 +1,98 @@ +From 6bc471b6c3aeaa7b95d1b86a1bb8d91a3c341fa5 Mon Sep 17 00:00:00 2001 +From: Alisa Roman +Date: Wed, 14 Jun 2023 18:52:43 +0300 +Subject: iio: adc: ad7192: Fix ac excitation feature + +From: Alisa Roman + +commit 6bc471b6c3aeaa7b95d1b86a1bb8d91a3c341fa5 upstream. + +AC excitation enable feature exposed to user on AD7192, allowing a bit +which should be 0 to be set. This feature is specific only to AD7195. AC +excitation attribute moved accordingly. + +In the AD7195 documentation, the AC excitation enable bit is on position +22 in the Configuration register. ACX macro changed to match correct +register and bit. + +Note that the fix tag is for the commit that moved the driver out of +staging. + +Fixes: b581f748cce0 ("staging: iio: adc: ad7192: move out of staging") +Signed-off-by: Alisa Roman +Cc: stable@vger.kernel.org +Reviewed-by: Nuno Sa +Link: https://lore.kernel.org/r/20230614155242.160296-1-alisa.roman@analog.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/adc/ad7192.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/drivers/iio/adc/ad7192.c ++++ b/drivers/iio/adc/ad7192.c +@@ -62,7 +62,6 @@ + #define AD7192_MODE_STA_MASK BIT(20) /* Status Register transmission Mask */ + #define AD7192_MODE_CLKSRC(x) (((x) & 0x3) << 18) /* Clock Source Select */ + #define AD7192_MODE_SINC3 BIT(15) /* SINC3 Filter Select */ +-#define AD7192_MODE_ACX BIT(14) /* AC excitation enable(AD7195 only)*/ + #define AD7192_MODE_ENPAR BIT(13) /* Parity Enable */ + #define AD7192_MODE_CLKDIV BIT(12) /* Clock divide by 2 (AD7190/2 only)*/ + #define AD7192_MODE_SCYCLE BIT(11) /* Single cycle conversion */ +@@ -91,6 +90,7 @@ + /* Configuration Register Bit Designations (AD7192_REG_CONF) */ + + #define AD7192_CONF_CHOP BIT(23) /* CHOP enable */ ++#define AD7192_CONF_ACX BIT(22) /* AC excitation enable(AD7195 only) */ + #define AD7192_CONF_REFSEL BIT(20) /* REFIN1/REFIN2 Reference Select */ + #define AD7192_CONF_CHAN(x) ((x) << 8) /* Channel select */ + #define AD7192_CONF_CHAN_MASK (0x7FF << 8) /* Channel select mask */ +@@ -472,7 +472,7 @@ static ssize_t ad7192_show_ac_excitation + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + struct ad7192_state *st = iio_priv(indio_dev); + +- return sysfs_emit(buf, "%d\n", !!(st->mode & AD7192_MODE_ACX)); ++ return sysfs_emit(buf, "%d\n", !!(st->conf & AD7192_CONF_ACX)); + } + + static ssize_t ad7192_show_bridge_switch(struct device *dev, +@@ -513,13 +513,13 @@ static ssize_t ad7192_set(struct device + + ad_sd_write_reg(&st->sd, AD7192_REG_GPOCON, 1, st->gpocon); + break; +- case AD7192_REG_MODE: ++ case AD7192_REG_CONF: + if (val) +- st->mode |= AD7192_MODE_ACX; ++ st->conf |= AD7192_CONF_ACX; + else +- st->mode &= ~AD7192_MODE_ACX; ++ st->conf &= ~AD7192_CONF_ACX; + +- ad_sd_write_reg(&st->sd, AD7192_REG_MODE, 3, st->mode); ++ ad_sd_write_reg(&st->sd, AD7192_REG_CONF, 3, st->conf); + break; + default: + ret = -EINVAL; +@@ -579,12 +579,11 @@ static IIO_DEVICE_ATTR(bridge_switch_en, + + static IIO_DEVICE_ATTR(ac_excitation_en, 0644, + ad7192_show_ac_excitation, ad7192_set, +- AD7192_REG_MODE); ++ AD7192_REG_CONF); + + static struct attribute *ad7192_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, + &iio_dev_attr_bridge_switch_en.dev_attr.attr, +- &iio_dev_attr_ac_excitation_en.dev_attr.attr, + NULL + }; + +@@ -595,6 +594,7 @@ static const struct attribute_group ad71 + static struct attribute *ad7195_attributes[] = { + &iio_dev_attr_filter_low_pass_3db_frequency_available.dev_attr.attr, + &iio_dev_attr_bridge_switch_en.dev_attr.attr, ++ &iio_dev_attr_ac_excitation_en.dev_attr.attr, + NULL + }; + diff --git a/queue-6.4/iio-adc-ina2xx-avoid-null-pointer-dereference-on-of-device-match.patch b/queue-6.4/iio-adc-ina2xx-avoid-null-pointer-dereference-on-of-device-match.patch new file mode 100644 index 00000000000..33d5f54caa1 --- /dev/null +++ b/queue-6.4/iio-adc-ina2xx-avoid-null-pointer-dereference-on-of-device-match.patch @@ -0,0 +1,95 @@ +From a41e19cc0d6b6a445a4133170b90271e4a2553dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alvin=20=C5=A0ipraga?= +Date: Mon, 19 Jun 2023 16:12:39 +0200 +Subject: iio: adc: ina2xx: avoid NULL pointer dereference on OF device match +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alvin Šipraga + +commit a41e19cc0d6b6a445a4133170b90271e4a2553dc upstream. + +The affected lines were resulting in a NULL pointer dereference on our +platform because the device tree contained the following list of +compatible strings: + + power-sensor@40 { + compatible = "ti,ina232", "ti,ina231"; + ... + }; + +Since the driver doesn't declare a compatible string "ti,ina232", the OF +matching succeeds on "ti,ina231". But the I2C device ID info is +populated via the first compatible string, cf. modalias population in +of_i2c_get_board_info(). Since there is no "ina232" entry in the legacy +I2C device ID table either, the struct i2c_device_id *id pointer in the +probe function is NULL. + +Fix this by using the already populated type variable instead, which +points to the proper driver data. Since the name is also wanted, add a +generic one to the ina2xx_config table. + +Signed-off-by: Alvin Šipraga +Fixes: c43a102e67db ("iio: ina2xx: add support for TI INA2xx Power Monitors") +Link: https://lore.kernel.org/r/20230619141239.2257392-1-alvin@pqrs.dk +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/adc/ina2xx-adc.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/iio/adc/ina2xx-adc.c ++++ b/drivers/iio/adc/ina2xx-adc.c +@@ -124,6 +124,7 @@ static const struct regmap_config ina2xx + enum ina2xx_ids { ina219, ina226 }; + + struct ina2xx_config { ++ const char *name; + u16 config_default; + int calibration_value; + int shunt_voltage_lsb; /* nV */ +@@ -155,6 +156,7 @@ struct ina2xx_chip_info { + + static const struct ina2xx_config ina2xx_config[] = { + [ina219] = { ++ .name = "ina219", + .config_default = INA219_CONFIG_DEFAULT, + .calibration_value = 4096, + .shunt_voltage_lsb = 10000, +@@ -164,6 +166,7 @@ static const struct ina2xx_config ina2xx + .chip_id = ina219, + }, + [ina226] = { ++ .name = "ina226", + .config_default = INA226_CONFIG_DEFAULT, + .calibration_value = 2048, + .shunt_voltage_lsb = 2500, +@@ -996,7 +999,7 @@ static int ina2xx_probe(struct i2c_clien + /* Patch the current config register with default. */ + val = chip->config->config_default; + +- if (id->driver_data == ina226) { ++ if (type == ina226) { + ina226_set_average(chip, INA226_DEFAULT_AVG, &val); + ina226_set_int_time_vbus(chip, INA226_DEFAULT_IT, &val); + ina226_set_int_time_vshunt(chip, INA226_DEFAULT_IT, &val); +@@ -1015,7 +1018,7 @@ static int ina2xx_probe(struct i2c_clien + } + + indio_dev->modes = INDIO_DIRECT_MODE; +- if (id->driver_data == ina226) { ++ if (type == ina226) { + indio_dev->channels = ina226_channels; + indio_dev->num_channels = ARRAY_SIZE(ina226_channels); + indio_dev->info = &ina226_info; +@@ -1024,7 +1027,7 @@ static int ina2xx_probe(struct i2c_clien + indio_dev->num_channels = ARRAY_SIZE(ina219_channels); + indio_dev->info = &ina219_info; + } +- indio_dev->name = id->name; ++ indio_dev->name = id ? id->name : chip->config->name; + + ret = devm_iio_kfifo_buffer_setup(&client->dev, indio_dev, + &ina2xx_setup_ops); diff --git a/queue-6.4/iio-adc-meson-fix-core-clock-enable-disable-moment.patch b/queue-6.4/iio-adc-meson-fix-core-clock-enable-disable-moment.patch new file mode 100644 index 00000000000..560be92a8f6 --- /dev/null +++ b/queue-6.4/iio-adc-meson-fix-core-clock-enable-disable-moment.patch @@ -0,0 +1,93 @@ +From 09738ccbc4148c62d6c8c4644ff4a099d57f49ad Mon Sep 17 00:00:00 2001 +From: George Stark +Date: Fri, 21 Jul 2023 13:23:08 +0300 +Subject: iio: adc: meson: fix core clock enable/disable moment + +From: George Stark + +commit 09738ccbc4148c62d6c8c4644ff4a099d57f49ad upstream. + +Enable core clock at probe stage and disable it at remove stage. +Core clock is responsible for turning on/off the entire SoC module so +it should be on before the first module register is touched and be off +at very last moment. + +Fixes: 3adbf3427330 ("iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs") +Signed-off-by: George Stark +Link: https://lore.kernel.org/r/20230721102413.255726-2-gnstark@sberdevices.ru +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/adc/meson_saradc.c | 23 ++++++++++++----------- + 1 file changed, 12 insertions(+), 11 deletions(-) + +--- a/drivers/iio/adc/meson_saradc.c ++++ b/drivers/iio/adc/meson_saradc.c +@@ -916,12 +916,6 @@ static int meson_sar_adc_hw_enable(struc + goto err_vref; + } + +- ret = clk_prepare_enable(priv->core_clk); +- if (ret) { +- dev_err(dev, "failed to enable core clk\n"); +- goto err_core_clk; +- } +- + regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, + MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); +@@ -948,8 +942,6 @@ err_adc_clk: + regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, + MESON_SAR_ADC_REG3_ADC_EN, 0); + meson_sar_adc_set_bandgap(indio_dev, false); +- clk_disable_unprepare(priv->core_clk); +-err_core_clk: + regulator_disable(priv->vref); + err_vref: + meson_sar_adc_unlock(indio_dev); +@@ -977,8 +969,6 @@ static void meson_sar_adc_hw_disable(str + + meson_sar_adc_set_bandgap(indio_dev, false); + +- clk_disable_unprepare(priv->core_clk); +- + regulator_disable(priv->vref); + + if (!ret) +@@ -1211,7 +1201,7 @@ static int meson_sar_adc_probe(struct pl + if (IS_ERR(priv->clkin)) + return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n"); + +- priv->core_clk = devm_clk_get(dev, "core"); ++ priv->core_clk = devm_clk_get_enabled(dev, "core"); + if (IS_ERR(priv->core_clk)) + return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n"); + +@@ -1294,15 +1284,26 @@ static int meson_sar_adc_remove(struct p + static int meson_sar_adc_suspend(struct device *dev) + { + struct iio_dev *indio_dev = dev_get_drvdata(dev); ++ struct meson_sar_adc_priv *priv = iio_priv(indio_dev); + + meson_sar_adc_hw_disable(indio_dev); + ++ clk_disable_unprepare(priv->core_clk); ++ + return 0; + } + + static int meson_sar_adc_resume(struct device *dev) + { + struct iio_dev *indio_dev = dev_get_drvdata(dev); ++ struct meson_sar_adc_priv *priv = iio_priv(indio_dev); ++ int ret; ++ ++ ret = clk_prepare_enable(priv->core_clk); ++ if (ret) { ++ dev_err(dev, "failed to enable core clk\n"); ++ return ret; ++ } + + return meson_sar_adc_hw_enable(indio_dev); + } diff --git a/queue-6.4/iio-core-prevent-invalid-memory-access-when-there-is-no-parent.patch b/queue-6.4/iio-core-prevent-invalid-memory-access-when-there-is-no-parent.patch new file mode 100644 index 00000000000..6969931cb7d --- /dev/null +++ b/queue-6.4/iio-core-prevent-invalid-memory-access-when-there-is-no-parent.patch @@ -0,0 +1,62 @@ +From b2a69969908fcaf68596dfc04369af0fe2e1d2f7 Mon Sep 17 00:00:00 2001 +From: Milan Zamazal +Date: Wed, 19 Jul 2023 10:32:08 +0200 +Subject: iio: core: Prevent invalid memory access when there is no parent +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Milan Zamazal + +commit b2a69969908fcaf68596dfc04369af0fe2e1d2f7 upstream. + +Commit 813665564b3d ("iio: core: Convert to use firmware node handle +instead of OF node") switched the kind of nodes to use for label +retrieval in device registration. Probably an unwanted change in that +commit was that if the device has no parent then NULL pointer is +accessed. This is what happens in the stock IIO dummy driver when a +new entry is created in configfs: + + # mkdir /sys/kernel/config/iio/devices/dummy/foo + BUG: kernel NULL pointer dereference, address: ... + ... + Call Trace: + __iio_device_register + iio_dummy_probe + +Since there seems to be no reason to make a parent device of an IIO +dummy device mandatory, let’s prevent the invalid memory access in +__iio_device_register when the parent device is NULL. With this +change, the IIO dummy driver works fine with configfs. + +Fixes: 813665564b3d ("iio: core: Convert to use firmware node handle instead of OF node") +Reviewed-by: Andy Shevchenko +Signed-off-by: Milan Zamazal +Link: https://lore.kernel.org/r/20230719083208.88149-1-mzamazal@redhat.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/industrialio-core.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/iio/industrialio-core.c ++++ b/drivers/iio/industrialio-core.c +@@ -1888,7 +1888,7 @@ static const struct iio_buffer_setup_ops + int __iio_device_register(struct iio_dev *indio_dev, struct module *this_mod) + { + struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev); +- struct fwnode_handle *fwnode; ++ struct fwnode_handle *fwnode = NULL; + int ret; + + if (!indio_dev->info) +@@ -1899,7 +1899,8 @@ int __iio_device_register(struct iio_dev + /* If the calling driver did not initialize firmware node, do it here */ + if (dev_fwnode(&indio_dev->dev)) + fwnode = dev_fwnode(&indio_dev->dev); +- else ++ /* The default dummy IIO device has no parent */ ++ else if (indio_dev->dev.parent) + fwnode = dev_fwnode(indio_dev->dev.parent); + device_set_node(&indio_dev->dev, fwnode); + diff --git a/queue-6.4/iio-cros_ec-fix-the-allocation-size-for-cros_ec_command.patch b/queue-6.4/iio-cros_ec-fix-the-allocation-size-for-cros_ec_command.patch new file mode 100644 index 00000000000..1760e60cd90 --- /dev/null +++ b/queue-6.4/iio-cros_ec-fix-the-allocation-size-for-cros_ec_command.patch @@ -0,0 +1,35 @@ +From 8a4629055ef55177b5b63dab1ecce676bd8cccdd Mon Sep 17 00:00:00 2001 +From: Yiyuan Guo +Date: Fri, 30 Jun 2023 22:37:19 +0800 +Subject: iio: cros_ec: Fix the allocation size for cros_ec_command + +From: Yiyuan Guo + +commit 8a4629055ef55177b5b63dab1ecce676bd8cccdd upstream. + +The struct cros_ec_command contains several integer fields and a +trailing array. An allocation size neglecting the integer fields can +lead to buffer overrun. + +Reviewed-by: Tzung-Bi Shih +Signed-off-by: Yiyuan Guo +Fixes: 974e6f02e27e ("iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub.") +Link: https://lore.kernel.org/r/20230630143719.1513906-1-yguoaz@gmail.com +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c ++++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c +@@ -253,7 +253,7 @@ int cros_ec_sensors_core_init(struct pla + platform_set_drvdata(pdev, indio_dev); + + state->ec = ec->ec_dev; +- state->msg = devm_kzalloc(&pdev->dev, ++ state->msg = devm_kzalloc(&pdev->dev, sizeof(*state->msg) + + max((u16)sizeof(struct ec_params_motion_sense), + state->ec->max_response), GFP_KERNEL); + if (!state->msg) diff --git a/queue-6.4/iio-frequency-admv1013-propagate-errors-from-regulator_get_voltage.patch b/queue-6.4/iio-frequency-admv1013-propagate-errors-from-regulator_get_voltage.patch new file mode 100644 index 00000000000..25f5c0fb902 --- /dev/null +++ b/queue-6.4/iio-frequency-admv1013-propagate-errors-from-regulator_get_voltage.patch @@ -0,0 +1,44 @@ +From 507397d19b5a296aa339f7a1bd16284f668a1906 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Tue, 18 Jul 2023 10:02:18 +0300 +Subject: iio: frequency: admv1013: propagate errors from regulator_get_voltage() + +From: Dan Carpenter + +commit 507397d19b5a296aa339f7a1bd16284f668a1906 upstream. + +The regulator_get_voltage() function returns negative error codes. +This function saves it to an unsigned int and then does some range +checking and, since the error code falls outside the correct range, +it returns -EINVAL. + +Beyond the messiness, this is bad because the regulator_get_voltage() +function can return -EPROBE_DEFER and it's important to propagate that +back properly so it can be handled. + +Fixes: da35a7b526d9 ("iio: frequency: admv1013: add support for ADMV1013") +Signed-off-by: Dan Carpenter +Link: https://lore.kernel.org/r/ce75aac3-2aba-4435-8419-02e59fdd862b@moroto.mountain +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/frequency/admv1013.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/iio/frequency/admv1013.c ++++ b/drivers/iio/frequency/admv1013.c +@@ -344,9 +344,12 @@ static int admv1013_update_quad_filters( + + static int admv1013_update_mixer_vgate(struct admv1013_state *st) + { +- unsigned int vcm, mixer_vgate; ++ unsigned int mixer_vgate; ++ int vcm; + + vcm = regulator_get_voltage(st->reg); ++ if (vcm < 0) ++ return vcm; + + if (vcm < 1800000) + mixer_vgate = (2389 * vcm / 1000000 + 8100) / 100; diff --git a/queue-6.4/iio-imu-lsm6dsx-fix-mount-matrix-retrieval.patch b/queue-6.4/iio-imu-lsm6dsx-fix-mount-matrix-retrieval.patch new file mode 100644 index 00000000000..f0f5e05e8cf --- /dev/null +++ b/queue-6.4/iio-imu-lsm6dsx-fix-mount-matrix-retrieval.patch @@ -0,0 +1,39 @@ +From 6811694eb2f6b7a4e97be2029edc7dd6a39460f8 Mon Sep 17 00:00:00 2001 +From: Alejandro Tafalla +Date: Fri, 14 Jul 2023 17:31:26 +0200 +Subject: iio: imu: lsm6dsx: Fix mount matrix retrieval + +From: Alejandro Tafalla + +commit 6811694eb2f6b7a4e97be2029edc7dd6a39460f8 upstream. + +The function lsm6dsx_get_acpi_mount_matrix should return an error when ACPI +support is not enabled to allow executing iio_read_mount_matrix in the +probe function. + +Fixes: dc3d25f22b88 ("iio: imu: lsm6dsx: Add ACPI mount matrix retrieval") +Signed-off-by: Alejandro Tafalla +Acked-by: Lorenzo Bianconi +Link: https://lore.kernel.org/r/20230714153132.27265-1-atafalla@dnyon.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +index 6a18b363cf73..b6e6b1df8a61 100644 +--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c ++++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +@@ -2687,7 +2687,7 @@ static int lsm6dsx_get_acpi_mount_matrix(struct device *dev, + static int lsm6dsx_get_acpi_mount_matrix(struct device *dev, + struct iio_mount_matrix *orientation) + { +- return false; ++ return -EOPNOTSUPP; + } + + #endif +-- +2.41.0 + diff --git a/queue-6.4/iio-light-bu27034-fix-scale-format.patch b/queue-6.4/iio-light-bu27034-fix-scale-format.patch new file mode 100644 index 00000000000..2f0a3ddc95a --- /dev/null +++ b/queue-6.4/iio-light-bu27034-fix-scale-format.patch @@ -0,0 +1,90 @@ +From d47b9b84292706784482a661324bbc178153781f Mon Sep 17 00:00:00 2001 +From: Matti Vaittinen +Date: Tue, 13 Jun 2023 12:34:36 +0300 +Subject: iio: light: bu27034: Fix scale format + +From: Matti Vaittinen + +commit d47b9b84292706784482a661324bbc178153781f upstream. + +The driver is expecting accuracy of NANOs for intensity scale in +raw_write. The IIO core is however defaulting to MICROs. This leads the +raw-write of smallest scales to never succeed as correct selector(s) are +not found. + +Fix this by implementing the .write_raw_get_fmt callback to use NANO +accuracy for writes of IIO_CHAN_INFO_SCALE. + +Signed-off-by: Matti Vaittinen +Fixes: e52afbd61039 ("iio: light: ROHM BU27034 Ambient Light Sensor") +Link: https://lore.kernel.org/r/5369117315cf05b88cf0ccb87373fd77190f6ca2.1686648422.git.mazziesaccount@gmail.com +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman +--- + drivers/iio/light/rohm-bu27034.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c +index e63ef5789cde..bf3de853a811 100644 +--- a/drivers/iio/light/rohm-bu27034.c ++++ b/drivers/iio/light/rohm-bu27034.c +@@ -575,7 +575,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan, + return -EINVAL; + + if (chan == BU27034_CHAN_ALS) { +- if (val == 0 && val2 == 1000) ++ if (val == 0 && val2 == 1000000) + return 0; + + return -EINVAL; +@@ -587,7 +587,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan, + goto unlock_out; + + ret = iio_gts_find_gain_sel_for_scale_using_time(&data->gts, time_sel, +- val, val2 * 1000, &gain_sel); ++ val, val2, &gain_sel); + if (ret) { + /* + * Could not support scale with given time. Need to change time. +@@ -624,7 +624,7 @@ static int bu27034_set_scale(struct bu27034_data *data, int chan, + + /* Can we provide requested scale with this time? */ + ret = iio_gts_find_gain_sel_for_scale_using_time( +- &data->gts, new_time_sel, val, val2 * 1000, ++ &data->gts, new_time_sel, val, val2, + &gain_sel); + if (ret) + continue; +@@ -1217,6 +1217,21 @@ static int bu27034_read_raw(struct iio_dev *idev, + } + } + ++static int bu27034_write_raw_get_fmt(struct iio_dev *indio_dev, ++ struct iio_chan_spec const *chan, ++ long mask) ++{ ++ ++ switch (mask) { ++ case IIO_CHAN_INFO_SCALE: ++ return IIO_VAL_INT_PLUS_NANO; ++ case IIO_CHAN_INFO_INT_TIME: ++ return IIO_VAL_INT_PLUS_MICRO; ++ default: ++ return -EINVAL; ++ } ++} ++ + static int bu27034_write_raw(struct iio_dev *idev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +@@ -1267,6 +1282,7 @@ static int bu27034_read_avail(struct iio_dev *idev, + static const struct iio_info bu27034_info = { + .read_raw = &bu27034_read_raw, + .write_raw = &bu27034_write_raw, ++ .write_raw_get_fmt = &bu27034_write_raw_get_fmt, + .read_avail = &bu27034_read_avail, + }; + +-- +2.41.0 + diff --git a/queue-6.4/misc-rtsx-judge-aspm-mode-to-set-petxcfg-reg.patch b/queue-6.4/misc-rtsx-judge-aspm-mode-to-set-petxcfg-reg.patch new file mode 100644 index 00000000000..adb57657fa7 --- /dev/null +++ b/queue-6.4/misc-rtsx-judge-aspm-mode-to-set-petxcfg-reg.patch @@ -0,0 +1,182 @@ +From 101bd907b4244a726980ee67f95ed9cafab6ff7a Mon Sep 17 00:00:00 2001 +From: Ricky WU +Date: Tue, 25 Jul 2023 09:10:54 +0000 +Subject: misc: rtsx: judge ASPM Mode to set PETXCFG Reg + +From: Ricky WU + +commit 101bd907b4244a726980ee67f95ed9cafab6ff7a upstream. + +ASPM Mode is ASPM_MODE_CFG need to judge the value of clkreq_0 +to set HIGH or LOW, if the ASPM Mode is ASPM_MODE_REG +always set to HIGH during the initialization. + +Cc: stable@vger.kernel.org +Signed-off-by: Ricky Wu +Link: https://lore.kernel.org/r/52906c6836374c8cb068225954c5543a@realtek.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/misc/cardreader/rts5227.c | 2 +- + drivers/misc/cardreader/rts5228.c | 18 ------------------ + drivers/misc/cardreader/rts5249.c | 3 +-- + drivers/misc/cardreader/rts5260.c | 18 ------------------ + drivers/misc/cardreader/rts5261.c | 18 ------------------ + drivers/misc/cardreader/rtsx_pcr.c | 5 ++++- + 6 files changed, 6 insertions(+), 58 deletions(-) + +--- a/drivers/misc/cardreader/rts5227.c ++++ b/drivers/misc/cardreader/rts5227.c +@@ -195,7 +195,7 @@ static int rts5227_extra_init_hw(struct + } + } + +- if (option->force_clkreq_0) ++ if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG) + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); + else +--- a/drivers/misc/cardreader/rts5228.c ++++ b/drivers/misc/cardreader/rts5228.c +@@ -435,17 +435,10 @@ static void rts5228_init_from_cfg(struct + option->ltr_enabled = false; + } + } +- +- if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN +- | PM_L1_1_EN | PM_L1_2_EN)) +- option->force_clkreq_0 = false; +- else +- option->force_clkreq_0 = true; + } + + static int rts5228_extra_init_hw(struct rtsx_pcr *pcr) + { +- struct rtsx_cr_option *option = &pcr->option; + + rtsx_pci_write_register(pcr, RTS5228_AUTOLOAD_CFG1, + CD_RESUME_EN_MASK, CD_RESUME_EN_MASK); +@@ -476,17 +469,6 @@ static int rts5228_extra_init_hw(struct + else + rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); + +- /* +- * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced +- * to drive low, and we forcibly request clock. +- */ +- if (option->force_clkreq_0) +- rtsx_pci_write_register(pcr, PETXCFG, +- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); +- else +- rtsx_pci_write_register(pcr, PETXCFG, +- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); +- + rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); + + if (pcr->rtd3_en) { +--- a/drivers/misc/cardreader/rts5249.c ++++ b/drivers/misc/cardreader/rts5249.c +@@ -327,12 +327,11 @@ static int rts5249_extra_init_hw(struct + } + } + +- + /* + * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced + * to drive low, and we forcibly request clock. + */ +- if (option->force_clkreq_0) ++ if (option->force_clkreq_0 && pcr->aspm_mode == ASPM_MODE_CFG) + rtsx_pci_write_register(pcr, PETXCFG, + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); + else +--- a/drivers/misc/cardreader/rts5260.c ++++ b/drivers/misc/cardreader/rts5260.c +@@ -517,17 +517,10 @@ static void rts5260_init_from_cfg(struct + option->ltr_enabled = false; + } + } +- +- if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN +- | PM_L1_1_EN | PM_L1_2_EN)) +- option->force_clkreq_0 = false; +- else +- option->force_clkreq_0 = true; + } + + static int rts5260_extra_init_hw(struct rtsx_pcr *pcr) + { +- struct rtsx_cr_option *option = &pcr->option; + + /* Set mcu_cnt to 7 to ensure data can be sampled properly */ + rtsx_pci_write_register(pcr, 0xFC03, 0x7F, 0x07); +@@ -546,17 +539,6 @@ static int rts5260_extra_init_hw(struct + + rts5260_init_hw(pcr); + +- /* +- * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced +- * to drive low, and we forcibly request clock. +- */ +- if (option->force_clkreq_0) +- rtsx_pci_write_register(pcr, PETXCFG, +- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); +- else +- rtsx_pci_write_register(pcr, PETXCFG, +- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); +- + rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00); + + return 0; +--- a/drivers/misc/cardreader/rts5261.c ++++ b/drivers/misc/cardreader/rts5261.c +@@ -498,17 +498,10 @@ static void rts5261_init_from_cfg(struct + option->ltr_enabled = false; + } + } +- +- if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN +- | PM_L1_1_EN | PM_L1_2_EN)) +- option->force_clkreq_0 = false; +- else +- option->force_clkreq_0 = true; + } + + static int rts5261_extra_init_hw(struct rtsx_pcr *pcr) + { +- struct rtsx_cr_option *option = &pcr->option; + u32 val; + + rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1, +@@ -554,17 +547,6 @@ static int rts5261_extra_init_hw(struct + else + rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00); + +- /* +- * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced +- * to drive low, and we forcibly request clock. +- */ +- if (option->force_clkreq_0) +- rtsx_pci_write_register(pcr, PETXCFG, +- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); +- else +- rtsx_pci_write_register(pcr, PETXCFG, +- FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); +- + rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB); + + if (pcr->rtd3_en) { +--- a/drivers/misc/cardreader/rtsx_pcr.c ++++ b/drivers/misc/cardreader/rtsx_pcr.c +@@ -1326,8 +1326,11 @@ static int rtsx_pci_init_hw(struct rtsx_ + return err; + } + +- if (pcr->aspm_mode == ASPM_MODE_REG) ++ if (pcr->aspm_mode == ASPM_MODE_REG) { + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, 0x30, 0x30); ++ rtsx_pci_write_register(pcr, PETXCFG, ++ FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); ++ } + + /* No CD interrupt if probing driver with card inserted. + * So we need to initialize pcr->card_exist here. diff --git a/queue-6.4/netfilter-nf_tables-adapt-set-backend-to-use-gc-transaction-api.patch b/queue-6.4/netfilter-nf_tables-adapt-set-backend-to-use-gc-transaction-api.patch new file mode 100644 index 00000000000..e2729da0f9c --- /dev/null +++ b/queue-6.4/netfilter-nf_tables-adapt-set-backend-to-use-gc-transaction-api.patch @@ -0,0 +1,547 @@ +From f6c383b8c31a93752a52697f8430a71dcbc46adf Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Wed, 9 Aug 2023 14:54:23 +0200 +Subject: netfilter: nf_tables: adapt set backend to use GC transaction API + +From: Pablo Neira Ayuso + +commit f6c383b8c31a93752a52697f8430a71dcbc46adf upstream. + +Use the GC transaction API to replace the old and buggy gc API and the +busy mark approach. + +No set elements are removed from async garbage collection anymore, +instead the _DEAD bit is set on so the set element is not visible from +lookup path anymore. Async GC enqueues transaction work that might be +aborted and retried later. + +rbtree and pipapo set backends does not set on the _DEAD bit from the +sync GC path since this runs in control plane path where mutex is held. +In this case, set elements are deactivated, removed and then released +via RCU callback, sync GC never fails. + +Fixes: 3c4287f62044 ("nf_tables: Add set type for arbitrary concatenation of ranges") +Fixes: 8d8540c4f5e0 ("netfilter: nft_set_rbtree: add timeout support") +Fixes: 9d0982927e79 ("netfilter: nft_hash: add support for timeouts") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/nf_tables_api.c | 7 - + net/netfilter/nft_set_hash.c | 77 +++++++++++++-------- + net/netfilter/nft_set_pipapo.c | 48 ++++++++++--- + net/netfilter/nft_set_rbtree.c | 146 ++++++++++++++++++++++++----------------- + 4 files changed, 174 insertions(+), 104 deletions(-) + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -6357,7 +6357,6 @@ static void nft_setelem_activate(struct + + if (nft_setelem_is_catchall(set, elem)) { + nft_set_elem_change_active(net, set, ext); +- nft_set_elem_clear_busy(ext); + } else { + set->ops->activate(net, set, elem); + } +@@ -6372,8 +6371,7 @@ static int nft_setelem_catchall_deactiva + + list_for_each_entry(catchall, &set->catchall_list, list) { + ext = nft_set_elem_ext(set, catchall->elem); +- if (!nft_is_active(net, ext) || +- nft_set_elem_mark_busy(ext)) ++ if (!nft_is_active(net, ext)) + continue; + + kfree(elem->priv); +@@ -7083,8 +7081,7 @@ static int nft_set_catchall_flush(const + + list_for_each_entry_rcu(catchall, &set->catchall_list, list) { + ext = nft_set_elem_ext(set, catchall->elem); +- if (!nft_set_elem_active(ext, genmask) || +- nft_set_elem_mark_busy(ext)) ++ if (!nft_set_elem_active(ext, genmask)) + continue; + + elem.priv = catchall->elem; +--- a/net/netfilter/nft_set_hash.c ++++ b/net/netfilter/nft_set_hash.c +@@ -59,6 +59,8 @@ static inline int nft_rhash_cmp(struct r + + if (memcmp(nft_set_ext_key(&he->ext), x->key, x->set->klen)) + return 1; ++ if (nft_set_elem_is_dead(&he->ext)) ++ return 1; + if (nft_set_elem_expired(&he->ext)) + return 1; + if (!nft_set_elem_active(&he->ext, x->genmask)) +@@ -188,7 +190,6 @@ static void nft_rhash_activate(const str + struct nft_rhash_elem *he = elem->priv; + + nft_set_elem_change_active(net, set, &he->ext); +- nft_set_elem_clear_busy(&he->ext); + } + + static bool nft_rhash_flush(const struct net *net, +@@ -196,12 +197,9 @@ static bool nft_rhash_flush(const struct + { + struct nft_rhash_elem *he = priv; + +- if (!nft_set_elem_mark_busy(&he->ext) || +- !nft_is_active(net, &he->ext)) { +- nft_set_elem_change_active(net, set, &he->ext); +- return true; +- } +- return false; ++ nft_set_elem_change_active(net, set, &he->ext); ++ ++ return true; + } + + static void *nft_rhash_deactivate(const struct net *net, +@@ -218,9 +216,8 @@ static void *nft_rhash_deactivate(const + + rcu_read_lock(); + he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params); +- if (he != NULL && +- !nft_rhash_flush(net, set, he)) +- he = NULL; ++ if (he) ++ nft_set_elem_change_active(net, set, &he->ext); + + rcu_read_unlock(); + +@@ -312,25 +309,48 @@ static bool nft_rhash_expr_needs_gc_run( + + static void nft_rhash_gc(struct work_struct *work) + { ++ struct nftables_pernet *nft_net; + struct nft_set *set; + struct nft_rhash_elem *he; + struct nft_rhash *priv; +- struct nft_set_gc_batch *gcb = NULL; + struct rhashtable_iter hti; ++ struct nft_trans_gc *gc; ++ struct net *net; ++ u32 gc_seq; + + priv = container_of(work, struct nft_rhash, gc_work.work); + set = nft_set_container_of(priv); ++ net = read_pnet(&set->net); ++ nft_net = nft_pernet(net); ++ gc_seq = READ_ONCE(nft_net->gc_seq); ++ ++ gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL); ++ if (!gc) ++ goto done; + + rhashtable_walk_enter(&priv->ht, &hti); + rhashtable_walk_start(&hti); + + while ((he = rhashtable_walk_next(&hti))) { + if (IS_ERR(he)) { +- if (PTR_ERR(he) != -EAGAIN) +- break; ++ if (PTR_ERR(he) != -EAGAIN) { ++ nft_trans_gc_destroy(gc); ++ gc = NULL; ++ goto try_later; ++ } + continue; + } + ++ /* Ruleset has been updated, try later. */ ++ if (READ_ONCE(nft_net->gc_seq) != gc_seq) { ++ nft_trans_gc_destroy(gc); ++ gc = NULL; ++ goto try_later; ++ } ++ ++ if (nft_set_elem_is_dead(&he->ext)) ++ goto dead_elem; ++ + if (nft_set_ext_exists(&he->ext, NFT_SET_EXT_EXPRESSIONS) && + nft_rhash_expr_needs_gc_run(set, &he->ext)) + goto needs_gc_run; +@@ -338,26 +358,26 @@ static void nft_rhash_gc(struct work_str + if (!nft_set_elem_expired(&he->ext)) + continue; + needs_gc_run: +- if (nft_set_elem_mark_busy(&he->ext)) +- continue; ++ nft_set_elem_dead(&he->ext); ++dead_elem: ++ gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); ++ if (!gc) ++ goto try_later; + +- gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); +- if (gcb == NULL) +- break; +- rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params); +- atomic_dec(&set->nelems); +- nft_set_gc_batch_add(gcb, he); ++ nft_trans_gc_elem_add(gc, he); + } ++ ++ gc = nft_trans_gc_catchall(gc, gc_seq); ++ ++try_later: ++ /* catchall list iteration requires rcu read side lock. */ + rhashtable_walk_stop(&hti); + rhashtable_walk_exit(&hti); + +- he = nft_set_catchall_gc(set); +- if (he) { +- gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); +- if (gcb) +- nft_set_gc_batch_add(gcb, he); +- } +- nft_set_gc_batch_complete(gcb); ++ if (gc) ++ nft_trans_gc_queue_async_done(gc); ++ ++done: + queue_delayed_work(system_power_efficient_wq, &priv->gc_work, + nft_set_gc_interval(set)); + } +@@ -420,7 +440,6 @@ static void nft_rhash_destroy(const stru + }; + + cancel_delayed_work_sync(&priv->gc_work); +- rcu_barrier(); + rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy, + (void *)&rhash_ctx); + } +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -1537,16 +1537,34 @@ static void pipapo_drop(struct nft_pipap + } + } + ++static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set, ++ struct nft_pipapo_elem *e) ++ ++{ ++ struct nft_set_elem elem = { ++ .priv = e, ++ }; ++ ++ nft_setelem_data_deactivate(net, set, &elem); ++} ++ + /** + * pipapo_gc() - Drop expired entries from set, destroy start and end elements + * @set: nftables API set representation + * @m: Matching data + */ +-static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m) ++static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m) + { ++ struct nft_set *set = (struct nft_set *) _set; + struct nft_pipapo *priv = nft_set_priv(set); ++ struct net *net = read_pnet(&set->net); + int rules_f0, first_rule = 0; + struct nft_pipapo_elem *e; ++ struct nft_trans_gc *gc; ++ ++ gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL); ++ if (!gc) ++ return; + + while ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) { + union nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS]; +@@ -1570,13 +1588,20 @@ static void pipapo_gc(const struct nft_s + f--; + i--; + e = f->mt[rulemap[i].to].e; +- if (nft_set_elem_expired(&e->ext) && +- !nft_set_elem_mark_busy(&e->ext)) { ++ ++ /* synchronous gc never fails, there is no need to set on ++ * NFT_SET_ELEM_DEAD_BIT. ++ */ ++ if (nft_set_elem_expired(&e->ext)) { + priv->dirty = true; +- pipapo_drop(m, rulemap); + +- rcu_barrier(); +- nft_set_elem_destroy(set, e, true); ++ gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); ++ if (!gc) ++ break; ++ ++ nft_pipapo_gc_deactivate(net, set, e); ++ pipapo_drop(m, rulemap); ++ nft_trans_gc_elem_add(gc, e); + + /* And check again current first rule, which is now the + * first we haven't checked. +@@ -1586,11 +1611,11 @@ static void pipapo_gc(const struct nft_s + } + } + +- e = nft_set_catchall_gc(set); +- if (e) +- nft_set_elem_destroy(set, e, true); +- +- priv->last_gc = jiffies; ++ gc = nft_trans_gc_catchall(gc, 0); ++ if (gc) { ++ nft_trans_gc_queue_sync_done(gc); ++ priv->last_gc = jiffies; ++ } + } + + /** +@@ -1715,7 +1740,6 @@ static void nft_pipapo_activate(const st + return; + + nft_set_elem_change_active(net, set, &e->ext); +- nft_set_elem_clear_busy(&e->ext); + } + + /** +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -46,6 +46,12 @@ static int nft_rbtree_cmp(const struct n + set->klen); + } + ++static bool nft_rbtree_elem_expired(const struct nft_rbtree_elem *rbe) ++{ ++ return nft_set_elem_expired(&rbe->ext) || ++ nft_set_elem_is_dead(&rbe->ext); ++} ++ + static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set, + const u32 *key, const struct nft_set_ext **ext, + unsigned int seq) +@@ -80,7 +86,7 @@ static bool __nft_rbtree_lookup(const st + continue; + } + +- if (nft_set_elem_expired(&rbe->ext)) ++ if (nft_rbtree_elem_expired(rbe)) + return false; + + if (nft_rbtree_interval_end(rbe)) { +@@ -98,7 +104,7 @@ static bool __nft_rbtree_lookup(const st + + if (set->flags & NFT_SET_INTERVAL && interval != NULL && + nft_set_elem_active(&interval->ext, genmask) && +- !nft_set_elem_expired(&interval->ext) && ++ !nft_rbtree_elem_expired(interval) && + nft_rbtree_interval_start(interval)) { + *ext = &interval->ext; + return true; +@@ -215,6 +221,18 @@ static void *nft_rbtree_get(const struct + return rbe; + } + ++static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, ++ struct nft_rbtree *priv, ++ struct nft_rbtree_elem *rbe) ++{ ++ struct nft_set_elem elem = { ++ .priv = rbe, ++ }; ++ ++ nft_setelem_data_deactivate(net, set, &elem); ++ rb_erase(&rbe->node, &priv->root); ++} ++ + static int nft_rbtree_gc_elem(const struct nft_set *__set, + struct nft_rbtree *priv, + struct nft_rbtree_elem *rbe, +@@ -222,11 +240,12 @@ static int nft_rbtree_gc_elem(const stru + { + struct nft_set *set = (struct nft_set *)__set; + struct rb_node *prev = rb_prev(&rbe->node); ++ struct net *net = read_pnet(&set->net); + struct nft_rbtree_elem *rbe_prev; +- struct nft_set_gc_batch *gcb; ++ struct nft_trans_gc *gc; + +- gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC); +- if (!gcb) ++ gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); ++ if (!gc) + return -ENOMEM; + + /* search for end interval coming before this element. +@@ -244,17 +263,28 @@ static int nft_rbtree_gc_elem(const stru + + if (prev) { + rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); ++ nft_rbtree_gc_remove(net, set, priv, rbe_prev); + +- rb_erase(&rbe_prev->node, &priv->root); +- atomic_dec(&set->nelems); +- nft_set_gc_batch_add(gcb, rbe_prev); ++ /* There is always room in this trans gc for this element, ++ * memory allocation never actually happens, hence, the warning ++ * splat in such case. No need to set NFT_SET_ELEM_DEAD_BIT, ++ * this is synchronous gc which never fails. ++ */ ++ gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); ++ if (WARN_ON_ONCE(!gc)) ++ return -ENOMEM; ++ ++ nft_trans_gc_elem_add(gc, rbe_prev); + } + +- rb_erase(&rbe->node, &priv->root); +- atomic_dec(&set->nelems); ++ nft_rbtree_gc_remove(net, set, priv, rbe); ++ gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); ++ if (WARN_ON_ONCE(!gc)) ++ return -ENOMEM; + +- nft_set_gc_batch_add(gcb, rbe); +- nft_set_gc_batch_complete(gcb); ++ nft_trans_gc_elem_add(gc, rbe); ++ ++ nft_trans_gc_queue_sync_done(gc); + + return 0; + } +@@ -482,7 +512,6 @@ static void nft_rbtree_activate(const st + struct nft_rbtree_elem *rbe = elem->priv; + + nft_set_elem_change_active(net, set, &rbe->ext); +- nft_set_elem_clear_busy(&rbe->ext); + } + + static bool nft_rbtree_flush(const struct net *net, +@@ -490,12 +519,9 @@ static bool nft_rbtree_flush(const struc + { + struct nft_rbtree_elem *rbe = priv; + +- if (!nft_set_elem_mark_busy(&rbe->ext) || +- !nft_is_active(net, &rbe->ext)) { +- nft_set_elem_change_active(net, set, &rbe->ext); +- return true; +- } +- return false; ++ nft_set_elem_change_active(net, set, &rbe->ext); ++ ++ return true; + } + + static void *nft_rbtree_deactivate(const struct net *net, +@@ -570,26 +596,40 @@ cont: + + static void nft_rbtree_gc(struct work_struct *work) + { +- struct nft_rbtree_elem *rbe, *rbe_end = NULL, *rbe_prev = NULL; +- struct nft_set_gc_batch *gcb = NULL; ++ struct nft_rbtree_elem *rbe, *rbe_end = NULL; ++ struct nftables_pernet *nft_net; + struct nft_rbtree *priv; ++ struct nft_trans_gc *gc; + struct rb_node *node; + struct nft_set *set; ++ unsigned int gc_seq; + struct net *net; +- u8 genmask; + + priv = container_of(work, struct nft_rbtree, gc_work.work); + set = nft_set_container_of(priv); + net = read_pnet(&set->net); +- genmask = nft_genmask_cur(net); ++ nft_net = nft_pernet(net); ++ gc_seq = READ_ONCE(nft_net->gc_seq); ++ ++ gc = nft_trans_gc_alloc(set, gc_seq, GFP_KERNEL); ++ if (!gc) ++ goto done; + + write_lock_bh(&priv->lock); + write_seqcount_begin(&priv->count); + for (node = rb_first(&priv->root); node != NULL; node = rb_next(node)) { ++ ++ /* Ruleset has been updated, try later. */ ++ if (READ_ONCE(nft_net->gc_seq) != gc_seq) { ++ nft_trans_gc_destroy(gc); ++ gc = NULL; ++ goto try_later; ++ } ++ + rbe = rb_entry(node, struct nft_rbtree_elem, node); + +- if (!nft_set_elem_active(&rbe->ext, genmask)) +- continue; ++ if (nft_set_elem_is_dead(&rbe->ext)) ++ goto dead_elem; + + /* elements are reversed in the rbtree for historical reasons, + * from highest to lowest value, that is why end element is +@@ -602,46 +642,36 @@ static void nft_rbtree_gc(struct work_st + if (!nft_set_elem_expired(&rbe->ext)) + continue; + +- if (nft_set_elem_mark_busy(&rbe->ext)) { +- rbe_end = NULL; ++ nft_set_elem_dead(&rbe->ext); ++ ++ if (!rbe_end) + continue; +- } + +- if (rbe_prev) { +- rb_erase(&rbe_prev->node, &priv->root); +- rbe_prev = NULL; +- } +- gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); +- if (!gcb) +- break; ++ nft_set_elem_dead(&rbe_end->ext); + +- atomic_dec(&set->nelems); +- nft_set_gc_batch_add(gcb, rbe); +- rbe_prev = rbe; +- +- if (rbe_end) { +- atomic_dec(&set->nelems); +- nft_set_gc_batch_add(gcb, rbe_end); +- rb_erase(&rbe_end->node, &priv->root); +- rbe_end = NULL; +- } +- node = rb_next(node); +- if (!node) +- break; ++ gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); ++ if (!gc) ++ goto try_later; ++ ++ nft_trans_gc_elem_add(gc, rbe_end); ++ rbe_end = NULL; ++dead_elem: ++ gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); ++ if (!gc) ++ goto try_later; ++ ++ nft_trans_gc_elem_add(gc, rbe); + } +- if (rbe_prev) +- rb_erase(&rbe_prev->node, &priv->root); ++ ++ gc = nft_trans_gc_catchall(gc, gc_seq); ++ ++try_later: + write_seqcount_end(&priv->count); + write_unlock_bh(&priv->lock); + +- rbe = nft_set_catchall_gc(set); +- if (rbe) { +- gcb = nft_set_gc_batch_check(set, gcb, GFP_ATOMIC); +- if (gcb) +- nft_set_gc_batch_add(gcb, rbe); +- } +- nft_set_gc_batch_complete(gcb); +- ++ if (gc) ++ nft_trans_gc_queue_async_done(gc); ++done: + queue_delayed_work(system_power_efficient_wq, &priv->gc_work, + nft_set_gc_interval(set)); + } diff --git a/queue-6.4/netfilter-nf_tables-don-t-skip-expired-elements-during-walk.patch b/queue-6.4/netfilter-nf_tables-don-t-skip-expired-elements-during-walk.patch new file mode 100644 index 00000000000..a05ea6ef67b --- /dev/null +++ b/queue-6.4/netfilter-nf_tables-don-t-skip-expired-elements-during-walk.patch @@ -0,0 +1,129 @@ +From 24138933b97b055d486e8064b4a1721702442a9b Mon Sep 17 00:00:00 2001 +From: Florian Westphal +Date: Wed, 9 Aug 2023 14:31:15 +0200 +Subject: netfilter: nf_tables: don't skip expired elements during walk + +From: Florian Westphal + +commit 24138933b97b055d486e8064b4a1721702442a9b upstream. + +There is an asymmetry between commit/abort and preparation phase if the +following conditions are met: + +1. set is a verdict map ("1.2.3.4 : jump foo") +2. timeouts are enabled + +In this case, following sequence is problematic: + +1. element E in set S refers to chain C +2. userspace requests removal of set S +3. kernel does a set walk to decrement chain->use count for all elements + from preparation phase +4. kernel does another set walk to remove elements from the commit phase + (or another walk to do a chain->use increment for all elements from + abort phase) + +If E has already expired in 1), it will be ignored during list walk, so its use count +won't have been changed. + +Then, when set is culled, ->destroy callback will zap the element via +nf_tables_set_elem_destroy(), but this function is only safe for +elements that have been deactivated earlier from the preparation phase: +lack of earlier deactivate removes the element but leaks the chain use +count, which results in a WARN splat when the chain gets removed later, +plus a leak of the nft_chain structure. + +Update pipapo_get() not to skip expired elements, otherwise flush +command reports bogus ENOENT errors. + +Fixes: 3c4287f62044 ("nf_tables: Add set type for arbitrary concatenation of ranges") +Fixes: 8d8540c4f5e0 ("netfilter: nft_set_rbtree: add timeout support") +Fixes: 9d0982927e79 ("netfilter: nft_hash: add support for timeouts") +Signed-off-by: Florian Westphal +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/nf_tables_api.c | 4 ++++ + net/netfilter/nft_set_hash.c | 2 -- + net/netfilter/nft_set_pipapo.c | 18 ++++++++++++------ + net/netfilter/nft_set_rbtree.c | 2 -- + 4 files changed, 16 insertions(+), 10 deletions(-) + +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -5590,8 +5590,12 @@ static int nf_tables_dump_setelem(const + const struct nft_set_iter *iter, + struct nft_set_elem *elem) + { ++ const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); + struct nft_set_dump_args *args; + ++ if (nft_set_elem_expired(ext)) ++ return 0; ++ + args = container_of(iter, struct nft_set_dump_args, iter); + return nf_tables_fill_setelem(args->skb, set, elem); + } +--- a/net/netfilter/nft_set_hash.c ++++ b/net/netfilter/nft_set_hash.c +@@ -278,8 +278,6 @@ static void nft_rhash_walk(const struct + + if (iter->count < iter->skip) + goto cont; +- if (nft_set_elem_expired(&he->ext)) +- goto cont; + if (!nft_set_elem_active(&he->ext, iter->genmask)) + goto cont; + +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -566,8 +566,7 @@ next_match: + goto out; + + if (last) { +- if (nft_set_elem_expired(&f->mt[b].e->ext) || +- (genmask && ++ if ((genmask && + !nft_set_elem_active(&f->mt[b].e->ext, genmask))) + goto next_match; + +@@ -601,8 +600,17 @@ out: + static void *nft_pipapo_get(const struct net *net, const struct nft_set *set, + const struct nft_set_elem *elem, unsigned int flags) + { +- return pipapo_get(net, set, (const u8 *)elem->key.val.data, +- nft_genmask_cur(net)); ++ struct nft_pipapo_elem *ret; ++ ++ ret = pipapo_get(net, set, (const u8 *)elem->key.val.data, ++ nft_genmask_cur(net)); ++ if (IS_ERR(ret)) ++ return ret; ++ ++ if (nft_set_elem_expired(&ret->ext)) ++ return ERR_PTR(-ENOENT); ++ ++ return ret; + } + + /** +@@ -2006,8 +2014,6 @@ static void nft_pipapo_walk(const struct + goto cont; + + e = f->mt[r].e; +- if (nft_set_elem_expired(&e->ext)) +- goto cont; + + elem.priv = e; + +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -552,8 +552,6 @@ static void nft_rbtree_walk(const struct + + if (iter->count < iter->skip) + goto cont; +- if (nft_set_elem_expired(&rbe->ext)) +- goto cont; + if (!nft_set_elem_active(&rbe->ext, iter->genmask)) + goto cont; + diff --git a/queue-6.4/netfilter-nf_tables-gc-transaction-api-to-avoid-race-with-control-plane.patch b/queue-6.4/netfilter-nf_tables-gc-transaction-api-to-avoid-race-with-control-plane.patch new file mode 100644 index 00000000000..51973afbdab --- /dev/null +++ b/queue-6.4/netfilter-nf_tables-gc-transaction-api-to-avoid-race-with-control-plane.patch @@ -0,0 +1,566 @@ +From 5f68718b34a531a556f2f50300ead2862278da26 Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Wed, 9 Aug 2023 14:31:54 +0200 +Subject: netfilter: nf_tables: GC transaction API to avoid race with control plane + +From: Pablo Neira Ayuso + +commit 5f68718b34a531a556f2f50300ead2862278da26 upstream. + +The set types rhashtable and rbtree use a GC worker to reclaim memory. +From system work queue, in periodic intervals, a scan of the table is +done. + +The major caveat here is that the nft transaction mutex is not held. +This causes a race between control plane and GC when they attempt to +delete the same element. + +We cannot grab the netlink mutex from the work queue, because the +control plane has to wait for the GC work queue in case the set is to be +removed, so we get following deadlock: + + cpu 1 cpu2 + GC work transaction comes in , lock nft mutex + `acquire nft mutex // BLOCKS + transaction asks to remove the set + set destruction calls cancel_work_sync() + +cancel_work_sync will now block forever, because it is waiting for the +mutex the caller already owns. + +This patch adds a new API that deals with garbage collection in two +steps: + +1) Lockless GC of expired elements sets on the NFT_SET_ELEM_DEAD_BIT + so they are not visible via lookup. Annotate current GC sequence in + the GC transaction. Enqueue GC transaction work as soon as it is + full. If ruleset is updated, then GC transaction is aborted and + retried later. + +2) GC work grabs the mutex. If GC sequence has changed then this GC + transaction lost race with control plane, abort it as it contains + stale references to objects and let GC try again later. If the + ruleset is intact, then this GC transaction deactivates and removes + the elements and it uses call_rcu() to destroy elements. + +Note that no elements are removed from GC lockless path, the _DEAD bit +is set and pointers are collected. GC catchall does not remove the +elements anymore too. There is a new set->dead flag that is set on to +abort the GC transaction to deal with set->ops->destroy() path which +removes the remaining elements in the set from commit_release, where no +mutex is held. + +To deal with GC when mutex is held, which allows safe deactivate and +removal, add sync GC API which releases the set element object via +call_rcu(). This is used by rbtree and pipapo backends which also +perform garbage collection from control plane path. + +Since element removal from sets can happen from control plane and +element garbage collection/timeout, it is necessary to keep the set +structure alive until all elements have been deactivated and destroyed. + +We cannot do a cancel_work_sync or flush_work in nft_set_destroy because +its called with the transaction mutex held, but the aforementioned async +work queue might be blocked on the very mutex that nft_set_destroy() +callchain is sitting on. + +This gives us the choice of ABBA deadlock or UaF. + +To avoid both, add set->refs refcount_t member. The GC API can then +increment the set refcount and release it once the elements have been +free'd. + +Set backends are adapted to use the GC transaction API in a follow up +patch entitled: + + ("netfilter: nf_tables: use gc transaction API in set backends") + +This is joint work with Florian Westphal. + +Fixes: cfed7e1b1f8e ("netfilter: nf_tables: add set garbage collection helpers") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + include/net/netfilter/nf_tables.h | 64 +++++++++ + net/netfilter/nf_tables_api.c | 248 ++++++++++++++++++++++++++++++++++++-- + 2 files changed, 300 insertions(+), 12 deletions(-) + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -512,6 +512,7 @@ struct nft_set_elem_expr { + * + * @list: table set list node + * @bindings: list of set bindings ++ * @refs: internal refcounting for async set destruction + * @table: table this set belongs to + * @net: netnamespace this set belongs to + * @name: name of the set +@@ -541,6 +542,7 @@ struct nft_set_elem_expr { + struct nft_set { + struct list_head list; + struct list_head bindings; ++ refcount_t refs; + struct nft_table *table; + possible_net_t net; + char *name; +@@ -562,7 +564,8 @@ struct nft_set { + struct list_head pending_update; + /* runtime data below here */ + const struct nft_set_ops *ops ____cacheline_aligned; +- u16 flags:14, ++ u16 flags:13, ++ dead:1, + genmask:2; + u8 klen; + u8 dlen; +@@ -1592,6 +1595,32 @@ static inline void nft_set_elem_clear_bu + clear_bit(NFT_SET_ELEM_BUSY_BIT, word); + } + ++#define NFT_SET_ELEM_DEAD_MASK (1 << 3) ++ ++#if defined(__LITTLE_ENDIAN_BITFIELD) ++#define NFT_SET_ELEM_DEAD_BIT 3 ++#elif defined(__BIG_ENDIAN_BITFIELD) ++#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 3) ++#else ++#error ++#endif ++ ++static inline void nft_set_elem_dead(struct nft_set_ext *ext) ++{ ++ unsigned long *word = (unsigned long *)ext; ++ ++ BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0); ++ set_bit(NFT_SET_ELEM_DEAD_BIT, word); ++} ++ ++static inline int nft_set_elem_is_dead(const struct nft_set_ext *ext) ++{ ++ unsigned long *word = (unsigned long *)ext; ++ ++ BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0); ++ return test_bit(NFT_SET_ELEM_DEAD_BIT, word); ++} ++ + /** + * struct nft_trans - nf_tables object update in transaction + * +@@ -1729,6 +1758,38 @@ struct nft_trans_flowtable { + #define nft_trans_flowtable_flags(trans) \ + (((struct nft_trans_flowtable *)trans->data)->flags) + ++#define NFT_TRANS_GC_BATCHCOUNT 256 ++ ++struct nft_trans_gc { ++ struct list_head list; ++ struct net *net; ++ struct nft_set *set; ++ u32 seq; ++ u8 count; ++ void *priv[NFT_TRANS_GC_BATCHCOUNT]; ++ struct rcu_head rcu; ++}; ++ ++struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set, ++ unsigned int gc_seq, gfp_t gfp); ++void nft_trans_gc_destroy(struct nft_trans_gc *trans); ++ ++struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc, ++ unsigned int gc_seq, gfp_t gfp); ++void nft_trans_gc_queue_async_done(struct nft_trans_gc *gc); ++ ++struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp); ++void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans); ++ ++void nft_trans_gc_elem_add(struct nft_trans_gc *gc, void *priv); ++ ++struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc, ++ unsigned int gc_seq); ++ ++void nft_setelem_data_deactivate(const struct net *net, ++ const struct nft_set *set, ++ struct nft_set_elem *elem); ++ + int __init nft_chain_filter_init(void); + void nft_chain_filter_fini(void); + +@@ -1755,6 +1816,7 @@ struct nftables_pernet { + struct mutex commit_mutex; + u64 table_handle; + unsigned int base_seq; ++ unsigned int gc_seq; + }; + + extern unsigned int nf_tables_net_id; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -31,7 +31,9 @@ static LIST_HEAD(nf_tables_expressions); + static LIST_HEAD(nf_tables_objects); + static LIST_HEAD(nf_tables_flowtables); + static LIST_HEAD(nf_tables_destroy_list); ++static LIST_HEAD(nf_tables_gc_list); + static DEFINE_SPINLOCK(nf_tables_destroy_list_lock); ++static DEFINE_SPINLOCK(nf_tables_gc_list_lock); + + enum { + NFT_VALIDATE_SKIP = 0, +@@ -120,6 +122,9 @@ static void nft_validate_state_update(st + static void nf_tables_trans_destroy_work(struct work_struct *w); + static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work); + ++static void nft_trans_gc_work(struct work_struct *work); ++static DECLARE_WORK(trans_gc_work, nft_trans_gc_work); ++ + static void nft_ctx_init(struct nft_ctx *ctx, + struct net *net, + const struct sk_buff *skb, +@@ -581,10 +586,6 @@ static int nft_trans_set_add(const struc + return __nft_trans_set_add(ctx, msg_type, set, NULL); + } + +-static void nft_setelem_data_deactivate(const struct net *net, +- const struct nft_set *set, +- struct nft_set_elem *elem); +- + static int nft_mapelem_deactivate(const struct nft_ctx *ctx, + struct nft_set *set, + const struct nft_set_iter *iter, +@@ -5054,6 +5055,7 @@ static int nf_tables_newset(struct sk_bu + + INIT_LIST_HEAD(&set->bindings); + INIT_LIST_HEAD(&set->catchall_list); ++ refcount_set(&set->refs, 1); + set->table = table; + write_pnet(&set->net, net); + set->ops = ops; +@@ -5121,6 +5123,14 @@ static void nft_set_catchall_destroy(con + } + } + ++static void nft_set_put(struct nft_set *set) ++{ ++ if (refcount_dec_and_test(&set->refs)) { ++ kfree(set->name); ++ kvfree(set); ++ } ++} ++ + static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) + { + int i; +@@ -5133,8 +5143,7 @@ static void nft_set_destroy(const struct + + set->ops->destroy(ctx, set); + nft_set_catchall_destroy(ctx, set); +- kfree(set->name); +- kvfree(set); ++ nft_set_put(set); + } + + static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info, +@@ -6255,7 +6264,8 @@ struct nft_set_ext *nft_set_catchall_loo + list_for_each_entry_rcu(catchall, &set->catchall_list, list) { + ext = nft_set_elem_ext(set, catchall->elem); + if (nft_set_elem_active(ext, genmask) && +- !nft_set_elem_expired(ext)) ++ !nft_set_elem_expired(ext) && ++ !nft_set_elem_is_dead(ext)) + return ext; + } + +@@ -6907,9 +6917,9 @@ static void nft_setelem_data_activate(co + nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use); + } + +-static void nft_setelem_data_deactivate(const struct net *net, +- const struct nft_set *set, +- struct nft_set_elem *elem) ++void nft_setelem_data_deactivate(const struct net *net, ++ const struct nft_set *set, ++ struct nft_set_elem *elem) + { + const struct nft_set_ext *ext = nft_set_elem_ext(set, elem->priv); + +@@ -9386,6 +9396,207 @@ void nft_chain_del(struct nft_chain *cha + list_del_rcu(&chain->list); + } + ++static void nft_trans_gc_setelem_remove(struct nft_ctx *ctx, ++ struct nft_trans_gc *trans) ++{ ++ void **priv = trans->priv; ++ unsigned int i; ++ ++ for (i = 0; i < trans->count; i++) { ++ struct nft_set_elem elem = { ++ .priv = priv[i], ++ }; ++ ++ nft_setelem_data_deactivate(ctx->net, trans->set, &elem); ++ nft_setelem_remove(ctx->net, trans->set, &elem); ++ } ++} ++ ++void nft_trans_gc_destroy(struct nft_trans_gc *trans) ++{ ++ nft_set_put(trans->set); ++ put_net(trans->net); ++ kfree(trans); ++} ++ ++static void nft_trans_gc_trans_free(struct rcu_head *rcu) ++{ ++ struct nft_set_elem elem = {}; ++ struct nft_trans_gc *trans; ++ struct nft_ctx ctx = {}; ++ unsigned int i; ++ ++ trans = container_of(rcu, struct nft_trans_gc, rcu); ++ ctx.net = read_pnet(&trans->set->net); ++ ++ for (i = 0; i < trans->count; i++) { ++ elem.priv = trans->priv[i]; ++ if (!nft_setelem_is_catchall(trans->set, &elem)) ++ atomic_dec(&trans->set->nelems); ++ ++ nf_tables_set_elem_destroy(&ctx, trans->set, elem.priv); ++ } ++ ++ nft_trans_gc_destroy(trans); ++} ++ ++static bool nft_trans_gc_work_done(struct nft_trans_gc *trans) ++{ ++ struct nftables_pernet *nft_net; ++ struct nft_ctx ctx = {}; ++ ++ nft_net = nft_pernet(trans->net); ++ ++ mutex_lock(&nft_net->commit_mutex); ++ ++ /* Check for race with transaction, otherwise this batch refers to ++ * stale objects that might not be there anymore. Skip transaction if ++ * set has been destroyed from control plane transaction in case gc ++ * worker loses race. ++ */ ++ if (READ_ONCE(nft_net->gc_seq) != trans->seq || trans->set->dead) { ++ mutex_unlock(&nft_net->commit_mutex); ++ return false; ++ } ++ ++ ctx.net = trans->net; ++ ctx.table = trans->set->table; ++ ++ nft_trans_gc_setelem_remove(&ctx, trans); ++ mutex_unlock(&nft_net->commit_mutex); ++ ++ return true; ++} ++ ++static void nft_trans_gc_work(struct work_struct *work) ++{ ++ struct nft_trans_gc *trans, *next; ++ LIST_HEAD(trans_gc_list); ++ ++ spin_lock(&nf_tables_destroy_list_lock); ++ list_splice_init(&nf_tables_gc_list, &trans_gc_list); ++ spin_unlock(&nf_tables_destroy_list_lock); ++ ++ list_for_each_entry_safe(trans, next, &trans_gc_list, list) { ++ list_del(&trans->list); ++ if (!nft_trans_gc_work_done(trans)) { ++ nft_trans_gc_destroy(trans); ++ continue; ++ } ++ call_rcu(&trans->rcu, nft_trans_gc_trans_free); ++ } ++} ++ ++struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set, ++ unsigned int gc_seq, gfp_t gfp) ++{ ++ struct net *net = read_pnet(&set->net); ++ struct nft_trans_gc *trans; ++ ++ trans = kzalloc(sizeof(*trans), gfp); ++ if (!trans) ++ return NULL; ++ ++ refcount_inc(&set->refs); ++ trans->set = set; ++ trans->net = get_net(net); ++ trans->seq = gc_seq; ++ ++ return trans; ++} ++ ++void nft_trans_gc_elem_add(struct nft_trans_gc *trans, void *priv) ++{ ++ trans->priv[trans->count++] = priv; ++} ++ ++static void nft_trans_gc_queue_work(struct nft_trans_gc *trans) ++{ ++ spin_lock(&nf_tables_gc_list_lock); ++ list_add_tail(&trans->list, &nf_tables_gc_list); ++ spin_unlock(&nf_tables_gc_list_lock); ++ ++ schedule_work(&trans_gc_work); ++} ++ ++static int nft_trans_gc_space(struct nft_trans_gc *trans) ++{ ++ return NFT_TRANS_GC_BATCHCOUNT - trans->count; ++} ++ ++struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc, ++ unsigned int gc_seq, gfp_t gfp) ++{ ++ if (nft_trans_gc_space(gc)) ++ return gc; ++ ++ nft_trans_gc_queue_work(gc); ++ ++ return nft_trans_gc_alloc(gc->set, gc_seq, gfp); ++} ++ ++void nft_trans_gc_queue_async_done(struct nft_trans_gc *trans) ++{ ++ if (trans->count == 0) { ++ nft_trans_gc_destroy(trans); ++ return; ++ } ++ ++ nft_trans_gc_queue_work(trans); ++} ++ ++struct nft_trans_gc *nft_trans_gc_queue_sync(struct nft_trans_gc *gc, gfp_t gfp) ++{ ++ if (WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net))) ++ return NULL; ++ ++ if (nft_trans_gc_space(gc)) ++ return gc; ++ ++ call_rcu(&gc->rcu, nft_trans_gc_trans_free); ++ ++ return nft_trans_gc_alloc(gc->set, 0, gfp); ++} ++ ++void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans) ++{ ++ WARN_ON_ONCE(!lockdep_commit_lock_is_held(trans->net)); ++ ++ if (trans->count == 0) { ++ nft_trans_gc_destroy(trans); ++ return; ++ } ++ ++ call_rcu(&trans->rcu, nft_trans_gc_trans_free); ++} ++ ++struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc, ++ unsigned int gc_seq) ++{ ++ struct nft_set_elem_catchall *catchall; ++ const struct nft_set *set = gc->set; ++ struct nft_set_ext *ext; ++ ++ list_for_each_entry_rcu(catchall, &set->catchall_list, list) { ++ ext = nft_set_elem_ext(set, catchall->elem); ++ ++ if (!nft_set_elem_expired(ext)) ++ continue; ++ if (nft_set_elem_is_dead(ext)) ++ goto dead_elem; ++ ++ nft_set_elem_dead(ext); ++dead_elem: ++ gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC); ++ if (!gc) ++ return NULL; ++ ++ nft_trans_gc_elem_add(gc, catchall->elem); ++ } ++ ++ return gc; ++} ++ + static void nf_tables_module_autoload_cleanup(struct net *net) + { + struct nftables_pernet *nft_net = nft_pernet(net); +@@ -9548,11 +9759,11 @@ static int nf_tables_commit(struct net * + { + struct nftables_pernet *nft_net = nft_pernet(net); + struct nft_trans *trans, *next; ++ unsigned int base_seq, gc_seq; + LIST_HEAD(set_update_list); + struct nft_trans_elem *te; + struct nft_chain *chain; + struct nft_table *table; +- unsigned int base_seq; + LIST_HEAD(adl); + int err; + +@@ -9629,6 +9840,10 @@ static int nf_tables_commit(struct net * + + WRITE_ONCE(nft_net->base_seq, base_seq); + ++ /* Bump gc counter, it becomes odd, this is the busy mark. */ ++ gc_seq = READ_ONCE(nft_net->gc_seq); ++ WRITE_ONCE(nft_net->gc_seq, ++gc_seq); ++ + /* step 3. Start new generation, rules_gen_X now in use. */ + net->nft.gencursor = nft_gencursor_next(net); + +@@ -9733,6 +9948,7 @@ static int nf_tables_commit(struct net * + break; + case NFT_MSG_DELSET: + case NFT_MSG_DESTROYSET: ++ nft_trans_set(trans)->dead = 1; + list_del_rcu(&nft_trans_set(trans)->list); + nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), + trans->msg_type, GFP_KERNEL); +@@ -9835,6 +10051,8 @@ static int nf_tables_commit(struct net * + nft_commit_notify(net, NETLINK_CB(skb).portid); + nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN); + nf_tables_commit_audit_log(&adl, nft_net->base_seq); ++ ++ WRITE_ONCE(nft_net->gc_seq, ++gc_seq); + nf_tables_commit_release(net); + + return 0; +@@ -10884,6 +11102,7 @@ static int __net_init nf_tables_init_net + INIT_LIST_HEAD(&nft_net->notify_list); + mutex_init(&nft_net->commit_mutex); + nft_net->base_seq = 1; ++ nft_net->gc_seq = 0; + + return 0; + } +@@ -10912,10 +11131,16 @@ static void __net_exit nf_tables_exit_ne + WARN_ON_ONCE(!list_empty(&nft_net->notify_list)); + } + ++static void nf_tables_exit_batch(struct list_head *net_exit_list) ++{ ++ flush_work(&trans_gc_work); ++} ++ + static struct pernet_operations nf_tables_net_ops = { + .init = nf_tables_init_net, + .pre_exit = nf_tables_pre_exit_net, + .exit = nf_tables_exit_net, ++ .exit_batch = nf_tables_exit_batch, + .id = &nf_tables_net_id, + .size = sizeof(struct nftables_pernet), + }; +@@ -10987,6 +11212,7 @@ static void __exit nf_tables_module_exit + nft_chain_filter_fini(); + nft_chain_route_fini(); + unregister_pernet_subsys(&nf_tables_net_ops); ++ cancel_work_sync(&trans_gc_work); + cancel_work_sync(&trans_destroy_work); + rcu_barrier(); + rhltable_destroy(&nft_objname_ht); diff --git a/queue-6.4/netfilter-nft_set_hash-mark-set-element-as-dead-when-deleting-from-packet-path.patch b/queue-6.4/netfilter-nft_set_hash-mark-set-element-as-dead-when-deleting-from-packet-path.patch new file mode 100644 index 00000000000..acb530218a6 --- /dev/null +++ b/queue-6.4/netfilter-nft_set_hash-mark-set-element-as-dead-when-deleting-from-packet-path.patch @@ -0,0 +1,43 @@ +From c92db3030492b8ad1d0faace7a93bbcf53850d0c Mon Sep 17 00:00:00 2001 +From: Pablo Neira Ayuso +Date: Wed, 9 Aug 2023 15:00:06 +0200 +Subject: netfilter: nft_set_hash: mark set element as dead when deleting from packet path + +From: Pablo Neira Ayuso + +commit c92db3030492b8ad1d0faace7a93bbcf53850d0c upstream. + +Set on the NFT_SET_ELEM_DEAD_BIT flag on this element, instead of +performing element removal which might race with an ongoing transaction. +Enable gc when dynamic flag is set on since dynset deletion requires +garbage collection after this patch. + +Fixes: d0a8d877da97 ("netfilter: nft_dynset: support for element deletion") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Greg Kroah-Hartman +--- + net/netfilter/nft_set_hash.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/netfilter/nft_set_hash.c ++++ b/net/netfilter/nft_set_hash.c +@@ -249,7 +249,9 @@ static bool nft_rhash_delete(const struc + if (he == NULL) + return false; + +- return rhashtable_remove_fast(&priv->ht, &he->node, nft_rhash_params) == 0; ++ nft_set_elem_dead(&he->ext); ++ ++ return true; + } + + static void nft_rhash_walk(const struct nft_ctx *ctx, struct nft_set *set, +@@ -412,7 +414,7 @@ static int nft_rhash_init(const struct n + return err; + + INIT_DEFERRABLE_WORK(&priv->gc_work, nft_rhash_gc); +- if (set->flags & NFT_SET_TIMEOUT) ++ if (set->flags & (NFT_SET_TIMEOUT | NFT_SET_EVAL)) + nft_rhash_gc_init(set); + + return 0; diff --git a/queue-6.4/revert-pci-mvebu-mark-driver-as-broken.patch b/queue-6.4/revert-pci-mvebu-mark-driver-as-broken.patch new file mode 100644 index 00000000000..e017163a122 --- /dev/null +++ b/queue-6.4/revert-pci-mvebu-mark-driver-as-broken.patch @@ -0,0 +1,39 @@ +From 3bfc37d92687b4b19056998cebc02f94fbc81427 Mon Sep 17 00:00:00 2001 +From: Bjorn Helgaas +Date: Fri, 4 Aug 2023 11:54:43 -0500 +Subject: Revert "PCI: mvebu: Mark driver as BROKEN" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Bjorn Helgaas + +commit 3bfc37d92687b4b19056998cebc02f94fbc81427 upstream. + +b3574f579ece ("PCI: mvebu: Mark driver as BROKEN") made it impossible to +enable the pci-mvebu driver. The driver does have known problems, but as +Russell and Uwe reported, it does work in some configurations, so removing +it broke some working setups. + +Revert b3574f579ece so pci-mvebu is available. + +Reported-by: Russell King (Oracle) +Link: https://lore.kernel.org/r/ZMzicVQEyHyZzBOc@shell.armlinux.org.uk +Reported-by: Uwe Kleine-König +Link: https://lore.kernel.org/r/20230804134622.pmbymxtzxj2yfhri@pengutronix.de +Signed-off-by: Bjorn Helgaas +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/Kconfig | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/pci/controller/Kconfig ++++ b/drivers/pci/controller/Kconfig +@@ -179,7 +179,6 @@ config PCI_MVEBU + depends on MVEBU_MBUS + depends on ARM + depends on OF +- depends on BROKEN + select PCI_BRIDGE_EMUL + help + Add support for Marvell EBU PCIe controller. This PCIe controller diff --git a/queue-6.4/series b/queue-6.4/series index abdb51d2e09..caecc1e4742 100644 --- a/queue-6.4/series +++ b/queue-6.4/series @@ -63,3 +63,34 @@ mm-memory-failure-fix-potential-unexpected-return-value-from-unpoison_memory.pat mm-memory-failure-avoid-false-hwpoison-page-mapped-error-info.patch drm-amd-pm-expose-swctf-threshold-setting-for-legacy-powerplay.patch drm-amd-pm-avoid-unintentional-shutdown-due-to-temperature-momentary-fluctuation.patch +iio-cros_ec-fix-the-allocation-size-for-cros_ec_command.patch +iio-frequency-admv1013-propagate-errors-from-regulator_get_voltage.patch +iio-adc-ad7192-fix-ac-excitation-feature.patch +iio-adc-meson-fix-core-clock-enable-disable-moment.patch +iio-adc-ina2xx-avoid-null-pointer-dereference-on-of-device-match.patch +binder-fix-memory-leak-in-binder_init.patch +misc-rtsx-judge-aspm-mode-to-set-petxcfg-reg.patch +thunderbolt-fix-memory-leak-in-tb_handle_dp_bandwidth_request.patch +usb-storage-alauda-fix-uninit-value-in-alauda_check_media.patch +usb-dwc3-properly-handle-processing-of-pending-events.patch +usb-gadget-core-help-prevent-panic-during-uvc-unconfigure.patch +usb-common-usb-conn-gpio-prevent-bailing-out-if-initial-role-is-none.patch +usb-typec-tcpm-fix-response-to-vsafe0v-event.patch +usb-typec-altmodes-displayport-signal-hpd-when-configuring-pin-assignment.patch +x86-srso-fix-build-breakage-with-the-llvm-linker.patch +x86-vdso-choose-the-right-gdt_entry_cpunode-for-32-bit-getcpu-on-64-bit-kernel.patch +x86-cpu-amd-enable-zenbleed-fix-for-amd-custom-apu-0405.patch +x86-mm-fix-vdso-and-vvar-placement-on-5-level-paging-machines.patch +x86-sev-do-not-try-to-parse-for-the-cc-blob-on-non-amd-hardware.patch +x86-linkage-fix-typo-of-build_vdso-in-asm-linkage.h.patch +x86-speculation-add-cpu_show_gds-prototype.patch +x86-move-gds_ucode_mitigated-declaration-to-header.patch +revert-pci-mvebu-mark-driver-as-broken.patch +drm-nouveau-disp-revert-a-null-check-inside-nouveau_connector_get_modes.patch +netfilter-nf_tables-don-t-skip-expired-elements-during-walk.patch +netfilter-nf_tables-gc-transaction-api-to-avoid-race-with-control-plane.patch +netfilter-nf_tables-adapt-set-backend-to-use-gc-transaction-api.patch +netfilter-nft_set_hash-mark-set-element-as-dead-when-deleting-from-packet-path.patch +iio-imu-lsm6dsx-fix-mount-matrix-retrieval.patch +iio-core-prevent-invalid-memory-access-when-there-is-no-parent.patch +iio-light-bu27034-fix-scale-format.patch diff --git a/queue-6.4/thunderbolt-fix-memory-leak-in-tb_handle_dp_bandwidth_request.patch b/queue-6.4/thunderbolt-fix-memory-leak-in-tb_handle_dp_bandwidth_request.patch new file mode 100644 index 00000000000..fa5cbb0a017 --- /dev/null +++ b/queue-6.4/thunderbolt-fix-memory-leak-in-tb_handle_dp_bandwidth_request.patch @@ -0,0 +1,31 @@ +From 596a5123cc782d458b057eb3837e66535cd0befa Mon Sep 17 00:00:00 2001 +From: Mika Westerberg +Date: Thu, 22 Jun 2023 14:59:12 +0300 +Subject: thunderbolt: Fix memory leak in tb_handle_dp_bandwidth_request() + +From: Mika Westerberg + +commit 596a5123cc782d458b057eb3837e66535cd0befa upstream. + +The memory allocated in tb_queue_dp_bandwidth_request() needs to be +released once the request is handled to avoid leaking it. + +Fixes: 6ce3563520be ("thunderbolt: Add support for DisplayPort bandwidth allocation mode") +Cc: stable@vger.kernel.org +Signed-off-by: Mika Westerberg +Signed-off-by: Greg Kroah-Hartman +--- + drivers/thunderbolt/tb.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/thunderbolt/tb.c ++++ b/drivers/thunderbolt/tb.c +@@ -1810,6 +1810,8 @@ unlock: + + pm_runtime_mark_last_busy(&tb->dev); + pm_runtime_put_autosuspend(&tb->dev); ++ ++ kfree(ev); + } + + static void tb_queue_dp_bandwidth_request(struct tb *tb, u64 route, u8 port) diff --git a/queue-6.4/usb-common-usb-conn-gpio-prevent-bailing-out-if-initial-role-is-none.patch b/queue-6.4/usb-common-usb-conn-gpio-prevent-bailing-out-if-initial-role-is-none.patch new file mode 100644 index 00000000000..73ff7481745 --- /dev/null +++ b/queue-6.4/usb-common-usb-conn-gpio-prevent-bailing-out-if-initial-role-is-none.patch @@ -0,0 +1,62 @@ +From 8e21a620c7e6e00347ade1a6ed4967b359eada5a Mon Sep 17 00:00:00 2001 +From: Prashanth K +Date: Tue, 1 Aug 2023 14:33:52 +0530 +Subject: usb: common: usb-conn-gpio: Prevent bailing out if initial role is none + +From: Prashanth K + +commit 8e21a620c7e6e00347ade1a6ed4967b359eada5a upstream. + +Currently if we bootup a device without cable connected, then +usb-conn-gpio won't call set_role() because last_role is same +as current role. This happens since last_role gets initialised +to zero during the probe. + +To avoid this, add a new flag initial_detection into struct +usb_conn_info, which prevents bailing out during initial +detection. + +Cc: # 5.4 +Fixes: 4602f3bff266 ("usb: common: add USB GPIO based connection detection driver") +Signed-off-by: Prashanth K +Tested-by: AngeloGioacchino Del Regno +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/1690880632-12588-1-git-send-email-quic_prashk@quicinc.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/common/usb-conn-gpio.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/usb/common/usb-conn-gpio.c ++++ b/drivers/usb/common/usb-conn-gpio.c +@@ -42,6 +42,7 @@ struct usb_conn_info { + + struct power_supply_desc desc; + struct power_supply *charger; ++ bool initial_detection; + }; + + /* +@@ -86,11 +87,13 @@ static void usb_conn_detect_cable(struct + dev_dbg(info->dev, "role %s -> %s, gpios: id %d, vbus %d\n", + usb_role_string(info->last_role), usb_role_string(role), id, vbus); + +- if (info->last_role == role) { ++ if (!info->initial_detection && info->last_role == role) { + dev_warn(info->dev, "repeated role: %s\n", usb_role_string(role)); + return; + } + ++ info->initial_detection = false; ++ + if (info->last_role == USB_ROLE_HOST && info->vbus) + regulator_disable(info->vbus); + +@@ -258,6 +261,7 @@ static int usb_conn_probe(struct platfor + device_set_wakeup_capable(&pdev->dev, true); + + /* Perform initial detection */ ++ info->initial_detection = true; + usb_conn_queue_dwork(info, 0); + + return 0; diff --git a/queue-6.4/usb-dwc3-properly-handle-processing-of-pending-events.patch b/queue-6.4/usb-dwc3-properly-handle-processing-of-pending-events.patch new file mode 100644 index 00000000000..d86115bb06a --- /dev/null +++ b/queue-6.4/usb-dwc3-properly-handle-processing-of-pending-events.patch @@ -0,0 +1,56 @@ +From 3ddaa6a274578e23745b7466346fc2650df8f959 Mon Sep 17 00:00:00 2001 +From: Elson Roy Serrao +Date: Tue, 1 Aug 2023 12:26:58 -0700 +Subject: usb: dwc3: Properly handle processing of pending events + +From: Elson Roy Serrao + +commit 3ddaa6a274578e23745b7466346fc2650df8f959 upstream. + +If dwc3 is runtime suspended we defer processing the event buffer +until resume, by setting the pending_events flag. Set this flag before +triggering resume to avoid race with the runtime resume callback. + +While handling the pending events, in addition to checking the event +buffer we also need to process it. Handle this by explicitly calling +dwc3_thread_interrupt(). Also balance the runtime pm get() operation +that triggered this processing. + +Cc: stable@vger.kernel.org +Fixes: fc8bb91bc83e ("usb: dwc3: implement runtime PM") +Signed-off-by: Elson Roy Serrao +Acked-by: Thinh Nguyen +Reviewed-by: Roger Quadros +Link: https://lore.kernel.org/r/20230801192658.19275-1-quic_eserrao@quicinc.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/dwc3/gadget.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -4448,9 +4448,14 @@ static irqreturn_t dwc3_check_event_buf( + u32 count; + + if (pm_runtime_suspended(dwc->dev)) { ++ dwc->pending_events = true; ++ /* ++ * Trigger runtime resume. The get() function will be balanced ++ * after processing the pending events in dwc3_process_pending ++ * events(). ++ */ + pm_runtime_get(dwc->dev); + disable_irq_nosync(dwc->irq_gadget); +- dwc->pending_events = true; + return IRQ_HANDLED; + } + +@@ -4711,6 +4716,8 @@ void dwc3_gadget_process_pending_events( + { + if (dwc->pending_events) { + dwc3_interrupt(dwc->irq_gadget, dwc->ev_buf); ++ dwc3_thread_interrupt(dwc->irq_gadget, dwc->ev_buf); ++ pm_runtime_put(dwc->dev); + dwc->pending_events = false; + enable_irq(dwc->irq_gadget); + } diff --git a/queue-6.4/usb-gadget-core-help-prevent-panic-during-uvc-unconfigure.patch b/queue-6.4/usb-gadget-core-help-prevent-panic-during-uvc-unconfigure.patch new file mode 100644 index 00000000000..9d3e664f951 --- /dev/null +++ b/queue-6.4/usb-gadget-core-help-prevent-panic-during-uvc-unconfigure.patch @@ -0,0 +1,85 @@ +From 65dadb2beeb7360232b09ebc4585b54475dfee06 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Sat, 29 Jul 2023 10:59:38 -0400 +Subject: USB: Gadget: core: Help prevent panic during UVC unconfigure + +From: Alan Stern + +commit 65dadb2beeb7360232b09ebc4585b54475dfee06 upstream. + +Avichal Rakesh reported a kernel panic that occurred when the UVC +gadget driver was removed from a gadget's configuration. The panic +involves a somewhat complicated interaction between the kernel driver +and a userspace component (as described in the Link tag below), but +the analysis did make one thing clear: The Gadget core should +accomodate gadget drivers calling usb_gadget_deactivate() as part of +their unbind procedure. + +Currently this doesn't work. gadget_unbind_driver() calls +driver->unbind() while holding the udc->connect_lock mutex, and +usb_gadget_deactivate() attempts to acquire that mutex, which will +result in a deadlock. + +The simple fix is for gadget_unbind_driver() to release the mutex when +invoking the ->unbind() callback. There is no particular reason for +it to be holding the mutex at that time, and the mutex isn't held +while the ->bind() callback is invoked. So we'll drop the mutex +before performing the unbind callback and reacquire it afterward. + +We'll also add a couple of comments to usb_gadget_activate() and +usb_gadget_deactivate(). Because they run in process context they +must not be called from a gadget driver's ->disconnect() callback, +which (according to the kerneldoc for struct usb_gadget_driver in +include/linux/usb/gadget.h) may run in interrupt context. This may +help prevent similar bugs from arising in the future. + +Reported-and-tested-by: Avichal Rakesh +Signed-off-by: Alan Stern +Fixes: 286d9975a838 ("usb: gadget: udc: core: Prevent soft_connect_store() race") +Link: https://lore.kernel.org/linux-usb/4d7aa3f4-22d9-9f5a-3d70-1bd7148ff4ba@google.com/ +Cc: Badhri Jagan Sridharan +Cc: +Link: https://lore.kernel.org/r/48b2f1f1-0639-46bf-bbfc-98cb05a24914@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/udc/core.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c +index cd58f2a4e7f3..7d49d8a0b00c 100644 +--- a/drivers/usb/gadget/udc/core.c ++++ b/drivers/usb/gadget/udc/core.c +@@ -822,6 +822,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_disconnect); + * usb_gadget_activate() is called. For example, user mode components may + * need to be activated before the system can talk to hosts. + * ++ * This routine may sleep; it must not be called in interrupt context ++ * (such as from within a gadget driver's disconnect() callback). ++ * + * Returns zero on success, else negative errno. + */ + int usb_gadget_deactivate(struct usb_gadget *gadget) +@@ -860,6 +863,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_deactivate); + * This routine activates gadget which was previously deactivated with + * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed. + * ++ * This routine may sleep; it must not be called in interrupt context. ++ * + * Returns zero on success, else negative errno. + */ + int usb_gadget_activate(struct usb_gadget *gadget) +@@ -1638,7 +1643,11 @@ static void gadget_unbind_driver(struct device *dev) + usb_gadget_disable_async_callbacks(udc); + if (gadget->irq) + synchronize_irq(gadget->irq); ++ mutex_unlock(&udc->connect_lock); ++ + udc->driver->unbind(gadget); ++ ++ mutex_lock(&udc->connect_lock); + usb_gadget_udc_stop_locked(udc); + mutex_unlock(&udc->connect_lock); + +-- +2.41.0 + diff --git a/queue-6.4/usb-storage-alauda-fix-uninit-value-in-alauda_check_media.patch b/queue-6.4/usb-storage-alauda-fix-uninit-value-in-alauda_check_media.patch new file mode 100644 index 00000000000..00d3e9dd804 --- /dev/null +++ b/queue-6.4/usb-storage-alauda-fix-uninit-value-in-alauda_check_media.patch @@ -0,0 +1,81 @@ +From a6ff6e7a9dd69364547751db0f626a10a6d628d2 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 2 Aug 2023 13:49:02 -0400 +Subject: usb-storage: alauda: Fix uninit-value in alauda_check_media() + +From: Alan Stern + +commit a6ff6e7a9dd69364547751db0f626a10a6d628d2 upstream. + +Syzbot got KMSAN to complain about access to an uninitialized value in +the alauda subdriver of usb-storage: + +BUG: KMSAN: uninit-value in alauda_transport+0x462/0x57f0 +drivers/usb/storage/alauda.c:1137 +CPU: 0 PID: 12279 Comm: usb-storage Not tainted 5.3.0-rc7+ #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS +Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x191/0x1f0 lib/dump_stack.c:113 + kmsan_report+0x13a/0x2b0 mm/kmsan/kmsan_report.c:108 + __msan_warning+0x73/0xe0 mm/kmsan/kmsan_instr.c:250 + alauda_check_media+0x344/0x3310 drivers/usb/storage/alauda.c:460 + +The problem is that alauda_check_media() doesn't verify that its USB +transfer succeeded before trying to use the received data. What +should happen if the transfer fails isn't entirely clear, but a +reasonably conservative approach is to pretend that no media is +present. + +A similar problem exists in a usb_stor_dbg() call in +alauda_get_media_status(). In this case, when an error occurs the +call is redundant, because usb_stor_ctrl_transfer() already will print +a debugging message. + +Finally, unrelated to the uninitialized memory access, is the fact +that alauda_check_media() performs DMA to a buffer on the stack. +Fortunately usb-storage provides a general purpose DMA-able buffer for +uses like this. We'll use it instead. + +Reported-and-tested-by: syzbot+e7d46eb426883fb97efd@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/all/0000000000007d25ff059457342d@google.com/T/ +Suggested-by: Christophe JAILLET +Signed-off-by: Alan Stern +Fixes: e80b0fade09e ("[PATCH] USB Storage: add alauda support") +Cc: +Link: https://lore.kernel.org/r/693d5d5e-f09b-42d0-8ed9-1f96cd30bcce@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/storage/alauda.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/usb/storage/alauda.c ++++ b/drivers/usb/storage/alauda.c +@@ -318,7 +318,8 @@ static int alauda_get_media_status(struc + rc = usb_stor_ctrl_transfer(us, us->recv_ctrl_pipe, + command, 0xc0, 0, 1, data, 2); + +- usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]); ++ if (rc == USB_STOR_XFER_GOOD) ++ usb_stor_dbg(us, "Media status %02X %02X\n", data[0], data[1]); + + return rc; + } +@@ -454,9 +455,14 @@ static int alauda_init_media(struct us_d + static int alauda_check_media(struct us_data *us) + { + struct alauda_info *info = (struct alauda_info *) us->extra; +- unsigned char status[2]; ++ unsigned char *status = us->iobuf; ++ int rc; + +- alauda_get_media_status(us, status); ++ rc = alauda_get_media_status(us, status); ++ if (rc != USB_STOR_XFER_GOOD) { ++ status[0] = 0xF0; /* Pretend there's no media */ ++ status[1] = 0; ++ } + + /* Check for no media or door open */ + if ((status[0] & 0x80) || ((status[0] & 0x1F) == 0x10) diff --git a/queue-6.4/usb-typec-altmodes-displayport-signal-hpd-when-configuring-pin-assignment.patch b/queue-6.4/usb-typec-altmodes-displayport-signal-hpd-when-configuring-pin-assignment.patch new file mode 100644 index 00000000000..82706ccffb3 --- /dev/null +++ b/queue-6.4/usb-typec-altmodes-displayport-signal-hpd-when-configuring-pin-assignment.patch @@ -0,0 +1,72 @@ +From 5a5ccd61cfd76156cb3e0373c300c509d05448ce Mon Sep 17 00:00:00 2001 +From: RD Babiera +Date: Wed, 26 Jul 2023 02:09:02 +0000 +Subject: usb: typec: altmodes/displayport: Signal hpd when configuring pin assignment + +From: RD Babiera + +commit 5a5ccd61cfd76156cb3e0373c300c509d05448ce upstream. + +When connecting to some DisplayPort partners, the initial status update +after entering DisplayPort Alt Mode notifies that the DFP_D/UFP_D is not in +the connected state. This leads to sending a configure message that keeps +the device in USB mode. The port partner then sets DFP_D/UFP_D to the +connected state and HPD to high in the same Attention message. Currently, +the HPD signal is dropped in order to handle configuration. + +This patch saves changes to the HPD signal when the device chooses to +configure during dp_altmode_status_update, and invokes sysfs_notify if +necessary for HPD after configuring. + +Fixes: 0e3bb7d6894d ("usb: typec: Add driver for DisplayPort alternate mode") +Cc: stable@vger.kernel.org +Signed-off-by: RD Babiera +Acked-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20230726020903.1409072-1-rdbabiera@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/altmodes/displayport.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +--- a/drivers/usb/typec/altmodes/displayport.c ++++ b/drivers/usb/typec/altmodes/displayport.c +@@ -60,6 +60,7 @@ struct dp_altmode { + + enum dp_state state; + bool hpd; ++ bool pending_hpd; + + struct mutex lock; /* device lock */ + struct work_struct work; +@@ -144,8 +145,13 @@ static int dp_altmode_status_update(stru + dp->state = DP_STATE_EXIT; + } else if (!(con & DP_CONF_CURRENTLY(dp->data.conf))) { + ret = dp_altmode_configure(dp, con); +- if (!ret) ++ if (!ret) { + dp->state = DP_STATE_CONFIGURE; ++ if (dp->hpd != hpd) { ++ dp->hpd = hpd; ++ dp->pending_hpd = true; ++ } ++ } + } else { + if (dp->hpd != hpd) { + drm_connector_oob_hotplug_event(dp->connector_fwnode); +@@ -161,6 +167,16 @@ static int dp_altmode_configured(struct + { + sysfs_notify(&dp->alt->dev.kobj, "displayport", "configuration"); + sysfs_notify(&dp->alt->dev.kobj, "displayport", "pin_assignment"); ++ /* ++ * If the DFP_D/UFP_D sends a change in HPD when first notifying the ++ * DisplayPort driver that it is connected, then we wait until ++ * configuration is complete to signal HPD. ++ */ ++ if (dp->pending_hpd) { ++ drm_connector_oob_hotplug_event(dp->connector_fwnode); ++ sysfs_notify(&dp->alt->dev.kobj, "displayport", "hpd"); ++ dp->pending_hpd = false; ++ } + + return dp_altmode_notify(dp); + } diff --git a/queue-6.4/usb-typec-tcpm-fix-response-to-vsafe0v-event.patch b/queue-6.4/usb-typec-tcpm-fix-response-to-vsafe0v-event.patch new file mode 100644 index 00000000000..6f58eaf1b9e --- /dev/null +++ b/queue-6.4/usb-typec-tcpm-fix-response-to-vsafe0v-event.patch @@ -0,0 +1,55 @@ +From 4270d2b4845e820b274702bfc2a7140f69e4d19d Mon Sep 17 00:00:00 2001 +From: Badhri Jagan Sridharan +Date: Wed, 12 Jul 2023 08:57:22 +0000 +Subject: usb: typec: tcpm: Fix response to vsafe0V event + +From: Badhri Jagan Sridharan + +commit 4270d2b4845e820b274702bfc2a7140f69e4d19d upstream. + +Do not transition to SNK_UNATTACHED state when receiving vsafe0v event +while in SNK_HARD_RESET_WAIT_VBUS. Ignore VBUS off events as well as +in some platforms VBUS off can be signalled more than once. + +[143515.364753] Requesting mux state 1, usb-role 2, orientation 2 +[143515.365520] pending state change SNK_HARD_RESET_SINK_OFF -> SNK_HARD_RESET_SINK_ON @ 650 ms [rev3 HARD_RESET] +[143515.632281] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_HARD_RESET_SINK_OFF, polarity 1, disconnected] +[143515.637214] VBUS on +[143515.664985] VBUS off +[143515.664992] state change SNK_HARD_RESET_SINK_OFF -> SNK_HARD_RESET_WAIT_VBUS [rev3 HARD_RESET] +[143515.665564] VBUS VSAFE0V +[143515.665566] state change SNK_HARD_RESET_WAIT_VBUS -> SNK_UNATTACHED [rev3 HARD_RESET] + +Fixes: 28b43d3d746b ("usb: typec: tcpm: Introduce vsafe0v for vbus") +Cc: +Signed-off-by: Badhri Jagan Sridharan +Acked-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20230712085722.1414743-1-badhri@google.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/tcpm/tcpm.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -5348,6 +5348,10 @@ static void _tcpm_pd_vbus_off(struct tcp + /* Do nothing, vbus drop expected */ + break; + ++ case SNK_HARD_RESET_WAIT_VBUS: ++ /* Do nothing, its OK to receive vbus off events */ ++ break; ++ + default: + if (port->pwr_role == TYPEC_SINK && port->attached) + tcpm_set_state(port, SNK_UNATTACHED, tcpm_wait_for_discharge(port)); +@@ -5394,6 +5398,9 @@ static void _tcpm_pd_vbus_vsafe0v(struct + case SNK_DEBOUNCED: + /*Do nothing, still waiting for VSAFE5V for connect */ + break; ++ case SNK_HARD_RESET_WAIT_VBUS: ++ /* Do nothing, its OK to receive vbus off events */ ++ break; + default: + if (port->pwr_role == TYPEC_SINK && port->auto_vbus_discharge_enabled) + tcpm_set_state(port, SNK_UNATTACHED, 0); diff --git a/queue-6.4/x86-cpu-amd-enable-zenbleed-fix-for-amd-custom-apu-0405.patch b/queue-6.4/x86-cpu-amd-enable-zenbleed-fix-for-amd-custom-apu-0405.patch new file mode 100644 index 00000000000..6c26795578e --- /dev/null +++ b/queue-6.4/x86-cpu-amd-enable-zenbleed-fix-for-amd-custom-apu-0405.patch @@ -0,0 +1,41 @@ +From 6dbef74aeb090d6bee7d64ef3fa82ae6fa53f271 Mon Sep 17 00:00:00 2001 +From: Cristian Ciocaltea +Date: Fri, 11 Aug 2023 23:37:05 +0300 +Subject: x86/cpu/amd: Enable Zenbleed fix for AMD Custom APU 0405 + +From: Cristian Ciocaltea + +commit 6dbef74aeb090d6bee7d64ef3fa82ae6fa53f271 upstream. + +Commit + + 522b1d69219d ("x86/cpu/amd: Add a Zenbleed fix") + +provided a fix for the Zen2 VZEROUPPER data corruption bug affecting +a range of CPU models, but the AMD Custom APU 0405 found on SteamDeck +was not listed, although it is clearly affected by the vulnerability. + +Add this CPU variant to the Zenbleed erratum list, in order to +unconditionally enable the fallback fix until a proper microcode update +is available. + +Fixes: 522b1d69219d ("x86/cpu/amd: Add a Zenbleed fix") +Signed-off-by: Cristian Ciocaltea +Signed-off-by: Borislav Petkov (AMD) +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20230811203705.1699914-1-cristian.ciocaltea@collabora.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/cpu/amd.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/x86/kernel/cpu/amd.c ++++ b/arch/x86/kernel/cpu/amd.c +@@ -73,6 +73,7 @@ static const int amd_erratum_1054[] = + static const int amd_zenbleed[] = + AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf), + AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf), ++ AMD_MODEL_RANGE(0x17, 0x90, 0x0, 0x91, 0xf), + AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf)); + + static const int amd_div0[] = diff --git a/queue-6.4/x86-linkage-fix-typo-of-build_vdso-in-asm-linkage.h.patch b/queue-6.4/x86-linkage-fix-typo-of-build_vdso-in-asm-linkage.h.patch new file mode 100644 index 00000000000..b9eaeb6364e --- /dev/null +++ b/queue-6.4/x86-linkage-fix-typo-of-build_vdso-in-asm-linkage.h.patch @@ -0,0 +1,43 @@ +From 7324f74d39531262b8e362f228b46512e6bee632 Mon Sep 17 00:00:00 2001 +From: Jinghao Jia +Date: Tue, 8 Aug 2023 14:23:53 -0400 +Subject: x86/linkage: Fix typo of BUILD_VDSO in asm/linkage.h + +From: Jinghao Jia + +commit 7324f74d39531262b8e362f228b46512e6bee632 upstream. + +The BUILD_VDSO macro was incorrectly spelled as BULID_VDSO in +asm/linkage.h. This causes the !defined(BULID_VDSO) directive to always +evaluate to true. + +Correct the spelling to BUILD_VDSO. + +Fixes: bea75b33895f ("x86/Kconfig: Introduce function padding") +Signed-off-by: Jinghao Jia +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Thomas Gleixner +Acked-by: Randy Dunlap +Cc: +Link: https://lore.kernel.org/r/20230808182353.76218-1-jinghao@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/linkage.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/linkage.h b/arch/x86/include/asm/linkage.h +index 0953aa32a324..97a3de7892d3 100644 +--- a/arch/x86/include/asm/linkage.h ++++ b/arch/x86/include/asm/linkage.h +@@ -21,7 +21,7 @@ + #define FUNCTION_PADDING + #endif + +-#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BULID_VDSO) ++#if (CONFIG_FUNCTION_ALIGNMENT > 8) && !defined(__DISABLE_EXPORTS) && !defined(BUILD_VDSO) + # define __FUNC_ALIGN __ALIGN; FUNCTION_PADDING + #else + # define __FUNC_ALIGN __ALIGN +-- +2.41.0 + diff --git a/queue-6.4/x86-mm-fix-vdso-and-vvar-placement-on-5-level-paging-machines.patch b/queue-6.4/x86-mm-fix-vdso-and-vvar-placement-on-5-level-paging-machines.patch new file mode 100644 index 00000000000..bf69cef9dc5 --- /dev/null +++ b/queue-6.4/x86-mm-fix-vdso-and-vvar-placement-on-5-level-paging-machines.patch @@ -0,0 +1,52 @@ +From 1b8b1aa90c9c0e825b181b98b8d9e249dc395470 Mon Sep 17 00:00:00 2001 +From: "Kirill A. Shutemov" +Date: Thu, 3 Aug 2023 18:16:09 +0300 +Subject: x86/mm: Fix VDSO and VVAR placement on 5-level paging machines + +From: Kirill A. Shutemov + +commit 1b8b1aa90c9c0e825b181b98b8d9e249dc395470 upstream. + +Yingcong has noticed that on the 5-level paging machine, VDSO and VVAR +VMAs are placed above the 47-bit border: + +8000001a9000-8000001ad000 r--p 00000000 00:00 0 [vvar] +8000001ad000-8000001af000 r-xp 00000000 00:00 0 [vdso] + +This might confuse users who are not aware of 5-level paging and expect +all userspace addresses to be under the 47-bit border. + +So far problem has only been triggered with ASLR disabled, although it +may also occur with ASLR enabled if the layout is randomized in a just +right way. + +The problem happens due to custom placement for the VMAs in the VDSO +code: vdso_addr() tries to place them above the stack and checks the +result against TASK_SIZE_MAX, which is wrong. TASK_SIZE_MAX is set to +the 56-bit border on 5-level paging machines. Use DEFAULT_MAP_WINDOW +instead. + +Fixes: b569bab78d8d ("x86/mm: Prepare to expose larger address space to userspace") +Reported-by: Yingcong Wu +Signed-off-by: Kirill A. Shutemov +Signed-off-by: Dave Hansen +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/all/20230803151609.22141-1-kirill.shutemov%40linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/entry/vdso/vma.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/entry/vdso/vma.c ++++ b/arch/x86/entry/vdso/vma.c +@@ -299,8 +299,8 @@ static unsigned long vdso_addr(unsigned + + /* Round the lowest possible end address up to a PMD boundary. */ + end = (start + len + PMD_SIZE - 1) & PMD_MASK; +- if (end >= TASK_SIZE_MAX) +- end = TASK_SIZE_MAX; ++ if (end >= DEFAULT_MAP_WINDOW) ++ end = DEFAULT_MAP_WINDOW; + end -= len; + + if (end > start) { diff --git a/queue-6.4/x86-move-gds_ucode_mitigated-declaration-to-header.patch b/queue-6.4/x86-move-gds_ucode_mitigated-declaration-to-header.patch new file mode 100644 index 00000000000..e10e3ba955a --- /dev/null +++ b/queue-6.4/x86-move-gds_ucode_mitigated-declaration-to-header.patch @@ -0,0 +1,48 @@ +From eb3515dc99c7c85f4170b50838136b2a193f8012 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Wed, 9 Aug 2023 15:05:00 +0200 +Subject: x86: Move gds_ucode_mitigated() declaration to header + +From: Arnd Bergmann + +commit eb3515dc99c7c85f4170b50838136b2a193f8012 upstream. + +The declaration got placed in the .c file of the caller, but that +causes a warning for the definition: + +arch/x86/kernel/cpu/bugs.c:682:6: error: no previous prototype for 'gds_ucode_mitigated' [-Werror=missing-prototypes] + +Move it to a header where both sides can observe it instead. + +Fixes: 81ac7e5d74174 ("KVM: Add GDS_NO support to KVM") +Signed-off-by: Arnd Bergmann +Signed-off-by: Dave Hansen +Tested-by: Daniel Sneddon +Cc: stable@kernel.org +Link: https://lore.kernel.org/all/20230809130530.1913368-2-arnd%40kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/processor.h | 2 ++ + arch/x86/kvm/x86.c | 2 -- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/include/asm/processor.h ++++ b/arch/x86/include/asm/processor.h +@@ -732,4 +732,6 @@ bool arch_is_platform_page(u64 paddr); + #define arch_is_platform_page arch_is_platform_page + #endif + ++extern bool gds_ucode_mitigated(void); ++ + #endif /* _ASM_X86_PROCESSOR_H */ +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -314,8 +314,6 @@ u64 __read_mostly host_xcr0; + + static struct kmem_cache *x86_emulator_cache; + +-extern bool gds_ucode_mitigated(void); +- + /* + * When called, it means the previous get/set msr reached an invalid msr. + * Return true if we want to ignore/silent this failed msr access. diff --git a/queue-6.4/x86-sev-do-not-try-to-parse-for-the-cc-blob-on-non-amd-hardware.patch b/queue-6.4/x86-sev-do-not-try-to-parse-for-the-cc-blob-on-non-amd-hardware.patch new file mode 100644 index 00000000000..9f657fa51ad --- /dev/null +++ b/queue-6.4/x86-sev-do-not-try-to-parse-for-the-cc-blob-on-non-amd-hardware.patch @@ -0,0 +1,118 @@ +From bee6cf1a80b54548a039e224c651bb15b644a480 Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Sun, 16 Jul 2023 20:22:20 +0200 +Subject: x86/sev: Do not try to parse for the CC blob on non-AMD hardware + +From: Borislav Petkov (AMD) + +commit bee6cf1a80b54548a039e224c651bb15b644a480 upstream. + +Tao Liu reported a boot hang on an Intel Atom machine due to an unmapped +EFI config table. The reason being that the CC blob which contains the +CPUID page for AMD SNP guests is parsed for before even checking +whether the machine runs on AMD hardware. + +Usually that's not a problem on !AMD hw - it simply won't find the CC +blob's GUID and return. However, if any parts of the config table +pointers array is not mapped, the kernel will #PF very early in the +decompressor stage without any opportunity to recover. + +Therefore, do a superficial CPUID check before poking for the CC blob. +This will fix the current issue on real hardware. It would also work as +a guest on a non-lying hypervisor. + +For the lying hypervisor, the check is done again, *after* parsing the +CC blob as the real CPUID page will be present then. + +Clear the #VC handler in case SEV-{ES,SNP} hasn't been detected, as +a precaution. + +Fixes: c01fce9cef84 ("x86/compressed: Add SEV-SNP feature detection/setup") +Reported-by: Tao Liu +Signed-off-by: Borislav Petkov (AMD) +Acked-by: Tom Lendacky +Tested-by: Tao Liu +Cc: +Link: https://lore.kernel.org/r/20230601072043.24439-1-ltao@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/boot/compressed/idt_64.c | 9 ++++++++- + arch/x86/boot/compressed/sev.c | 37 +++++++++++++++++++++++++++++++++++-- + 2 files changed, 43 insertions(+), 3 deletions(-) + +--- a/arch/x86/boot/compressed/idt_64.c ++++ b/arch/x86/boot/compressed/idt_64.c +@@ -63,7 +63,14 @@ void load_stage2_idt(void) + set_idt_entry(X86_TRAP_PF, boot_page_fault); + + #ifdef CONFIG_AMD_MEM_ENCRYPT +- set_idt_entry(X86_TRAP_VC, boot_stage2_vc); ++ /* ++ * Clear the second stage #VC handler in case guest types ++ * needing #VC have not been detected. ++ */ ++ if (sev_status & BIT(1)) ++ set_idt_entry(X86_TRAP_VC, boot_stage2_vc); ++ else ++ set_idt_entry(X86_TRAP_VC, NULL); + #endif + + load_boot_idt(&boot_idt_desc); +--- a/arch/x86/boot/compressed/sev.c ++++ b/arch/x86/boot/compressed/sev.c +@@ -353,12 +353,45 @@ void sev_enable(struct boot_params *bp) + bp->cc_blob_address = 0; + + /* ++ * Do an initial SEV capability check before snp_init() which ++ * loads the CPUID page and the same checks afterwards are done ++ * without the hypervisor and are trustworthy. ++ * ++ * If the HV fakes SEV support, the guest will crash'n'burn ++ * which is good enough. ++ */ ++ ++ /* Check for the SME/SEV support leaf */ ++ eax = 0x80000000; ++ ecx = 0; ++ native_cpuid(&eax, &ebx, &ecx, &edx); ++ if (eax < 0x8000001f) ++ return; ++ ++ /* ++ * Check for the SME/SEV feature: ++ * CPUID Fn8000_001F[EAX] ++ * - Bit 0 - Secure Memory Encryption support ++ * - Bit 1 - Secure Encrypted Virtualization support ++ * CPUID Fn8000_001F[EBX] ++ * - Bits 5:0 - Pagetable bit position used to indicate encryption ++ */ ++ eax = 0x8000001f; ++ ecx = 0; ++ native_cpuid(&eax, &ebx, &ecx, &edx); ++ /* Check whether SEV is supported */ ++ if (!(eax & BIT(1))) ++ return; ++ ++ /* + * Setup/preliminary detection of SNP. This will be sanity-checked + * against CPUID/MSR values later. + */ + snp = snp_init(bp); + +- /* Check for the SME/SEV support leaf */ ++ /* Now repeat the checks with the SNP CPUID table. */ ++ ++ /* Recheck the SME/SEV support leaf */ + eax = 0x80000000; + ecx = 0; + native_cpuid(&eax, &ebx, &ecx, &edx); +@@ -366,7 +399,7 @@ void sev_enable(struct boot_params *bp) + return; + + /* +- * Check for the SME/SEV feature: ++ * Recheck for the SME/SEV feature: + * CPUID Fn8000_001F[EAX] + * - Bit 0 - Secure Memory Encryption support + * - Bit 1 - Secure Encrypted Virtualization support diff --git a/queue-6.4/x86-speculation-add-cpu_show_gds-prototype.patch b/queue-6.4/x86-speculation-add-cpu_show_gds-prototype.patch new file mode 100644 index 00000000000..8d08a3a239c --- /dev/null +++ b/queue-6.4/x86-speculation-add-cpu_show_gds-prototype.patch @@ -0,0 +1,38 @@ +From a57c27c7ad85c420b7de44c6ee56692d51709dda Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Wed, 9 Aug 2023 15:04:59 +0200 +Subject: x86/speculation: Add cpu_show_gds() prototype + +From: Arnd Bergmann + +commit a57c27c7ad85c420b7de44c6ee56692d51709dda upstream. + +The newly added function has two definitions but no prototypes: + +drivers/base/cpu.c:605:16: error: no previous prototype for 'cpu_show_gds' [-Werror=missing-prototypes] + +Add a declaration next to the other ones for this file to avoid the +warning. + +Fixes: 8974eb588283b ("x86/speculation: Add Gather Data Sampling mitigation") +Signed-off-by: Arnd Bergmann +Signed-off-by: Dave Hansen +Tested-by: Daniel Sneddon +Cc: stable@kernel.org +Link: https://lore.kernel.org/all/20230809130530.1913368-1-arnd%40kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/cpu.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/cpu.h ++++ b/include/linux/cpu.h +@@ -72,6 +72,8 @@ extern ssize_t cpu_show_retbleed(struct + struct device_attribute *attr, char *buf); + extern ssize_t cpu_show_spec_rstack_overflow(struct device *dev, + struct device_attribute *attr, char *buf); ++extern ssize_t cpu_show_gds(struct device *dev, ++ struct device_attribute *attr, char *buf); + + extern __printf(4, 5) + struct device *cpu_device_create(struct device *parent, void *drvdata, diff --git a/queue-6.4/x86-srso-fix-build-breakage-with-the-llvm-linker.patch b/queue-6.4/x86-srso-fix-build-breakage-with-the-llvm-linker.patch new file mode 100644 index 00000000000..c630d9af052 --- /dev/null +++ b/queue-6.4/x86-srso-fix-build-breakage-with-the-llvm-linker.patch @@ -0,0 +1,62 @@ +From cbe8ded48b939b9d55d2c5589ab56caa7b530709 Mon Sep 17 00:00:00 2001 +From: Nick Desaulniers +Date: Wed, 9 Aug 2023 09:40:26 -0700 +Subject: x86/srso: Fix build breakage with the LLVM linker + +From: Nick Desaulniers + +commit cbe8ded48b939b9d55d2c5589ab56caa7b530709 upstream. + +The assertion added to verify the difference in bits set of the +addresses of srso_untrain_ret_alias() and srso_safe_ret_alias() would fail +to link in LLVM's ld.lld linker with the following error: + + ld.lld: error: ./arch/x86/kernel/vmlinux.lds:210: at least one side of + the expression must be absolute + ld.lld: error: ./arch/x86/kernel/vmlinux.lds:211: at least one side of + the expression must be absolute + +Use ABSOLUTE to evaluate the expression referring to at least one of the +symbols so that LLD can evaluate the linker script. + +Also, add linker version info to the comment about XOR being unsupported +in either ld.bfd or ld.lld until somewhat recently. + +Fixes: fb3bd914b3ec ("x86/srso: Add a Speculative RAS Overflow mitigation") +Closes: https://lore.kernel.org/llvm/CA+G9fYsdUeNu-gwbs0+T6XHi4hYYk=Y9725-wFhZ7gJMspLDRA@mail.gmail.com/ +Reported-by: Nathan Chancellor +Reported-by: Daniel Kolesa +Reported-by: Naresh Kamboju +Suggested-by: Sven Volkinsfeld +Signed-off-by: Nick Desaulniers +Signed-off-by: Borislav Petkov (AMD) +Link: https://github.com/ClangBuiltLinux/linux/issues/1907 +Link: https://lore.kernel.org/r/20230809-gds-v1-1-eaac90b0cbcc@google.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/vmlinux.lds.S | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/arch/x86/kernel/vmlinux.lds.S ++++ b/arch/x86/kernel/vmlinux.lds.S +@@ -529,11 +529,17 @@ INIT_PER_CPU(irq_stack_backing_store); + + #ifdef CONFIG_CPU_SRSO + /* +- * GNU ld cannot do XOR so do: (A | B) - (A & B) in order to compute the XOR ++ * GNU ld cannot do XOR until 2.41. ++ * https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=f6f78318fca803c4907fb8d7f6ded8295f1947b1 ++ * ++ * LLVM lld cannot do XOR until lld-17. ++ * https://github.com/llvm/llvm-project/commit/fae96104d4378166cbe5c875ef8ed808a356f3fb ++ * ++ * Instead do: (A | B) - (A & B) in order to compute the XOR + * of the two function addresses: + */ +-. = ASSERT(((srso_untrain_ret_alias | srso_safe_ret_alias) - +- (srso_untrain_ret_alias & srso_safe_ret_alias)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)), ++. = ASSERT(((ABSOLUTE(srso_untrain_ret_alias) | srso_safe_ret_alias) - ++ (ABSOLUTE(srso_untrain_ret_alias) & srso_safe_ret_alias)) == ((1 << 2) | (1 << 8) | (1 << 14) | (1 << 20)), + "SRSO function pair won't alias"); + #endif + diff --git a/queue-6.4/x86-vdso-choose-the-right-gdt_entry_cpunode-for-32-bit-getcpu-on-64-bit-kernel.patch b/queue-6.4/x86-vdso-choose-the-right-gdt_entry_cpunode-for-32-bit-getcpu-on-64-bit-kernel.patch new file mode 100644 index 00000000000..b380c9d05ae --- /dev/null +++ b/queue-6.4/x86-vdso-choose-the-right-gdt_entry_cpunode-for-32-bit-getcpu-on-64-bit-kernel.patch @@ -0,0 +1,46 @@ +From 39163d5479285a36522b6e8f9cc568cc4987db08 Mon Sep 17 00:00:00 2001 +From: Xin Li +Date: Tue, 21 Mar 2023 23:17:58 -0700 +Subject: x86/vdso: Choose the right GDT_ENTRY_CPUNODE for 32-bit getcpu() on 64-bit kernel + +From: Xin Li + +commit 39163d5479285a36522b6e8f9cc568cc4987db08 upstream. + +The vDSO getcpu() reads CPU ID from the GDT_ENTRY_CPUNODE entry when the RDPID +instruction is not available. And GDT_ENTRY_CPUNODE is defined as 28 on 32-bit +Linux kernel and 15 on 64-bit. But the 32-bit getcpu() on 64-bit Linux kernel +is compiled with 32-bit Linux kernel GDT_ENTRY_CPUNODE, i.e., 28, beyond the +64-bit Linux kernel GDT limit. Thus, it just fails _silently_. + +When BUILD_VDSO32_64 is defined, choose the 64-bit Linux kernel GDT definitions +to compile the 32-bit getcpu(). + +Fixes: 877cff5296faa6e ("x86/vdso: Fake 32bit VDSO build on 64bit compile for vgetcpu") +Reported-by: kernel test robot +Reported-by: Shan Kang +Signed-off-by: Xin Li +Signed-off-by: Thomas Gleixner +Link: https://lore.kernel.org/r/20230322061758.10639-1-xin3.li@intel.com +Link: https://lore.kernel.org/oe-lkp/202303020903.b01fd1de-yujie.liu@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/segment.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h +index 794f69625780..9d6411c65920 100644 +--- a/arch/x86/include/asm/segment.h ++++ b/arch/x86/include/asm/segment.h +@@ -56,7 +56,7 @@ + + #define GDT_ENTRY_INVALID_SEG 0 + +-#ifdef CONFIG_X86_32 ++#if defined(CONFIG_X86_32) && !defined(BUILD_VDSO32_64) + /* + * The layout of the per-CPU GDT under Linux: + * +-- +2.41.0 +