]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 12 Aug 2023 16:58:17 +0000 (18:58 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 12 Aug 2023 16:58:17 +0000 (18:58 +0200)
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

32 files changed:
queue-6.4/binder-fix-memory-leak-in-binder_init.patch [new file with mode: 0644]
queue-6.4/drm-nouveau-disp-revert-a-null-check-inside-nouveau_connector_get_modes.patch [new file with mode: 0644]
queue-6.4/iio-adc-ad7192-fix-ac-excitation-feature.patch [new file with mode: 0644]
queue-6.4/iio-adc-ina2xx-avoid-null-pointer-dereference-on-of-device-match.patch [new file with mode: 0644]
queue-6.4/iio-adc-meson-fix-core-clock-enable-disable-moment.patch [new file with mode: 0644]
queue-6.4/iio-core-prevent-invalid-memory-access-when-there-is-no-parent.patch [new file with mode: 0644]
queue-6.4/iio-cros_ec-fix-the-allocation-size-for-cros_ec_command.patch [new file with mode: 0644]
queue-6.4/iio-frequency-admv1013-propagate-errors-from-regulator_get_voltage.patch [new file with mode: 0644]
queue-6.4/iio-imu-lsm6dsx-fix-mount-matrix-retrieval.patch [new file with mode: 0644]
queue-6.4/iio-light-bu27034-fix-scale-format.patch [new file with mode: 0644]
queue-6.4/misc-rtsx-judge-aspm-mode-to-set-petxcfg-reg.patch [new file with mode: 0644]
queue-6.4/netfilter-nf_tables-adapt-set-backend-to-use-gc-transaction-api.patch [new file with mode: 0644]
queue-6.4/netfilter-nf_tables-don-t-skip-expired-elements-during-walk.patch [new file with mode: 0644]
queue-6.4/netfilter-nf_tables-gc-transaction-api-to-avoid-race-with-control-plane.patch [new file with mode: 0644]
queue-6.4/netfilter-nft_set_hash-mark-set-element-as-dead-when-deleting-from-packet-path.patch [new file with mode: 0644]
queue-6.4/revert-pci-mvebu-mark-driver-as-broken.patch [new file with mode: 0644]
queue-6.4/series
queue-6.4/thunderbolt-fix-memory-leak-in-tb_handle_dp_bandwidth_request.patch [new file with mode: 0644]
queue-6.4/usb-common-usb-conn-gpio-prevent-bailing-out-if-initial-role-is-none.patch [new file with mode: 0644]
queue-6.4/usb-dwc3-properly-handle-processing-of-pending-events.patch [new file with mode: 0644]
queue-6.4/usb-gadget-core-help-prevent-panic-during-uvc-unconfigure.patch [new file with mode: 0644]
queue-6.4/usb-storage-alauda-fix-uninit-value-in-alauda_check_media.patch [new file with mode: 0644]
queue-6.4/usb-typec-altmodes-displayport-signal-hpd-when-configuring-pin-assignment.patch [new file with mode: 0644]
queue-6.4/usb-typec-tcpm-fix-response-to-vsafe0v-event.patch [new file with mode: 0644]
queue-6.4/x86-cpu-amd-enable-zenbleed-fix-for-amd-custom-apu-0405.patch [new file with mode: 0644]
queue-6.4/x86-linkage-fix-typo-of-build_vdso-in-asm-linkage.h.patch [new file with mode: 0644]
queue-6.4/x86-mm-fix-vdso-and-vvar-placement-on-5-level-paging-machines.patch [new file with mode: 0644]
queue-6.4/x86-move-gds_ucode_mitigated-declaration-to-header.patch [new file with mode: 0644]
queue-6.4/x86-sev-do-not-try-to-parse-for-the-cc-blob-on-non-amd-hardware.patch [new file with mode: 0644]
queue-6.4/x86-speculation-add-cpu_show_gds-prototype.patch [new file with mode: 0644]
queue-6.4/x86-srso-fix-build-breakage-with-the-llvm-linker.patch [new file with mode: 0644]
queue-6.4/x86-vdso-choose-the-right-gdt_entry_cpunode-for-32-bit-getcpu-on-64-bit-kernel.patch [new file with mode: 0644]

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 (file)
index 0000000..b76191e
--- /dev/null
@@ -0,0 +1,61 @@
+From adb9743d6a08778b78d62d16b4230346d3508986 Mon Sep 17 00:00:00 2001
+From: Qi Zheng <zhengqi.arch@bytedance.com>
+Date: Sun, 25 Jun 2023 15:49:37 +0000
+Subject: binder: fix memory leak in binder_init()
+
+From: Qi Zheng <zhengqi.arch@bytedance.com>
+
+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 <zhengqi.arch@bytedance.com>
+Acked-by: Carlos Llamas <cmllamas@google.com>
+Fixes: f2517eb76f1f ("android: binder: Add global lru shrinker to binder")
+Cc: stable <stable@kernel.org>
+Link: https://lore.kernel.org/r/20230625154937.64316-1-qi.zheng@linux.dev
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7bd7185
--- /dev/null
@@ -0,0 +1,40 @@
+From d5712cd22b9cf109fded1b7f178f4c1888c8b84b Mon Sep 17 00:00:00 2001
+From: Karol Herbst <kherbst@redhat.com>
+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 <kherbst@redhat.com>
+
+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 <news@kravcenko.com>
+Cc: Lyude Paul <lyude@redhat.com>
+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 <kherbst@redhat.com>
+Reviewed-by: Lyude Paul <lyude@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230805101813.2603989-1-kherbst@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..da026fd
--- /dev/null
@@ -0,0 +1,98 @@
+From 6bc471b6c3aeaa7b95d1b86a1bb8d91a3c341fa5 Mon Sep 17 00:00:00 2001
+From: Alisa Roman <alisa.roman@analog.com>
+Date: Wed, 14 Jun 2023 18:52:43 +0300
+Subject: iio: adc: ad7192: Fix ac excitation feature
+
+From: Alisa Roman <alisa.roman@analog.com>
+
+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 <alisa.roman@analog.com>
+Cc: stable@vger.kernel.org
+Reviewed-by: Nuno Sa <nuno.sa@analog.com>
+Link: https://lore.kernel.org/r/20230614155242.160296-1-alisa.roman@analog.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..33d5f54
--- /dev/null
@@ -0,0 +1,95 @@
+From a41e19cc0d6b6a445a4133170b90271e4a2553dc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Alvin=20=C5=A0ipraga?= <alsi@bang-olufsen.dk>
+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 <alsi@bang-olufsen.dk>
+
+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 <alsi@bang-olufsen.dk>
+Fixes: c43a102e67db ("iio: ina2xx: add support for TI INA2xx Power Monitors")
+Link: https://lore.kernel.org/r/20230619141239.2257392-1-alvin@pqrs.dk
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..560be92
--- /dev/null
@@ -0,0 +1,93 @@
+From 09738ccbc4148c62d6c8c4644ff4a099d57f49ad Mon Sep 17 00:00:00 2001
+From: George Stark <gnstark@sberdevices.ru>
+Date: Fri, 21 Jul 2023 13:23:08 +0300
+Subject: iio: adc: meson: fix core clock enable/disable moment
+
+From: George Stark <gnstark@sberdevices.ru>
+
+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 <gnstark@sberdevices.ru>
+Link: https://lore.kernel.org/r/20230721102413.255726-2-gnstark@sberdevices.ru
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6969931
--- /dev/null
@@ -0,0 +1,62 @@
+From b2a69969908fcaf68596dfc04369af0fe2e1d2f7 Mon Sep 17 00:00:00 2001
+From: Milan Zamazal <mzamazal@redhat.com>
+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 <mzamazal@redhat.com>
+
+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 <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Milan Zamazal <mzamazal@redhat.com>
+Link: https://lore.kernel.org/r/20230719083208.88149-1-mzamazal@redhat.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..1760e60
--- /dev/null
@@ -0,0 +1,35 @@
+From 8a4629055ef55177b5b63dab1ecce676bd8cccdd Mon Sep 17 00:00:00 2001
+From: Yiyuan Guo <yguoaz@gmail.com>
+Date: Fri, 30 Jun 2023 22:37:19 +0800
+Subject: iio: cros_ec: Fix the allocation size for cros_ec_command
+
+From: Yiyuan Guo <yguoaz@gmail.com>
+
+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 <tzungbi@kernel.org>
+Signed-off-by: Yiyuan Guo <yguoaz@gmail.com>
+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: <Stable@vger.kerenl.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..25f5c0f
--- /dev/null
@@ -0,0 +1,44 @@
+From 507397d19b5a296aa339f7a1bd16284f668a1906 Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@linaro.org>
+Date: Tue, 18 Jul 2023 10:02:18 +0300
+Subject: iio: frequency: admv1013: propagate errors from regulator_get_voltage()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+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 <dan.carpenter@linaro.org>
+Link: https://lore.kernel.org/r/ce75aac3-2aba-4435-8419-02e59fdd862b@moroto.mountain
+Cc: <Stable@vger.kernel.org>
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..f0f5e05
--- /dev/null
@@ -0,0 +1,39 @@
+From 6811694eb2f6b7a4e97be2029edc7dd6a39460f8 Mon Sep 17 00:00:00 2001
+From: Alejandro Tafalla <atafalla@dnyon.com>
+Date: Fri, 14 Jul 2023 17:31:26 +0200
+Subject: iio: imu: lsm6dsx: Fix mount matrix retrieval
+
+From: Alejandro Tafalla <atafalla@dnyon.com>
+
+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 <atafalla@dnyon.com>
+Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://lore.kernel.org/r/20230714153132.27265-1-atafalla@dnyon.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2f0a3dd
--- /dev/null
@@ -0,0 +1,90 @@
+From d47b9b84292706784482a661324bbc178153781f Mon Sep 17 00:00:00 2001
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+Date: Tue, 13 Jun 2023 12:34:36 +0300
+Subject: iio: light: bu27034: Fix scale format
+
+From: Matti Vaittinen <mazziesaccount@gmail.com>
+
+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 <mazziesaccount@gmail.com>
+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 <Jonathan.Cameron@huawei.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..adb5765
--- /dev/null
@@ -0,0 +1,182 @@
+From 101bd907b4244a726980ee67f95ed9cafab6ff7a Mon Sep 17 00:00:00 2001
+From: Ricky WU <ricky_wu@realtek.com>
+Date: Tue, 25 Jul 2023 09:10:54 +0000
+Subject: misc: rtsx: judge ASPM Mode to set PETXCFG Reg
+
+From: Ricky WU <ricky_wu@realtek.com>
+
+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 <ricky_wu@realtek.com>
+Link: https://lore.kernel.org/r/52906c6836374c8cb068225954c5543a@realtek.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..e2729da
--- /dev/null
@@ -0,0 +1,547 @@
+From f6c383b8c31a93752a52697f8430a71dcbc46adf Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+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 <pablo@netfilter.org>
+
+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 <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..a05ea6e
--- /dev/null
@@ -0,0 +1,129 @@
+From 24138933b97b055d486e8064b4a1721702442a9b Mon Sep 17 00:00:00 2001
+From: Florian Westphal <fw@strlen.de>
+Date: Wed, 9 Aug 2023 14:31:15 +0200
+Subject: netfilter: nf_tables: don't skip expired elements during walk
+
+From: Florian Westphal <fw@strlen.de>
+
+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 <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..51973af
--- /dev/null
@@ -0,0 +1,566 @@
+From 5f68718b34a531a556f2f50300ead2862278da26 Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+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 <pablo@netfilter.org>
+
+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 <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..acb5302
--- /dev/null
@@ -0,0 +1,43 @@
+From c92db3030492b8ad1d0faace7a93bbcf53850d0c Mon Sep 17 00:00:00 2001
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+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 <pablo@netfilter.org>
+
+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 <pablo@netfilter.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..e017163
--- /dev/null
@@ -0,0 +1,39 @@
+From 3bfc37d92687b4b19056998cebc02f94fbc81427 Mon Sep 17 00:00:00 2001
+From: Bjorn Helgaas <bhelgaas@google.com>
+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 <bhelgaas@google.com>
+
+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) <linux@armlinux.org.uk>
+Link: https://lore.kernel.org/r/ZMzicVQEyHyZzBOc@shell.armlinux.org.uk
+Reported-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Link: https://lore.kernel.org/r/20230804134622.pmbymxtzxj2yfhri@pengutronix.de
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
index abdb51d2e097834cd9c894517f3e672dec09fcbe..caecc1e47429354146b28ccb61dd59eea18034ab 100644 (file)
@@ -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 (file)
index 0000000..fa5cbb0
--- /dev/null
@@ -0,0 +1,31 @@
+From 596a5123cc782d458b057eb3837e66535cd0befa Mon Sep 17 00:00:00 2001
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+Date: Thu, 22 Jun 2023 14:59:12 +0300
+Subject: thunderbolt: Fix memory leak in tb_handle_dp_bandwidth_request()
+
+From: Mika Westerberg <mika.westerberg@linux.intel.com>
+
+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 <mika.westerberg@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..73ff748
--- /dev/null
@@ -0,0 +1,62 @@
+From 8e21a620c7e6e00347ade1a6ed4967b359eada5a Mon Sep 17 00:00:00 2001
+From: Prashanth K <quic_prashk@quicinc.com>
+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 <quic_prashk@quicinc.com>
+
+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: <stable@vger.kernel.org> # 5.4
+Fixes: 4602f3bff266 ("usb: common: add USB GPIO based connection detection driver")
+Signed-off-by: Prashanth K <quic_prashk@quicinc.com>
+Tested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/1690880632-12588-1-git-send-email-quic_prashk@quicinc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..d86115b
--- /dev/null
@@ -0,0 +1,56 @@
+From 3ddaa6a274578e23745b7466346fc2650df8f959 Mon Sep 17 00:00:00 2001
+From: Elson Roy Serrao <quic_eserrao@quicinc.com>
+Date: Tue, 1 Aug 2023 12:26:58 -0700
+Subject: usb: dwc3: Properly handle processing of pending events
+
+From: Elson Roy Serrao <quic_eserrao@quicinc.com>
+
+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 <quic_eserrao@quicinc.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Reviewed-by: Roger Quadros <rogerq@kernel.org>
+Link: https://lore.kernel.org/r/20230801192658.19275-1-quic_eserrao@quicinc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9d3e664
--- /dev/null
@@ -0,0 +1,85 @@
+From 65dadb2beeb7360232b09ebc4585b54475dfee06 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Sat, 29 Jul 2023 10:59:38 -0400
+Subject: USB: Gadget: core: Help prevent panic during UVC unconfigure
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <arakesh@google.com>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+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 <badhri@google.com>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/48b2f1f1-0639-46bf-bbfc-98cb05a24914@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..00d3e9d
--- /dev/null
@@ -0,0 +1,81 @@
+From a6ff6e7a9dd69364547751db0f626a10a6d628d2 Mon Sep 17 00:00:00 2001
+From: Alan Stern <stern@rowland.harvard.edu>
+Date: Wed, 2 Aug 2023 13:49:02 -0400
+Subject: usb-storage: alauda: Fix uninit-value in alauda_check_media()
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+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 <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Fixes: e80b0fade09e ("[PATCH] USB Storage: add alauda support")
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/693d5d5e-f09b-42d0-8ed9-1f96cd30bcce@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..82706cc
--- /dev/null
@@ -0,0 +1,72 @@
+From 5a5ccd61cfd76156cb3e0373c300c509d05448ce Mon Sep 17 00:00:00 2001
+From: RD Babiera <rdbabiera@google.com>
+Date: Wed, 26 Jul 2023 02:09:02 +0000
+Subject: usb: typec: altmodes/displayport: Signal hpd when configuring pin assignment
+
+From: RD Babiera <rdbabiera@google.com>
+
+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 <rdbabiera@google.com>
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20230726020903.1409072-1-rdbabiera@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6f58eaf
--- /dev/null
@@ -0,0 +1,55 @@
+From 4270d2b4845e820b274702bfc2a7140f69e4d19d Mon Sep 17 00:00:00 2001
+From: Badhri Jagan Sridharan <badhri@google.com>
+Date: Wed, 12 Jul 2023 08:57:22 +0000
+Subject: usb: typec: tcpm: Fix response to vsafe0V event
+
+From: Badhri Jagan Sridharan <badhri@google.com>
+
+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: <stable@vger.kernel.org>
+Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20230712085722.1414743-1-badhri@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6c26795
--- /dev/null
@@ -0,0 +1,41 @@
+From 6dbef74aeb090d6bee7d64ef3fa82ae6fa53f271 Mon Sep 17 00:00:00 2001
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+Date: Fri, 11 Aug 2023 23:37:05 +0300
+Subject: x86/cpu/amd: Enable Zenbleed fix for AMD Custom APU 0405
+
+From: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
+
+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 <cristian.ciocaltea@collabora.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230811203705.1699914-1-cristian.ciocaltea@collabora.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..b9eaeb6
--- /dev/null
@@ -0,0 +1,43 @@
+From 7324f74d39531262b8e362f228b46512e6bee632 Mon Sep 17 00:00:00 2001
+From: Jinghao Jia <jinghao@linux.ibm.com>
+Date: Tue, 8 Aug 2023 14:23:53 -0400
+Subject: x86/linkage: Fix typo of BUILD_VDSO in asm/linkage.h
+
+From: Jinghao Jia <jinghao@linux.ibm.com>
+
+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 <jinghao@linux.ibm.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Randy Dunlap <rdunlap@infradead.org>
+Cc: <stable@kernel.org>
+Link: https://lore.kernel.org/r/20230808182353.76218-1-jinghao@linux.ibm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..bf69cef
--- /dev/null
@@ -0,0 +1,52 @@
+From 1b8b1aa90c9c0e825b181b98b8d9e249dc395470 Mon Sep 17 00:00:00 2001
+From: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
+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 <kirill.shutemov@linux.intel.com>
+
+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 <yingcong.wu@intel.com>
+Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+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 <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..e10e3ba
--- /dev/null
@@ -0,0 +1,48 @@
+From eb3515dc99c7c85f4170b50838136b2a193f8012 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Wed, 9 Aug 2023 15:05:00 +0200
+Subject: x86: Move gds_ucode_mitigated() declaration to header
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+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 <arnd@arndb.de>
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Tested-by: Daniel Sneddon <daniel.sneddon@linux.intel.com>
+Cc: stable@kernel.org
+Link: https://lore.kernel.org/all/20230809130530.1913368-2-arnd%40kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9f657fa
--- /dev/null
@@ -0,0 +1,118 @@
+From bee6cf1a80b54548a039e224c651bb15b644a480 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+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) <bp@alien8.de>
+
+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 <ltao@redhat.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
+Tested-by: Tao Liu <ltao@redhat.com>
+Cc: <stable@kernel.org>
+Link: https://lore.kernel.org/r/20230601072043.24439-1-ltao@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..8d08a3a
--- /dev/null
@@ -0,0 +1,38 @@
+From a57c27c7ad85c420b7de44c6ee56692d51709dda Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd@arndb.de>
+Date: Wed, 9 Aug 2023 15:04:59 +0200
+Subject: x86/speculation: Add cpu_show_gds() prototype
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+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 <arnd@arndb.de>
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Tested-by: Daniel Sneddon <daniel.sneddon@linux.intel.com>
+Cc: stable@kernel.org
+Link: https://lore.kernel.org/all/20230809130530.1913368-1-arnd%40kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..c630d9a
--- /dev/null
@@ -0,0 +1,62 @@
+From cbe8ded48b939b9d55d2c5589ab56caa7b530709 Mon Sep 17 00:00:00 2001
+From: Nick Desaulniers <ndesaulniers@google.com>
+Date: Wed, 9 Aug 2023 09:40:26 -0700
+Subject: x86/srso: Fix build breakage with the LLVM linker
+
+From: Nick Desaulniers <ndesaulniers@google.com>
+
+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 <nathan@kernel.org>
+Reported-by: Daniel Kolesa <daniel@octaforge.org>
+Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
+Suggested-by: Sven Volkinsfeld <thyrc@gmx.net>
+Signed-off-by: Nick Desaulniers <ndesaulniers@google.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+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 <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..b380c9d
--- /dev/null
@@ -0,0 +1,46 @@
+From 39163d5479285a36522b6e8f9cc568cc4987db08 Mon Sep 17 00:00:00 2001
+From: Xin Li <xin3.li@intel.com>
+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 <xin3.li@intel.com>
+
+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 <yujie.liu@intel.com>
+Reported-by: Shan Kang <shan.kang@intel.com>
+Signed-off-by: Xin Li <xin3.li@intel.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+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 <gregkh@linuxfoundation.org>
+---
+ 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
+