]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.15
authorSasha Levin <sashal@kernel.org>
Tue, 19 Sep 2023 17:29:04 +0000 (13:29 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 19 Sep 2023 17:29:04 +0000 (13:29 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
92 files changed:
queue-5.15/acpi-video-add-backlight-native-dmi-quirk-for-lenovo.patch [new file with mode: 0644]
queue-5.15/acpi-x86-s2idle-catch-multiple-acpi_type_package-obj.patch [new file with mode: 0644]
queue-5.15/acpica-add-aml_no_operand_resolve-flag-to-timer.patch [new file with mode: 0644]
queue-5.15/alsa-hda-intel-dsp-cfg-add-lunarlake-support.patch [new file with mode: 0644]
queue-5.15/alx-fix-oob-read-compiler-warning.patch [new file with mode: 0644]
queue-5.15/arm-9317-1-kexec-make-smp-stop-calls-asynchronous.patch [new file with mode: 0644]
queue-5.15/arm64-dts-qcom-sm6125-pdx201-correct-ramoops-pmsg-si.patch [new file with mode: 0644]
queue-5.15/arm64-dts-qcom-sm8150-kumano-correct-ramoops-pmsg-si.patch [new file with mode: 0644]
queue-5.15/arm64-dts-qcom-sm8250-edo-correct-ramoops-pmsg-size.patch [new file with mode: 0644]
queue-5.15/autofs-fix-memory-leak-of-waitqueues-in-autofs_catat.patch [new file with mode: 0644]
queue-5.15/btrfs-add-a-helper-to-read-the-superblock-metadata_u.patch [new file with mode: 0644]
queue-5.15/btrfs-compare-the-correct-fsid-metadata_uuid-in-btrf.patch [new file with mode: 0644]
queue-5.15/btrfs-move-btrfs_pinned_by_swapfile-prototype-into-v.patch [new file with mode: 0644]
queue-5.15/btrfs-output-extra-debug-info-if-we-failed-to-find-a.patch [new file with mode: 0644]
queue-5.15/bus-ti-sysc-configure-uart-quirks-for-k3-soc.patch [new file with mode: 0644]
queue-5.15/crypto-lib-mpi-avoid-null-pointer-deref-in-mpi_cmp_u.patch [new file with mode: 0644]
queue-5.15/crypto-lrw-xts-replace-strlcpy-with-strscpy.patch [new file with mode: 0644]
queue-5.15/devlink-remove-reload-failed-checks-in-params-get-se.patch [new file with mode: 0644]
queue-5.15/drm-amd-display-blocking-invalid-420-modes-on-hdmi-t.patch [new file with mode: 0644]
queue-5.15/drm-bridge-tc358762-instruct-dsi-host-to-generate-hs.patch [new file with mode: 0644]
queue-5.15/drm-exynos-fix-a-possible-null-pointer-dereference-d.patch [new file with mode: 0644]
queue-5.15/drm-gm12u320-fix-the-timeout-usage-for-usb_bulk_msg.patch [new file with mode: 0644]
queue-5.15/ext2-fix-datatype-of-block-number-in-ext2_xattr_set2.patch [new file with mode: 0644]
queue-5.15/fs-jfs-prevent-double-free-in-dbunmount-after-failed.patch [new file with mode: 0644]
queue-5.15/hw_breakpoint-fix-single-stepping-when-using-bpf_ove.patch [new file with mode: 0644]
queue-5.15/interconnect-fix-locking-for-runpm-vs-reclaim.patch [new file with mode: 0644]
queue-5.15/jbd2-correct-the-end-of-the-journal-recovery-scan-ra.patch [new file with mode: 0644]
queue-5.15/jbd2-fix-use-after-free-of-transaction_t-race.patch [new file with mode: 0644]
queue-5.15/jbd2-kill-t_handle_lock-transaction-spinlock.patch [new file with mode: 0644]
queue-5.15/jbd2-refactor-wait-logic-for-transaction-updates-int.patch [new file with mode: 0644]
queue-5.15/jbd2-rename-jbd_debug-to-jbd2_debug.patch [new file with mode: 0644]
queue-5.15/jfs-fix-invalid-free-of-jfs_ip-ipimap-i_imap-in-diun.patch [new file with mode: 0644]
queue-5.15/kernel-fork-beware-of-__put_task_struct-calling-cont.patch [new file with mode: 0644]
queue-5.15/kobject-add-sanity-check-for-kset-kobj.ktype-in-kset.patch [new file with mode: 0644]
queue-5.15/libbpf-free-btf_vmlinux-when-closing-bpf_object.patch [new file with mode: 0644]
queue-5.15/locks-fix-kasan-use-after-free-in-trace_event_raw_ev.patch [new file with mode: 0644]
queue-5.15/md-raid1-fix-error-iso-c90-forbids-mixed-declaration.patch [new file with mode: 0644]
queue-5.15/md-raid1-fix-potential-oob-in-raid1_remove_disk.patch [new file with mode: 0644]
queue-5.15/media-af9005-fix-null-ptr-deref-in-af9005_i2c_xfer.patch [new file with mode: 0644]
queue-5.15/media-anysee-fix-null-ptr-deref-in-anysee_master_xfe.patch [new file with mode: 0644]
queue-5.15/media-az6007-fix-null-ptr-deref-in-az6007_i2c_xfer.patch [new file with mode: 0644]
queue-5.15/media-dvb-usb-v2-af9035-fix-null-ptr-deref-in-af9035.patch [new file with mode: 0644]
queue-5.15/media-dvb-usb-v2-gl861-fix-null-ptr-deref-in-gl861_i.patch [new file with mode: 0644]
queue-5.15/media-dw2102-fix-null-ptr-deref-in-dw2102_i2c_transf.patch [new file with mode: 0644]
queue-5.15/media-pci-cx23885-replace-bug-with-error-return.patch [new file with mode: 0644]
queue-5.15/media-pci-ipu3-cio2-initialise-timing-struct-to-avoi.patch [new file with mode: 0644]
queue-5.15/media-tuners-qt1010-replace-bug_on-with-a-regular-er.patch [new file with mode: 0644]
queue-5.15/mips-use-grep-e-instead-of-egrep.patch [new file with mode: 0644]
queue-5.15/mmc-sdhci-esdhc-imx-improve-esdhc_flag_err010450.patch [new file with mode: 0644]
queue-5.15/mtd-rawnand-brcmnand-allow-soc-to-provide-i-o-operat.patch [new file with mode: 0644]
queue-5.15/mtd-rawnand-brcmnand-fix-ecc-level-field-setting-for.patch [new file with mode: 0644]
queue-5.15/netfilter-ebtables-fix-fortify-warnings-in-size_entr.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-gc-transaction-race-with-netns-d.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-make-validation-state-per-table.patch [new file with mode: 0644]
queue-5.15/netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch [new file with mode: 0644]
queue-5.15/netfilter-nft_set_hash-mark-set-element-as-dead-when.patch [new file with mode: 0644]
queue-5.15/pci-fu740-set-the-number-of-msi-vectors.patch [new file with mode: 0644]
queue-5.15/perf-build-update-build-rule-for-generated-files.patch [new file with mode: 0644]
queue-5.15/perf-imx_ddr-speed-up-overflow-frequency-of-cycle.patch [new file with mode: 0644]
queue-5.15/perf-jevents-switch-build-to-use-jevents.py.patch [new file with mode: 0644]
queue-5.15/perf-smmuv3-enable-hisilicon-erratum-162001900-quirk.patch [new file with mode: 0644]
queue-5.15/perf-test-remove-bash-construct-from-stat_bpf_counte.patch [new file with mode: 0644]
queue-5.15/perf-test-shell-stat_bpf_counters-fix-test-on-intel.patch [new file with mode: 0644]
queue-5.15/powerpc-pseries-fix-possible-memory-leak-in-ibmebus_.patch [new file with mode: 0644]
queue-5.15/printk-consolidate-console-deferred-printing.patch [new file with mode: 0644]
queue-5.15/rcuscale-move-rcu_scale_writer-schedule_timeout_unin.patch [new file with mode: 0644]
queue-5.15/samples-hw_breakpoint-fix-building-without-module-un.patch [new file with mode: 0644]
queue-5.15/samples-hw_breakpoint-fix-kernel-bug-invalid-opcode-.patch [new file with mode: 0644]
queue-5.15/scftorture-forgive-memory-allocation-failure-if-kasa.patch [new file with mode: 0644]
queue-5.15/scsi-lpfc-fix-the-null-vs-is_err-bug-for-debugfs_cre.patch [new file with mode: 0644]
queue-5.15/scsi-qla2xxx-fix-null-vs-is_err-bug-for-debugfs_crea.patch [new file with mode: 0644]
queue-5.15/scsi-target-iscsi-fix-buffer-overflow-in-lio_target_.patch [new file with mode: 0644]
queue-5.15/selftests-tracing-fix-to-unmount-tracefs-for-recover.patch [new file with mode: 0644]
queue-5.15/serial-cpm_uart-avoid-suspicious-locking.patch [new file with mode: 0644]
queue-5.15/series [new file with mode: 0644]
queue-5.15/tools-iio-iio_generic_buffer-fix-some-integer-type-a.patch [new file with mode: 0644]
queue-5.15/tpm_tis-resend-command-to-recover-from-data-transfer.patch [new file with mode: 0644]
queue-5.15/usb-cdns3-put-the-cdns-set-active-part-outside-the-s.patch [new file with mode: 0644]
queue-5.15/usb-ehci-add-workaround-for-chipidea-portsc.pec-bug.patch [new file with mode: 0644]
queue-5.15/usb-gadget-fsl_qe_udc-validate-endpoint-index-for-ch.patch [new file with mode: 0644]
queue-5.15/wifi-ath9k-fix-fortify-warnings.patch [new file with mode: 0644]
queue-5.15/wifi-ath9k-fix-printk-specifier.patch [new file with mode: 0644]
queue-5.15/wifi-mac80211-check-s1g-action-frame-size.patch [new file with mode: 0644]
queue-5.15/wifi-mac80211_hwsim-drop-short-frames.patch [new file with mode: 0644]
queue-5.15/wifi-mwifiex-fix-fortify-warning.patch [new file with mode: 0644]
queue-5.15/wifi-wil6210-fix-fortify-warnings.patch [new file with mode: 0644]
queue-5.15/x86-boot-compressed-reserve-more-memory-for-page-tab.patch [new file with mode: 0644]
queue-5.15/x86-purgatory-remove-lto-flags.patch [new file with mode: 0644]

diff --git a/queue-5.15/acpi-video-add-backlight-native-dmi-quirk-for-lenovo.patch b/queue-5.15/acpi-video-add-backlight-native-dmi-quirk-for-lenovo.patch
new file mode 100644 (file)
index 0000000..abba45e
--- /dev/null
@@ -0,0 +1,47 @@
+From e44ff03dc949f6b0a9aaf56242e2472d5c0a6ee0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 18 Apr 2023 08:42:00 +0200
+Subject: ACPI: video: Add backlight=native DMI quirk for Lenovo Ideapad Z470
+
+From: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+
+[ Upstream commit 96b709be183c56293933ef45b8b75f8af268c6de ]
+
+The Lenovo Ideapad Z470 predates Windows 8, so it defaults to using
+acpi_video for backlight control. But this is not functional on this
+model.
+
+Add a DMI quirk to use the native backlight interface which works.
+
+Link: https://bugzilla.suse.com/show_bug.cgi?id=1208724
+Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/video_detect.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
+index 038542b3a80a7..5afc42d52e49b 100644
+--- a/drivers/acpi/video_detect.c
++++ b/drivers/acpi/video_detect.c
+@@ -307,6 +307,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
+               DMI_MATCH(DMI_BOARD_NAME, "Lenovo IdeaPad S405"),
+               },
+       },
++      {
++       /* https://bugzilla.suse.com/show_bug.cgi?id=1208724 */
++       .callback = video_detect_force_native,
++       /* Lenovo Ideapad Z470 */
++       .matches = {
++              DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++              DMI_MATCH(DMI_PRODUCT_VERSION, "IdeaPad Z470"),
++              },
++      },
+       {
+        /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
+        .callback = video_detect_force_native,
+-- 
+2.40.1
+
diff --git a/queue-5.15/acpi-x86-s2idle-catch-multiple-acpi_type_package-obj.patch b/queue-5.15/acpi-x86-s2idle-catch-multiple-acpi_type_package-obj.patch
new file mode 100644 (file)
index 0000000..f8470ce
--- /dev/null
@@ -0,0 +1,41 @@
+From 374b85f8efa815db8491671792f2c18c1e53ac20 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Aug 2023 14:40:03 -0500
+Subject: ACPI: x86: s2idle: Catch multiple ACPI_TYPE_PACKAGE objects
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 883cf0d4cf288313b71146ddebdf5d647b76c78b ]
+
+If a badly constructed firmware includes multiple `ACPI_TYPE_PACKAGE`
+objects while evaluating the AMD LPS0 _DSM, there will be a memory
+leak.  Explicitly guard against this.
+
+Suggested-by: Bjorn Helgaas <helgaas@kernel.org>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/x86/s2idle.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
+index 946e0160ad3bf..ada989670d9b8 100644
+--- a/drivers/acpi/x86/s2idle.c
++++ b/drivers/acpi/x86/s2idle.c
+@@ -111,6 +111,12 @@ static void lpi_device_get_constraints_amd(void)
+               union acpi_object *package = &out_obj->package.elements[i];
+               if (package->type == ACPI_TYPE_PACKAGE) {
++                      if (lpi_constraints_table) {
++                              acpi_handle_err(lps0_device_handle,
++                                              "Duplicate constraints list\n");
++                              goto free_acpi_buffer;
++                      }
++
+                       lpi_constraints_table = kcalloc(package->package.count,
+                                                       sizeof(*lpi_constraints_table),
+                                                       GFP_KERNEL);
+-- 
+2.40.1
+
diff --git a/queue-5.15/acpica-add-aml_no_operand_resolve-flag-to-timer.patch b/queue-5.15/acpica-add-aml_no_operand_resolve-flag-to-timer.patch
new file mode 100644 (file)
index 0000000..b2a4738
--- /dev/null
@@ -0,0 +1,60 @@
+From 125fa92251d76a156855e2f5d6d660e962121298 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Jun 2023 22:26:06 +0000
+Subject: ACPICA: Add AML_NO_OPERAND_RESOLVE flag to Timer
+
+From: Abhishek Mainkar <abmainkar@nvidia.com>
+
+[ Upstream commit 3a21ffdbc825e0919db9da0e27ee5ff2cc8a863e ]
+
+ACPICA commit 90310989a0790032f5a0140741ff09b545af4bc5
+
+According to the ACPI specification 19.6.134, no argument is required to be passed for ASL Timer instruction. For taking care of no argument, AML_NO_OPERAND_RESOLVE flag is added to ASL Timer instruction opcode.
+
+When ASL timer instruction interpreted by ACPI interpreter, getting error. After adding AML_NO_OPERAND_RESOLVE flag to ASL Timer instruction opcode, issue is not observed.
+
+=============================================================
+UBSAN: array-index-out-of-bounds in acpica/dswexec.c:401:12 index -1 is out of range for type 'union acpi_operand_object *[9]'
+CPU: 37 PID: 1678 Comm: cat Not tainted
+6.0.0-dev-th500-6.0.y-1+bcf8c46459e407-generic-64k
+HW name: NVIDIA BIOS v1.1.1-d7acbfc-dirty 12/19/2022 Call trace:
+ dump_backtrace+0xe0/0x130
+ show_stack+0x20/0x60
+ dump_stack_lvl+0x68/0x84
+ dump_stack+0x18/0x34
+ ubsan_epilogue+0x10/0x50
+ __ubsan_handle_out_of_bounds+0x80/0x90
+ acpi_ds_exec_end_op+0x1bc/0x6d8
+ acpi_ps_parse_loop+0x57c/0x618
+ acpi_ps_parse_aml+0x1e0/0x4b4
+ acpi_ps_execute_method+0x24c/0x2b8
+ acpi_ns_evaluate+0x3a8/0x4bc
+ acpi_evaluate_object+0x15c/0x37c
+ acpi_evaluate_integer+0x54/0x15c
+ show_power+0x8c/0x12c [acpi_power_meter]
+
+Link: https://github.com/acpica/acpica/commit/90310989
+Signed-off-by: Abhishek Mainkar <abmainkar@nvidia.com>
+Signed-off-by: Bob Moore <robert.moore@intel.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/acpica/psopcode.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c
+index 3e80eb1a5f35c..590326c200a28 100644
+--- a/drivers/acpi/acpica/psopcode.c
++++ b/drivers/acpi/acpica/psopcode.c
+@@ -603,7 +603,7 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
+ /* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
+                        AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
+-                       AML_FLAGS_EXEC_0A_0T_1R),
++                       AML_FLAGS_EXEC_0A_0T_1R | AML_NO_OPERAND_RESOLVE),
+ /* ACPI 5.0 opcodes */
+-- 
+2.40.1
+
diff --git a/queue-5.15/alsa-hda-intel-dsp-cfg-add-lunarlake-support.patch b/queue-5.15/alsa-hda-intel-dsp-cfg-add-lunarlake-support.patch
new file mode 100644 (file)
index 0000000..a03c006
--- /dev/null
@@ -0,0 +1,43 @@
+From 4f860cc68babab85c57b9fd5ddffbbb0fec22135 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Aug 2023 10:01:04 -0500
+Subject: ALSA: hda: intel-dsp-cfg: add LunarLake support
+
+From: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+
+[ Upstream commit d2852b8c045ebd31d753b06f2810df5be30ed56a ]
+
+One more PCI ID for the road.
+
+Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
+Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
+Link: https://lore.kernel.org/r/20230802150105.24604-5-pierre-louis.bossart@linux.intel.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/hda/intel-dsp-config.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
+index 513eadcc38d90..c69d069b3f2b6 100644
+--- a/sound/hda/intel-dsp-config.c
++++ b/sound/hda/intel-dsp-config.c
+@@ -385,6 +385,14 @@ static const struct config_entry config_table[] = {
+       },
+ #endif
++/* Lunar Lake */
++#if IS_ENABLED(CONFIG_SND_SOC_SOF_LUNARLAKE)
++      /* Lunarlake-P */
++      {
++              .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
++              .device = PCI_DEVICE_ID_INTEL_HDA_LNL_P,
++      },
++#endif
+ };
+ static const struct config_entry *snd_intel_dsp_find_config
+-- 
+2.40.1
+
diff --git a/queue-5.15/alx-fix-oob-read-compiler-warning.patch b/queue-5.15/alx-fix-oob-read-compiler-warning.patch
new file mode 100644 (file)
index 0000000..f9c5e05
--- /dev/null
@@ -0,0 +1,54 @@
+From da48caa43bd9bcdd52de428d5d8294226370675a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Aug 2023 09:32:18 +0800
+Subject: alx: fix OOB-read compiler warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: GONG, Ruiqi <gongruiqi1@huawei.com>
+
+[ Upstream commit 3a198c95c95da10ad844cbeade2fe40bdf14c411 ]
+
+The following message shows up when compiling with W=1:
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘alx_get_ethtool_stats’ at drivers/net/ethernet/atheros/alx/ethtool.c:297:2:
+./include/linux/fortify-string.h:592:4: error: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Werror=attribute-warning]
+  592 |    __read_overflow2_field(q_size_field, size);
+      |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In order to get alx stats altogether, alx_get_ethtool_stats() reads
+beyond hw->stats.rx_ok. Fix this warning by directly copying hw->stats,
+and refactor the unnecessarily complicated BUILD_BUG_ON btw.
+
+Signed-off-by: GONG, Ruiqi <gongruiqi1@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/20230821013218.1614265-1-gongruiqi@huaweicloud.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/atheros/alx/ethtool.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c
+index b716adacd8159..7f6b69a523676 100644
+--- a/drivers/net/ethernet/atheros/alx/ethtool.c
++++ b/drivers/net/ethernet/atheros/alx/ethtool.c
+@@ -292,9 +292,8 @@ static void alx_get_ethtool_stats(struct net_device *netdev,
+       spin_lock(&alx->stats_lock);
+       alx_update_hw_stats(hw);
+-      BUILD_BUG_ON(sizeof(hw->stats) - offsetof(struct alx_hw_stats, rx_ok) <
+-                   ALX_NUM_STATS * sizeof(u64));
+-      memcpy(data, &hw->stats.rx_ok, ALX_NUM_STATS * sizeof(u64));
++      BUILD_BUG_ON(sizeof(hw->stats) != ALX_NUM_STATS * sizeof(u64));
++      memcpy(data, &hw->stats, sizeof(hw->stats));
+       spin_unlock(&alx->stats_lock);
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/arm-9317-1-kexec-make-smp-stop-calls-asynchronous.patch b/queue-5.15/arm-9317-1-kexec-make-smp-stop-calls-asynchronous.patch
new file mode 100644 (file)
index 0000000..1eb757a
--- /dev/null
@@ -0,0 +1,81 @@
+From 459df8e69650d9eb92d69dfa290b2c9ccc052b38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 8 Aug 2023 09:37:32 +0100
+Subject: ARM: 9317/1: kexec: Make smp stop calls asynchronous
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mårten Lindahl <marten.lindahl@axis.com>
+
+[ Upstream commit 8922ba71c969d2a0c01a94372a71477d879470de ]
+
+If a panic is triggered by a hrtimer interrupt all online cpus will be
+notified and set offline. But as highlighted by commit 19dbdcb8039c
+("smp: Warn on function calls from softirq context") this call should
+not be made synchronous with disabled interrupts:
+
+ softdog: Initiating panic
+ Kernel panic - not syncing: Software Watchdog Timer expired
+ WARNING: CPU: 1 PID: 0 at kernel/smp.c:753 smp_call_function_many_cond
+   unwind_backtrace:
+     show_stack
+     dump_stack_lvl
+     __warn
+     warn_slowpath_fmt
+     smp_call_function_many_cond
+     smp_call_function
+     crash_smp_send_stop.part.0
+     machine_crash_shutdown
+     __crash_kexec
+     panic
+     softdog_fire
+     __hrtimer_run_queues
+     hrtimer_interrupt
+
+Make the smp call for machine_crash_nonpanic_core() asynchronous.
+
+Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/kernel/machine_kexec.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
+index f567032a09c0b..6d1938d1b4df7 100644
+--- a/arch/arm/kernel/machine_kexec.c
++++ b/arch/arm/kernel/machine_kexec.c
+@@ -92,16 +92,28 @@ void machine_crash_nonpanic_core(void *unused)
+       }
+ }
++static DEFINE_PER_CPU(call_single_data_t, cpu_stop_csd) =
++      CSD_INIT(machine_crash_nonpanic_core, NULL);
++
+ void crash_smp_send_stop(void)
+ {
+       static int cpus_stopped;
+       unsigned long msecs;
++      call_single_data_t *csd;
++      int cpu, this_cpu = raw_smp_processor_id();
+       if (cpus_stopped)
+               return;
+       atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+-      smp_call_function(machine_crash_nonpanic_core, NULL, false);
++      for_each_online_cpu(cpu) {
++              if (cpu == this_cpu)
++                      continue;
++
++              csd = &per_cpu(cpu_stop_csd, cpu);
++              smp_call_function_single_async(cpu, csd);
++      }
++
+       msecs = 1000; /* Wait at most a second for the other cpus to stop */
+       while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+               mdelay(1);
+-- 
+2.40.1
+
diff --git a/queue-5.15/arm64-dts-qcom-sm6125-pdx201-correct-ramoops-pmsg-si.patch b/queue-5.15/arm64-dts-qcom-sm6125-pdx201-correct-ramoops-pmsg-si.patch
new file mode 100644 (file)
index 0000000..d1429b6
--- /dev/null
@@ -0,0 +1,39 @@
+From 3b8d1531691f3007602d91e471ac4a9e9c4ad950 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:38 +0200
+Subject: arm64: dts: qcom: sm6125-pdx201: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit c42f5452de6ad2599c6e5e2a64c180a4ac835d27 ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+  sm6125-sony-xperia-seine-pdx201.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-3-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
+index 47f8e5397ebba..8625fb3a7f0a7 100644
+--- a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
++++ b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
+@@ -74,7 +74,7 @@ pstore_mem: ramoops@ffc00000 {
+                       reg = <0x0 0xffc40000 0x0 0xc0000>;
+                       record-size = <0x1000>;
+                       console-size = <0x40000>;
+-                      msg-size = <0x20000 0x20000>;
++                      pmsg-size = <0x20000>;
+               };
+               cmdline_mem: memory@ffd00000 {
+-- 
+2.40.1
+
diff --git a/queue-5.15/arm64-dts-qcom-sm8150-kumano-correct-ramoops-pmsg-si.patch b/queue-5.15/arm64-dts-qcom-sm8150-kumano-correct-ramoops-pmsg-si.patch
new file mode 100644 (file)
index 0000000..6dbed4d
--- /dev/null
@@ -0,0 +1,39 @@
+From 84a669aef5ca58d22a47f69b373c0a7622bf53ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:41 +0200
+Subject: arm64: dts: qcom: sm8150-kumano: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 4e6b942f092653ebcdbbc0819b2d1f08ab415bdc ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+  sm8150-sony-xperia-kumano-griffin.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-6-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
+index 04c71f74ab72d..c9aa7764fc59a 100644
+--- a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
+@@ -127,7 +127,7 @@ ramoops@ffc00000 {
+                       reg = <0x0 0xffc00000 0x0 0x100000>;
+                       record-size = <0x1000>;
+                       console-size = <0x40000>;
+-                      msg-size = <0x20000 0x20000>;
++                      pmsg-size = <0x20000>;
+                       ecc-size = <16>;
+                       no-map;
+               };
+-- 
+2.40.1
+
diff --git a/queue-5.15/arm64-dts-qcom-sm8250-edo-correct-ramoops-pmsg-size.patch b/queue-5.15/arm64-dts-qcom-sm8250-edo-correct-ramoops-pmsg-size.patch
new file mode 100644 (file)
index 0000000..e709a7b
--- /dev/null
@@ -0,0 +1,39 @@
+From e399bc82cc21add3a781776a036689ebe9b03704 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 18 Jun 2023 13:44:42 +0200
+Subject: arm64: dts: qcom: sm8250-edo: correct ramoops pmsg-size
+
+From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+[ Upstream commit 7dc3606f91427414d00a2fb09e6e0e32c14c2093 ]
+
+There is no 'msg-size' property in ramoops, so assume intention was for
+'pmsg-size':
+
+  sm8250-sony-xperia-edo-pdx206.dtb: ramoops@ffc00000: Unevaluated properties are not allowed ('msg-size' was unexpected)
+
+Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
+Link: https://lore.kernel.org/r/20230618114442.140185-7-krzysztof.kozlowski@linaro.org
+Signed-off-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
+index e622cbe167b0d..aeec0b6a1d7d2 100644
+--- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
++++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
+@@ -126,7 +126,7 @@ ramoops@ffc00000 {
+                       reg = <0x0 0xffc00000 0x0 0x100000>;
+                       record-size = <0x1000>;
+                       console-size = <0x40000>;
+-                      msg-size = <0x20000 0x20000>;
++                      pmsg-size = <0x20000>;
+                       ecc-size = <16>;
+                       no-map;
+               };
+-- 
+2.40.1
+
diff --git a/queue-5.15/autofs-fix-memory-leak-of-waitqueues-in-autofs_catat.patch b/queue-5.15/autofs-fix-memory-leak-of-waitqueues-in-autofs_catat.patch
new file mode 100644 (file)
index 0000000..60a415a
--- /dev/null
@@ -0,0 +1,106 @@
+From 3dea8441155ef580ee28a40f06570a6f8b8c5c75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:33:12 +0800
+Subject: autofs: fix memory leak of waitqueues in autofs_catatonic_mode
+
+From: Fedor Pchelkin <pchelkin@ispras.ru>
+
+[ Upstream commit ccbe77f7e45dfb4420f7f531b650c00c6e9c7507 ]
+
+Syzkaller reports a memory leak:
+
+BUG: memory leak
+unreferenced object 0xffff88810b279e00 (size 96):
+  comm "syz-executor399", pid 3631, jiffies 4294964921 (age 23.870s)
+  hex dump (first 32 bytes):
+    00 00 00 00 00 00 00 00 08 9e 27 0b 81 88 ff ff  ..........'.....
+    08 9e 27 0b 81 88 ff ff 00 00 00 00 00 00 00 00  ..'.............
+  backtrace:
+    [<ffffffff814cfc90>] kmalloc_trace+0x20/0x90 mm/slab_common.c:1046
+    [<ffffffff81bb75ca>] kmalloc include/linux/slab.h:576 [inline]
+    [<ffffffff81bb75ca>] autofs_wait+0x3fa/0x9a0 fs/autofs/waitq.c:378
+    [<ffffffff81bb88a7>] autofs_do_expire_multi+0xa7/0x3e0 fs/autofs/expire.c:593
+    [<ffffffff81bb8c33>] autofs_expire_multi+0x53/0x80 fs/autofs/expire.c:619
+    [<ffffffff81bb6972>] autofs_root_ioctl_unlocked+0x322/0x3b0 fs/autofs/root.c:897
+    [<ffffffff81bb6a95>] autofs_root_ioctl+0x25/0x30 fs/autofs/root.c:910
+    [<ffffffff81602a9c>] vfs_ioctl fs/ioctl.c:51 [inline]
+    [<ffffffff81602a9c>] __do_sys_ioctl fs/ioctl.c:870 [inline]
+    [<ffffffff81602a9c>] __se_sys_ioctl fs/ioctl.c:856 [inline]
+    [<ffffffff81602a9c>] __x64_sys_ioctl+0xfc/0x140 fs/ioctl.c:856
+    [<ffffffff84608225>] do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+    [<ffffffff84608225>] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80
+    [<ffffffff84800087>] entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+autofs_wait_queue structs should be freed if their wait_ctr becomes zero.
+Otherwise they will be lost.
+
+In this case an AUTOFS_IOC_EXPIRE_MULTI ioctl is done, then a new
+waitqueue struct is allocated in autofs_wait(), its initial wait_ctr
+equals 2. After that wait_event_killable() is interrupted (it returns
+-ERESTARTSYS), so that 'wq->name.name == NULL' condition may be not
+satisfied. Actually, this condition can be satisfied when
+autofs_wait_release() or autofs_catatonic_mode() is called and, what is
+also important, wait_ctr is decremented in those places. Upon the exit of
+autofs_wait(), wait_ctr is decremented to 1. Then the unmounting process
+begins: kill_sb calls autofs_catatonic_mode(), which should have freed the
+waitqueues, but it only decrements its usage counter to zero which is not
+a correct behaviour.
+
+edit:imk
+This description is of course not correct. The umount performed as a result
+of an expire is a umount of a mount that has been automounted, it's not the
+autofs mount itself. They happen independently, usually after everything
+mounted within the autofs file system has been expired away. If everything
+hasn't been expired away the automount daemon can still exit leaving mounts
+in place. But expires done in both cases will result in a notification that
+calls autofs_wait_release() with a result status. The problem case is the
+summary execution of of the automount daemon. In this case any waiting
+processes won't be woken up until either they are terminated or the mount
+is umounted.
+end edit: imk
+
+So in catatonic mode we should free waitqueues which counter becomes zero.
+
+edit: imk
+Initially I was concerned that the calling of autofs_wait_release() and
+autofs_catatonic_mode() was not mutually exclusive but that can't be the
+case (obviously) because the queue entry (or entries) is removed from the
+list when either of these two functions are called. Consequently the wait
+entry will be freed by only one of these functions or by the woken process
+in autofs_wait() depending on the order of the calls.
+end edit: imk
+
+Reported-by: syzbot+5e53f70e69ff0c0a1c0c@syzkaller.appspotmail.com
+Suggested-by: Takeshi Misawa <jeliantsurux@gmail.com>
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Signed-off-by: Alexey Khoroshilov <khoroshilov@ispras.ru>
+Signed-off-by: Ian Kent <raven@themaw.net>
+Cc: Matthew Wilcox <willy@infradead.org>
+Cc: Andrei Vagin <avagin@gmail.com>
+Cc: autofs@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Message-Id: <169112719161.7590.6700123246297365841.stgit@donald.themaw.net>
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/autofs/waitq.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/fs/autofs/waitq.c b/fs/autofs/waitq.c
+index 54c1f8b8b0757..efdc76732faed 100644
+--- a/fs/autofs/waitq.c
++++ b/fs/autofs/waitq.c
+@@ -32,8 +32,9 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
+               wq->status = -ENOENT; /* Magic is gone - report failure */
+               kfree(wq->name.name - wq->offset);
+               wq->name.name = NULL;
+-              wq->wait_ctr--;
+               wake_up_interruptible(&wq->queue);
++              if (!--wq->wait_ctr)
++                      kfree(wq);
+               wq = nwq;
+       }
+       fput(sbi->pipe);        /* Close the pipe */
+-- 
+2.40.1
+
diff --git a/queue-5.15/btrfs-add-a-helper-to-read-the-superblock-metadata_u.patch b/queue-5.15/btrfs-add-a-helper-to-read-the-superblock-metadata_u.patch
new file mode 100644 (file)
index 0000000..7f123b6
--- /dev/null
@@ -0,0 +1,58 @@
+From be2e1d5e33d31e42fbbf194f8ac52f7ca39bf480 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 19:16:32 +0800
+Subject: btrfs: add a helper to read the superblock metadata_uuid
+
+From: Anand Jain <anand.jain@oracle.com>
+
+[ Upstream commit 4844c3664a72d36cc79752cb651c78860b14c240 ]
+
+In some cases, we need to read the FSID from the superblock when the
+metadata_uuid is not set, and otherwise, read the metadata_uuid. So,
+add a helper.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Tested-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 6bfe3959b0e7 ("btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/volumes.c | 8 ++++++++
+ fs/btrfs/volumes.h | 1 +
+ 2 files changed, 9 insertions(+)
+
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index 0e9236a745b81..56ea2ec26436f 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -709,6 +709,14 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
+       return -EINVAL;
+ }
++u8 *btrfs_sb_fsid_ptr(struct btrfs_super_block *sb)
++{
++      bool has_metadata_uuid = (btrfs_super_incompat_flags(sb) &
++                                BTRFS_FEATURE_INCOMPAT_METADATA_UUID);
++
++      return has_metadata_uuid ? sb->metadata_uuid : sb->fsid;
++}
++
+ /*
+  * Handle scanned device having its CHANGING_FSID_V2 flag set and the fs_devices
+  * being created with a disk that has already completed its fsid change. Such
+diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
+index 1f6461b568659..eb91d6eb78ceb 100644
+--- a/fs/btrfs/volumes.h
++++ b/fs/btrfs/volumes.h
+@@ -623,5 +623,6 @@ int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
+ int btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
+ bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr);
++u8 *btrfs_sb_fsid_ptr(struct btrfs_super_block *sb);
+ #endif
+-- 
+2.40.1
+
diff --git a/queue-5.15/btrfs-compare-the-correct-fsid-metadata_uuid-in-btrf.patch b/queue-5.15/btrfs-compare-the-correct-fsid-metadata_uuid-in-btrf.patch
new file mode 100644 (file)
index 0000000..bc20ab5
--- /dev/null
@@ -0,0 +1,66 @@
+From d32b33cde252666ab58801ce671ad7c80a14ef8e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 31 Jul 2023 19:16:35 +0800
+Subject: btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super
+
+From: Anand Jain <anand.jain@oracle.com>
+
+[ Upstream commit 6bfe3959b0e7a526f5c64747801a8613f002f05a ]
+
+The function btrfs_validate_super() should verify the metadata_uuid in
+the provided superblock argument. Because, all its callers expect it to
+do that.
+
+Such as in the following stacks:
+
+  write_all_supers()
+   sb = fs_info->super_for_commit;
+   btrfs_validate_write_super(.., sb)
+     btrfs_validate_super(.., sb, ..)
+
+  scrub_one_super()
+       btrfs_validate_super(.., sb, ..)
+
+And
+   check_dev_super()
+       btrfs_validate_super(.., sb, ..)
+
+However, it currently verifies the fs_info::super_copy::metadata_uuid
+instead.  Fix this using the correct metadata_uuid in the superblock
+argument.
+
+CC: stable@vger.kernel.org # 5.4+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Tested-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
+Signed-off-by: Anand Jain <anand.jain@oracle.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/disk-io.c | 8 +++-----
+ 1 file changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index 6e0fdfd98f234..f0654fe80b346 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -2605,13 +2605,11 @@ int btrfs_validate_super(struct btrfs_fs_info *fs_info,
+               ret = -EINVAL;
+       }
+-      if (btrfs_fs_incompat(fs_info, METADATA_UUID) &&
+-          memcmp(fs_info->fs_devices->metadata_uuid,
+-                 fs_info->super_copy->metadata_uuid, BTRFS_FSID_SIZE)) {
++      if (memcmp(fs_info->fs_devices->metadata_uuid, btrfs_sb_fsid_ptr(sb),
++                 BTRFS_FSID_SIZE) != 0) {
+               btrfs_err(fs_info,
+ "superblock metadata_uuid doesn't match metadata uuid of fs_devices: %pU != %pU",
+-                      fs_info->super_copy->metadata_uuid,
+-                      fs_info->fs_devices->metadata_uuid);
++                        btrfs_sb_fsid_ptr(sb), fs_info->fs_devices->metadata_uuid);
+               ret = -EINVAL;
+       }
+-- 
+2.40.1
+
diff --git a/queue-5.15/btrfs-move-btrfs_pinned_by_swapfile-prototype-into-v.patch b/queue-5.15/btrfs-move-btrfs_pinned_by_swapfile-prototype-into-v.patch
new file mode 100644 (file)
index 0000000..ceb4292
--- /dev/null
@@ -0,0 +1,50 @@
+From a0c448701a2a9f8424a92975a89e5a106ba9a3a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Sep 2022 19:04:40 -0400
+Subject: btrfs: move btrfs_pinned_by_swapfile prototype into volumes.h
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit c2e79e865b87c2920a3cd39de69c35f2bc758a51 ]
+
+This is defined in volumes.c, move the prototype into volumes.h.
+
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: Anand Jain <anand.jain@oracle.com>
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Stable-dep-of: 6bfe3959b0e7 ("btrfs: compare the correct fsid/metadata_uuid in btrfs_validate_super")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/ctree.h   | 2 --
+ fs/btrfs/volumes.h | 2 ++
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
+index 02d3ee6c7d9b0..1467bf439cb48 100644
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -536,8 +536,6 @@ struct btrfs_swapfile_pin {
+       int bg_extent_count;
+ };
+-bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr);
+-
+ enum {
+       BTRFS_FS_BARRIER,
+       BTRFS_FS_CLOSING_START,
+diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
+index b49fa784e5ba3..1f6461b568659 100644
+--- a/fs/btrfs/volumes.h
++++ b/fs/btrfs/volumes.h
+@@ -622,4 +622,6 @@ const char *btrfs_bg_type_to_raid_name(u64 flags);
+ int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
+ int btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
++bool btrfs_pinned_by_swapfile(struct btrfs_fs_info *fs_info, void *ptr);
++
+ #endif
+-- 
+2.40.1
+
diff --git a/queue-5.15/btrfs-output-extra-debug-info-if-we-failed-to-find-a.patch b/queue-5.15/btrfs-output-extra-debug-info-if-we-failed-to-find-a.patch
new file mode 100644 (file)
index 0000000..5336361
--- /dev/null
@@ -0,0 +1,52 @@
+From c77600d3b3e704450560c619f569dd42e3f09f68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Aug 2023 19:02:28 +0800
+Subject: btrfs: output extra debug info if we failed to find an inline backref
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit 7f72f50547b7af4ddf985b07fc56600a4deba281 ]
+
+[BUG]
+Syzbot reported several warning triggered inside
+lookup_inline_extent_backref().
+
+[CAUSE]
+As usual, the reproducer doesn't reliably trigger locally here, but at
+least we know the WARN_ON() is triggered when an inline backref can not
+be found, and it can only be triggered when @insert is true. (I.e.
+inserting a new inline backref, which means the backref should already
+exist)
+
+[ENHANCEMENT]
+After the WARN_ON(), dump all the parameters and the extent tree
+leaf to help debug.
+
+Link: https://syzkaller.appspot.com/bug?extid=d6f9ff86c1d804ba2bc6
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/extent-tree.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
+index 597cc2607481c..48f2de789b755 100644
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -860,6 +860,11 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
+               err = -ENOENT;
+               goto out;
+       } else if (WARN_ON(ret)) {
++              btrfs_print_leaf(path->nodes[0]);
++              btrfs_err(fs_info,
++"extent item not found for insert, bytenr %llu num_bytes %llu parent %llu root_objectid %llu owner %llu offset %llu",
++                        bytenr, num_bytes, parent, root_objectid, owner,
++                        offset);
+               err = -EIO;
+               goto out;
+       }
+-- 
+2.40.1
+
diff --git a/queue-5.15/bus-ti-sysc-configure-uart-quirks-for-k3-soc.patch b/queue-5.15/bus-ti-sysc-configure-uart-quirks-for-k3-soc.patch
new file mode 100644 (file)
index 0000000..470245b
--- /dev/null
@@ -0,0 +1,39 @@
+From a10d6ebfc7e48e8c40dc78f65ff272cbb7e2a362 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 13:38:01 +0300
+Subject: bus: ti-sysc: Configure uart quirks for k3 SoC
+
+From: Tony Lindgren <tony@atomide.com>
+
+[ Upstream commit 03a711d3cb83692733f865312f49e665c49de6de ]
+
+Enable the uart quirks similar to the earlier SoCs. Let's assume we are
+likely going to need a k3 specific quirk mask separate from the earlier
+SoCs, so let's not start changing the revision register mask at this point.
+
+Note that SYSC_QUIRK_LEGACY_IDLE will be needed until we can remove the
+need for pm_runtime_irq_safe() from 8250_omap driver.
+
+Reviewed-by: Nishanth Menon <nm@ti.com>
+Signed-off-by: Tony Lindgren <tony@atomide.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/ti-sysc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
+index 436c0f3563d79..74ab6cf031ce0 100644
+--- a/drivers/bus/ti-sysc.c
++++ b/drivers/bus/ti-sysc.c
+@@ -1504,6 +1504,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
+                  SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
+       SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff,
+                  SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
++      SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47424e03, 0xffffffff,
++                 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
+       /* Quirks that need to be set based on the module address */
+       SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff,
+-- 
+2.40.1
+
diff --git a/queue-5.15/crypto-lib-mpi-avoid-null-pointer-deref-in-mpi_cmp_u.patch b/queue-5.15/crypto-lib-mpi-avoid-null-pointer-deref-in-mpi_cmp_u.patch
new file mode 100644 (file)
index 0000000..cb80a4b
--- /dev/null
@@ -0,0 +1,45 @@
+From f7e50e935666d1382095d39c501ce1dc6191df6b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 4 Aug 2023 09:32:18 +0000
+Subject: crypto: lib/mpi - avoid null pointer deref in mpi_cmp_ui()
+
+From: Mark O'Donovan <shiftee@posteo.net>
+
+[ Upstream commit 9e47a758b70167c9301d2b44d2569f86c7796f2d ]
+
+During NVMeTCP Authentication a controller can trigger a kernel
+oops by specifying the 8192 bit Diffie Hellman group and passing
+a correctly sized, but zeroed Diffie Hellamn value.
+mpi_cmp_ui() was detecting this if the second parameter was 0,
+but 1 is passed from dh_is_pubkey_valid(). This causes the null
+pointer u->d to be dereferenced towards the end of mpi_cmp_ui()
+
+Signed-off-by: Mark O'Donovan <shiftee@posteo.net>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/mpi/mpi-cmp.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c
+index c4cfa3ff05818..0835b6213235e 100644
+--- a/lib/mpi/mpi-cmp.c
++++ b/lib/mpi/mpi-cmp.c
+@@ -25,8 +25,12 @@ int mpi_cmp_ui(MPI u, unsigned long v)
+       mpi_limb_t limb = v;
+       mpi_normalize(u);
+-      if (!u->nlimbs && !limb)
+-              return 0;
++      if (u->nlimbs == 0) {
++              if (v == 0)
++                      return 0;
++              else
++                      return -1;
++      }
+       if (u->sign)
+               return -1;
+       if (u->nlimbs > 1)
+-- 
+2.40.1
+
diff --git a/queue-5.15/crypto-lrw-xts-replace-strlcpy-with-strscpy.patch b/queue-5.15/crypto-lrw-xts-replace-strlcpy-with-strscpy.patch
new file mode 100644 (file)
index 0000000..940cb8e
--- /dev/null
@@ -0,0 +1,70 @@
+From ce0b5bbcccafb9b52b73af808b0ca3a92e1f7bc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 20 Jun 2023 20:08:32 +0000
+Subject: crypto: lrw,xts - Replace strlcpy with strscpy
+
+From: Azeem Shaikh <azeemshaikh38@gmail.com>
+
+[ Upstream commit babb80b3ecc6f40c962e13c654ebcd27f25ee327 ]
+
+strlcpy() reads the entire source buffer first.
+This read may exceed the destination size limit.
+This is both inefficient and can lead to linear read
+overflows if a source string is not NUL-terminated [1].
+In an effort to remove strlcpy() completely [2], replace
+strlcpy() here with strscpy().
+
+Direct replacement is safe here since return value of -errno
+is used to check for truncation instead of sizeof(dest).
+
+[1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
+[2] https://github.com/KSPP/linux/issues/89
+
+Signed-off-by: Azeem Shaikh <azeemshaikh38@gmail.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ crypto/lrw.c | 6 +++---
+ crypto/xts.c | 6 +++---
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/crypto/lrw.c b/crypto/lrw.c
+index bcf09fbc750af..80d9076e42e0b 100644
+--- a/crypto/lrw.c
++++ b/crypto/lrw.c
+@@ -357,10 +357,10 @@ static int lrw_create(struct crypto_template *tmpl, struct rtattr **tb)
+        * cipher name.
+        */
+       if (!strncmp(cipher_name, "ecb(", 4)) {
+-              unsigned len;
++              int len;
+-              len = strlcpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
+-              if (len < 2 || len >= sizeof(ecb_name))
++              len = strscpy(ecb_name, cipher_name + 4, sizeof(ecb_name));
++              if (len < 2)
+                       goto err_free_inst;
+               if (ecb_name[len - 1] != ')')
+diff --git a/crypto/xts.c b/crypto/xts.c
+index de6cbcf69bbd6..b05020657cdc8 100644
+--- a/crypto/xts.c
++++ b/crypto/xts.c
+@@ -396,10 +396,10 @@ static int xts_create(struct crypto_template *tmpl, struct rtattr **tb)
+        * cipher name.
+        */
+       if (!strncmp(cipher_name, "ecb(", 4)) {
+-              unsigned len;
++              int len;
+-              len = strlcpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
+-              if (len < 2 || len >= sizeof(ctx->name))
++              len = strscpy(ctx->name, cipher_name + 4, sizeof(ctx->name));
++              if (len < 2)
+                       goto err_free_inst;
+               if (ctx->name[len - 1] != ')')
+-- 
+2.40.1
+
diff --git a/queue-5.15/devlink-remove-reload-failed-checks-in-params-get-se.patch b/queue-5.15/devlink-remove-reload-failed-checks-in-params-get-se.patch
new file mode 100644 (file)
index 0000000..da4afe8
--- /dev/null
@@ -0,0 +1,68 @@
+From 5540fd63dea6acabecddda7ea1740ef0ffe223b6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Jul 2023 11:44:19 +0200
+Subject: devlink: remove reload failed checks in params get/set callbacks
+
+From: Jiri Pirko <jiri@nvidia.com>
+
+[ Upstream commit 633d76ad01ad0321a1ace3e5cc4fed06753d7ac4 ]
+
+The checks in question were introduced by:
+commit 6b4db2e528f6 ("devlink: Fix use-after-free after a failed reload").
+That fixed an issue of reload with mlxsw driver.
+
+Back then, that was a valid fix, because there was a limitation
+in place that prevented drivers from registering/unregistering params
+when devlink instance was registered.
+
+It was possible to do the fix differently by changing drivers to
+register/unregister params in appropriate places making sure the ops
+operate only on memory which is allocated and initialized. But that,
+as a dependency, would require to remove the limitation mentioned above.
+
+Eventually, this limitation was lifted by:
+commit 1d18bb1a4ddd ("devlink: allow registering parameters after the instance")
+
+Also, the alternative fix (which also fixed another issue) was done by:
+commit 74cbc3c03c82 ("mlxsw: spectrum_acl_tcam: Move devlink param to TCAM code").
+
+Therefore, the checks are no longer relevant. Each driver should make
+sure to have the params registered only when the memory the ops
+are working with is allocated and initialized.
+
+So remove the checks.
+
+Signed-off-by: Jiri Pirko <jiri@nvidia.com>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Reviewed-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/devlink.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/net/core/devlink.c b/net/core/devlink.c
+index b4d7a7f749c18..db76c55e1a6d7 100644
+--- a/net/core/devlink.c
++++ b/net/core/devlink.c
+@@ -4413,7 +4413,7 @@ static int devlink_param_get(struct devlink *devlink,
+                            const struct devlink_param *param,
+                            struct devlink_param_gset_ctx *ctx)
+ {
+-      if (!param->get || devlink->reload_failed)
++      if (!param->get)
+               return -EOPNOTSUPP;
+       return param->get(devlink, param->id, ctx);
+ }
+@@ -4422,7 +4422,7 @@ static int devlink_param_set(struct devlink *devlink,
+                            const struct devlink_param *param,
+                            struct devlink_param_gset_ctx *ctx)
+ {
+-      if (!param->set || devlink->reload_failed)
++      if (!param->set)
+               return -EOPNOTSUPP;
+       return param->set(devlink, param->id, ctx);
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/drm-amd-display-blocking-invalid-420-modes-on-hdmi-t.patch b/queue-5.15/drm-amd-display-blocking-invalid-420-modes-on-hdmi-t.patch
new file mode 100644 (file)
index 0000000..0c5f4d5
--- /dev/null
@@ -0,0 +1,42 @@
+From b828cab305955bbedd913b5a03110c322459d0a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jul 2023 16:57:36 -0400
+Subject: drm/amd/display: Blocking invalid 420 modes on HDMI TMDS for DCN31
+
+From: Leo Chen <sancchen@amd.com>
+
+[ Upstream commit 026a71babf48efb6b9884a3a66fa31aec9e1ea54 ]
+
+[Why & How]
+HDMI TMDS does not have ODM support. Filtering 420 modes that
+exceed the 4096 FMT limitation on DCN31 will resolve
+intermittent corruptions issues.
+
+Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
+Acked-by: Tom Chung <chiahsuan.chung@amd.com>
+Signed-off-by: Leo Chen <sancchen@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c    | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+index aa0507e017926..c5e0de4f77b31 100644
+--- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
++++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c
+@@ -4162,7 +4162,9 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
+                               }
+                               if (v->OutputFormat[k] == dm_420 && v->HActive[k] > DCN31_MAX_FMT_420_BUFFER_WIDTH
+                                               && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) {
+-                                      if (v->HActive[k] / 2 > DCN31_MAX_FMT_420_BUFFER_WIDTH) {
++                                      if (v->Output[k] == dm_hdmi) {
++                                              FMTBufferExceeded = true;
++                                      } else if (v->HActive[k] / 2 > DCN31_MAX_FMT_420_BUFFER_WIDTH) {
+                                               v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1;
+                                               v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1;
+-- 
+2.40.1
+
diff --git a/queue-5.15/drm-bridge-tc358762-instruct-dsi-host-to-generate-hs.patch b/queue-5.15/drm-bridge-tc358762-instruct-dsi-host-to-generate-hs.patch
new file mode 100644 (file)
index 0000000..d2c4fa2
--- /dev/null
@@ -0,0 +1,38 @@
+From 12a6145dc109804d6a33362a0bdcd8f5847f57f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Jun 2023 22:19:00 +0200
+Subject: drm/bridge: tc358762: Instruct DSI host to generate HSE packets
+
+From: Marek Vasut <marex@denx.de>
+
+[ Upstream commit 362fa8f6e6a05089872809f4465bab9d011d05b3 ]
+
+This bridge seems to need the HSE packet, otherwise the image is
+shifted up and corrupted at the bottom. This makes the bridge
+work with Samsung DSIM on i.MX8MM and i.MX8MP.
+
+Signed-off-by: Marek Vasut <marex@denx.de>
+Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
+Signed-off-by: Robert Foss <rfoss@kernel.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230615201902.566182-3-marex@denx.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/tc358762.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
+index 1bfdfc6affafe..21c57d3435687 100644
+--- a/drivers/gpu/drm/bridge/tc358762.c
++++ b/drivers/gpu/drm/bridge/tc358762.c
+@@ -224,7 +224,7 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
+       dsi->lanes = 1;
+       dsi->format = MIPI_DSI_FMT_RGB888;
+       dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
+-                        MIPI_DSI_MODE_LPM;
++                        MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_VIDEO_HSE;
+       ret = tc358762_parse_dt(ctx);
+       if (ret < 0)
+-- 
+2.40.1
+
diff --git a/queue-5.15/drm-exynos-fix-a-possible-null-pointer-dereference-d.patch b/queue-5.15/drm-exynos-fix-a-possible-null-pointer-dereference-d.patch
new file mode 100644 (file)
index 0000000..6595102
--- /dev/null
@@ -0,0 +1,61 @@
+From 3a10fcb58f5e05a48cd61b4e9fbabba29505be14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 30 Jun 2023 10:19:06 +0800
+Subject: drm/exynos: fix a possible null-pointer dereference due to data race
+ in exynos_drm_crtc_atomic_disable()
+
+From: Tuo Li <islituo@gmail.com>
+
+[ Upstream commit 2e63972a2de14482d0eae1a03a73e379f1c3f44c ]
+
+The variable crtc->state->event is often protected by the lock
+crtc->dev->event_lock when is accessed. However, it is accessed as a
+condition of an if statement in exynos_drm_crtc_atomic_disable() without
+holding the lock:
+
+  if (crtc->state->event && !crtc->state->active)
+
+However, if crtc->state->event is changed to NULL by another thread right
+after the conditions of the if statement is checked to be true, a
+null-pointer dereference can occur in drm_crtc_send_vblank_event():
+
+  e->pipe = pipe;
+
+To fix this possible null-pointer dereference caused by data race, the
+spin lock coverage is extended to protect the if statement as well as the
+function call to drm_crtc_send_vblank_event().
+
+Reported-by: BassCheck <bass@buaa.edu.cn>
+Link: https://sites.google.com/view/basscheck/home
+Signed-off-by: Tuo Li <islituo@gmail.com>
+Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+Added relevant link.
+Signed-off-by: Inki Dae <inki.dae@samsung.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/exynos/exynos_drm_crtc.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+index 4153f302de7c4..d19e796c20613 100644
+--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
++++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+@@ -39,13 +39,12 @@ static void exynos_drm_crtc_atomic_disable(struct drm_crtc *crtc,
+       if (exynos_crtc->ops->atomic_disable)
+               exynos_crtc->ops->atomic_disable(exynos_crtc);
++      spin_lock_irq(&crtc->dev->event_lock);
+       if (crtc->state->event && !crtc->state->active) {
+-              spin_lock_irq(&crtc->dev->event_lock);
+               drm_crtc_send_vblank_event(crtc, crtc->state->event);
+-              spin_unlock_irq(&crtc->dev->event_lock);
+-
+               crtc->state->event = NULL;
+       }
++      spin_unlock_irq(&crtc->dev->event_lock);
+ }
+ static int exynos_crtc_atomic_check(struct drm_crtc *crtc,
+-- 
+2.40.1
+
diff --git a/queue-5.15/drm-gm12u320-fix-the-timeout-usage-for-usb_bulk_msg.patch b/queue-5.15/drm-gm12u320-fix-the-timeout-usage-for-usb_bulk_msg.patch
new file mode 100644 (file)
index 0000000..cec5c12
--- /dev/null
@@ -0,0 +1,59 @@
+From 5db934eca7e9ab6004d863fa0a0f70cebb7fc3f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Sep 2023 10:14:20 +0800
+Subject: drm: gm12u320: Fix the timeout usage for usb_bulk_msg()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit 7583028d359db3cd0072badcc576b4f9455fd27a ]
+
+The timeout arg of usb_bulk_msg() is ms already, which has been converted
+to jiffies by msecs_to_jiffies() in usb_start_wait_urb(). So fix the usage
+by removing the redundant msecs_to_jiffies() in the macros.
+
+And as Hans suggested, also remove msecs_to_jiffies() for the IDLE_TIMEOUT
+macro to make it consistent here and so change IDLE_TIMEOUT to
+msecs_to_jiffies(IDLE_TIMEOUT) where it is used.
+
+Fixes: e4f86e437164 ("drm: Add Grain Media GM12U320 driver v2")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Suggested-by: Hans de Goede <hdegoede@redhat.com>
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Link: https://patchwork.freedesktop.org/patch/msgid/20230904021421.1663892-1-ruanjinjie@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/tiny/gm12u320.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
+index 6bc0c298739cc..9985a4419bb0c 100644
+--- a/drivers/gpu/drm/tiny/gm12u320.c
++++ b/drivers/gpu/drm/tiny/gm12u320.c
+@@ -67,10 +67,10 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)");
+ #define READ_STATUS_SIZE              13
+ #define MISC_VALUE_SIZE                       4
+-#define CMD_TIMEOUT                   msecs_to_jiffies(200)
+-#define DATA_TIMEOUT                  msecs_to_jiffies(1000)
+-#define IDLE_TIMEOUT                  msecs_to_jiffies(2000)
+-#define FIRST_FRAME_TIMEOUT           msecs_to_jiffies(2000)
++#define CMD_TIMEOUT                   200
++#define DATA_TIMEOUT                  1000
++#define IDLE_TIMEOUT                  2000
++#define FIRST_FRAME_TIMEOUT           2000
+ #define MISC_REQ_GET_SET_ECO_A                0xff
+ #define MISC_REQ_GET_SET_ECO_B                0x35
+@@ -386,7 +386,7 @@ static void gm12u320_fb_update_work(struct work_struct *work)
+        * switches back to showing its logo.
+        */
+       queue_delayed_work(system_long_wq, &gm12u320->fb_update.work,
+-                         IDLE_TIMEOUT);
++                         msecs_to_jiffies(IDLE_TIMEOUT));
+       return;
+ err:
+-- 
+2.40.1
+
diff --git a/queue-5.15/ext2-fix-datatype-of-block-number-in-ext2_xattr_set2.patch b/queue-5.15/ext2-fix-datatype-of-block-number-in-ext2_xattr_set2.patch
new file mode 100644 (file)
index 0000000..616b0cb
--- /dev/null
@@ -0,0 +1,55 @@
+From 8b0f09044cf75bb6969c682e14cfc2ec0177e31f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 12:03:40 +0200
+Subject: ext2: fix datatype of block number in ext2_xattr_set2()
+
+From: Georg Ottinger <g.ottinger@gmx.at>
+
+[ Upstream commit e88076348425b7d0491c8c98d8732a7df8de7aa3 ]
+
+I run a small server that uses external hard drives for backups. The
+backup software I use uses ext2 filesystems with 4KiB block size and
+the server is running SELinux and therefore relies on xattr. I recently
+upgraded the hard drives from 4TB to 12TB models. I noticed that after
+transferring some TBs I got a filesystem error "Freeing blocks not in
+datazone - block = 18446744071529317386, count = 1" and the backup
+process stopped. Trying to fix the fs with e2fsck resulted in a
+completely corrupted fs. The error probably came from ext2_free_blocks(),
+and because of the large number 18e19 this problem immediately looked
+like some kind of integer overflow. Whereas the 4TB fs was about 1e9
+blocks, the new 12TB is about 3e9 blocks. So, searching the ext2 code,
+I came across the line in fs/ext2/xattr.c:745 where ext2_new_block()
+is called and the resulting block number is stored in the variable block
+as an int datatype. If a block with a block number greater than
+INT32_MAX is returned, this variable overflows and the call to
+sb_getblk() at line fs/ext2/xattr.c:750 fails, then the call to
+ext2_free_blocks() produces the error.
+
+Signed-off-by: Georg Ottinger <g.ottinger@gmx.at>
+Signed-off-by: Jan Kara <jack@suse.cz>
+Message-Id: <20230815100340.22121-1-g.ottinger@gmx.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/ext2/xattr.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c
+index 841fa6d9d744b..f1dc11dab0d88 100644
+--- a/fs/ext2/xattr.c
++++ b/fs/ext2/xattr.c
+@@ -694,10 +694,10 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh,
+                       /* We need to allocate a new block */
+                       ext2_fsblk_t goal = ext2_group_first_block_no(sb,
+                                               EXT2_I(inode)->i_block_group);
+-                      int block = ext2_new_block(inode, goal, &error);
++                      ext2_fsblk_t block = ext2_new_block(inode, goal, &error);
+                       if (error)
+                               goto cleanup;
+-                      ea_idebug(inode, "creating block %d", block);
++                      ea_idebug(inode, "creating block %lu", block);
+                       new_bh = sb_getblk(sb, block);
+                       if (unlikely(!new_bh)) {
+-- 
+2.40.1
+
diff --git a/queue-5.15/fs-jfs-prevent-double-free-in-dbunmount-after-failed.patch b/queue-5.15/fs-jfs-prevent-double-free-in-dbunmount-after-failed.patch
new file mode 100644 (file)
index 0000000..5afab76
--- /dev/null
@@ -0,0 +1,121 @@
+From 47f3f08642c74c9ecf8cb24410bd125e9d092bdb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 1 Jul 2023 17:05:42 +0300
+Subject: fs/jfs: prevent double-free in dbUnmount() after failed jfs_remount()
+
+From: Andrew Kanner <andrew.kanner@gmail.com>
+
+[ Upstream commit cade5397e5461295f3cb87880534b6a07cafa427 ]
+
+Syzkaller reported the following issue:
+==================================================================
+BUG: KASAN: double-free in slab_free mm/slub.c:3787 [inline]
+BUG: KASAN: double-free in __kmem_cache_free+0x71/0x110 mm/slub.c:3800
+Free of addr ffff888086408000 by task syz-executor.4/12750
+[...]
+Call Trace:
+ <TASK>
+[...]
+ kasan_report_invalid_free+0xac/0xd0 mm/kasan/report.c:482
+ ____kasan_slab_free+0xfb/0x120
+ kasan_slab_free include/linux/kasan.h:177 [inline]
+ slab_free_hook mm/slub.c:1781 [inline]
+ slab_free_freelist_hook+0x12e/0x1a0 mm/slub.c:1807
+ slab_free mm/slub.c:3787 [inline]
+ __kmem_cache_free+0x71/0x110 mm/slub.c:3800
+ dbUnmount+0xf4/0x110 fs/jfs/jfs_dmap.c:264
+ jfs_umount+0x248/0x3b0 fs/jfs/jfs_umount.c:87
+ jfs_put_super+0x86/0x190 fs/jfs/super.c:194
+ generic_shutdown_super+0x130/0x310 fs/super.c:492
+ kill_block_super+0x79/0xd0 fs/super.c:1386
+ deactivate_locked_super+0xa7/0xf0 fs/super.c:332
+ cleanup_mnt+0x494/0x520 fs/namespace.c:1291
+ task_work_run+0x243/0x300 kernel/task_work.c:179
+ resume_user_mode_work include/linux/resume_user_mode.h:49 [inline]
+ exit_to_user_mode_loop+0x124/0x150 kernel/entry/common.c:171
+ exit_to_user_mode_prepare+0xb2/0x140 kernel/entry/common.c:203
+ __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline]
+ syscall_exit_to_user_mode+0x26/0x60 kernel/entry/common.c:296
+ do_syscall_64+0x49/0xb0 arch/x86/entry/common.c:86
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[...]
+ </TASK>
+
+Allocated by task 13352:
+ kasan_save_stack mm/kasan/common.c:45 [inline]
+ kasan_set_track+0x3d/0x60 mm/kasan/common.c:52
+ ____kasan_kmalloc mm/kasan/common.c:371 [inline]
+ __kasan_kmalloc+0x97/0xb0 mm/kasan/common.c:380
+ kmalloc include/linux/slab.h:580 [inline]
+ dbMount+0x54/0x980 fs/jfs/jfs_dmap.c:164
+ jfs_mount+0x1dd/0x830 fs/jfs/jfs_mount.c:121
+ jfs_fill_super+0x590/0xc50 fs/jfs/super.c:556
+ mount_bdev+0x26c/0x3a0 fs/super.c:1359
+ legacy_get_tree+0xea/0x180 fs/fs_context.c:610
+ vfs_get_tree+0x88/0x270 fs/super.c:1489
+ do_new_mount+0x289/0xad0 fs/namespace.c:3145
+ do_mount fs/namespace.c:3488 [inline]
+ __do_sys_mount fs/namespace.c:3697 [inline]
+ __se_sys_mount+0x2d3/0x3c0 fs/namespace.c:3674
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+
+Freed by task 13352:
+ kasan_save_stack mm/kasan/common.c:45 [inline]
+ kasan_set_track+0x3d/0x60 mm/kasan/common.c:52
+ kasan_save_free_info+0x27/0x40 mm/kasan/generic.c:518
+ ____kasan_slab_free+0xd6/0x120 mm/kasan/common.c:236
+ kasan_slab_free include/linux/kasan.h:177 [inline]
+ slab_free_hook mm/slub.c:1781 [inline]
+ slab_free_freelist_hook+0x12e/0x1a0 mm/slub.c:1807
+ slab_free mm/slub.c:3787 [inline]
+ __kmem_cache_free+0x71/0x110 mm/slub.c:3800
+ dbUnmount+0xf4/0x110 fs/jfs/jfs_dmap.c:264
+ jfs_mount_rw+0x545/0x740 fs/jfs/jfs_mount.c:247
+ jfs_remount+0x3db/0x710 fs/jfs/super.c:454
+ reconfigure_super+0x3bc/0x7b0 fs/super.c:935
+ vfs_fsconfig_locked fs/fsopen.c:254 [inline]
+ __do_sys_fsconfig fs/fsopen.c:439 [inline]
+ __se_sys_fsconfig+0xad5/0x1060 fs/fsopen.c:314
+ do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+ do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[...]
+
+JFS_SBI(ipbmap->i_sb)->bmap wasn't set to NULL after kfree() in
+dbUnmount().
+
+Syzkaller uses faultinject to reproduce this KASAN double-free
+warning. The issue is triggered if either diMount() or dbMount() fail
+in jfs_remount(), since diUnmount() or dbUnmount() already happened in
+such a case - they will do double-free on next execution: jfs_umount
+or jfs_remount.
+
+Tested on both upstream and jfs-next by syzkaller.
+
+Reported-and-tested-by: syzbot+6a93efb725385bc4b2e9@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/all/000000000000471f2d05f1ce8bad@google.com/T/
+Link: https://syzkaller.appspot.com/bug?extid=6a93efb725385bc4b2e9
+Signed-off-by: Andrew Kanner <andrew.kanner@gmail.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_dmap.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
+index f235a3d270a01..da4f9c3b714fe 100644
+--- a/fs/jfs/jfs_dmap.c
++++ b/fs/jfs/jfs_dmap.c
+@@ -269,6 +269,7 @@ int dbUnmount(struct inode *ipbmap, int mounterror)
+       /* free the memory for the in-memory bmap. */
+       kfree(bmp);
++      JFS_SBI(ipbmap->i_sb)->bmap = NULL;
+       return (0);
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/hw_breakpoint-fix-single-stepping-when-using-bpf_ove.patch b/queue-5.15/hw_breakpoint-fix-single-stepping-when-using-bpf_ove.patch
new file mode 100644 (file)
index 0000000..c63fecb
--- /dev/null
@@ -0,0 +1,150 @@
+From 52436e4b93a8f7c8f6ea87c0d328056d9668904e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 5 Jun 2023 12:19:23 -0700
+Subject: hw_breakpoint: fix single-stepping when using bpf_overflow_handler
+
+From: Tomislav Novak <tnovak@meta.com>
+
+[ Upstream commit d11a69873d9a7435fe6a48531e165ab80a8b1221 ]
+
+Arm platforms use is_default_overflow_handler() to determine if the
+hw_breakpoint code should single-step over the breakpoint trigger or
+let the custom handler deal with it.
+
+Since bpf_overflow_handler() currently isn't recognized as a default
+handler, attaching a BPF program to a PERF_TYPE_BREAKPOINT event causes
+it to keep firing (the instruction triggering the data abort exception
+is never skipped). For example:
+
+  # bpftrace -e 'watchpoint:0x10000:4:w { print("hit") }' -c ./test
+  Attaching 1 probe...
+  hit
+  hit
+  [...]
+  ^C
+
+(./test performs a single 4-byte store to 0x10000)
+
+This patch replaces the check with uses_default_overflow_handler(),
+which accounts for the bpf_overflow_handler() case by also testing
+if one of the perf_event_output functions gets invoked indirectly,
+via orig_default_handler.
+
+Signed-off-by: Tomislav Novak <tnovak@meta.com>
+Tested-by: Samuel Gosselin <sgosselin@google.com> # arm64
+Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Link: https://lore.kernel.org/linux-arm-kernel/20220923203644.2731604-1-tnovak@fb.com/
+Link: https://lore.kernel.org/r/20230605191923.1219974-1-tnovak@meta.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/arm/kernel/hw_breakpoint.c   |  8 ++++----
+ arch/arm64/kernel/hw_breakpoint.c |  4 ++--
+ include/linux/perf_event.h        | 22 +++++++++++++++++++---
+ 3 files changed, 25 insertions(+), 9 deletions(-)
+
+diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
+index b1423fb130ea4..8f1fa7aac31fb 100644
+--- a/arch/arm/kernel/hw_breakpoint.c
++++ b/arch/arm/kernel/hw_breakpoint.c
+@@ -626,7 +626,7 @@ int hw_breakpoint_arch_parse(struct perf_event *bp,
+       hw->address &= ~alignment_mask;
+       hw->ctrl.len <<= offset;
+-      if (is_default_overflow_handler(bp)) {
++      if (uses_default_overflow_handler(bp)) {
+               /*
+                * Mismatch breakpoints are required for single-stepping
+                * breakpoints.
+@@ -798,7 +798,7 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+                * Otherwise, insert a temporary mismatch breakpoint so that
+                * we can single-step over the watchpoint trigger.
+                */
+-              if (!is_default_overflow_handler(wp))
++              if (!uses_default_overflow_handler(wp))
+                       continue;
+ step:
+               enable_single_step(wp, instruction_pointer(regs));
+@@ -811,7 +811,7 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
+               info->trigger = addr;
+               pr_debug("watchpoint fired: address = 0x%x\n", info->trigger);
+               perf_bp_event(wp, regs);
+-              if (is_default_overflow_handler(wp))
++              if (uses_default_overflow_handler(wp))
+                       enable_single_step(wp, instruction_pointer(regs));
+       }
+@@ -886,7 +886,7 @@ static void breakpoint_handler(unsigned long unknown, struct pt_regs *regs)
+                       info->trigger = addr;
+                       pr_debug("breakpoint fired: address = 0x%x\n", addr);
+                       perf_bp_event(bp, regs);
+-                      if (is_default_overflow_handler(bp))
++                      if (uses_default_overflow_handler(bp))
+                               enable_single_step(bp, addr);
+                       goto unlock;
+               }
+diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c
+index 2a7f21314cde6..c30fa24458328 100644
+--- a/arch/arm64/kernel/hw_breakpoint.c
++++ b/arch/arm64/kernel/hw_breakpoint.c
+@@ -654,7 +654,7 @@ static int breakpoint_handler(unsigned long unused, unsigned long esr,
+               perf_bp_event(bp, regs);
+               /* Do we need to handle the stepping? */
+-              if (is_default_overflow_handler(bp))
++              if (uses_default_overflow_handler(bp))
+                       step = 1;
+ unlock:
+               rcu_read_unlock();
+@@ -733,7 +733,7 @@ static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
+ static int watchpoint_report(struct perf_event *wp, unsigned long addr,
+                            struct pt_regs *regs)
+ {
+-      int step = is_default_overflow_handler(wp);
++      int step = uses_default_overflow_handler(wp);
+       struct arch_hw_breakpoint *info = counter_arch_bp(wp);
+       info->trigger = addr;
+diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
+index 014eb0a963fcb..5806fc4dc7e59 100644
+--- a/include/linux/perf_event.h
++++ b/include/linux/perf_event.h
+@@ -1084,15 +1084,31 @@ extern int perf_event_output(struct perf_event *event,
+                            struct pt_regs *regs);
+ static inline bool
+-is_default_overflow_handler(struct perf_event *event)
++__is_default_overflow_handler(perf_overflow_handler_t overflow_handler)
+ {
+-      if (likely(event->overflow_handler == perf_event_output_forward))
++      if (likely(overflow_handler == perf_event_output_forward))
+               return true;
+-      if (unlikely(event->overflow_handler == perf_event_output_backward))
++      if (unlikely(overflow_handler == perf_event_output_backward))
+               return true;
+       return false;
+ }
++#define is_default_overflow_handler(event) \
++      __is_default_overflow_handler((event)->overflow_handler)
++
++#ifdef CONFIG_BPF_SYSCALL
++static inline bool uses_default_overflow_handler(struct perf_event *event)
++{
++      if (likely(is_default_overflow_handler(event)))
++              return true;
++
++      return __is_default_overflow_handler(event->orig_overflow_handler);
++}
++#else
++#define uses_default_overflow_handler(event) \
++      is_default_overflow_handler(event)
++#endif
++
+ extern void
+ perf_event_header__init_id(struct perf_event_header *header,
+                          struct perf_sample_data *data,
+-- 
+2.40.1
+
diff --git a/queue-5.15/interconnect-fix-locking-for-runpm-vs-reclaim.patch b/queue-5.15/interconnect-fix-locking-for-runpm-vs-reclaim.patch
new file mode 100644 (file)
index 0000000..9a58f7c
--- /dev/null
@@ -0,0 +1,249 @@
+From 99fb6aa85e3a9c45443684833a60087148bacd41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 10:11:40 -0700
+Subject: interconnect: Fix locking for runpm vs reclaim
+
+From: Rob Clark <robdclark@chromium.org>
+
+[ Upstream commit af42269c3523492d71ebbe11fefae2653e9cdc78 ]
+
+For cases where icc_bw_set() can be called in callbaths that could
+deadlock against shrinker/reclaim, such as runpm resume, we need to
+decouple the icc locking.  Introduce a new icc_bw_lock for cases where
+we need to serialize bw aggregation and update to decouple that from
+paths that require memory allocation such as node/link creation/
+destruction.
+
+Fixes this lockdep splat:
+
+   ======================================================
+   WARNING: possible circular locking dependency detected
+   6.2.0-rc8-debug+ #554 Not tainted
+   ------------------------------------------------------
+   ring0/132 is trying to acquire lock:
+   ffffff80871916d0 (&gmu->lock){+.+.}-{3:3}, at: a6xx_pm_resume+0xf0/0x234
+
+   but task is already holding lock:
+   ffffffdb5aee57e8 (dma_fence_map){++++}-{0:0}, at: msm_job_run+0x68/0x150
+
+   which lock already depends on the new lock.
+
+   the existing dependency chain (in reverse order) is:
+
+   -> #4 (dma_fence_map){++++}-{0:0}:
+          __dma_fence_might_wait+0x74/0xc0
+          dma_resv_lockdep+0x1f4/0x2f4
+          do_one_initcall+0x104/0x2bc
+          kernel_init_freeable+0x344/0x34c
+          kernel_init+0x30/0x134
+          ret_from_fork+0x10/0x20
+
+   -> #3 (mmu_notifier_invalidate_range_start){+.+.}-{0:0}:
+          fs_reclaim_acquire+0x80/0xa8
+          slab_pre_alloc_hook.constprop.0+0x40/0x25c
+          __kmem_cache_alloc_node+0x60/0x1cc
+          __kmalloc+0xd8/0x100
+          topology_parse_cpu_capacity+0x8c/0x178
+          get_cpu_for_node+0x88/0xc4
+          parse_cluster+0x1b0/0x28c
+          parse_cluster+0x8c/0x28c
+          init_cpu_topology+0x168/0x188
+          smp_prepare_cpus+0x24/0xf8
+          kernel_init_freeable+0x18c/0x34c
+          kernel_init+0x30/0x134
+          ret_from_fork+0x10/0x20
+
+   -> #2 (fs_reclaim){+.+.}-{0:0}:
+          __fs_reclaim_acquire+0x3c/0x48
+          fs_reclaim_acquire+0x54/0xa8
+          slab_pre_alloc_hook.constprop.0+0x40/0x25c
+          __kmem_cache_alloc_node+0x60/0x1cc
+          __kmalloc+0xd8/0x100
+          kzalloc.constprop.0+0x14/0x20
+          icc_node_create_nolock+0x4c/0xc4
+          icc_node_create+0x38/0x58
+          qcom_icc_rpmh_probe+0x1b8/0x248
+          platform_probe+0x70/0xc4
+          really_probe+0x158/0x290
+          __driver_probe_device+0xc8/0xe0
+          driver_probe_device+0x44/0x100
+          __driver_attach+0xf8/0x108
+          bus_for_each_dev+0x78/0xc4
+          driver_attach+0x2c/0x38
+          bus_add_driver+0xd0/0x1d8
+          driver_register+0xbc/0xf8
+          __platform_driver_register+0x30/0x3c
+          qnoc_driver_init+0x24/0x30
+          do_one_initcall+0x104/0x2bc
+          kernel_init_freeable+0x344/0x34c
+          kernel_init+0x30/0x134
+          ret_from_fork+0x10/0x20
+
+   -> #1 (icc_lock){+.+.}-{3:3}:
+          __mutex_lock+0xcc/0x3c8
+          mutex_lock_nested+0x30/0x44
+          icc_set_bw+0x88/0x2b4
+          _set_opp_bw+0x8c/0xd8
+          _set_opp+0x19c/0x300
+          dev_pm_opp_set_opp+0x84/0x94
+          a6xx_gmu_resume+0x18c/0x804
+          a6xx_pm_resume+0xf8/0x234
+          adreno_runtime_resume+0x2c/0x38
+          pm_generic_runtime_resume+0x30/0x44
+          __rpm_callback+0x15c/0x174
+          rpm_callback+0x78/0x7c
+          rpm_resume+0x318/0x524
+          __pm_runtime_resume+0x78/0xbc
+          adreno_load_gpu+0xc4/0x17c
+          msm_open+0x50/0x120
+          drm_file_alloc+0x17c/0x228
+          drm_open_helper+0x74/0x118
+          drm_open+0xa0/0x144
+          drm_stub_open+0xd4/0xe4
+          chrdev_open+0x1b8/0x1e4
+          do_dentry_open+0x2f8/0x38c
+          vfs_open+0x34/0x40
+          path_openat+0x64c/0x7b4
+          do_filp_open+0x54/0xc4
+          do_sys_openat2+0x9c/0x100
+          do_sys_open+0x50/0x7c
+          __arm64_sys_openat+0x28/0x34
+          invoke_syscall+0x8c/0x128
+          el0_svc_common.constprop.0+0xa0/0x11c
+          do_el0_svc+0xac/0xbc
+          el0_svc+0x48/0xa0
+          el0t_64_sync_handler+0xac/0x13c
+          el0t_64_sync+0x190/0x194
+
+   -> #0 (&gmu->lock){+.+.}-{3:3}:
+          __lock_acquire+0xe00/0x1060
+          lock_acquire+0x1e0/0x2f8
+          __mutex_lock+0xcc/0x3c8
+          mutex_lock_nested+0x30/0x44
+          a6xx_pm_resume+0xf0/0x234
+          adreno_runtime_resume+0x2c/0x38
+          pm_generic_runtime_resume+0x30/0x44
+          __rpm_callback+0x15c/0x174
+          rpm_callback+0x78/0x7c
+          rpm_resume+0x318/0x524
+          __pm_runtime_resume+0x78/0xbc
+          pm_runtime_get_sync.isra.0+0x14/0x20
+          msm_gpu_submit+0x58/0x178
+          msm_job_run+0x78/0x150
+          drm_sched_main+0x290/0x370
+          kthread+0xf0/0x100
+          ret_from_fork+0x10/0x20
+
+   other info that might help us debug this:
+
+   Chain exists of:
+     &gmu->lock --> mmu_notifier_invalidate_range_start --> dma_fence_map
+
+    Possible unsafe locking scenario:
+
+          CPU0                    CPU1
+          ----                    ----
+     lock(dma_fence_map);
+                                  lock(mmu_notifier_invalidate_range_start);
+                                  lock(dma_fence_map);
+     lock(&gmu->lock);
+
+    *** DEADLOCK ***
+
+   2 locks held by ring0/132:
+    #0: ffffff8087191170 (&gpu->lock){+.+.}-{3:3}, at: msm_job_run+0x64/0x150
+    #1: ffffffdb5aee57e8 (dma_fence_map){++++}-{0:0}, at: msm_job_run+0x68/0x150
+
+   stack backtrace:
+   CPU: 7 PID: 132 Comm: ring0 Not tainted 6.2.0-rc8-debug+ #554
+   Hardware name: Google Lazor (rev1 - 2) with LTE (DT)
+   Call trace:
+    dump_backtrace.part.0+0xb4/0xf8
+    show_stack+0x20/0x38
+    dump_stack_lvl+0x9c/0xd0
+    dump_stack+0x18/0x34
+    print_circular_bug+0x1b4/0x1f0
+    check_noncircular+0x78/0xac
+    __lock_acquire+0xe00/0x1060
+    lock_acquire+0x1e0/0x2f8
+    __mutex_lock+0xcc/0x3c8
+    mutex_lock_nested+0x30/0x44
+    a6xx_pm_resume+0xf0/0x234
+    adreno_runtime_resume+0x2c/0x38
+    pm_generic_runtime_resume+0x30/0x44
+    __rpm_callback+0x15c/0x174
+    rpm_callback+0x78/0x7c
+    rpm_resume+0x318/0x524
+    __pm_runtime_resume+0x78/0xbc
+    pm_runtime_get_sync.isra.0+0x14/0x20
+    msm_gpu_submit+0x58/0x178
+    msm_job_run+0x78/0x150
+    drm_sched_main+0x290/0x370
+    kthread+0xf0/0x100
+    ret_from_fork+0x10/0x20
+
+Signed-off-by: Rob Clark <robdclark@chromium.org>
+Link: https://lore.kernel.org/r/20230807171148.210181-7-robdclark@gmail.com
+Signed-off-by: Georgi Djakov <djakov@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/interconnect/core.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
+index 14d785e5629e6..df88d9e9fb551 100644
+--- a/drivers/interconnect/core.c
++++ b/drivers/interconnect/core.c
+@@ -29,6 +29,7 @@ static LIST_HEAD(icc_providers);
+ static int providers_count;
+ static bool synced_state;
+ static DEFINE_MUTEX(icc_lock);
++static DEFINE_MUTEX(icc_bw_lock);
+ static struct dentry *icc_debugfs_dir;
+ static void icc_summary_show_one(struct seq_file *s, struct icc_node *n)
+@@ -632,7 +633,7 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
+       if (WARN_ON(IS_ERR(path) || !path->num_nodes))
+               return -EINVAL;
+-      mutex_lock(&icc_lock);
++      mutex_lock(&icc_bw_lock);
+       old_avg = path->reqs[0].avg_bw;
+       old_peak = path->reqs[0].peak_bw;
+@@ -664,7 +665,7 @@ int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw)
+               apply_constraints(path);
+       }
+-      mutex_unlock(&icc_lock);
++      mutex_unlock(&icc_bw_lock);
+       trace_icc_set_bw_end(path, ret);
+@@ -967,6 +968,7 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
+               return;
+       mutex_lock(&icc_lock);
++      mutex_lock(&icc_bw_lock);
+       node->provider = provider;
+       list_add_tail(&node->node_list, &provider->nodes);
+@@ -992,6 +994,7 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
+       node->avg_bw = 0;
+       node->peak_bw = 0;
++      mutex_unlock(&icc_bw_lock);
+       mutex_unlock(&icc_lock);
+ }
+ EXPORT_SYMBOL_GPL(icc_node_add);
+@@ -1119,6 +1122,7 @@ void icc_sync_state(struct device *dev)
+               return;
+       mutex_lock(&icc_lock);
++      mutex_lock(&icc_bw_lock);
+       synced_state = true;
+       list_for_each_entry(p, &icc_providers, provider_list) {
+               dev_dbg(p->dev, "interconnect provider is in synced state\n");
+-- 
+2.40.1
+
diff --git a/queue-5.15/jbd2-correct-the-end-of-the-journal-recovery-scan-ra.patch b/queue-5.15/jbd2-correct-the-end-of-the-journal-recovery-scan-ra.patch
new file mode 100644 (file)
index 0000000..7e59379
--- /dev/null
@@ -0,0 +1,81 @@
+From 854c61d691b457a88e3928b61d9bd80a688c7d01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 26 Jun 2023 15:33:22 +0800
+Subject: jbd2: correct the end of the journal recovery scan range
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+[ Upstream commit 2dfba3bb40ad8536b9fa802364f2d40da31aa88e ]
+
+We got a filesystem inconsistency issue below while running generic/475
+I/O failure pressure test with fast_commit feature enabled.
+
+ Symlink /p3/d3/d1c/d6c/dd6/dce/l101 (inode #132605) is invalid.
+
+If fast_commit feature is enabled, a special fast_commit journal area is
+appended to the end of the normal journal area. The journal->j_last
+point to the first unused block behind the normal journal area instead
+of the whole log area, and the journal->j_fc_last point to the first
+unused block behind the fast_commit journal area. While doing journal
+recovery, do_one_pass(PASS_SCAN) should first scan the normal journal
+area and turn around to the first block once it meet journal->j_last,
+but the wrap() macro misuse the journal->j_fc_last, so the recovering
+could not read the next magic block (commit block perhaps) and would end
+early mistakenly and missing tN and every transaction after it in the
+following example. Finally, it could lead to filesystem inconsistency.
+
+ | normal journal area                             | fast commit area |
+ +-------------------------------------------------+------------------+
+ | tN(rere) | tN+1 |~| tN-x |...| tN-1 | tN(front) |       ....       |
+ +-------------------------------------------------+------------------+
+                     /                             /                  /
+                start               journal->j_last journal->j_fc_last
+
+This patch fix it by use the correct ending journal->j_last.
+
+Fixes: 5b849b5f96b4 ("jbd2: fast commit recovery path")
+Cc: stable@kernel.org
+Reported-by: Theodore Ts'o <tytso@mit.edu>
+Link: https://lore.kernel.org/linux-ext4/20230613043120.GB1584772@mit.edu/
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20230626073322.3956567-1-yi.zhang@huaweicloud.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/recovery.c | 12 +++---------
+ 1 file changed, 3 insertions(+), 9 deletions(-)
+
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 18f525f7f4063..cce36a76fd021 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -224,12 +224,8 @@ static int count_tags(journal_t *journal, struct buffer_head *bh)
+ /* Make sure we wrap around the log correctly! */
+ #define wrap(journal, var)                                            \
+ do {                                                                  \
+-      unsigned long _wrap_last =                                      \
+-              jbd2_has_feature_fast_commit(journal) ?                 \
+-                      (journal)->j_fc_last : (journal)->j_last;       \
+-                                                                      \
+-      if (var >= _wrap_last)                                          \
+-              var -= (_wrap_last - (journal)->j_first);               \
++      if (var >= (journal)->j_last)                                   \
++              var -= ((journal)->j_last - (journal)->j_first);        \
+ } while (0)
+ static int fc_do_one_pass(journal_t *journal,
+@@ -512,9 +508,7 @@ static int do_one_pass(journal_t *journal,
+                               break;
+               jbd2_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
+-                        next_commit_ID, next_log_block,
+-                        jbd2_has_feature_fast_commit(journal) ?
+-                        journal->j_fc_last : journal->j_last);
++                        next_commit_ID, next_log_block, journal->j_last);
+               /* Skip over each chunk of the transaction looking
+                * either the next descriptor block or the final commit
+-- 
+2.40.1
+
diff --git a/queue-5.15/jbd2-fix-use-after-free-of-transaction_t-race.patch b/queue-5.15/jbd2-fix-use-after-free-of-transaction_t-race.patch
new file mode 100644 (file)
index 0000000..ed21d8a
--- /dev/null
@@ -0,0 +1,98 @@
+From 595c6ae2d96f1536443ae80d3599e42159e94ebf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Feb 2022 21:07:11 +0530
+Subject: jbd2: fix use-after-free of transaction_t race
+
+From: Ritesh Harjani <riteshh@linux.ibm.com>
+
+[ Upstream commit cc16eecae687912238ee6efbff71ad31e2bc414e ]
+
+jbd2_journal_wait_updates() is called with j_state_lock held. But if
+there is a commit in progress, then this transaction might get committed
+and freed via jbd2_journal_commit_transaction() ->
+jbd2_journal_free_transaction(), when we release j_state_lock.
+So check for journal->j_running_transaction everytime we release and
+acquire j_state_lock to avoid use-after-free issue.
+
+Link: https://lore.kernel.org/r/948c2fed518ae739db6a8f7f83f1d58b504f87d0.1644497105.git.ritesh.list@gmail.com
+Fixes: 4f98186848707f53 ("jbd2: refactor wait logic for transaction updates into a common function")
+Cc: stable@kernel.org
+Reported-and-tested-by: syzbot+afa2ca5171d93e44b348@syzkaller.appspotmail.com
+Reviewed-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Ritesh Harjani <riteshh@linux.ibm.com>
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 2dfba3bb40ad ("jbd2: correct the end of the journal recovery scan range")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/transaction.c | 41 +++++++++++++++++++++++++----------------
+ 1 file changed, 25 insertions(+), 16 deletions(-)
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 69aed72c8206d..59292b82d4424 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -842,27 +842,38 @@ EXPORT_SYMBOL(jbd2_journal_restart);
+  */
+ void jbd2_journal_wait_updates(journal_t *journal)
+ {
+-      transaction_t *commit_transaction = journal->j_running_transaction;
++      DEFINE_WAIT(wait);
+-      if (!commit_transaction)
+-              return;
++      while (1) {
++              /*
++               * Note that the running transaction can get freed under us if
++               * this transaction is getting committed in
++               * jbd2_journal_commit_transaction() ->
++               * jbd2_journal_free_transaction(). This can only happen when we
++               * release j_state_lock -> schedule() -> acquire j_state_lock.
++               * Hence we should everytime retrieve new j_running_transaction
++               * value (after j_state_lock release acquire cycle), else it may
++               * lead to use-after-free of old freed transaction.
++               */
++              transaction_t *transaction = journal->j_running_transaction;
+-      spin_lock(&commit_transaction->t_handle_lock);
+-      while (atomic_read(&commit_transaction->t_updates)) {
+-              DEFINE_WAIT(wait);
++              if (!transaction)
++                      break;
++              spin_lock(&transaction->t_handle_lock);
+               prepare_to_wait(&journal->j_wait_updates, &wait,
+-                                      TASK_UNINTERRUPTIBLE);
+-              if (atomic_read(&commit_transaction->t_updates)) {
+-                      spin_unlock(&commit_transaction->t_handle_lock);
+-                      write_unlock(&journal->j_state_lock);
+-                      schedule();
+-                      write_lock(&journal->j_state_lock);
+-                      spin_lock(&commit_transaction->t_handle_lock);
++                              TASK_UNINTERRUPTIBLE);
++              if (!atomic_read(&transaction->t_updates)) {
++                      spin_unlock(&transaction->t_handle_lock);
++                      finish_wait(&journal->j_wait_updates, &wait);
++                      break;
+               }
++              spin_unlock(&transaction->t_handle_lock);
++              write_unlock(&journal->j_state_lock);
++              schedule();
+               finish_wait(&journal->j_wait_updates, &wait);
++              write_lock(&journal->j_state_lock);
+       }
+-      spin_unlock(&commit_transaction->t_handle_lock);
+ }
+ /**
+@@ -877,8 +888,6 @@ void jbd2_journal_wait_updates(journal_t *journal)
+  */
+ void jbd2_journal_lock_updates(journal_t *journal)
+ {
+-      DEFINE_WAIT(wait);
+-
+       jbd2_might_wait_for_commit(journal);
+       write_lock(&journal->j_state_lock);
+-- 
+2.40.1
+
diff --git a/queue-5.15/jbd2-kill-t_handle_lock-transaction-spinlock.patch b/queue-5.15/jbd2-kill-t_handle_lock-transaction-spinlock.patch
new file mode 100644 (file)
index 0000000..ba5f3c0
--- /dev/null
@@ -0,0 +1,183 @@
+From 1900631a08796f9632672056dbc5067e4bb4ea6e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 16 Feb 2022 12:30:35 +0530
+Subject: jbd2: kill t_handle_lock transaction spinlock
+
+From: Ritesh Harjani <riteshh@linux.ibm.com>
+
+[ Upstream commit f7f497cb702462e8505ff3d8d4e7722ad95626a1 ]
+
+This patch kills t_handle_lock transaction spinlock completely from
+jbd2.
+
+To explain the reasoning, currently there were three sites at which
+this spinlock was used.
+
+1. jbd2_journal_wait_updates()
+   a. Based on careful code review it can be seen that, we don't need this
+      lock here. This is since we wait for any currently ongoing updates
+      based on a atomic variable t_updates. And we anyway don't take any
+      t_handle_lock while in stop_this_handle().
+      i.e.
+
+       write_lock(&journal->j_state_lock()
+       jbd2_journal_wait_updates()                     stop_this_handle()
+               while (atomic_read(txn->t_updates) {            |
+               DEFINE_WAIT(wait);                              |
+               prepare_to_wait();                              |
+               if (atomic_read(txn->t_updates)                 if (atomic_dec_and_test(txn->t_updates))
+                       write_unlock(&journal->j_state_lock);
+                       schedule();                                     wake_up()
+                       write_lock(&journal->j_state_lock);
+               finish_wait();
+          }
+       txn->t_state = T_COMMIT
+       write_unlock(&journal->j_state_lock);
+
+   b.  Also note that between atomic_inc(&txn->t_updates) in
+       start_this_handle() and jbd2_journal_wait_updates(), the
+       synchronization happens via read_lock(journal->j_state_lock) in
+       start_this_handle();
+
+2. jbd2_journal_extend()
+   a. jbd2_journal_extend() is called with the handle of each process from
+      task_struct. So no lock required in updating member fields of handle_t
+
+   b. For member fields of h_transaction, all updates happens only via
+      atomic APIs (which is also within read_lock()).
+      So, no need of this transaction spinlock.
+
+3. update_t_max_wait()
+   Based on Jan suggestion, this can be carefully removed using atomic
+   cmpxchg API.
+   Note that there can be several processes which are waiting for a new
+   transaction to be allocated and started. For doing this only one
+   process will succeed in taking write_lock() and allocating a new txn.
+   After that all of the process will be updating the t_max_wait (max
+   transaction wait time). This can be done via below method w/o taking
+   any locks using atomic cmpxchg.
+   For more details refer [1]
+
+          new = get_new_val();
+          old = READ_ONCE(ptr->max_val);
+          while (old < new)
+               old = cmpxchg(&ptr->max_val, old, new);
+
+[1]: https://lwn.net/Articles/849237/
+
+Suggested-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Ritesh Harjani <riteshh@linux.ibm.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/d89e599658b4a1f3893a48c6feded200073037fc.1644992076.git.riteshh@linux.ibm.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 2dfba3bb40ad ("jbd2: correct the end of the journal recovery scan range")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/transaction.c | 28 +++++++++-------------------
+ include/linux/jbd2.h  |  3 ---
+ 2 files changed, 9 insertions(+), 22 deletions(-)
+
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 59292b82d4424..b31145b2bb6bf 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -107,7 +107,6 @@ static void jbd2_get_transaction(journal_t *journal,
+       transaction->t_start_time = ktime_get();
+       transaction->t_tid = journal->j_transaction_sequence++;
+       transaction->t_expires = jiffies + journal->j_commit_interval;
+-      spin_lock_init(&transaction->t_handle_lock);
+       atomic_set(&transaction->t_updates, 0);
+       atomic_set(&transaction->t_outstanding_credits,
+                  jbd2_descriptor_blocks_per_trans(journal) +
+@@ -139,24 +138,21 @@ static void jbd2_get_transaction(journal_t *journal,
+ /*
+  * Update transaction's maximum wait time, if debugging is enabled.
+  *
+- * In order for t_max_wait to be reliable, it must be protected by a
+- * lock.  But doing so will mean that start_this_handle() can not be
+- * run in parallel on SMP systems, which limits our scalability.  So
+- * unless debugging is enabled, we no longer update t_max_wait, which
+- * means that maximum wait time reported by the jbd2_run_stats
+- * tracepoint will always be zero.
++ * t_max_wait is carefully updated here with use of atomic compare exchange.
++ * Note that there could be multiplre threads trying to do this simultaneously
++ * hence using cmpxchg to avoid any use of locks in this case.
+  */
+ static inline void update_t_max_wait(transaction_t *transaction,
+                                    unsigned long ts)
+ {
+ #ifdef CONFIG_JBD2_DEBUG
++      unsigned long oldts, newts;
+       if (jbd2_journal_enable_debug &&
+           time_after(transaction->t_start, ts)) {
+-              ts = jbd2_time_diff(ts, transaction->t_start);
+-              spin_lock(&transaction->t_handle_lock);
+-              if (ts > transaction->t_max_wait)
+-                      transaction->t_max_wait = ts;
+-              spin_unlock(&transaction->t_handle_lock);
++              newts = jbd2_time_diff(ts, transaction->t_start);
++              oldts = READ_ONCE(transaction->t_max_wait);
++              while (oldts < newts)
++                      oldts = cmpxchg(&transaction->t_max_wait, oldts, newts);
+       }
+ #endif
+ }
+@@ -690,7 +686,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks, int revoke_records)
+               DIV_ROUND_UP(
+                       handle->h_revoke_credits_requested,
+                       journal->j_revoke_records_per_block);
+-      spin_lock(&transaction->t_handle_lock);
+       wanted = atomic_add_return(nblocks,
+                                  &transaction->t_outstanding_credits);
+@@ -698,7 +693,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks, int revoke_records)
+               jbd_debug(3, "denied handle %p %d blocks: "
+                         "transaction too large\n", handle, nblocks);
+               atomic_sub(nblocks, &transaction->t_outstanding_credits);
+-              goto unlock;
++              goto error_out;
+       }
+       trace_jbd2_handle_extend(journal->j_fs_dev->bd_dev,
+@@ -714,8 +709,6 @@ int jbd2_journal_extend(handle_t *handle, int nblocks, int revoke_records)
+       result = 0;
+       jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
+-unlock:
+-      spin_unlock(&transaction->t_handle_lock);
+ error_out:
+       read_unlock(&journal->j_state_lock);
+       return result;
+@@ -860,15 +853,12 @@ void jbd2_journal_wait_updates(journal_t *journal)
+               if (!transaction)
+                       break;
+-              spin_lock(&transaction->t_handle_lock);
+               prepare_to_wait(&journal->j_wait_updates, &wait,
+                               TASK_UNINTERRUPTIBLE);
+               if (!atomic_read(&transaction->t_updates)) {
+-                      spin_unlock(&transaction->t_handle_lock);
+                       finish_wait(&journal->j_wait_updates, &wait);
+                       break;
+               }
+-              spin_unlock(&transaction->t_handle_lock);
+               write_unlock(&journal->j_state_lock);
+               schedule();
+               finish_wait(&journal->j_wait_updates, &wait);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index 03d8ba98cbeb7..f29fda630b2de 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -554,9 +554,6 @@ struct transaction_chp_stats_s {
+  *    ->j_list_lock
+  *
+  *    j_state_lock
+- *    ->t_handle_lock
+- *
+- *    j_state_lock
+  *    ->j_list_lock                   (journal_unmap_buffer)
+  *
+  */
+-- 
+2.40.1
+
diff --git a/queue-5.15/jbd2-refactor-wait-logic-for-transaction-updates-int.patch b/queue-5.15/jbd2-refactor-wait-logic-for-transaction-updates-int.patch
new file mode 100644 (file)
index 0000000..26b9dda
--- /dev/null
@@ -0,0 +1,168 @@
+From e598f6cd22307481bf195bbfc799d2a8ce822f7d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jan 2022 17:41:51 +0530
+Subject: jbd2: refactor wait logic for transaction updates into a common
+ function
+
+From: Ritesh Harjani <riteshh@linux.ibm.com>
+
+[ Upstream commit 4f98186848707f530669238d90e0562d92a78aab ]
+
+No functionality change as such in this patch. This only refactors the
+common piece of code which waits for t_updates to finish into a common
+function named as jbd2_journal_wait_updates(journal_t *)
+
+Signed-off-by: Ritesh Harjani <riteshh@linux.ibm.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/8c564f70f4b2591171677a2a74fccb22a7b6c3a4.1642416995.git.riteshh@linux.ibm.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 2dfba3bb40ad ("jbd2: correct the end of the journal recovery scan range")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/commit.c      | 19 +++-------------
+ fs/jbd2/transaction.c | 53 ++++++++++++++++++++++++++-----------------
+ include/linux/jbd2.h  |  4 +++-
+ 3 files changed, 38 insertions(+), 38 deletions(-)
+
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 20294c1bbeab7..2705850ca6460 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -484,22 +484,9 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       stats.run.rs_running = jbd2_time_diff(commit_transaction->t_start,
+                                             stats.run.rs_locked);
+-      spin_lock(&commit_transaction->t_handle_lock);
+-      while (atomic_read(&commit_transaction->t_updates)) {
+-              DEFINE_WAIT(wait);
++      // waits for any t_updates to finish
++      jbd2_journal_wait_updates(journal);
+-              prepare_to_wait(&journal->j_wait_updates, &wait,
+-                                      TASK_UNINTERRUPTIBLE);
+-              if (atomic_read(&commit_transaction->t_updates)) {
+-                      spin_unlock(&commit_transaction->t_handle_lock);
+-                      write_unlock(&journal->j_state_lock);
+-                      schedule();
+-                      write_lock(&journal->j_state_lock);
+-                      spin_lock(&commit_transaction->t_handle_lock);
+-              }
+-              finish_wait(&journal->j_wait_updates, &wait);
+-      }
+-      spin_unlock(&commit_transaction->t_handle_lock);
+       commit_transaction->t_state = T_SWITCH;
+       J_ASSERT (atomic_read(&commit_transaction->t_outstanding_credits) <=
+@@ -819,7 +806,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       commit_transaction->t_state = T_COMMIT_DFLUSH;
+       write_unlock(&journal->j_state_lock);
+-      /* 
++      /*
+        * If the journal is not located on the file system device,
+        * then we must flush the file system device before we issue
+        * the commit record
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index 62e68c5b8ec3d..69aed72c8206d 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -449,7 +449,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+       }
+       /* OK, account for the buffers that this operation expects to
+-       * use and add the handle to the running transaction. 
++       * use and add the handle to the running transaction.
+        */
+       update_t_max_wait(transaction, ts);
+       handle->h_transaction = transaction;
+@@ -836,6 +836,35 @@ int jbd2_journal_restart(handle_t *handle, int nblocks)
+ }
+ EXPORT_SYMBOL(jbd2_journal_restart);
++/*
++ * Waits for any outstanding t_updates to finish.
++ * This is called with write j_state_lock held.
++ */
++void jbd2_journal_wait_updates(journal_t *journal)
++{
++      transaction_t *commit_transaction = journal->j_running_transaction;
++
++      if (!commit_transaction)
++              return;
++
++      spin_lock(&commit_transaction->t_handle_lock);
++      while (atomic_read(&commit_transaction->t_updates)) {
++              DEFINE_WAIT(wait);
++
++              prepare_to_wait(&journal->j_wait_updates, &wait,
++                                      TASK_UNINTERRUPTIBLE);
++              if (atomic_read(&commit_transaction->t_updates)) {
++                      spin_unlock(&commit_transaction->t_handle_lock);
++                      write_unlock(&journal->j_state_lock);
++                      schedule();
++                      write_lock(&journal->j_state_lock);
++                      spin_lock(&commit_transaction->t_handle_lock);
++              }
++              finish_wait(&journal->j_wait_updates, &wait);
++      }
++      spin_unlock(&commit_transaction->t_handle_lock);
++}
++
+ /**
+  * jbd2_journal_lock_updates () - establish a transaction barrier.
+  * @journal:  Journal to establish a barrier on.
+@@ -863,27 +892,9 @@ void jbd2_journal_lock_updates(journal_t *journal)
+               write_lock(&journal->j_state_lock);
+       }
+-      /* Wait until there are no running updates */
+-      while (1) {
+-              transaction_t *transaction = journal->j_running_transaction;
+-
+-              if (!transaction)
+-                      break;
++      /* Wait until there are no running t_updates */
++      jbd2_journal_wait_updates(journal);
+-              spin_lock(&transaction->t_handle_lock);
+-              prepare_to_wait(&journal->j_wait_updates, &wait,
+-                              TASK_UNINTERRUPTIBLE);
+-              if (!atomic_read(&transaction->t_updates)) {
+-                      spin_unlock(&transaction->t_handle_lock);
+-                      finish_wait(&journal->j_wait_updates, &wait);
+-                      break;
+-              }
+-              spin_unlock(&transaction->t_handle_lock);
+-              write_unlock(&journal->j_state_lock);
+-              schedule();
+-              finish_wait(&journal->j_wait_updates, &wait);
+-              write_lock(&journal->j_state_lock);
+-      }
+       write_unlock(&journal->j_state_lock);
+       /*
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index ade8a6d7acff9..03d8ba98cbeb7 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -594,7 +594,7 @@ struct transaction_s
+        */
+       unsigned long           t_log_start;
+-      /* 
++      /*
+        * Number of buffers on the t_buffers list [j_list_lock, no locks
+        * needed for jbd2 thread]
+        */
+@@ -1538,6 +1538,8 @@ extern int        jbd2_journal_flush(journal_t *journal, unsigned int flags);
+ extern void    jbd2_journal_lock_updates (journal_t *);
+ extern void    jbd2_journal_unlock_updates (journal_t *);
++void jbd2_journal_wait_updates(journal_t *);
++
+ extern journal_t * jbd2_journal_init_dev(struct block_device *bdev,
+                               struct block_device *fs_dev,
+                               unsigned long long start, int len, int bsize);
+-- 
+2.40.1
+
diff --git a/queue-5.15/jbd2-rename-jbd_debug-to-jbd2_debug.patch b/queue-5.15/jbd2-rename-jbd_debug-to-jbd2_debug.patch
new file mode 100644 (file)
index 0000000..b31871a
--- /dev/null
@@ -0,0 +1,660 @@
+From 5ba2c41042c9f8973c9fccea693bdb728a6fa3c5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jun 2022 13:23:48 +0200
+Subject: jbd2: rename jbd_debug() to jbd2_debug()
+
+From: Jan Kara <jack@suse.cz>
+
+[ Upstream commit cb3b3bf22cf33707d684e74207908ba0ef3b6467 ]
+
+The name of jbd_debug() is confusing as all functions inside jbd2 have
+jbd2_ prefix. Rename jbd_debug() to jbd2_debug(). No functional changes.
+
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Lukas Czerner <lczerner@redhat.com>
+Link: https://lore.kernel.org/r/20220608112355.4397-2-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Stable-dep-of: 2dfba3bb40ad ("jbd2: correct the end of the journal recovery scan range")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jbd2/checkpoint.c  |  6 +++---
+ fs/jbd2/commit.c      | 30 +++++++++++++++---------------
+ fs/jbd2/journal.c     | 34 +++++++++++++++++-----------------
+ fs/jbd2/recovery.c    | 30 +++++++++++++++---------------
+ fs/jbd2/revoke.c      |  8 ++++----
+ fs/jbd2/transaction.c | 26 +++++++++++++-------------
+ include/linux/jbd2.h  |  4 ++--
+ 7 files changed, 69 insertions(+), 69 deletions(-)
+
+diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c
+index 95d5bb7d825a6..f033ac807013c 100644
+--- a/fs/jbd2/checkpoint.c
++++ b/fs/jbd2/checkpoint.c
+@@ -165,7 +165,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+       tid_t                   this_tid;
+       int                     result, batch_count = 0;
+-      jbd_debug(1, "Start checkpoint\n");
++      jbd2_debug(1, "Start checkpoint\n");
+       /*
+        * First thing: if there are any transactions in the log which
+@@ -174,7 +174,7 @@ int jbd2_log_do_checkpoint(journal_t *journal)
+        */
+       result = jbd2_cleanup_journal_tail(journal);
+       trace_jbd2_checkpoint(journal, result);
+-      jbd_debug(1, "cleanup_journal_tail returned %d\n", result);
++      jbd2_debug(1, "cleanup_journal_tail returned %d\n", result);
+       if (result <= 0)
+               return result;
+@@ -725,5 +725,5 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
+       trace_jbd2_drop_transaction(journal, transaction);
+-      jbd_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
++      jbd2_debug(1, "Dropping transaction %d, all done\n", transaction->t_tid);
+ }
+diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
+index 2705850ca6460..e058ef1839377 100644
+--- a/fs/jbd2/commit.c
++++ b/fs/jbd2/commit.c
+@@ -419,7 +419,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       /* Do we need to erase the effects of a prior jbd2_journal_flush? */
+       if (journal->j_flags & JBD2_FLUSHED) {
+-              jbd_debug(3, "super block updated\n");
++              jbd2_debug(3, "super block updated\n");
+               mutex_lock_io(&journal->j_checkpoint_mutex);
+               /*
+                * We hold j_checkpoint_mutex so tail cannot change under us.
+@@ -433,7 +433,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+                                               REQ_SYNC);
+               mutex_unlock(&journal->j_checkpoint_mutex);
+       } else {
+-              jbd_debug(3, "superblock not updated\n");
++              jbd2_debug(3, "superblock not updated\n");
+       }
+       J_ASSERT(journal->j_running_transaction != NULL);
+@@ -465,7 +465,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       commit_transaction = journal->j_running_transaction;
+       trace_jbd2_start_commit(journal, commit_transaction);
+-      jbd_debug(1, "JBD2: starting commit of transaction %d\n",
++      jbd2_debug(1, "JBD2: starting commit of transaction %d\n",
+                       commit_transaction->t_tid);
+       write_lock(&journal->j_state_lock);
+@@ -538,7 +538,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       __jbd2_journal_clean_checkpoint_list(journal, false);
+       spin_unlock(&journal->j_list_lock);
+-      jbd_debug(3, "JBD2: commit phase 1\n");
++      jbd2_debug(3, "JBD2: commit phase 1\n");
+       /*
+        * Clear revoked flag to reflect there is no revoked buffers
+@@ -571,7 +571,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       wake_up_all(&journal->j_wait_transaction_locked);
+       write_unlock(&journal->j_state_lock);
+-      jbd_debug(3, "JBD2: commit phase 2a\n");
++      jbd2_debug(3, "JBD2: commit phase 2a\n");
+       /*
+        * Now start flushing things to disk, in the order they appear
+@@ -584,7 +584,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       blk_start_plug(&plug);
+       jbd2_journal_write_revoke_records(commit_transaction, &log_bufs);
+-      jbd_debug(3, "JBD2: commit phase 2b\n");
++      jbd2_debug(3, "JBD2: commit phase 2b\n");
+       /*
+        * Way to go: we have now written out all of the data for a
+@@ -640,7 +640,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+               if (!descriptor) {
+                       J_ASSERT (bufs == 0);
+-                      jbd_debug(4, "JBD2: get descriptor\n");
++                      jbd2_debug(4, "JBD2: get descriptor\n");
+                       descriptor = jbd2_journal_get_descriptor_buffer(
+                                                       commit_transaction,
+@@ -650,7 +650,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+                               continue;
+                       }
+-                      jbd_debug(4, "JBD2: got buffer %llu (%p)\n",
++                      jbd2_debug(4, "JBD2: got buffer %llu (%p)\n",
+                               (unsigned long long)descriptor->b_blocknr,
+                               descriptor->b_data);
+                       tagp = &descriptor->b_data[sizeof(journal_header_t)];
+@@ -735,7 +735,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+                   commit_transaction->t_buffers == NULL ||
+                   space_left < tag_bytes + 16 + csum_size) {
+-                      jbd_debug(4, "JBD2: Submit %d IOs\n", bufs);
++                      jbd2_debug(4, "JBD2: Submit %d IOs\n", bufs);
+                       /* Write an end-of-descriptor marker before
+                            submitting the IOs.  "tag" still points to
+@@ -837,7 +837,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+          so we incur less scheduling load.
+       */
+-      jbd_debug(3, "JBD2: commit phase 3\n");
++      jbd2_debug(3, "JBD2: commit phase 3\n");
+       while (!list_empty(&io_bufs)) {
+               struct buffer_head *bh = list_entry(io_bufs.prev,
+@@ -880,7 +880,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       J_ASSERT (commit_transaction->t_shadow_list == NULL);
+-      jbd_debug(3, "JBD2: commit phase 4\n");
++      jbd2_debug(3, "JBD2: commit phase 4\n");
+       /* Here we wait for the revoke record and descriptor record buffers */
+       while (!list_empty(&log_bufs)) {
+@@ -904,7 +904,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       if (err)
+               jbd2_journal_abort(journal, err);
+-      jbd_debug(3, "JBD2: commit phase 5\n");
++      jbd2_debug(3, "JBD2: commit phase 5\n");
+       write_lock(&journal->j_state_lock);
+       J_ASSERT(commit_transaction->t_state == T_COMMIT_DFLUSH);
+       commit_transaction->t_state = T_COMMIT_JFLUSH;
+@@ -943,7 +943,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+            transaction can be removed from any checkpoint list it was on
+            before. */
+-      jbd_debug(3, "JBD2: commit phase 6\n");
++      jbd2_debug(3, "JBD2: commit phase 6\n");
+       J_ASSERT(list_empty(&commit_transaction->t_inode_list));
+       J_ASSERT(commit_transaction->t_buffers == NULL);
+@@ -1120,7 +1120,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+       /* Done with this transaction! */
+-      jbd_debug(3, "JBD2: commit phase 7\n");
++      jbd2_debug(3, "JBD2: commit phase 7\n");
+       J_ASSERT(commit_transaction->t_state == T_COMMIT_JFLUSH);
+@@ -1162,7 +1162,7 @@ void jbd2_journal_commit_transaction(journal_t *journal)
+               journal->j_fc_cleanup_callback(journal, 1, commit_transaction->t_tid);
+       trace_jbd2_end_commit(journal, commit_transaction);
+-      jbd_debug(1, "JBD2: commit %d complete, head %d\n",
++      jbd2_debug(1, "JBD2: commit %d complete, head %d\n",
+                 journal->j_commit_sequence, journal->j_tail_sequence);
+       write_lock(&journal->j_state_lock);
+diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
+index 580d2fdfe21f5..11fbc9b6ec5cb 100644
+--- a/fs/jbd2/journal.c
++++ b/fs/jbd2/journal.c
+@@ -203,11 +203,11 @@ static int kjournald2(void *arg)
+       if (journal->j_flags & JBD2_UNMOUNT)
+               goto end_loop;
+-      jbd_debug(1, "commit_sequence=%u, commit_request=%u\n",
++      jbd2_debug(1, "commit_sequence=%u, commit_request=%u\n",
+               journal->j_commit_sequence, journal->j_commit_request);
+       if (journal->j_commit_sequence != journal->j_commit_request) {
+-              jbd_debug(1, "OK, requests differ\n");
++              jbd2_debug(1, "OK, requests differ\n");
+               write_unlock(&journal->j_state_lock);
+               del_timer_sync(&journal->j_commit_timer);
+               jbd2_journal_commit_transaction(journal);
+@@ -222,7 +222,7 @@ static int kjournald2(void *arg)
+                * good idea, because that depends on threads that may
+                * be already stopped.
+                */
+-              jbd_debug(1, "Now suspending kjournald2\n");
++              jbd2_debug(1, "Now suspending kjournald2\n");
+               write_unlock(&journal->j_state_lock);
+               try_to_freeze();
+               write_lock(&journal->j_state_lock);
+@@ -252,7 +252,7 @@ static int kjournald2(void *arg)
+               finish_wait(&journal->j_wait_commit, &wait);
+       }
+-      jbd_debug(1, "kjournald2 wakes\n");
++      jbd2_debug(1, "kjournald2 wakes\n");
+       /*
+        * Were we woken up by a commit wakeup event?
+@@ -260,7 +260,7 @@ static int kjournald2(void *arg)
+       transaction = journal->j_running_transaction;
+       if (transaction && time_after_eq(jiffies, transaction->t_expires)) {
+               journal->j_commit_request = transaction->t_tid;
+-              jbd_debug(1, "woke because of timeout\n");
++              jbd2_debug(1, "woke because of timeout\n");
+       }
+       goto loop;
+@@ -268,7 +268,7 @@ static int kjournald2(void *arg)
+       del_timer_sync(&journal->j_commit_timer);
+       journal->j_task = NULL;
+       wake_up(&journal->j_wait_done_commit);
+-      jbd_debug(1, "Journal thread exiting.\n");
++      jbd2_debug(1, "Journal thread exiting.\n");
+       write_unlock(&journal->j_state_lock);
+       return 0;
+ }
+@@ -500,7 +500,7 @@ int __jbd2_log_start_commit(journal_t *journal, tid_t target)
+                */
+               journal->j_commit_request = target;
+-              jbd_debug(1, "JBD2: requesting commit %u/%u\n",
++              jbd2_debug(1, "JBD2: requesting commit %u/%u\n",
+                         journal->j_commit_request,
+                         journal->j_commit_sequence);
+               journal->j_running_transaction->t_requested = jiffies;
+@@ -705,7 +705,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid)
+       }
+ #endif
+       while (tid_gt(tid, journal->j_commit_sequence)) {
+-              jbd_debug(1, "JBD2: want %u, j_commit_sequence=%u\n",
++              jbd2_debug(1, "JBD2: want %u, j_commit_sequence=%u\n",
+                                 tid, journal->j_commit_sequence);
+               read_unlock(&journal->j_state_lock);
+               wake_up(&journal->j_wait_commit);
+@@ -1123,7 +1123,7 @@ int __jbd2_update_log_tail(journal_t *journal, tid_t tid, unsigned long block)
+               freed += journal->j_last - journal->j_first;
+       trace_jbd2_update_log_tail(journal, tid, block, freed);
+-      jbd_debug(1,
++      jbd2_debug(1,
+                 "Cleaning journal tail from %u to %u (offset %lu), "
+                 "freeing %lu\n",
+                 journal->j_tail_sequence, tid, block, freed);
+@@ -1498,7 +1498,7 @@ journal_t *jbd2_journal_init_inode(struct inode *inode)
+               return NULL;
+       }
+-      jbd_debug(1, "JBD2: inode %s/%ld, size %lld, bits %d, blksize %ld\n",
++      jbd2_debug(1, "JBD2: inode %s/%ld, size %lld, bits %d, blksize %ld\n",
+                 inode->i_sb->s_id, inode->i_ino, (long long) inode->i_size,
+                 inode->i_sb->s_blocksize_bits, inode->i_sb->s_blocksize);
+@@ -1577,7 +1577,7 @@ static int journal_reset(journal_t *journal)
+        * attempting a write to a potential-readonly device.
+        */
+       if (sb->s_start == 0) {
+-              jbd_debug(1, "JBD2: Skipping superblock update on recovered sb "
++              jbd2_debug(1, "JBD2: Skipping superblock update on recovered sb "
+                       "(start %ld, seq %u, errno %d)\n",
+                       journal->j_tail, journal->j_tail_sequence,
+                       journal->j_errno);
+@@ -1680,7 +1680,7 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid,
+       }
+       BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
+-      jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
++      jbd2_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n",
+                 tail_block, tail_tid);
+       lock_buffer(journal->j_sb_buffer);
+@@ -1721,7 +1721,7 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op)
+               return;
+       }
+-      jbd_debug(1, "JBD2: Marking journal as empty (seq %u)\n",
++      jbd2_debug(1, "JBD2: Marking journal as empty (seq %u)\n",
+                 journal->j_tail_sequence);
+       sb->s_sequence = cpu_to_be32(journal->j_tail_sequence);
+@@ -1867,7 +1867,7 @@ void jbd2_journal_update_sb_errno(journal_t *journal)
+       errcode = journal->j_errno;
+       if (errcode == -ESHUTDOWN)
+               errcode = 0;
+-      jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
++      jbd2_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode);
+       sb->s_errno    = cpu_to_be32(errcode);
+       jbd2_write_superblock(journal, REQ_SYNC | REQ_FUA);
+@@ -2339,7 +2339,7 @@ int jbd2_journal_set_features(journal_t *journal, unsigned long compat,
+           compat & JBD2_FEATURE_COMPAT_CHECKSUM)
+               compat &= ~JBD2_FEATURE_COMPAT_CHECKSUM;
+-      jbd_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n",
++      jbd2_debug(1, "Setting new features 0x%lx/0x%lx/0x%lx\n",
+                 compat, ro, incompat);
+       sb = journal->j_superblock;
+@@ -2408,7 +2408,7 @@ void jbd2_journal_clear_features(journal_t *journal, unsigned long compat,
+ {
+       journal_superblock_t *sb;
+-      jbd_debug(1, "Clear features 0x%lx/0x%lx/0x%lx\n",
++      jbd2_debug(1, "Clear features 0x%lx/0x%lx/0x%lx\n",
+                 compat, ro, incompat);
+       sb = journal->j_superblock;
+@@ -2865,7 +2865,7 @@ static struct journal_head *journal_alloc_journal_head(void)
+ #endif
+       ret = kmem_cache_zalloc(jbd2_journal_head_cache, GFP_NOFS);
+       if (!ret) {
+-              jbd_debug(1, "out of memory for journal_head\n");
++              jbd2_debug(1, "out of memory for journal_head\n");
+               pr_notice_ratelimited("ENOMEM in %s, retrying.\n", __func__);
+               ret = kmem_cache_zalloc(jbd2_journal_head_cache,
+                               GFP_NOFS | __GFP_NOFAIL);
+diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c
+index 3c5dd010e39d2..18f525f7f4063 100644
+--- a/fs/jbd2/recovery.c
++++ b/fs/jbd2/recovery.c
+@@ -245,11 +245,11 @@ static int fc_do_one_pass(journal_t *journal,
+               return 0;
+       while (next_fc_block <= journal->j_fc_last) {
+-              jbd_debug(3, "Fast commit replay: next block %ld\n",
++              jbd2_debug(3, "Fast commit replay: next block %ld\n",
+                         next_fc_block);
+               err = jread(&bh, journal, next_fc_block);
+               if (err) {
+-                      jbd_debug(3, "Fast commit replay: read error\n");
++                      jbd2_debug(3, "Fast commit replay: read error\n");
+                       break;
+               }
+@@ -264,7 +264,7 @@ static int fc_do_one_pass(journal_t *journal,
+       }
+       if (err)
+-              jbd_debug(3, "Fast commit replay failed, err = %d\n", err);
++              jbd2_debug(3, "Fast commit replay failed, err = %d\n", err);
+       return err;
+ }
+@@ -298,7 +298,7 @@ int jbd2_journal_recover(journal_t *journal)
+        */
+       if (!sb->s_start) {
+-              jbd_debug(1, "No recovery required, last transaction %d\n",
++              jbd2_debug(1, "No recovery required, last transaction %d\n",
+                         be32_to_cpu(sb->s_sequence));
+               journal->j_transaction_sequence = be32_to_cpu(sb->s_sequence) + 1;
+               return 0;
+@@ -310,10 +310,10 @@ int jbd2_journal_recover(journal_t *journal)
+       if (!err)
+               err = do_one_pass(journal, &info, PASS_REPLAY);
+-      jbd_debug(1, "JBD2: recovery, exit status %d, "
++      jbd2_debug(1, "JBD2: recovery, exit status %d, "
+                 "recovered transactions %u to %u\n",
+                 err, info.start_transaction, info.end_transaction);
+-      jbd_debug(1, "JBD2: Replayed %d and revoked %d/%d blocks\n",
++      jbd2_debug(1, "JBD2: Replayed %d and revoked %d/%d blocks\n",
+                 info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
+       /* Restart the log at the next transaction ID, thus invalidating
+@@ -363,7 +363,7 @@ int jbd2_journal_skip_recovery(journal_t *journal)
+ #ifdef CONFIG_JBD2_DEBUG
+               int dropped = info.end_transaction - 
+                       be32_to_cpu(journal->j_superblock->s_sequence);
+-              jbd_debug(1,
++              jbd2_debug(1,
+                         "JBD2: ignoring %d transaction%s from the journal.\n",
+                         dropped, (dropped == 1) ? "" : "s");
+ #endif
+@@ -485,7 +485,7 @@ static int do_one_pass(journal_t *journal,
+       if (pass == PASS_SCAN)
+               info->start_transaction = first_commit_ID;
+-      jbd_debug(1, "Starting recovery pass %d\n", pass);
++      jbd2_debug(1, "Starting recovery pass %d\n", pass);
+       /*
+        * Now we walk through the log, transaction by transaction,
+@@ -511,7 +511,7 @@ static int do_one_pass(journal_t *journal,
+                       if (tid_geq(next_commit_ID, info->end_transaction))
+                               break;
+-              jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
++              jbd2_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
+                         next_commit_ID, next_log_block,
+                         jbd2_has_feature_fast_commit(journal) ?
+                         journal->j_fc_last : journal->j_last);
+@@ -520,7 +520,7 @@ static int do_one_pass(journal_t *journal,
+                * either the next descriptor block or the final commit
+                * record. */
+-              jbd_debug(3, "JBD2: checking block %ld\n", next_log_block);
++              jbd2_debug(3, "JBD2: checking block %ld\n", next_log_block);
+               err = jread(&bh, journal, next_log_block);
+               if (err)
+                       goto failed;
+@@ -543,7 +543,7 @@ static int do_one_pass(journal_t *journal,
+               blocktype = be32_to_cpu(tmp->h_blocktype);
+               sequence = be32_to_cpu(tmp->h_sequence);
+-              jbd_debug(3, "Found magic %d, sequence %d\n",
++              jbd2_debug(3, "Found magic %d, sequence %d\n",
+                         blocktype, sequence);
+               if (sequence != next_commit_ID) {
+@@ -576,7 +576,7 @@ static int do_one_pass(journal_t *journal,
+                                       goto failed;
+                               }
+                               need_check_commit_time = true;
+-                              jbd_debug(1,
++                              jbd2_debug(1,
+                                       "invalid descriptor block found in %lu\n",
+                                       next_log_block);
+                       }
+@@ -759,7 +759,7 @@ static int do_one_pass(journal_t *journal,
+                                * It likely does not belong to same journal,
+                                * just end this recovery with success.
+                                */
+-                              jbd_debug(1, "JBD2: Invalid checksum ignored in transaction %u, likely stale data\n",
++                              jbd2_debug(1, "JBD2: Invalid checksum ignored in transaction %u, likely stale data\n",
+                                         next_commit_ID);
+                               brelse(bh);
+                               goto done;
+@@ -827,7 +827,7 @@ static int do_one_pass(journal_t *journal,
+                       if (pass == PASS_SCAN &&
+                           !jbd2_descriptor_block_csum_verify(journal,
+                                                              bh->b_data)) {
+-                              jbd_debug(1, "JBD2: invalid revoke block found in %lu\n",
++                              jbd2_debug(1, "JBD2: invalid revoke block found in %lu\n",
+                                         next_log_block);
+                               need_check_commit_time = true;
+                       }
+@@ -846,7 +846,7 @@ static int do_one_pass(journal_t *journal,
+                       continue;
+               default:
+-                      jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
++                      jbd2_debug(3, "Unrecognised magic %d, end of scan.\n",
+                                 blocktype);
+                       brelse(bh);
+                       goto done;
+diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
+index fa608788b93d7..4556e46890244 100644
+--- a/fs/jbd2/revoke.c
++++ b/fs/jbd2/revoke.c
+@@ -398,7 +398,7 @@ int jbd2_journal_revoke(handle_t *handle, unsigned long long blocknr,
+       }
+       handle->h_revoke_credits--;
+-      jbd_debug(2, "insert revoke for block %llu, bh_in=%p\n",blocknr, bh_in);
++      jbd2_debug(2, "insert revoke for block %llu, bh_in=%p\n",blocknr, bh_in);
+       err = insert_revoke_hash(journal, blocknr,
+                               handle->h_transaction->t_tid);
+       BUFFER_TRACE(bh_in, "exit");
+@@ -428,7 +428,7 @@ int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
+       int did_revoke = 0;     /* akpm: debug */
+       struct buffer_head *bh = jh2bh(jh);
+-      jbd_debug(4, "journal_head %p, cancelling revoke\n", jh);
++      jbd2_debug(4, "journal_head %p, cancelling revoke\n", jh);
+       /* Is the existing Revoke bit valid?  If so, we trust it, and
+        * only perform the full cancel if the revoke bit is set.  If
+@@ -444,7 +444,7 @@ int jbd2_journal_cancel_revoke(handle_t *handle, struct journal_head *jh)
+       if (need_cancel) {
+               record = find_revoke_record(journal, bh->b_blocknr);
+               if (record) {
+-                      jbd_debug(4, "cancelled existing revoke on "
++                      jbd2_debug(4, "cancelled existing revoke on "
+                                 "blocknr %llu\n", (unsigned long long)bh->b_blocknr);
+                       spin_lock(&journal->j_revoke_lock);
+                       list_del(&record->hash);
+@@ -560,7 +560,7 @@ void jbd2_journal_write_revoke_records(transaction_t *transaction,
+       }
+       if (descriptor)
+               flush_descriptor(journal, descriptor, offset);
+-      jbd_debug(1, "Wrote %d revoke records\n", count);
++      jbd2_debug(1, "Wrote %d revoke records\n", count);
+ }
+ /*
+diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
+index b31145b2bb6bf..c2125203ef2d9 100644
+--- a/fs/jbd2/transaction.c
++++ b/fs/jbd2/transaction.c
+@@ -374,7 +374,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+                       return -ENOMEM;
+       }
+-      jbd_debug(3, "New handle %p going live.\n", handle);
++      jbd2_debug(3, "New handle %p going live.\n", handle);
+       /*
+        * We need to hold j_state_lock until t_updates has been incremented,
+@@ -454,7 +454,7 @@ static int start_this_handle(journal_t *journal, handle_t *handle,
+       handle->h_start_jiffies = jiffies;
+       atomic_inc(&transaction->t_updates);
+       atomic_inc(&transaction->t_handle_count);
+-      jbd_debug(4, "Handle %p given %d credits (total %d, free %lu)\n",
++      jbd2_debug(4, "Handle %p given %d credits (total %d, free %lu)\n",
+                 handle, blocks,
+                 atomic_read(&transaction->t_outstanding_credits),
+                 jbd2_log_space_left(journal));
+@@ -675,7 +675,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks, int revoke_records)
+       /* Don't extend a locked-down transaction! */
+       if (transaction->t_state != T_RUNNING) {
+-              jbd_debug(3, "denied handle %p %d blocks: "
++              jbd2_debug(3, "denied handle %p %d blocks: "
+                         "transaction not running\n", handle, nblocks);
+               goto error_out;
+       }
+@@ -690,7 +690,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks, int revoke_records)
+                                  &transaction->t_outstanding_credits);
+       if (wanted > journal->j_max_transaction_buffers) {
+-              jbd_debug(3, "denied handle %p %d blocks: "
++              jbd2_debug(3, "denied handle %p %d blocks: "
+                         "transaction too large\n", handle, nblocks);
+               atomic_sub(nblocks, &transaction->t_outstanding_credits);
+               goto error_out;
+@@ -708,7 +708,7 @@ int jbd2_journal_extend(handle_t *handle, int nblocks, int revoke_records)
+       handle->h_revoke_credits_requested += revoke_records;
+       result = 0;
+-      jbd_debug(3, "extended handle %p by %d\n", handle, nblocks);
++      jbd2_debug(3, "extended handle %p by %d\n", handle, nblocks);
+ error_out:
+       read_unlock(&journal->j_state_lock);
+       return result;
+@@ -796,7 +796,7 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int revoke_records,
+        * First unlink the handle from its current transaction, and start the
+        * commit on that.
+        */
+-      jbd_debug(2, "restarting handle %p\n", handle);
++      jbd2_debug(2, "restarting handle %p\n", handle);
+       stop_this_handle(handle);
+       handle->h_transaction = NULL;
+@@ -980,7 +980,7 @@ do_get_write_access(handle_t *handle, struct journal_head *jh,
+       journal = transaction->t_journal;
+-      jbd_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
++      jbd2_debug(5, "journal_head %p, force_copy %d\n", jh, force_copy);
+       JBUFFER_TRACE(jh, "entry");
+ repeat:
+@@ -1280,7 +1280,7 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
+       struct journal_head *jh = jbd2_journal_add_journal_head(bh);
+       int err;
+-      jbd_debug(5, "journal_head %p\n", jh);
++      jbd2_debug(5, "journal_head %p\n", jh);
+       err = -EROFS;
+       if (is_handle_aborted(handle))
+               goto out;
+@@ -1503,7 +1503,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
+        * of the running transaction.
+        */
+       jh = bh2jh(bh);
+-      jbd_debug(5, "journal_head %p\n", jh);
++      jbd2_debug(5, "journal_head %p\n", jh);
+       JBUFFER_TRACE(jh, "entry");
+       /*
+@@ -1836,7 +1836,7 @@ int jbd2_journal_stop(handle_t *handle)
+       pid_t pid;
+       if (--handle->h_ref > 0) {
+-              jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1,
++              jbd2_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1,
+                                                handle->h_ref);
+               if (is_handle_aborted(handle))
+                       return -EIO;
+@@ -1856,7 +1856,7 @@ int jbd2_journal_stop(handle_t *handle)
+       if (is_handle_aborted(handle))
+               err = -EIO;
+-      jbd_debug(4, "Handle %p going down\n", handle);
++      jbd2_debug(4, "Handle %p going down\n", handle);
+       trace_jbd2_handle_stats(journal->j_fs_dev->bd_dev,
+                               tid, handle->h_type, handle->h_line_no,
+                               jiffies - handle->h_start_jiffies,
+@@ -1934,7 +1934,7 @@ int jbd2_journal_stop(handle_t *handle)
+                * completes the commit thread, it just doesn't write
+                * anything to disk. */
+-              jbd_debug(2, "transaction too old, requesting commit for "
++              jbd2_debug(2, "transaction too old, requesting commit for "
+                                       "handle %p\n", handle);
+               /* This is non-blocking */
+               jbd2_log_start_commit(journal, tid);
+@@ -2678,7 +2678,7 @@ static int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode,
+               return -EROFS;
+       journal = transaction->t_journal;
+-      jbd_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino,
++      jbd2_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino,
+                       transaction->t_tid);
+       spin_lock(&journal->j_list_lock);
+diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
+index f29fda630b2de..d19f527ade3bb 100644
+--- a/include/linux/jbd2.h
++++ b/include/linux/jbd2.h
+@@ -58,10 +58,10 @@ extern ushort jbd2_journal_enable_debug;
+ void __jbd2_debug(int level, const char *file, const char *func,
+                 unsigned int line, const char *fmt, ...);
+-#define jbd_debug(n, fmt, a...) \
++#define jbd2_debug(n, fmt, a...) \
+       __jbd2_debug((n), __FILE__, __func__, __LINE__, (fmt), ##a)
+ #else
+-#define jbd_debug(n, fmt, a...)  no_printk(fmt, ##a)
++#define jbd2_debug(n, fmt, a...)  no_printk(fmt, ##a)
+ #endif
+ extern void *jbd2_alloc(size_t size, gfp_t flags);
+-- 
+2.40.1
+
diff --git a/queue-5.15/jfs-fix-invalid-free-of-jfs_ip-ipimap-i_imap-in-diun.patch b/queue-5.15/jfs-fix-invalid-free-of-jfs_ip-ipimap-i_imap-in-diun.patch
new file mode 100644 (file)
index 0000000..2de317e
--- /dev/null
@@ -0,0 +1,77 @@
+From ff5940620f1406ffb52dc2a7c4d580239fee7350 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 1 Dec 2022 20:46:28 +0800
+Subject: jfs: fix invalid free of JFS_IP(ipimap)->i_imap in diUnmount
+
+From: Liu Shixin via Jfs-discussion <jfs-discussion@lists.sourceforge.net>
+
+[ Upstream commit 6e2bda2c192d0244b5a78b787ef20aa10cb319b7 ]
+
+syzbot found an invalid-free in diUnmount:
+
+BUG: KASAN: double-free in slab_free mm/slub.c:3661 [inline]
+BUG: KASAN: double-free in __kmem_cache_free+0x71/0x110 mm/slub.c:3674
+Free of addr ffff88806f410000 by task syz-executor131/3632
+
+ CPU: 0 PID: 3632 Comm: syz-executor131 Not tainted 6.1.0-rc7-syzkaller-00012-gca57f02295f1 #0
+ Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022
+ Call Trace:
+  <TASK>
+  __dump_stack lib/dump_stack.c:88 [inline]
+  dump_stack_lvl+0x1b1/0x28e lib/dump_stack.c:106
+  print_address_description+0x74/0x340 mm/kasan/report.c:284
+  print_report+0x107/0x1f0 mm/kasan/report.c:395
+  kasan_report_invalid_free+0xac/0xd0 mm/kasan/report.c:460
+  ____kasan_slab_free+0xfb/0x120
+  kasan_slab_free include/linux/kasan.h:177 [inline]
+  slab_free_hook mm/slub.c:1724 [inline]
+  slab_free_freelist_hook+0x12e/0x1a0 mm/slub.c:1750
+  slab_free mm/slub.c:3661 [inline]
+  __kmem_cache_free+0x71/0x110 mm/slub.c:3674
+  diUnmount+0xef/0x100 fs/jfs/jfs_imap.c:195
+  jfs_umount+0x108/0x370 fs/jfs/jfs_umount.c:63
+  jfs_put_super+0x86/0x190 fs/jfs/super.c:194
+  generic_shutdown_super+0x130/0x310 fs/super.c:492
+  kill_block_super+0x79/0xd0 fs/super.c:1428
+  deactivate_locked_super+0xa7/0xf0 fs/super.c:332
+  cleanup_mnt+0x494/0x520 fs/namespace.c:1186
+  task_work_run+0x243/0x300 kernel/task_work.c:179
+  exit_task_work include/linux/task_work.h:38 [inline]
+  do_exit+0x664/0x2070 kernel/exit.c:820
+  do_group_exit+0x1fd/0x2b0 kernel/exit.c:950
+  __do_sys_exit_group kernel/exit.c:961 [inline]
+  __se_sys_exit_group kernel/exit.c:959 [inline]
+  __x64_sys_exit_group+0x3b/0x40 kernel/exit.c:959
+  do_syscall_x64 arch/x86/entry/common.c:50 [inline]
+  do_syscall_64+0x3d/0xb0 arch/x86/entry/common.c:80
+  entry_SYSCALL_64_after_hwframe+0x63/0xcd
+[...]
+
+JFS_IP(ipimap)->i_imap is not setting to NULL after free in diUnmount.
+If jfs_remount() free JFS_IP(ipimap)->i_imap but then failed at diMount().
+JFS_IP(ipimap)->i_imap will be freed once again.
+Fix this problem by setting JFS_IP(ipimap)->i_imap to NULL after free.
+
+Reported-by: syzbot+90a11e6b1e810785c6ff@syzkaller.appspotmail.com
+Signed-off-by: Liu Shixin <liushixin2@huawei.com>
+Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/jfs/jfs_imap.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c
+index 799d3837e7c2b..4899663996d81 100644
+--- a/fs/jfs/jfs_imap.c
++++ b/fs/jfs/jfs_imap.c
+@@ -193,6 +193,7 @@ int diUnmount(struct inode *ipimap, int mounterror)
+        * free in-memory control structure
+        */
+       kfree(imap);
++      JFS_IP(ipimap)->i_imap = NULL;
+       return (0);
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/kernel-fork-beware-of-__put_task_struct-calling-cont.patch b/queue-5.15/kernel-fork-beware-of-__put_task_struct-calling-cont.patch
new file mode 100644 (file)
index 0000000..4eb0377
--- /dev/null
@@ -0,0 +1,128 @@
+From 418f367b01468c0c2bacdb9c58cf747bc37c80a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 14 Jun 2023 09:23:21 -0300
+Subject: kernel/fork: beware of __put_task_struct() calling context
+
+From: Wander Lairson Costa <wander@redhat.com>
+
+[ Upstream commit d243b34459cea30cfe5f3a9b2feb44e7daff9938 ]
+
+Under PREEMPT_RT, __put_task_struct() indirectly acquires sleeping
+locks. Therefore, it can't be called from an non-preemptible context.
+
+One practical example is splat inside inactive_task_timer(), which is
+called in a interrupt context:
+
+  CPU: 1 PID: 2848 Comm: life Kdump: loaded Tainted: G W ---------
+   Hardware name: HP ProLiant DL388p Gen8, BIOS P70 07/15/2012
+   Call Trace:
+   dump_stack_lvl+0x57/0x7d
+   mark_lock_irq.cold+0x33/0xba
+   mark_lock+0x1e7/0x400
+   mark_usage+0x11d/0x140
+   __lock_acquire+0x30d/0x930
+   lock_acquire.part.0+0x9c/0x210
+   rt_spin_lock+0x27/0xe0
+   refill_obj_stock+0x3d/0x3a0
+   kmem_cache_free+0x357/0x560
+   inactive_task_timer+0x1ad/0x340
+   __run_hrtimer+0x8a/0x1a0
+   __hrtimer_run_queues+0x91/0x130
+   hrtimer_interrupt+0x10f/0x220
+   __sysvec_apic_timer_interrupt+0x7b/0xd0
+   sysvec_apic_timer_interrupt+0x4f/0xd0
+   asm_sysvec_apic_timer_interrupt+0x12/0x20
+   RIP: 0033:0x7fff196bf6f5
+
+Instead of calling __put_task_struct() directly, we defer it using
+call_rcu(). A more natural approach would use a workqueue, but since
+in PREEMPT_RT, we can't allocate dynamic memory from atomic context,
+the code would become more complex because we would need to put the
+work_struct instance in the task_struct and initialize it when we
+allocate a new task_struct.
+
+The issue is reproducible with stress-ng:
+
+  while true; do
+      stress-ng --sched deadline --sched-period 1000000000 \
+             --sched-runtime 800000000 --sched-deadline \
+             1000000000 --mmapfork 23 -t 20
+  done
+
+Reported-by: Hu Chunyu <chuhu@redhat.com>
+Suggested-by: Oleg Nesterov <oleg@redhat.com>
+Suggested-by: Valentin Schneider <vschneid@redhat.com>
+Suggested-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Wander Lairson Costa <wander@redhat.com>
+Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20230614122323.37957-2-wander@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/sched/task.h | 28 +++++++++++++++++++++++++++-
+ kernel/fork.c              |  8 ++++++++
+ 2 files changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h
+index d23977e9035d4..0c2d008099151 100644
+--- a/include/linux/sched/task.h
++++ b/include/linux/sched/task.h
+@@ -108,10 +108,36 @@ static inline struct task_struct *get_task_struct(struct task_struct *t)
+ }
+ extern void __put_task_struct(struct task_struct *t);
++extern void __put_task_struct_rcu_cb(struct rcu_head *rhp);
+ static inline void put_task_struct(struct task_struct *t)
+ {
+-      if (refcount_dec_and_test(&t->usage))
++      if (!refcount_dec_and_test(&t->usage))
++              return;
++
++      /*
++       * under PREEMPT_RT, we can't call put_task_struct
++       * in atomic context because it will indirectly
++       * acquire sleeping locks.
++       *
++       * call_rcu() will schedule delayed_put_task_struct_rcu()
++       * to be called in process context.
++       *
++       * __put_task_struct() is called when
++       * refcount_dec_and_test(&t->usage) succeeds.
++       *
++       * This means that it can't "conflict" with
++       * put_task_struct_rcu_user() which abuses ->rcu the same
++       * way; rcu_users has a reference so task->usage can't be
++       * zero after rcu_users 1 -> 0 transition.
++       *
++       * delayed_free_task() also uses ->rcu, but it is only called
++       * when it fails to fork a process. Therefore, there is no
++       * way it can conflict with put_task_struct().
++       */
++      if (IS_ENABLED(CONFIG_PREEMPT_RT) && !preemptible())
++              call_rcu(&t->rcu, __put_task_struct_rcu_cb);
++      else
+               __put_task_struct(t);
+ }
+diff --git a/kernel/fork.c b/kernel/fork.c
+index ace0717c71e27..753e641f617bd 100644
+--- a/kernel/fork.c
++++ b/kernel/fork.c
+@@ -764,6 +764,14 @@ void __put_task_struct(struct task_struct *tsk)
+ }
+ EXPORT_SYMBOL_GPL(__put_task_struct);
++void __put_task_struct_rcu_cb(struct rcu_head *rhp)
++{
++      struct task_struct *task = container_of(rhp, struct task_struct, rcu);
++
++      __put_task_struct(task);
++}
++EXPORT_SYMBOL_GPL(__put_task_struct_rcu_cb);
++
+ void __init __weak arch_task_cache_init(void) { }
+ /*
+-- 
+2.40.1
+
diff --git a/queue-5.15/kobject-add-sanity-check-for-kset-kobj.ktype-in-kset.patch b/queue-5.15/kobject-add-sanity-check-for-kset-kobj.ktype-in-kset.patch
new file mode 100644 (file)
index 0000000..22c63db
--- /dev/null
@@ -0,0 +1,60 @@
+From 55a624b6198db8fa3acaf62b28016322cb985324 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 5 Aug 2023 16:41:13 +0800
+Subject: kobject: Add sanity check for kset->kobj.ktype in kset_register()
+
+From: Zhen Lei <thunder.leizhen@huawei.com>
+
+[ Upstream commit 4d0fe8c52bb3029d83e323c961221156ab98680b ]
+
+When I register a kset in the following way:
+       static struct kset my_kset;
+       kobject_set_name(&my_kset.kobj, "my_kset");
+        ret = kset_register(&my_kset);
+
+A null pointer dereference exception is occurred:
+[ 4453.568337] Unable to handle kernel NULL pointer dereference at \
+virtual address 0000000000000028
+... ...
+[ 4453.810361] Call trace:
+[ 4453.813062]  kobject_get_ownership+0xc/0x34
+[ 4453.817493]  kobject_add_internal+0x98/0x274
+[ 4453.822005]  kset_register+0x5c/0xb4
+[ 4453.825820]  my_kobj_init+0x44/0x1000 [my_kset]
+... ...
+
+Because I didn't initialize my_kset.kobj.ktype.
+
+According to the description in Documentation/core-api/kobject.rst:
+ - A ktype is the type of object that embeds a kobject.  Every structure
+   that embeds a kobject needs a corresponding ktype.
+
+So add sanity check to make sure kset->kobj.ktype is not NULL.
+
+Signed-off-by: Zhen Lei <thunder.leizhen@huawei.com>
+Link: https://lore.kernel.org/r/20230805084114.1298-2-thunder.leizhen@huaweicloud.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ lib/kobject.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/lib/kobject.c b/lib/kobject.c
+index 184a3dab26991..b6ccb4cced635 100644
+--- a/lib/kobject.c
++++ b/lib/kobject.c
+@@ -882,6 +882,11 @@ int kset_register(struct kset *k)
+       if (!k)
+               return -EINVAL;
++      if (!k->kobj.ktype) {
++              pr_err("must have a ktype to be initialized properly!\n");
++              return -EINVAL;
++      }
++
+       kset_init(k);
+       err = kobject_add_internal(&k->kobj);
+       if (err)
+-- 
+2.40.1
+
diff --git a/queue-5.15/libbpf-free-btf_vmlinux-when-closing-bpf_object.patch b/queue-5.15/libbpf-free-btf_vmlinux-when-closing-bpf_object.patch
new file mode 100644 (file)
index 0000000..233d959
--- /dev/null
@@ -0,0 +1,41 @@
+From 42997ebcfae405d18b1fdc0435f79013ddaeb23b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Aug 2023 12:38:40 -0700
+Subject: libbpf: Free btf_vmlinux when closing bpf_object
+
+From: Hao Luo <haoluo@google.com>
+
+[ Upstream commit 29d67fdebc42af6466d1909c60fdd1ef4f3e5240 ]
+
+I hit a memory leak when testing bpf_program__set_attach_target().
+Basically, set_attach_target() may allocate btf_vmlinux, for example,
+when setting attach target for bpf_iter programs. But btf_vmlinux
+is freed only in bpf_object_load(), which means if we only open
+bpf object but not load it, setting attach target may leak
+btf_vmlinux.
+
+So let's free btf_vmlinux in bpf_object__close() anyway.
+
+Signed-off-by: Hao Luo <haoluo@google.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20230822193840.1509809-1-haoluo@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/lib/bpf/libbpf.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
+index f87a15bbf53b3..9b8a0fe0eb1c3 100644
+--- a/tools/lib/bpf/libbpf.c
++++ b/tools/lib/bpf/libbpf.c
+@@ -7559,6 +7559,7 @@ void bpf_object__close(struct bpf_object *obj)
+       bpf_object__elf_finish(obj);
+       bpf_object__unload(obj);
+       btf__free(obj->btf);
++      btf__free(obj->btf_vmlinux);
+       btf_ext__free(obj->btf_ext);
+       for (i = 0; i < obj->nr_maps; i++)
+-- 
+2.40.1
+
diff --git a/queue-5.15/locks-fix-kasan-use-after-free-in-trace_event_raw_ev.patch b/queue-5.15/locks-fix-kasan-use-after-free-in-trace_event_raw_ev.patch
new file mode 100644 (file)
index 0000000..77856c8
--- /dev/null
@@ -0,0 +1,88 @@
+From b9e9ba290773a55bc6a80f14fb3abe3003f06af0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jul 2023 13:19:04 +0800
+Subject: locks: fix KASAN: use-after-free in
+ trace_event_raw_event_filelock_lock
+
+From: Will Shiu <Will.Shiu@mediatek.com>
+
+[ Upstream commit 74f6f5912693ce454384eaeec48705646a21c74f ]
+
+As following backtrace, the struct file_lock request , in posix_lock_inode
+is free before ftrace function using.
+Replace the ftrace function ahead free flow could fix the use-after-free
+issue.
+
+[name:report&]===============================================
+BUG:KASAN: use-after-free in trace_event_raw_event_filelock_lock+0x80/0x12c
+[name:report&]Read at addr f6ffff8025622620 by task NativeThread/16753
+[name:report_hw_tags&]Pointer tag: [f6], memory tag: [fe]
+[name:report&]
+BT:
+Hardware name: MT6897 (DT)
+Call trace:
+ dump_backtrace+0xf8/0x148
+ show_stack+0x18/0x24
+ dump_stack_lvl+0x60/0x7c
+ print_report+0x2c8/0xa08
+ kasan_report+0xb0/0x120
+ __do_kernel_fault+0xc8/0x248
+ do_bad_area+0x30/0xdc
+ do_tag_check_fault+0x1c/0x30
+ do_mem_abort+0x58/0xbc
+ el1_abort+0x3c/0x5c
+ el1h_64_sync_handler+0x54/0x90
+ el1h_64_sync+0x68/0x6c
+ trace_event_raw_event_filelock_lock+0x80/0x12c
+ posix_lock_inode+0xd0c/0xd60
+ do_lock_file_wait+0xb8/0x190
+ fcntl_setlk+0x2d8/0x440
+...
+[name:report&]
+[name:report&]Allocated by task 16752:
+...
+ slab_post_alloc_hook+0x74/0x340
+ kmem_cache_alloc+0x1b0/0x2f0
+ posix_lock_inode+0xb0/0xd60
+...
+ [name:report&]
+ [name:report&]Freed by task 16752:
+...
+  kmem_cache_free+0x274/0x5b0
+  locks_dispose_list+0x3c/0x148
+  posix_lock_inode+0xc40/0xd60
+  do_lock_file_wait+0xb8/0x190
+  fcntl_setlk+0x2d8/0x440
+  do_fcntl+0x150/0xc18
+...
+
+Signed-off-by: Will Shiu <Will.Shiu@mediatek.com>
+Signed-off-by: Jeff Layton <jlayton@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/locks.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/fs/locks.c b/fs/locks.c
+index 881fd16905c61..4899a4666f24d 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1339,6 +1339,7 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
+  out:
+       spin_unlock(&ctx->flc_lock);
+       percpu_up_read(&file_rwsem);
++      trace_posix_lock_inode(inode, request, error);
+       /*
+        * Free any unused locks.
+        */
+@@ -1347,7 +1348,6 @@ static int posix_lock_inode(struct inode *inode, struct file_lock *request,
+       if (new_fl2)
+               locks_free_lock(new_fl2);
+       locks_dispose_list(&dispose);
+-      trace_posix_lock_inode(inode, request, error);
+       return error;
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/md-raid1-fix-error-iso-c90-forbids-mixed-declaration.patch b/queue-5.15/md-raid1-fix-error-iso-c90-forbids-mixed-declaration.patch
new file mode 100644 (file)
index 0000000..e567bbf
--- /dev/null
@@ -0,0 +1,54 @@
+From f32f532c3099cbbe10a0f7d51cbe5c96dda13247 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Sep 2023 14:25:23 -0700
+Subject: md/raid1: fix error: ISO C90 forbids mixed declarations
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nigel Croxon <ncroxon@redhat.com>
+
+[ Upstream commit df203da47f4428bc286fc99318936416253a321c ]
+
+There is a compile error when this commit is added:
+md: raid1: fix potential OOB in raid1_remove_disk()
+
+drivers/md/raid1.c: In function 'raid1_remove_disk':
+drivers/md/raid1.c:1844:9: error: ISO C90 forbids mixed declarations
+and code [-Werror=declaration-after-statement]
+1844 |         struct raid1_info *p = conf->mirrors + number;
+     |         ^~~~~~
+
+That's because the new code was inserted before the struct.
+The change is move the struct command above this commit.
+
+Fixes: 8b0472b50bcf ("md: raid1: fix potential OOB in raid1_remove_disk()")
+Signed-off-by: Nigel Croxon <ncroxon@redhat.com>
+Signed-off-by: Song Liu <song@kernel.org>
+Link: https://lore.kernel.org/r/46d929d0-2aab-4cf2-b2bf-338963e8ba5a@redhat.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid1.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 5360d6ed16e05..8427c9767a61b 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1820,12 +1820,11 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
+       struct r1conf *conf = mddev->private;
+       int err = 0;
+       int number = rdev->raid_disk;
++      struct raid1_info *p = conf->mirrors + number;
+       if (unlikely(number >= conf->raid_disks))
+               goto abort;
+-      struct raid1_info *p = conf->mirrors + number;
+-
+       if (rdev != p->rdev)
+               p = conf->mirrors + conf->raid_disks + number;
+-- 
+2.40.1
+
diff --git a/queue-5.15/md-raid1-fix-potential-oob-in-raid1_remove_disk.patch b/queue-5.15/md-raid1-fix-potential-oob-in-raid1_remove_disk.patch
new file mode 100644 (file)
index 0000000..9b43275
--- /dev/null
@@ -0,0 +1,46 @@
+From fa10fc7570e31e22f8cb85d6e1708d7769add7f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jul 2023 15:53:53 +0800
+Subject: md: raid1: fix potential OOB in raid1_remove_disk()
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 8b0472b50bcf0f19a5119b00a53b63579c8e1e4d ]
+
+If rddev->raid_disk is greater than mddev->raid_disks, there will be
+an out-of-bounds in raid1_remove_disk(). We have already found
+similar reports as follows:
+
+1) commit d17f744e883b ("md-raid10: fix KASAN warning")
+2) commit 1ebc2cec0b7d ("dm raid: fix KASAN warning in raid5_remove_disk")
+
+Fix this bug by checking whether the "number" variable is
+valid.
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Reviewed-by: Yu Kuai <yukuai3@huawei.com>
+Link: https://lore.kernel.org/r/tencent_0D24426FAC6A21B69AC0C03CE4143A508F09@qq.com
+Signed-off-by: Song Liu <song@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/raid1.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
+index 084bfea6ad316..5360d6ed16e05 100644
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1820,6 +1820,10 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
+       struct r1conf *conf = mddev->private;
+       int err = 0;
+       int number = rdev->raid_disk;
++
++      if (unlikely(number >= conf->raid_disks))
++              goto abort;
++
+       struct raid1_info *p = conf->mirrors + number;
+       if (rdev != p->rdev)
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-af9005-fix-null-ptr-deref-in-af9005_i2c_xfer.patch b/queue-5.15/media-af9005-fix-null-ptr-deref-in-af9005_i2c_xfer.patch
new file mode 100644 (file)
index 0000000..4071a51
--- /dev/null
@@ -0,0 +1,52 @@
+From dd3b7c394b1d224e0074af465cda676879d96dfe Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jul 2023 23:24:11 +0800
+Subject: media: af9005: Fix null-ptr-deref in af9005_i2c_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit f4ee84f27625ce1fdf41e8483fa0561a1b837d10 ]
+
+In af9005_i2c_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach af9005_i2c_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb/af9005.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c
+index b6a2436d16e97..9af54fcbed1de 100644
+--- a/drivers/media/usb/dvb-usb/af9005.c
++++ b/drivers/media/usb/dvb-usb/af9005.c
+@@ -422,6 +422,10 @@ static int af9005_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+               if (ret == 0)
+                       ret = 2;
+       } else {
++              if (msg[0].len < 2) {
++                      ret = -EOPNOTSUPP;
++                      goto unlock;
++              }
+               /* write one or more registers */
+               reg = msg[0].buf[0];
+               addr = msg[0].addr;
+@@ -431,6 +435,7 @@ static int af9005_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                       ret = 1;
+       }
++unlock:
+       mutex_unlock(&d->i2c_mutex);
+       return ret;
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-anysee-fix-null-ptr-deref-in-anysee_master_xfe.patch b/queue-5.15/media-anysee-fix-null-ptr-deref-in-anysee_master_xfe.patch
new file mode 100644 (file)
index 0000000..b63c473
--- /dev/null
@@ -0,0 +1,43 @@
+From 1af4f7ef7e2ef0d8a9620b53ca07a42fe3084127 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jul 2023 00:02:20 +0800
+Subject: media: anysee: fix null-ptr-deref in anysee_master_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit c30411266fd67ea3c02a05c157231654d5a3bdc9 ]
+
+In anysee_master_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach anysee_master_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+[hverkuil: add spaces around +]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/anysee.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
+index aa45b5d263f6b..a1235d0cce92f 100644
+--- a/drivers/media/usb/dvb-usb-v2/anysee.c
++++ b/drivers/media/usb/dvb-usb-v2/anysee.c
+@@ -202,7 +202,7 @@ static int anysee_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+       while (i < num) {
+               if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+-                      if (msg[i].len > 2 || msg[i+1].len > 60) {
++                      if (msg[i].len != 2 || msg[i + 1].len > 60) {
+                               ret = -EOPNOTSUPP;
+                               break;
+                       }
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-az6007-fix-null-ptr-deref-in-az6007_i2c_xfer.patch b/queue-5.15/media-az6007-fix-null-ptr-deref-in-az6007_i2c_xfer.patch
new file mode 100644 (file)
index 0000000..ef629b7
--- /dev/null
@@ -0,0 +1,55 @@
+From fbd3afcd8e8fa757937237e8d20e3e6ece087436 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 9 Jul 2023 00:28:17 +0800
+Subject: media: az6007: Fix null-ptr-deref in az6007_i2c_xfer()
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 1047f9343011f2cedc73c64829686206a7e9fc3f ]
+
+In az6007_i2c_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach az6007_i2c_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/az6007.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/az6007.c b/drivers/media/usb/dvb-usb-v2/az6007.c
+index 7524c90f5da61..6cbfe75791c21 100644
+--- a/drivers/media/usb/dvb-usb-v2/az6007.c
++++ b/drivers/media/usb/dvb-usb-v2/az6007.c
+@@ -788,6 +788,10 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+                       if (az6007_xfer_debug)
+                               printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n",
+                                      addr, msgs[i].len);
++                      if (msgs[i].len < 1) {
++                              ret = -EIO;
++                              goto err;
++                      }
+                       req = AZ6007_I2C_WR;
+                       index = msgs[i].buf[0];
+                       value = addr | (1 << 8);
+@@ -802,6 +806,10 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+                       if (az6007_xfer_debug)
+                               printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n",
+                                      addr, msgs[i].len);
++                      if (msgs[i].len < 1) {
++                              ret = -EIO;
++                              goto err;
++                      }
+                       req = AZ6007_I2C_RD;
+                       index = msgs[i].buf[0];
+                       value = addr;
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-dvb-usb-v2-af9035-fix-null-ptr-deref-in-af9035.patch b/queue-5.15/media-dvb-usb-v2-af9035-fix-null-ptr-deref-in-af9035.patch
new file mode 100644 (file)
index 0000000..ecdb0ec
--- /dev/null
@@ -0,0 +1,64 @@
+From bb3bea574b69a3d7849905e008890aced7be6a42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jul 2023 00:06:54 +0800
+Subject: media: dvb-usb-v2: af9035: Fix null-ptr-deref in
+ af9035_i2c_master_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 7bf744f2de0a848fb1d717f5831b03db96feae89 ]
+
+In af9035_i2c_master_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach af9035_i2c_master_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/af9035.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
+index 5eef37b00a520..39d9e4f7682c2 100644
+--- a/drivers/media/usb/dvb-usb-v2/af9035.c
++++ b/drivers/media/usb/dvb-usb-v2/af9035.c
+@@ -322,6 +322,8 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+                       ret = -EOPNOTSUPP;
+               } else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
+                          (msg[0].addr == state->af9033_i2c_addr[1])) {
++                      if (msg[0].len < 3 || msg[1].len < 1)
++                              return -EOPNOTSUPP;
+                       /* demod access via firmware interface */
+                       u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+                                       msg[0].buf[2];
+@@ -381,6 +383,8 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+                       ret = -EOPNOTSUPP;
+               } else if ((msg[0].addr == state->af9033_i2c_addr[0]) ||
+                          (msg[0].addr == state->af9033_i2c_addr[1])) {
++                      if (msg[0].len < 3)
++                              return -EOPNOTSUPP;
+                       /* demod access via firmware interface */
+                       u32 reg = msg[0].buf[0] << 16 | msg[0].buf[1] << 8 |
+                                       msg[0].buf[2];
+@@ -388,10 +392,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
+                       if (msg[0].addr == state->af9033_i2c_addr[1])
+                               reg |= 0x100000;
+-                      ret = (msg[0].len >= 3) ? af9035_wr_regs(d, reg,
+-                                                               &msg[0].buf[3],
+-                                                               msg[0].len - 3)
+-                                              : -EOPNOTSUPP;
++                      ret = af9035_wr_regs(d, reg, &msg[0].buf[3], msg[0].len - 3);
+               } else {
+                       /* I2C write */
+                       u8 buf[MAX_XFER_SIZE];
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-dvb-usb-v2-gl861-fix-null-ptr-deref-in-gl861_i.patch b/queue-5.15/media-dvb-usb-v2-gl861-fix-null-ptr-deref-in-gl861_i.patch
new file mode 100644 (file)
index 0000000..d61b716
--- /dev/null
@@ -0,0 +1,42 @@
+From 35f1226d661c758cd32f7cecff00e3240cf98479 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 10 Jul 2023 13:32:13 +0800
+Subject: media: dvb-usb-v2: gl861: Fix null-ptr-deref in gl861_i2c_master_xfer
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit b97719a66970601cd3151a3e2020f4454a1c4ff6 ]
+
+In gl861_i2c_master_xfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach gl861_i2c_master_xfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 0ed554fd769a
+("media: dvb-usb: az6027: fix null-ptr-deref in az6027_i2c_xfer()")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb-v2/gl861.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
+index 0c434259c36f1..c71e7b93476de 100644
+--- a/drivers/media/usb/dvb-usb-v2/gl861.c
++++ b/drivers/media/usb/dvb-usb-v2/gl861.c
+@@ -120,7 +120,7 @@ static int gl861_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+       } else if (num == 2 && !(msg[0].flags & I2C_M_RD) &&
+                  (msg[1].flags & I2C_M_RD)) {
+               /* I2C write + read */
+-              if (msg[0].len > 1 || msg[1].len > sizeof(ctx->buf)) {
++              if (msg[0].len != 1 || msg[1].len > sizeof(ctx->buf)) {
+                       ret = -EOPNOTSUPP;
+                       goto err;
+               }
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-dw2102-fix-null-ptr-deref-in-dw2102_i2c_transf.patch b/queue-5.15/media-dw2102-fix-null-ptr-deref-in-dw2102_i2c_transf.patch
new file mode 100644 (file)
index 0000000..6c2ea70
--- /dev/null
@@ -0,0 +1,98 @@
+From 7f504eb0e567a201d83e41f8406676cf9b1fa584 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 8 Jul 2023 18:22:52 +0800
+Subject: media: dw2102: Fix null-ptr-deref in dw2102_i2c_transfer()
+
+From: Zhang Shurong <zhang_shurong@foxmail.com>
+
+[ Upstream commit 5ae544d94abc8ff77b1b9bf8774def3fa5689b5b ]
+
+In dw2102_i2c_transfer, msg is controlled by user. When msg[i].buf
+is null and msg[i].len is zero, former checks on msg[i].buf would be
+passed. Malicious data finally reach dw2102_i2c_transfer. If accessing
+msg[i].buf[0] without sanity check, null ptr deref would happen.
+We add check on msg[i].len to prevent crash.
+
+Similar commit:
+commit 950e252cb469
+("[media] dw2102: limit messages to buffer size")
+
+Signed-off-by: Zhang Shurong <zhang_shurong@foxmail.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/usb/dvb-usb/dw2102.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
+index 1ed62a80067c6..253d13bdb63e5 100644
+--- a/drivers/media/usb/dvb-usb/dw2102.c
++++ b/drivers/media/usb/dvb-usb/dw2102.c
+@@ -128,6 +128,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+       switch (num) {
+       case 2:
++              if (msg[0].len < 1) {
++                      num = -EOPNOTSUPP;
++                      break;
++              }
+               /* read stv0299 register */
+               value = msg[0].buf[0];/* register */
+               for (i = 0; i < msg[1].len; i++) {
+@@ -139,6 +143,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+       case 1:
+               switch (msg[0].addr) {
+               case 0x68:
++                      if (msg[0].len < 2) {
++                              num = -EOPNOTSUPP;
++                              break;
++                      }
+                       /* write to stv0299 register */
+                       buf6[0] = 0x2a;
+                       buf6[1] = msg[0].buf[0];
+@@ -148,6 +156,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                       break;
+               case 0x60:
+                       if (msg[0].flags == 0) {
++                              if (msg[0].len < 4) {
++                                      num = -EOPNOTSUPP;
++                                      break;
++                              }
+                       /* write to tuner pll */
+                               buf6[0] = 0x2c;
+                               buf6[1] = 5;
+@@ -159,6 +171,10 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                               dw210x_op_rw(d->udev, 0xb2, 0, 0,
+                                               buf6, 7, DW210X_WRITE_MSG);
+                       } else {
++                              if (msg[0].len < 1) {
++                                      num = -EOPNOTSUPP;
++                                      break;
++                              }
+                       /* read from tuner */
+                               dw210x_op_rw(d->udev, 0xb5, 0, 0,
+                                               buf6, 1, DW210X_READ_MSG);
+@@ -166,12 +182,20 @@ static int dw2102_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                       }
+                       break;
+               case (DW2102_RC_QUERY):
++                      if (msg[0].len < 2) {
++                              num = -EOPNOTSUPP;
++                              break;
++                      }
+                       dw210x_op_rw(d->udev, 0xb8, 0, 0,
+                                       buf6, 2, DW210X_READ_MSG);
+                       msg[0].buf[0] = buf6[0];
+                       msg[0].buf[1] = buf6[1];
+                       break;
+               case (DW2102_VOLTAGE_CTRL):
++                      if (msg[0].len < 1) {
++                              num = -EOPNOTSUPP;
++                              break;
++                      }
+                       buf6[0] = 0x30;
+                       buf6[1] = msg[0].buf[0];
+                       dw210x_op_rw(d->udev, 0xb2, 0, 0,
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-pci-cx23885-replace-bug-with-error-return.patch b/queue-5.15/media-pci-cx23885-replace-bug-with-error-return.patch
new file mode 100644 (file)
index 0000000..43c6984
--- /dev/null
@@ -0,0 +1,36 @@
+From 1b2add980537754c544a3ee7b72a73a7e54a56e3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 21 Jul 2023 10:23:42 +0200
+Subject: media: pci: cx23885: replace BUG with error return
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit 2e1796fd4904fdd6062a8e4589778ea899ea0c8d ]
+
+It was completely unnecessary to use BUG in buffer_prepare().
+Just replace it with an error return. This also fixes a smatch warning:
+
+drivers/media/pci/cx23885/cx23885-video.c:422 buffer_prepare() error: uninitialized symbol 'ret'.
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/pci/cx23885/cx23885-video.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
+index b01499f810697..6851e01da1c5b 100644
+--- a/drivers/media/pci/cx23885/cx23885-video.c
++++ b/drivers/media/pci/cx23885/cx23885-video.c
+@@ -413,7 +413,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
+                               dev->height >> 1);
+               break;
+       default:
+-              BUG();
++              return -EINVAL; /* should not happen */
+       }
+       dprintk(2, "[%p/%d] buffer_init - %dx%d %dbpp 0x%08x - dma=0x%08lx\n",
+               buf, buf->vb.vb2_buf.index,
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-pci-ipu3-cio2-initialise-timing-struct-to-avoi.patch b/queue-5.15/media-pci-ipu3-cio2-initialise-timing-struct-to-avoi.patch
new file mode 100644 (file)
index 0000000..f2acde8
--- /dev/null
@@ -0,0 +1,37 @@
+From 6d06649aac3ae8944d5eff546c0e66c0b5d7efd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Aug 2023 10:14:30 +0300
+Subject: media: pci: ipu3-cio2: Initialise timing struct to avoid a compiler
+ warning
+
+From: Sakari Ailus <sakari.ailus@linux.intel.com>
+
+[ Upstream commit 9d7531be3085a8f013cf173ccc4e72e3cf493538 ]
+
+Initialise timing struct in cio2_hw_init() to zero in order to avoid a
+compiler warning. The warning was a false positive.
+
+Reported-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+index 3a8af3936e93a..162ab089124f3 100644
+--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
++++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+@@ -345,7 +345,7 @@ static int cio2_hw_init(struct cio2_device *cio2, struct cio2_queue *q)
+       void __iomem *const base = cio2->base;
+       u8 lanes, csi2bus = q->csi2.port;
+       u8 sensor_vc = SENSOR_VIR_CH_DFLT;
+-      struct cio2_csi2_timing timing;
++      struct cio2_csi2_timing timing = { 0 };
+       int i, r;
+       fmt = cio2_find_format(NULL, &q->subdev_fmt.code);
+-- 
+2.40.1
+
diff --git a/queue-5.15/media-tuners-qt1010-replace-bug_on-with-a-regular-er.patch b/queue-5.15/media-tuners-qt1010-replace-bug_on-with-a-regular-er.patch
new file mode 100644 (file)
index 0000000..48866b6
--- /dev/null
@@ -0,0 +1,46 @@
+From 4f9a21374fc2dab5a49aeb0e790253432708f23e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 20 Jul 2023 08:20:51 +0200
+Subject: media: tuners: qt1010: replace BUG_ON with a regular error
+
+From: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+
+[ Upstream commit ee630b29ea44d1851bb6c903f400956604834463 ]
+
+BUG_ON is unnecessary here, and in addition it confuses smatch.
+Replacing this with an error return help resolve this smatch
+warning:
+
+drivers/media/tuners/qt1010.c:350 qt1010_init() error: buffer overflow 'i2c_data' 34 <= 34
+
+Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/media/tuners/qt1010.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/media/tuners/qt1010.c b/drivers/media/tuners/qt1010.c
+index 60931367b82ca..48fc79cd40273 100644
+--- a/drivers/media/tuners/qt1010.c
++++ b/drivers/media/tuners/qt1010.c
+@@ -345,11 +345,12 @@ static int qt1010_init(struct dvb_frontend *fe)
+                       else
+                               valptr = &tmpval;
+-                      BUG_ON(i >= ARRAY_SIZE(i2c_data) - 1);
+-
+-                      err = qt1010_init_meas1(priv, i2c_data[i+1].reg,
+-                                              i2c_data[i].reg,
+-                                              i2c_data[i].val, valptr);
++                      if (i >= ARRAY_SIZE(i2c_data) - 1)
++                              err = -EIO;
++                      else
++                              err = qt1010_init_meas1(priv, i2c_data[i + 1].reg,
++                                                      i2c_data[i].reg,
++                                                      i2c_data[i].val, valptr);
+                       i++;
+                       break;
+               }
+-- 
+2.40.1
+
diff --git a/queue-5.15/mips-use-grep-e-instead-of-egrep.patch b/queue-5.15/mips-use-grep-e-instead-of-egrep.patch
new file mode 100644 (file)
index 0000000..b5ff58d
--- /dev/null
@@ -0,0 +1,60 @@
+From 6bc0644b6fcfc2d16f757051088a9317effb872b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Nov 2022 16:28:11 +0800
+Subject: MIPS: Use "grep -E" instead of "egrep"
+
+From: Tiezhu Yang <yangtiezhu@loongson.cn>
+
+[ Upstream commit d42f0c6ad502c9f612410e125ebdf290cce8bdc3 ]
+
+The latest version of grep claims the egrep is now obsolete so the build
+now contains warnings that look like:
+       egrep: warning: egrep is obsolescent; using grep -E
+fix this up by moving the related file to use "grep -E" instead.
+
+Here are the steps to install the latest grep:
+
+  wget http://ftp.gnu.org/gnu/grep/grep-3.8.tar.gz
+  tar xf grep-3.8.tar.gz
+  cd grep-3.8 && ./configure && make
+  sudo make install
+  export PATH=/usr/local/bin:$PATH
+
+Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
+Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+Stable-dep-of: 4fe4a6374c4d ("MIPS: Only fiddle with CHECKFLAGS if `need-compiler'")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/mips/Makefile      | 2 +-
+ arch/mips/vdso/Makefile | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/Makefile b/arch/mips/Makefile
+index 151e98698f763..3830217fab414 100644
+--- a/arch/mips/Makefile
++++ b/arch/mips/Makefile
+@@ -323,7 +323,7 @@ KBUILD_LDFLAGS             += -m $(ld-emul)
+ ifdef need-compiler
+ CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
+-      egrep -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
++      grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
+       sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
+ endif
+diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
+index 1b2ea34c3d3bb..ed090ef30757c 100644
+--- a/arch/mips/vdso/Makefile
++++ b/arch/mips/vdso/Makefile
+@@ -68,7 +68,7 @@ KCOV_INSTRUMENT := n
+ # Check that we don't have PIC 'jalr t9' calls left
+ quiet_cmd_vdso_mips_check = VDSOCHK $@
+-      cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \
++      cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | grep -E -h "jalr.*t9" > /dev/null; \
+                      then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \
+                            rm -f $@; /bin/false); fi
+-- 
+2.40.1
+
diff --git a/queue-5.15/mmc-sdhci-esdhc-imx-improve-esdhc_flag_err010450.patch b/queue-5.15/mmc-sdhci-esdhc-imx-improve-esdhc_flag_err010450.patch
new file mode 100644 (file)
index 0000000..f405a31
--- /dev/null
@@ -0,0 +1,54 @@
+From c89535a0f2df73eb9a7bf20f657c308bc8c9bbd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Aug 2023 23:48:53 +0200
+Subject: mmc: sdhci-esdhc-imx: improve ESDHC_FLAG_ERR010450
+
+From: Giulio Benetti <giulio.benetti@benettiengineering.com>
+
+[ Upstream commit 5ae4b0d8875caa44946e579420c7fd5740d58653 ]
+
+Errata ERR010450 only shows up if voltage is 1.8V, but if the device is
+supplied by 3v3 the errata can be ignored. So let's check for if quirk
+SDHCI_QUIRK2_NO_1_8_V is defined or not before limiting the frequency.
+
+Cc: Jim Reinhart <jimr@tekvox.com>
+Cc: James Autry <jautry@tekvox.com>
+Cc: Matthew Maron <matthewm@tekvox.com>
+Signed-off-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
+Acked-by: Haibo Chen <haibo.chen@nxp.com>
+Acked-by: Adrian Hunter <adrian.hunter@intel.com>
+Link: https://lore.kernel.org/r/20230811214853.8623-1-giulio.benetti@benettiengineering.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/sdhci-esdhc-imx.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index a6aa33dcd2a2e..d8a4080712365 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -171,8 +171,8 @@
+ #define ESDHC_FLAG_HS400              BIT(9)
+ /*
+  * The IP has errata ERR010450
+- * uSDHC: Due to the I/O timing limit, for SDR mode, SD card clock can't
+- * exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
++ * uSDHC: At 1.8V due to the I/O timing limit, for SDR mode, SD card
++ * clock can't exceed 150MHz, for DDR mode, SD card clock can't exceed 45MHz.
+  */
+ #define ESDHC_FLAG_ERR010450          BIT(10)
+ /* The IP supports HS400ES mode */
+@@ -917,7 +917,8 @@ static inline void esdhc_pltfm_set_clock(struct sdhci_host *host,
+               | ESDHC_CLOCK_MASK);
+       sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
+-      if (imx_data->socdata->flags & ESDHC_FLAG_ERR010450) {
++      if ((imx_data->socdata->flags & ESDHC_FLAG_ERR010450) &&
++          (!(host->quirks2 & SDHCI_QUIRK2_NO_1_8_V))) {
+               unsigned int max_clock;
+               max_clock = imx_data->is_ddr ? 45000000 : 150000000;
+-- 
+2.40.1
+
diff --git a/queue-5.15/mtd-rawnand-brcmnand-allow-soc-to-provide-i-o-operat.patch b/queue-5.15/mtd-rawnand-brcmnand-allow-soc-to-provide-i-o-operat.patch
new file mode 100644 (file)
index 0000000..6327798
--- /dev/null
@@ -0,0 +1,165 @@
+From 908b0df812deb5537af1653bda150da6a0b7ff3e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Jan 2022 10:46:07 -0800
+Subject: mtd: rawnand: brcmnand: Allow SoC to provide I/O operations
+
+From: Florian Fainelli <f.fainelli@gmail.com>
+
+[ Upstream commit 25f97138f8c225dbf365b428a94d7b30a6daefb3 ]
+
+Allow a brcmnand_soc instance to provide a custom set of I/O operations
+which we will require when using this driver on a BCMA bus which is not
+directly memory mapped I/O. Update the nand_{read,write}_reg accordingly
+to use the SoC operations if provided.
+
+To minimize the penalty on other SoCs which do support standard MMIO
+accesses, we use a static key which is disabled by default and gets
+enabled if a soc implementation does provide I/O operations.
+
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20220107184614.2670254-3-f.fainelli@gmail.com
+Stable-dep-of: 2ec2839a9062 ("mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2 controller")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 28 +++++++++++++++++++++--
+ drivers/mtd/nand/raw/brcmnand/brcmnand.h | 29 ++++++++++++++++++++++++
+ 2 files changed, 55 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+index c1afadb50eecc..f20a3154a0adb 100644
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -25,6 +25,7 @@
+ #include <linux/of.h>
+ #include <linux/of_platform.h>
+ #include <linux/slab.h>
++#include <linux/static_key.h>
+ #include <linux/list.h>
+ #include <linux/log2.h>
+@@ -207,6 +208,8 @@ enum {
+ struct brcmnand_host;
++static DEFINE_STATIC_KEY_FALSE(brcmnand_soc_has_ops_key);
++
+ struct brcmnand_controller {
+       struct device           *dev;
+       struct nand_controller  controller;
+@@ -592,15 +595,25 @@ enum {
+       INTFC_CTLR_READY                = BIT(31),
+ };
++static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
++{
++      return static_branch_unlikely(&brcmnand_soc_has_ops_key);
++}
++
+ static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs)
+ {
++      if (brcmnand_non_mmio_ops(ctrl))
++              return brcmnand_soc_read(ctrl->soc, offs);
+       return brcmnand_readl(ctrl->nand_base + offs);
+ }
+ static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs,
+                                u32 val)
+ {
+-      brcmnand_writel(val, ctrl->nand_base + offs);
++      if (brcmnand_non_mmio_ops(ctrl))
++              brcmnand_soc_write(ctrl->soc, val, offs);
++      else
++              brcmnand_writel(val, ctrl->nand_base + offs);
+ }
+ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
+@@ -766,13 +779,18 @@ static inline void brcmnand_rmw_reg(struct brcmnand_controller *ctrl,
+ static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word)
+ {
++      if (brcmnand_non_mmio_ops(ctrl))
++              return brcmnand_soc_read(ctrl->soc, BRCMNAND_NON_MMIO_FC_ADDR);
+       return __raw_readl(ctrl->nand_fc + word * 4);
+ }
+ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl,
+                                    int word, u32 val)
+ {
+-      __raw_writel(val, ctrl->nand_fc + word * 4);
++      if (brcmnand_non_mmio_ops(ctrl))
++              brcmnand_soc_write(ctrl->soc, val, BRCMNAND_NON_MMIO_FC_ADDR);
++      else
++              __raw_writel(val, ctrl->nand_fc + word * 4);
+ }
+ static inline void edu_writel(struct brcmnand_controller *ctrl,
+@@ -3034,6 +3052,12 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
+       dev_set_drvdata(dev, ctrl);
+       ctrl->dev = dev;
++      /* Enable the static key if the soc provides I/O operations indicating
++       * that a non-memory mapped IO access path must be used
++       */
++      if (brcmnand_soc_has_ops(ctrl->soc))
++              static_branch_enable(&brcmnand_soc_has_ops_key);
++
+       init_completion(&ctrl->done);
+       init_completion(&ctrl->dma_done);
+       init_completion(&ctrl->edu_done);
+diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.h b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
+index eb498fbe505ec..f1f93d85f50d2 100644
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.h
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h
+@@ -11,12 +11,25 @@
+ struct platform_device;
+ struct dev_pm_ops;
++struct brcmnand_io_ops;
++
++/* Special register offset constant to intercept a non-MMIO access
++ * to the flash cache register space. This is intentionally large
++ * not to overlap with an existing offset.
++ */
++#define BRCMNAND_NON_MMIO_FC_ADDR     0xffffffff
+ struct brcmnand_soc {
+       bool (*ctlrdy_ack)(struct brcmnand_soc *soc);
+       void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en);
+       void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare,
+                                bool is_param);
++      const struct brcmnand_io_ops *ops;
++};
++
++struct brcmnand_io_ops {
++      u32 (*read_reg)(struct brcmnand_soc *soc, u32 offset);
++      void (*write_reg)(struct brcmnand_soc *soc, u32 val, u32 offset);
+ };
+ static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc,
+@@ -58,6 +71,22 @@ static inline void brcmnand_writel(u32 val, void __iomem *addr)
+               writel_relaxed(val, addr);
+ }
++static inline bool brcmnand_soc_has_ops(struct brcmnand_soc *soc)
++{
++      return soc && soc->ops && soc->ops->read_reg && soc->ops->write_reg;
++}
++
++static inline u32 brcmnand_soc_read(struct brcmnand_soc *soc, u32 offset)
++{
++      return soc->ops->read_reg(soc, offset);
++}
++
++static inline void brcmnand_soc_write(struct brcmnand_soc *soc, u32 val,
++                                    u32 offset)
++{
++      soc->ops->write_reg(soc, val, offset);
++}
++
+ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc);
+ int brcmnand_remove(struct platform_device *pdev);
+-- 
+2.40.1
+
diff --git a/queue-5.15/mtd-rawnand-brcmnand-fix-ecc-level-field-setting-for.patch b/queue-5.15/mtd-rawnand-brcmnand-fix-ecc-level-field-setting-for.patch
new file mode 100644 (file)
index 0000000..cee9494
--- /dev/null
@@ -0,0 +1,161 @@
+From 1b69ac54f392f464f7af1ad004e279f4d81d602c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Jul 2023 11:29:05 -0700
+Subject: mtd: rawnand: brcmnand: Fix ECC level field setting for v7.2
+ controller
+
+From: William Zhang <william.zhang@broadcom.com>
+
+[ Upstream commit 2ec2839a9062db8a592525a3fdabd42dcd9a3a9b ]
+
+v7.2 controller has different ECC level field size and shift in the acc
+control register than its predecessor and successor controller. It needs
+to be set specifically.
+
+Fixes: decba6d47869 ("mtd: brcmnand: Add v7.2 controller support")
+Signed-off-by: William Zhang <william.zhang@broadcom.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20230706182909.79151-2-william.zhang@broadcom.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/brcmnand/brcmnand.c | 74 +++++++++++++-----------
+ 1 file changed, 41 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+index f20a3154a0adb..c1e7ab13e7773 100644
+--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c
++++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c
+@@ -271,6 +271,7 @@ struct brcmnand_controller {
+       const unsigned int      *page_sizes;
+       unsigned int            page_size_shift;
+       unsigned int            max_oob;
++      u32                     ecc_level_shift;
+       u32                     features;
+       /* for low-power standby/resume only */
+@@ -595,6 +596,34 @@ enum {
+       INTFC_CTLR_READY                = BIT(31),
+ };
++/***********************************************************************
++ * NAND ACC CONTROL bitfield
++ *
++ * Some bits have remained constant throughout hardware revision, while
++ * others have shifted around.
++ ***********************************************************************/
++
++/* Constant for all versions (where supported) */
++enum {
++      /* See BRCMNAND_HAS_CACHE_MODE */
++      ACC_CONTROL_CACHE_MODE                          = BIT(22),
++
++      /* See BRCMNAND_HAS_PREFETCH */
++      ACC_CONTROL_PREFETCH                            = BIT(23),
++
++      ACC_CONTROL_PAGE_HIT                            = BIT(24),
++      ACC_CONTROL_WR_PREEMPT                          = BIT(25),
++      ACC_CONTROL_PARTIAL_PAGE                        = BIT(26),
++      ACC_CONTROL_RD_ERASED                           = BIT(27),
++      ACC_CONTROL_FAST_PGM_RDIN                       = BIT(28),
++      ACC_CONTROL_WR_ECC                              = BIT(30),
++      ACC_CONTROL_RD_ECC                              = BIT(31),
++};
++
++#define       ACC_CONTROL_ECC_SHIFT                   16
++/* Only for v7.2 */
++#define       ACC_CONTROL_ECC_EXT_SHIFT               13
++
+ static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl)
+ {
+       return static_branch_unlikely(&brcmnand_soc_has_ops_key);
+@@ -732,6 +761,12 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl)
+       else if (of_property_read_bool(ctrl->dev->of_node, "brcm,nand-has-wp"))
+               ctrl->features |= BRCMNAND_HAS_WP;
++      /* v7.2 has different ecc level shift in the acc register */
++      if (ctrl->nand_version == 0x0702)
++              ctrl->ecc_level_shift = ACC_CONTROL_ECC_EXT_SHIFT;
++      else
++              ctrl->ecc_level_shift = ACC_CONTROL_ECC_SHIFT;
++
+       return 0;
+ }
+@@ -920,30 +955,6 @@ static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl)
+       return 0;
+ }
+-/***********************************************************************
+- * NAND ACC CONTROL bitfield
+- *
+- * Some bits have remained constant throughout hardware revision, while
+- * others have shifted around.
+- ***********************************************************************/
+-
+-/* Constant for all versions (where supported) */
+-enum {
+-      /* See BRCMNAND_HAS_CACHE_MODE */
+-      ACC_CONTROL_CACHE_MODE                          = BIT(22),
+-
+-      /* See BRCMNAND_HAS_PREFETCH */
+-      ACC_CONTROL_PREFETCH                            = BIT(23),
+-
+-      ACC_CONTROL_PAGE_HIT                            = BIT(24),
+-      ACC_CONTROL_WR_PREEMPT                          = BIT(25),
+-      ACC_CONTROL_PARTIAL_PAGE                        = BIT(26),
+-      ACC_CONTROL_RD_ERASED                           = BIT(27),
+-      ACC_CONTROL_FAST_PGM_RDIN                       = BIT(28),
+-      ACC_CONTROL_WR_ECC                              = BIT(30),
+-      ACC_CONTROL_RD_ECC                              = BIT(31),
+-};
+-
+ static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
+ {
+       if (ctrl->nand_version == 0x0702)
+@@ -956,18 +967,15 @@ static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl)
+               return GENMASK(4, 0);
+ }
+-#define NAND_ACC_CONTROL_ECC_SHIFT    16
+-#define NAND_ACC_CONTROL_ECC_EXT_SHIFT        13
+-
+ static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl)
+ {
+       u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f;
+-      mask <<= NAND_ACC_CONTROL_ECC_SHIFT;
++      mask <<= ACC_CONTROL_ECC_SHIFT;
+       /* v7.2 includes additional ECC levels */
+-      if (ctrl->nand_version >= 0x0702)
+-              mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT;
++      if (ctrl->nand_version == 0x0702)
++              mask |= 0x7 << ACC_CONTROL_ECC_EXT_SHIFT;
+       return mask;
+ }
+@@ -981,8 +989,8 @@ static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en)
+       if (en) {
+               acc_control |= ecc_flags; /* enable RD/WR ECC */
+-              acc_control |= host->hwcfg.ecc_level
+-                             << NAND_ACC_CONTROL_ECC_SHIFT;
++              acc_control &= ~brcmnand_ecc_level_mask(ctrl);
++              acc_control |= host->hwcfg.ecc_level << ctrl->ecc_level_shift;
+       } else {
+               acc_control &= ~ecc_flags; /* disable RD/WR ECC */
+               acc_control &= ~brcmnand_ecc_level_mask(ctrl);
+@@ -2582,7 +2590,7 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
+       tmp &= ~brcmnand_ecc_level_mask(ctrl);
+       tmp &= ~brcmnand_spare_area_mask(ctrl);
+       if (ctrl->nand_version >= 0x0302) {
+-              tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT;
++              tmp |= cfg->ecc_level << ctrl->ecc_level_shift;
+               tmp |= cfg->spare_area_size;
+       }
+       nand_writereg(ctrl, acc_control_offs, tmp);
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-ebtables-fix-fortify-warnings-in-size_entr.patch b/queue-5.15/netfilter-ebtables-fix-fortify-warnings-in-size_entr.patch
new file mode 100644 (file)
index 0000000..27e35d7
--- /dev/null
@@ -0,0 +1,84 @@
+From 80cca7246c9bbcd4c2dadfe4af445d674ab2862d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 15:45:03 +0800
+Subject: netfilter: ebtables: fix fortify warnings in size_entry_mwt()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: GONG, Ruiqi <gongruiqi1@huawei.com>
+
+[ Upstream commit a7ed3465daa240bdf01a5420f64336fee879c09d ]
+
+When compiling with gcc 13 and CONFIG_FORTIFY_SOURCE=y, the following
+warning appears:
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘size_entry_mwt’ at net/bridge/netfilter/ebtables.c:2118:2:
+./include/linux/fortify-string.h:592:25: error: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Werror=attribute-warning]
+  592 |                         __read_overflow2_field(q_size_field, size);
+      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The compiler is complaining:
+
+memcpy(&offsets[1], &entry->watchers_offset,
+                       sizeof(offsets) - sizeof(offsets[0]));
+
+where memcpy reads beyong &entry->watchers_offset to copy
+{watchers,target,next}_offset altogether into offsets[]. Silence the
+warning by wrapping these three up via struct_group().
+
+Signed-off-by: GONG, Ruiqi <gongruiqi1@huawei.com>
+Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/uapi/linux/netfilter_bridge/ebtables.h | 14 ++++++++------
+ net/bridge/netfilter/ebtables.c                |  3 +--
+ 2 files changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/include/uapi/linux/netfilter_bridge/ebtables.h b/include/uapi/linux/netfilter_bridge/ebtables.h
+index a494cf43a7552..b0caad82b6937 100644
+--- a/include/uapi/linux/netfilter_bridge/ebtables.h
++++ b/include/uapi/linux/netfilter_bridge/ebtables.h
+@@ -182,12 +182,14 @@ struct ebt_entry {
+       unsigned char sourcemsk[ETH_ALEN];
+       unsigned char destmac[ETH_ALEN];
+       unsigned char destmsk[ETH_ALEN];
+-      /* sizeof ebt_entry + matches */
+-      unsigned int watchers_offset;
+-      /* sizeof ebt_entry + matches + watchers */
+-      unsigned int target_offset;
+-      /* sizeof ebt_entry + matches + watchers + target */
+-      unsigned int next_offset;
++      __struct_group(/* no tag */, offsets, /* no attrs */,
++              /* sizeof ebt_entry + matches */
++              unsigned int watchers_offset;
++              /* sizeof ebt_entry + matches + watchers */
++              unsigned int target_offset;
++              /* sizeof ebt_entry + matches + watchers + target */
++              unsigned int next_offset;
++      );
+       unsigned char elems[0] __attribute__ ((aligned (__alignof__(struct ebt_replace))));
+ };
+diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
+index a09b2fc11c80e..c0389199c0dcb 100644
+--- a/net/bridge/netfilter/ebtables.c
++++ b/net/bridge/netfilter/ebtables.c
+@@ -2114,8 +2114,7 @@ static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *ba
+               return ret;
+       offsets[0] = sizeof(struct ebt_entry); /* matches come first */
+-      memcpy(&offsets[1], &entry->watchers_offset,
+-                      sizeof(offsets) - sizeof(offsets[0]));
++      memcpy(&offsets[1], &entry->offsets, sizeof(entry->offsets));
+       if (state->buf_kern_start) {
+               buf_start = state->buf_kern_start + state->buf_kern_offset;
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch b/queue-5.15/netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch
new file mode 100644 (file)
index 0000000..cde6381
--- /dev/null
@@ -0,0 +1,557 @@
+From 48cf24f34ae00731911dd80cb9e9d11b774ec428 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.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>
+
+[ Upstream commit f6c383b8c31a93752a52697f8430a71dcbc46adf ]
+
+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: Sasha Levin <sashal@kernel.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 | 144 ++++++++++++++++++++-------------
+ 4 files changed, 173 insertions(+), 103 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 2333f5da1eb97..616fd19d5cedc 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -6003,7 +6003,6 @@ static void nft_setelem_activate(struct net *net, struct nft_set *set,
+       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);
+       }
+@@ -6018,8 +6017,7 @@ static int nft_setelem_catchall_deactivate(const struct net *net,
+       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);
+@@ -6719,8 +6717,7 @@ static int nft_set_catchall_flush(const struct nft_ctx *ctx,
+       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;
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index 0b73cb0e752f7..960cbd56c0406 100644
+--- 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 rhashtable_compare_arg *arg,
+       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 struct net *net, const struct nft_set *set,
+       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 net *net,
+ {
+       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 struct net *net,
+       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();
+@@ -314,25 +311,48 @@ static bool nft_rhash_expr_needs_gc_run(const struct nft_set *set,
+ 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;
+@@ -340,26 +360,26 @@ static void nft_rhash_gc(struct work_struct *work)
+               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));
+ }
+@@ -422,7 +442,6 @@ static void nft_rhash_destroy(const struct nft_ctx *ctx,
+       };
+       cancel_delayed_work_sync(&priv->gc_work);
+-      rcu_barrier();
+       rhashtable_free_and_destroy(&priv->ht, nft_rhash_elem_destroy,
+                                   (void *)&rhash_ctx);
+ }
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index 8c16681884b7e..0a49c59a22dbd 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -1536,16 +1536,34 @@ static void pipapo_drop(struct nft_pipapo_match *m,
+       }
+ }
++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];
+@@ -1569,13 +1587,20 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
+               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.
+@@ -1585,11 +1610,11 @@ static void pipapo_gc(const struct nft_set *set, struct nft_pipapo_match *m)
+               }
+       }
+-      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;
++      }
+ }
+ /**
+@@ -1725,7 +1750,6 @@ static void nft_pipapo_activate(const struct net *net,
+               return;
+       nft_set_elem_change_active(net, set, &e->ext);
+-      nft_set_elem_clear_busy(&e->ext);
+ }
+ /**
+diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
+index 8d73fffd2d09d..7015153b7be18 100644
+--- 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 nft_set *set,
+                     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 struct net *net, const struct nft_set *set
+                               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 struct net *net, const struct nft_set *set
+       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 net *net, const struct nft_set *set,
+       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 struct nft_set *__set,
+ {
+       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 struct nft_set *__set,
+       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_trans_gc_elem_add(gc, rbe);
+-      nft_set_gc_batch_add(gcb, rbe);
+-      nft_set_gc_batch_complete(gcb);
++      nft_trans_gc_queue_sync_done(gc);
+       return 0;
+ }
+@@ -482,7 +512,6 @@ static void nft_rbtree_activate(const struct net *net,
+       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 struct net *net,
+ {
+       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,
+@@ -572,26 +598,40 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
+ 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
+@@ -604,46 +644,36 @@ static void nft_rbtree_gc(struct work_struct *work)
+               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;
++              gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
++              if (!gc)
++                      goto try_later;
+-              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;
++              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));
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch b/queue-5.15/netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch
new file mode 100644 (file)
index 0000000..411578a
--- /dev/null
@@ -0,0 +1,120 @@
+From cca7d158a67d5df21dd05e4de7d05eb7734ed59b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 15:39:00 +0200
+Subject: netfilter: nf_tables: fix GC transaction races with netns and netlink
+ event exit path
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 6a33d8b73dfac0a41f3877894b38082bd0c9a5bc ]
+
+Netlink event path is missing a synchronization point with GC
+transactions. Add GC sequence number update to netns release path and
+netlink event path, any GC transaction losing race will be discarded.
+
+Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 36 +++++++++++++++++++++++++++++++----
+ 1 file changed, 32 insertions(+), 4 deletions(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 75b04c01f7b81..3e17d2403d899 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -9202,6 +9202,22 @@ static void nft_set_commit_update(struct list_head *set_update_list)
+       }
+ }
++static unsigned int nft_gc_seq_begin(struct nftables_pernet *nft_net)
++{
++      unsigned int gc_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);
++
++      return gc_seq;
++}
++
++static void nft_gc_seq_end(struct nftables_pernet *nft_net, unsigned int gc_seq)
++{
++      WRITE_ONCE(nft_net->gc_seq, ++gc_seq);
++}
++
+ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ {
+       struct nftables_pernet *nft_net = nft_pernet(net);
+@@ -9287,9 +9303,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+       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);
++      gc_seq = nft_gc_seq_begin(nft_net);
+       /* step 3. Start new generation, rules_gen_X now in use. */
+       net->nft.gencursor = nft_gencursor_next(net);
+@@ -9480,7 +9494,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+       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);
++      nft_gc_seq_end(nft_net, gc_seq);
+       nf_tables_commit_release(net);
+       return 0;
+@@ -10463,6 +10477,7 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
+       struct net *net = n->net;
+       unsigned int deleted;
+       bool restart = false;
++      unsigned int gc_seq;
+       if (event != NETLINK_URELEASE || n->protocol != NETLINK_NETFILTER)
+               return NOTIFY_DONE;
+@@ -10470,6 +10485,9 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
+       nft_net = nft_pernet(net);
+       deleted = 0;
+       mutex_lock(&nft_net->commit_mutex);
++
++      gc_seq = nft_gc_seq_begin(nft_net);
++
+       if (!list_empty(&nf_tables_destroy_list))
+               nf_tables_trans_destroy_flush_work();
+ again:
+@@ -10492,6 +10510,8 @@ static int nft_rcv_nl_event(struct notifier_block *this, unsigned long event,
+               if (restart)
+                       goto again;
+       }
++      nft_gc_seq_end(nft_net, gc_seq);
++
+       mutex_unlock(&nft_net->commit_mutex);
+       return NOTIFY_DONE;
+@@ -10529,12 +10549,20 @@ static void __net_exit nf_tables_pre_exit_net(struct net *net)
+ static void __net_exit nf_tables_exit_net(struct net *net)
+ {
+       struct nftables_pernet *nft_net = nft_pernet(net);
++      unsigned int gc_seq;
+       mutex_lock(&nft_net->commit_mutex);
++
++      gc_seq = nft_gc_seq_begin(nft_net);
++
+       if (!list_empty(&nft_net->commit_list) ||
+           !list_empty(&nft_net->module_list))
+               __nf_tables_abort(net, NFNL_ABORT_NONE);
++
+       __nft_release_tables(net);
++
++      nft_gc_seq_end(nft_net, gc_seq);
++
+       mutex_unlock(&nft_net->commit_mutex);
+       WARN_ON_ONCE(!list_empty(&nft_net->tables));
+       WARN_ON_ONCE(!list_empty(&nft_net->module_list));
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch b/queue-5.15/netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch
new file mode 100644 (file)
index 0000000..ade4f90
--- /dev/null
@@ -0,0 +1,54 @@
+From e815552d39d047879f8453c5a1007dc4be47bbf3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Aug 2023 23:59:03 +0200
+Subject: netfilter: nf_tables: fix kdoc warnings after gc rework
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 08713cb006b6f07434f276c5ee214fb20c7fd965 ]
+
+Jakub Kicinski says:
+  We've got some new kdoc warnings here:
+  net/netfilter/nft_set_pipapo.c:1557: warning: Function parameter or member '_set' not described in 'pipapo_gc'
+  net/netfilter/nft_set_pipapo.c:1557: warning: Excess function parameter 'set' description in 'pipapo_gc'
+  include/net/netfilter/nf_tables.h:577: warning: Function parameter or member 'dead' not described in 'nft_set'
+
+Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
+Fixes: f6c383b8c31a ("netfilter: nf_tables: adapt set backend to use GC transaction API")
+Reported-by: Jakub Kicinski <kuba@kernel.org>
+Closes: https://lore.kernel.org/netdev/20230810104638.746e46f1@kernel.org/
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h | 1 +
+ net/netfilter/nft_set_pipapo.c    | 2 +-
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index cd3b5b9db8890..86ffb222f4d74 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -499,6 +499,7 @@ struct nft_set_elem_expr {
+  *    @expr: stateful expression
+  *    @ops: set ops
+  *    @flags: set flags
++ *    @dead: set will be freed, never cleared
+  *    @genmask: generation mask
+  *    @klen: key length
+  *    @dlen: data length
+diff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c
+index 0a49c59a22dbd..03472c1d9d548 100644
+--- a/net/netfilter/nft_set_pipapo.c
++++ b/net/netfilter/nft_set_pipapo.c
+@@ -1549,7 +1549,7 @@ static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set,
+ /**
+  * pipapo_gc() - Drop expired entries from set, destroy start and end elements
+- * @set:      nftables API set representation
++ * @_set:     nftables API set representation
+  * @m:                Matching data
+  */
+ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch b/queue-5.15/netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch
new file mode 100644 (file)
index 0000000..06dd390
--- /dev/null
@@ -0,0 +1,574 @@
+From 96c686573801202fe04d4ebce7e3cf7aa8caea2a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.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>
+
+[ Upstream commit 5f68718b34a531a556f2f50300ead2862278da26 ]
+
+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: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h |  64 +++++++-
+ net/netfilter/nf_tables_api.c     | 248 ++++++++++++++++++++++++++++--
+ 2 files changed, 300 insertions(+), 12 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index b8d967e0eb1e2..a6bf58316a5d8 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -477,6 +477,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
+@@ -506,6 +507,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;
+@@ -527,7 +529,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;
+@@ -1527,6 +1530,32 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
+       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
+  *
+@@ -1658,6 +1687,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);
+@@ -1684,6 +1745,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;
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index dde19be41610d..2333f5da1eb97 100644
+--- 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(struct nft_table *table, u8 new_validate_s
+ 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 struct nft_ctx *ctx, int msg_type,
+       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,
+@@ -4756,6 +4757,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
+       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;
+@@ -4823,6 +4825,14 @@ static void nft_set_catchall_destroy(const struct nft_ctx *ctx,
+       }
+ }
++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;
+@@ -4835,8 +4845,7 @@ static void nft_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
+       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,
+@@ -5901,7 +5910,8 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
+       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;
+       }
+@@ -6545,9 +6555,9 @@ static void nft_setelem_data_activate(const struct net *net,
+               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);
+@@ -8882,6 +8892,207 @@ void nft_chain_del(struct nft_chain *chain)
+       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);
+@@ -9044,11 +9255,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+ {
+       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;
+@@ -9125,6 +9336,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+       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);
+@@ -9213,6 +9428,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+                       nft_trans_destroy(trans);
+                       break;
+               case NFT_MSG_DELSET:
++                      nft_trans_set(trans)->dead = 1;
+                       list_del_rcu(&nft_trans_set(trans)->list);
+                       nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
+                                            NFT_MSG_DELSET, GFP_KERNEL);
+@@ -9312,6 +9528,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
+       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;
+@@ -10343,6 +10561,7 @@ static int __net_init nf_tables_init_net(struct net *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;
+ }
+@@ -10371,10 +10590,16 @@ static void __net_exit nf_tables_exit_net(struct net *net)
+       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),
+ };
+@@ -10446,6 +10671,7 @@ static void __exit nf_tables_module_exit(void)
+       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);
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nf_tables-gc-transaction-race-with-netns-d.patch b/queue-5.15/netfilter-nf_tables-gc-transaction-race-with-netns-d.patch
new file mode 100644 (file)
index 0000000..d446956
--- /dev/null
@@ -0,0 +1,42 @@
+From 253a905cb384b9233d3d834adcc1469af2019946 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 15:39:01 +0200
+Subject: netfilter: nf_tables: GC transaction race with netns dismantle
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 02c6c24402bf1c1e986899c14ba22a10b510916b ]
+
+Use maybe_get_net() since GC workqueue might race with netns exit path.
+
+Fixes: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_tables_api.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 3e17d2403d899..33023b42698bb 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -8944,9 +8944,14 @@ struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
+       if (!trans)
+               return NULL;
++      trans->net = maybe_get_net(net);
++      if (!trans->net) {
++              kfree(trans);
++              return NULL;
++      }
++
+       refcount_inc(&set->refs);
+       trans->set = set;
+-      trans->net = get_net(net);
+       trans->seq = gc_seq;
+       return trans;
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nf_tables-make-validation-state-per-table.patch b/queue-5.15/netfilter-nf_tables-make-validation-state-per-table.patch
new file mode 100644 (file)
index 0000000..ce15993
--- /dev/null
@@ -0,0 +1,172 @@
+From b03c5ec538908fb0c7547a140322500dd34ff912 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 13 Apr 2023 17:13:20 +0200
+Subject: netfilter: nf_tables: make validation state per table
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 00c320f9b75560628e840bef027a27c746706759 ]
+
+We only need to validate tables that saw changes in the current
+transaction.
+
+The existing code revalidates all tables, but this isn't needed as
+cross-table jumps are not allowed (chains have table scope).
+
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Stable-dep-of: 5f68718b34a5 ("netfilter: nf_tables: GC transaction API to avoid race with control plane")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h |  3 ++-
+ net/netfilter/nf_tables_api.c     | 38 +++++++++++++++----------------
+ 2 files changed, 20 insertions(+), 21 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index 1458b3eae8ada..b8d967e0eb1e2 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -1183,6 +1183,7 @@ static inline void nft_use_inc_restore(u32 *use)
+  *    @genmask: generation mask
+  *    @afinfo: address family info
+  *    @name: name of the table
++ *    @validate_state: internal, set when transaction adds jumps
+  */
+ struct nft_table {
+       struct list_head                list;
+@@ -1201,6 +1202,7 @@ struct nft_table {
+       char                            *name;
+       u16                             udlen;
+       u8                              *udata;
++      u8                              validate_state;
+ };
+ static inline bool nft_table_has_owner(const struct nft_table *table)
+@@ -1682,7 +1684,6 @@ struct nftables_pernet {
+       struct mutex            commit_mutex;
+       u64                     table_handle;
+       unsigned int            base_seq;
+-      u8                      validate_state;
+ };
+ extern unsigned int nf_tables_net_id;
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index d84da11aaee5c..dde19be41610d 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -102,11 +102,9 @@ static const u8 nft2audit_op[NFT_MSG_MAX] = { // enum nf_tables_msg_types
+       [NFT_MSG_DELFLOWTABLE]  = AUDIT_NFT_OP_FLOWTABLE_UNREGISTER,
+ };
+-static void nft_validate_state_update(struct net *net, u8 new_validate_state)
++static void nft_validate_state_update(struct nft_table *table, u8 new_validate_state)
+ {
+-      struct nftables_pernet *nft_net = nft_pernet(net);
+-
+-      switch (nft_net->validate_state) {
++      switch (table->validate_state) {
+       case NFT_VALIDATE_SKIP:
+               WARN_ON_ONCE(new_validate_state == NFT_VALIDATE_DO);
+               break;
+@@ -117,7 +115,7 @@ static void nft_validate_state_update(struct net *net, u8 new_validate_state)
+                       return;
+       }
+-      nft_net->validate_state = new_validate_state;
++      table->validate_state = new_validate_state;
+ }
+ static void nf_tables_trans_destroy_work(struct work_struct *w);
+ static DECLARE_WORK(trans_destroy_work, nf_tables_trans_destroy_work);
+@@ -1286,6 +1284,7 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
+       if (table == NULL)
+               goto err_kzalloc;
++      table->validate_state = NFT_VALIDATE_SKIP;
+       table->name = nla_strdup(attr, GFP_KERNEL);
+       if (table->name == NULL)
+               goto err_strdup;
+@@ -3650,7 +3649,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
+               }
+               if (expr_info[i].ops->validate)
+-                      nft_validate_state_update(net, NFT_VALIDATE_NEED);
++                      nft_validate_state_update(table, NFT_VALIDATE_NEED);
+               expr_info[i].ops = NULL;
+               expr = nft_expr_next(expr);
+@@ -3704,7 +3703,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
+       if (flow)
+               nft_trans_flow_rule(trans) = flow;
+-      if (nft_net->validate_state == NFT_VALIDATE_DO)
++      if (table->validate_state == NFT_VALIDATE_DO)
+               return nft_table_validate(net, table);
+       return 0;
+@@ -6347,7 +6346,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+                       if (desc.type == NFT_DATA_VERDICT &&
+                           (elem.data.val.verdict.code == NFT_GOTO ||
+                            elem.data.val.verdict.code == NFT_JUMP))
+-                              nft_validate_state_update(ctx->net,
++                              nft_validate_state_update(ctx->table,
+                                                         NFT_VALIDATE_NEED);
+               }
+@@ -6465,7 +6464,6 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
+                               const struct nfnl_info *info,
+                               const struct nlattr * const nla[])
+ {
+-      struct nftables_pernet *nft_net = nft_pernet(info->net);
+       struct netlink_ext_ack *extack = info->extack;
+       u8 genmask = nft_genmask_next(info->net);
+       u8 family = info->nfmsg->nfgen_family;
+@@ -6503,7 +6501,7 @@ static int nf_tables_newsetelem(struct sk_buff *skb,
+                       return err;
+       }
+-      if (nft_net->validate_state == NFT_VALIDATE_DO)
++      if (table->validate_state == NFT_VALIDATE_DO)
+               return nft_table_validate(net, table);
+       return 0;
+@@ -8600,19 +8598,20 @@ static int nf_tables_validate(struct net *net)
+       struct nftables_pernet *nft_net = nft_pernet(net);
+       struct nft_table *table;
+-      switch (nft_net->validate_state) {
+-      case NFT_VALIDATE_SKIP:
+-              break;
+-      case NFT_VALIDATE_NEED:
+-              nft_validate_state_update(net, NFT_VALIDATE_DO);
+-              fallthrough;
+-      case NFT_VALIDATE_DO:
+-              list_for_each_entry(table, &nft_net->tables, list) {
++      list_for_each_entry(table, &nft_net->tables, list) {
++              switch (table->validate_state) {
++              case NFT_VALIDATE_SKIP:
++                      continue;
++              case NFT_VALIDATE_NEED:
++                      nft_validate_state_update(table, NFT_VALIDATE_DO);
++                      fallthrough;
++              case NFT_VALIDATE_DO:
+                       if (nft_table_validate(net, table) < 0)
+                               return -EAGAIN;
++
++                      nft_validate_state_update(table, NFT_VALIDATE_SKIP);
+               }
+-              nft_validate_state_update(net, NFT_VALIDATE_SKIP);
+               break;
+       }
+@@ -10344,7 +10343,6 @@ static int __net_init nf_tables_init_net(struct net *net)
+       INIT_LIST_HEAD(&nft_net->notify_list);
+       mutex_init(&nft_net->commit_mutex);
+       nft_net->base_seq = 1;
+-      nft_net->validate_state = NFT_VALIDATE_SKIP;
+       return 0;
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch b/queue-5.15/netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch
new file mode 100644 (file)
index 0000000..b10f919
--- /dev/null
@@ -0,0 +1,221 @@
+From 7be3a56c7758beebca3e24138a8ac8af23300285 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 15:00:36 +0200
+Subject: netfilter: nf_tables: remove busy mark and gc batch API
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit a2dd0233cbc4d8a0abb5f64487487ffc9265beb5 ]
+
+Ditch it, it has been replace it by the GC transaction API and it has no
+clients anymore.
+
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/netfilter/nf_tables.h | 98 +------------------------------
+ net/netfilter/nf_tables_api.c     | 48 +--------------
+ 2 files changed, 4 insertions(+), 142 deletions(-)
+
+diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
+index a6bf58316a5d8..cd3b5b9db8890 100644
+--- a/include/net/netfilter/nf_tables.h
++++ b/include/net/netfilter/nf_tables.h
+@@ -564,7 +564,6 @@ struct nft_set *nft_set_lookup_global(const struct net *net,
+ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
+                                           const struct nft_set *set);
+-void *nft_set_catchall_gc(const struct nft_set *set);
+ static inline unsigned long nft_set_gc_interval(const struct nft_set *set)
+ {
+@@ -779,62 +778,6 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
+ void nf_tables_set_elem_destroy(const struct nft_ctx *ctx,
+                               const struct nft_set *set, void *elem);
+-/**
+- *    struct nft_set_gc_batch_head - nf_tables set garbage collection batch
+- *
+- *    @rcu: rcu head
+- *    @set: set the elements belong to
+- *    @cnt: count of elements
+- */
+-struct nft_set_gc_batch_head {
+-      struct rcu_head                 rcu;
+-      const struct nft_set            *set;
+-      unsigned int                    cnt;
+-};
+-
+-#define NFT_SET_GC_BATCH_SIZE ((PAGE_SIZE -                             \
+-                                sizeof(struct nft_set_gc_batch_head)) / \
+-                               sizeof(void *))
+-
+-/**
+- *    struct nft_set_gc_batch - nf_tables set garbage collection batch
+- *
+- *    @head: GC batch head
+- *    @elems: garbage collection elements
+- */
+-struct nft_set_gc_batch {
+-      struct nft_set_gc_batch_head    head;
+-      void                            *elems[NFT_SET_GC_BATCH_SIZE];
+-};
+-
+-struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
+-                                              gfp_t gfp);
+-void nft_set_gc_batch_release(struct rcu_head *rcu);
+-
+-static inline void nft_set_gc_batch_complete(struct nft_set_gc_batch *gcb)
+-{
+-      if (gcb != NULL)
+-              call_rcu(&gcb->head.rcu, nft_set_gc_batch_release);
+-}
+-
+-static inline struct nft_set_gc_batch *
+-nft_set_gc_batch_check(const struct nft_set *set, struct nft_set_gc_batch *gcb,
+-                     gfp_t gfp)
+-{
+-      if (gcb != NULL) {
+-              if (gcb->head.cnt + 1 < ARRAY_SIZE(gcb->elems))
+-                      return gcb;
+-              nft_set_gc_batch_complete(gcb);
+-      }
+-      return nft_set_gc_batch_alloc(set, gfp);
+-}
+-
+-static inline void nft_set_gc_batch_add(struct nft_set_gc_batch *gcb,
+-                                      void *elem)
+-{
+-      gcb->elems[gcb->head.cnt++] = elem;
+-}
+-
+ struct nft_expr_ops;
+ /**
+  *    struct nft_expr_type - nf_tables expression type
+@@ -1495,47 +1438,12 @@ static inline void nft_set_elem_change_active(const struct net *net,
+ #endif /* IS_ENABLED(CONFIG_NF_TABLES) */
+-/*
+- * We use a free bit in the genmask field to indicate the element
+- * is busy, meaning it is currently being processed either by
+- * the netlink API or GC.
+- *
+- * Even though the genmask is only a single byte wide, this works
+- * because the extension structure if fully constant once initialized,
+- * so there are no non-atomic write accesses unless it is already
+- * marked busy.
+- */
+-#define NFT_SET_ELEM_BUSY_MASK        (1 << 2)
+-
+-#if defined(__LITTLE_ENDIAN_BITFIELD)
+-#define NFT_SET_ELEM_BUSY_BIT 2
+-#elif defined(__BIG_ENDIAN_BITFIELD)
+-#define NFT_SET_ELEM_BUSY_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
+-#else
+-#error
+-#endif
+-
+-static inline int nft_set_elem_mark_busy(struct nft_set_ext *ext)
+-{
+-      unsigned long *word = (unsigned long *)ext;
+-
+-      BUILD_BUG_ON(offsetof(struct nft_set_ext, genmask) != 0);
+-      return test_and_set_bit(NFT_SET_ELEM_BUSY_BIT, word);
+-}
+-
+-static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
+-{
+-      unsigned long *word = (unsigned long *)ext;
+-
+-      clear_bit(NFT_SET_ELEM_BUSY_BIT, word);
+-}
+-
+-#define NFT_SET_ELEM_DEAD_MASK        (1 << 3)
++#define NFT_SET_ELEM_DEAD_MASK        (1 << 2)
+ #if defined(__LITTLE_ENDIAN_BITFIELD)
+-#define NFT_SET_ELEM_DEAD_BIT 3
++#define NFT_SET_ELEM_DEAD_BIT 2
+ #elif defined(__BIG_ENDIAN_BITFIELD)
+-#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 3)
++#define NFT_SET_ELEM_DEAD_BIT (BITS_PER_LONG - BITS_PER_BYTE + 2)
+ #else
+ #error
+ #endif
+diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
+index 616fd19d5cedc..75b04c01f7b81 100644
+--- a/net/netfilter/nf_tables_api.c
++++ b/net/netfilter/nf_tables_api.c
+@@ -5919,29 +5919,6 @@ struct nft_set_ext *nft_set_catchall_lookup(const struct net *net,
+ }
+ EXPORT_SYMBOL_GPL(nft_set_catchall_lookup);
+-void *nft_set_catchall_gc(const struct nft_set *set)
+-{
+-      struct nft_set_elem_catchall *catchall, *next;
+-      struct nft_set_ext *ext;
+-      void *elem = NULL;
+-
+-      list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
+-              ext = nft_set_elem_ext(set, catchall->elem);
+-
+-              if (!nft_set_elem_expired(ext) ||
+-                  nft_set_elem_mark_busy(ext))
+-                      continue;
+-
+-              elem = catchall->elem;
+-              list_del_rcu(&catchall->list);
+-              kfree_rcu(catchall, rcu);
+-              break;
+-      }
+-
+-      return elem;
+-}
+-EXPORT_SYMBOL_GPL(nft_set_catchall_gc);
+-
+ static int nft_setelem_catchall_insert(const struct net *net,
+                                      struct nft_set *set,
+                                      const struct nft_set_elem *elem,
+@@ -6406,7 +6383,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+               goto err_elem_expr;
+       }
+-      ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK;
++      ext->genmask = nft_genmask_cur(ctx->net);
+       err = nft_setelem_insert(ctx->net, set, &elem, &ext2, flags);
+       if (err) {
+@@ -6786,29 +6763,6 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
+       return err;
+ }
+-void nft_set_gc_batch_release(struct rcu_head *rcu)
+-{
+-      struct nft_set_gc_batch *gcb;
+-      unsigned int i;
+-
+-      gcb = container_of(rcu, struct nft_set_gc_batch, head.rcu);
+-      for (i = 0; i < gcb->head.cnt; i++)
+-              nft_set_elem_destroy(gcb->head.set, gcb->elems[i], true);
+-      kfree(gcb);
+-}
+-
+-struct nft_set_gc_batch *nft_set_gc_batch_alloc(const struct nft_set *set,
+-                                              gfp_t gfp)
+-{
+-      struct nft_set_gc_batch *gcb;
+-
+-      gcb = kzalloc(sizeof(*gcb), gfp);
+-      if (gcb == NULL)
+-              return gcb;
+-      gcb->head.set = set;
+-      return gcb;
+-}
+-
+ /*
+  * Stateful objects
+  */
+-- 
+2.40.1
+
diff --git a/queue-5.15/netfilter-nft_set_hash-mark-set-element-as-dead-when.patch b/queue-5.15/netfilter-nft_set_hash-mark-set-element-as-dead-when.patch
new file mode 100644 (file)
index 0000000..caac51f
--- /dev/null
@@ -0,0 +1,49 @@
+From 46c14671cf0c641c8bd41ccc54019a08e2b0d04a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.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>
+
+[ Upstream commit c92db3030492b8ad1d0faace7a93bbcf53850d0c ]
+
+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: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nft_set_hash.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
+index 960cbd56c0406..8dfa97105d8a3 100644
+--- a/net/netfilter/nft_set_hash.c
++++ b/net/netfilter/nft_set_hash.c
+@@ -249,7 +249,9 @@ static bool nft_rhash_delete(const struct nft_set *set,
+       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,
+@@ -414,7 +416,7 @@ static int nft_rhash_init(const struct nft_set *set,
+               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;
+-- 
+2.40.1
+
diff --git a/queue-5.15/pci-fu740-set-the-number-of-msi-vectors.patch b/queue-5.15/pci-fu740-set-the-number-of-msi-vectors.patch
new file mode 100644 (file)
index 0000000..85f0555
--- /dev/null
@@ -0,0 +1,43 @@
+From 9356ee89dd0410aa5c21f37afd670c5a8ac59f42 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Aug 2023 05:56:21 +0000
+Subject: PCI: fu740: Set the number of MSI vectors
+
+From: Yong-Xuan Wang <yongxuan.wang@sifive.com>
+
+[ Upstream commit 551a60e1225e71fff8efd9390204c505b0870e0f ]
+
+The iMSI-RX module of the DW PCIe controller provides multiple sets of
+MSI_CTRL_INT_i_* registers, and each set is capable of handling 32 MSI
+interrupts. However, the fu740 PCIe controller driver only enabled one set
+of MSI_CTRL_INT_i_* registers, as the total number of supported interrupts
+was not specified.
+
+Set the supported number of MSI vectors to enable all the MSI_CTRL_INT_i_*
+registers on the fu740 PCIe core, allowing the system to fully utilize the
+available MSI interrupts.
+
+Link: https://lore.kernel.org/r/20230807055621.2431-1-yongxuan.wang@sifive.com
+Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com>
+Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
+Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/controller/dwc/pcie-fu740.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/pci/controller/dwc/pcie-fu740.c b/drivers/pci/controller/dwc/pcie-fu740.c
+index 78d002be4f821..f6c71c1b657b6 100644
+--- a/drivers/pci/controller/dwc/pcie-fu740.c
++++ b/drivers/pci/controller/dwc/pcie-fu740.c
+@@ -301,6 +301,7 @@ static int fu740_pcie_probe(struct platform_device *pdev)
+       pci->dev = dev;
+       pci->ops = &dw_pcie_ops;
+       pci->pp.ops = &fu740_pcie_host_ops;
++      pci->pp.num_vectors = MAX_MSI_IRQS;
+       /* SiFive specific region: mgmt */
+       afp->mgmt_base = devm_platform_ioremap_resource_byname(pdev, "mgmt");
+-- 
+2.40.1
+
diff --git a/queue-5.15/perf-build-update-build-rule-for-generated-files.patch b/queue-5.15/perf-build-update-build-rule-for-generated-files.patch
new file mode 100644 (file)
index 0000000..86d9d65
--- /dev/null
@@ -0,0 +1,87 @@
+From 5ffff079925fe9e90d7fa9826c20c4d7838a6f8a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Jul 2023 19:24:46 -0700
+Subject: perf build: Update build rule for generated files
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit 7822a8913f4c51c7d1aff793b525d60c3384fb5b ]
+
+The bison and flex generate C files from the source (.y and .l)
+files.  When O= option is used, they are saved in a separate directory
+but the default build rule assumes the .C files are in the source
+directory.  So it might read invalid file if there are generated files
+from an old version.  The same is true for the pmu-events files.
+
+For example, the following command would cause a build failure:
+
+  $ git checkout v6.3
+  $ make -C tools/perf  # build in the same directory
+
+  $ git checkout v6.5-rc2
+  $ mkdir build  # create a build directory
+  $ make -C tools/perf O=build  # build in a different directory but it
+                                # refers files in the source directory
+
+Let's update the build rule to specify those cases explicitly to depend
+on the files in the output directory.
+
+Note that it's not a complete fix and it needs the next patch for the
+include path too.
+
+Fixes: 80eeb67fe577aa76 ("perf jevents: Program to convert JSON file")
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Anup Sharma <anupnewsmail@gmail.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230728022447.1323563-1-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/build/Makefile.build  | 10 ++++++++++
+ tools/perf/pmu-events/Build |  6 ++++++
+ 2 files changed, 16 insertions(+)
+
+diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
+index 715092fc6a239..0f0aba16bdee7 100644
+--- a/tools/build/Makefile.build
++++ b/tools/build/Makefile.build
+@@ -116,6 +116,16 @@ $(OUTPUT)%.s: %.c FORCE
+       $(call rule_mkdir)
+       $(call if_changed_dep,cc_s_c)
++# bison and flex files are generated in the OUTPUT directory
++# so it needs a separate rule to depend on them properly
++$(OUTPUT)%-bison.o: $(OUTPUT)%-bison.c FORCE
++      $(call rule_mkdir)
++      $(call if_changed_dep,$(host)cc_o_c)
++
++$(OUTPUT)%-flex.o: $(OUTPUT)%-flex.c FORCE
++      $(call rule_mkdir)
++      $(call if_changed_dep,$(host)cc_o_c)
++
+ # Gather build data:
+ #   obj-y        - list of build objects
+ #   subdir-y     - list of directories to nest
+diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
+index 5ec5ce8c31bab..ea8c41f9c7398 100644
+--- a/tools/perf/pmu-events/Build
++++ b/tools/perf/pmu-events/Build
+@@ -25,3 +25,9 @@ $(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JSON_TEST) $(JEVENTS_PY)
+       $(call rule_mkdir)
+       $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(SRCARCH) pmu-events/arch $@
+ endif
++
++# pmu-events.c file is generated in the OUTPUT directory so it needs a
++# separate rule to depend on it properly
++$(OUTPUT)pmu-events/pmu-events.o: $(PMU_EVENTS_C)
++      $(call rule_mkdir)
++      $(call if_changed_dep,cc_o_c)
+-- 
+2.40.1
+
diff --git a/queue-5.15/perf-imx_ddr-speed-up-overflow-frequency-of-cycle.patch b/queue-5.15/perf-imx_ddr-speed-up-overflow-frequency-of-cycle.patch
new file mode 100644 (file)
index 0000000..785b926
--- /dev/null
@@ -0,0 +1,89 @@
+From a1701c5c5318ce7e8ca895e11aabc370ad2b8435 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Aug 2023 09:54:37 +0800
+Subject: perf/imx_ddr: speed up overflow frequency of cycle
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+[ Upstream commit e89ecd8368860bf05437eabd07d292c316221cfc ]
+
+For i.MX8MP, we cannot ensure that cycle counter overflow occurs at least
+4 times as often as other events. Due to byte counters will count for any
+event configured, it will overflow more often. And if byte counters
+overflow that related counters would stop since they share the
+COUNTER_CNTL. We can speed up cycle counter overflow frequency by setting
+counter parameter (CP) field of cycle counter. In this way, we can avoid
+stop counting byte counters when interrupt didn't come and the byte
+counters can be fetched or updated from each cycle counter overflow
+interrupt.
+
+Because we initialize CP filed to shorten counter0 overflow time, the cycle
+counter will start couting from a fixed/base value each time. We need to
+remove the base from the result too. Therefore, we could get precise result
+from cycle counter.
+
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20230811015438.1999307-1-xu.yang_2@nxp.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/perf/fsl_imx8_ddr_perf.c | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c
+index 4daa782c48df0..6f6bc0a446ff6 100644
+--- a/drivers/perf/fsl_imx8_ddr_perf.c
++++ b/drivers/perf/fsl_imx8_ddr_perf.c
+@@ -28,6 +28,8 @@
+ #define CNTL_CLEAR_MASK               0xFFFFFFFD
+ #define CNTL_OVER_MASK                0xFFFFFFFE
++#define CNTL_CP_SHIFT         16
++#define CNTL_CP_MASK          (0xFF << CNTL_CP_SHIFT)
+ #define CNTL_CSV_SHIFT                24
+ #define CNTL_CSV_MASK         (0xFFU << CNTL_CSV_SHIFT)
+@@ -35,6 +37,8 @@
+ #define EVENT_CYCLES_COUNTER  0
+ #define NUM_COUNTERS          4
++/* For removing bias if cycle counter CNTL.CP is set to 0xf0 */
++#define CYCLES_COUNTER_MASK   0x0FFFFFFF
+ #define AXI_MASKING_REVERT    0xffff0000      /* AXI_MASKING(MSB 16bits) + AXI_ID(LSB 16bits) */
+ #define to_ddr_pmu(p)         container_of(p, struct ddr_pmu, pmu)
+@@ -429,6 +433,17 @@ static void ddr_perf_counter_enable(struct ddr_pmu *pmu, int config,
+               writel(0, pmu->base + reg);
+               val = CNTL_EN | CNTL_CLEAR;
+               val |= FIELD_PREP(CNTL_CSV_MASK, config);
++
++              /*
++               * On i.MX8MP we need to bias the cycle counter to overflow more often.
++               * We do this by initializing bits [23:16] of the counter value via the
++               * COUNTER_CTRL Counter Parameter (CP) field.
++               */
++              if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER_ENHANCED) {
++                      if (counter == EVENT_CYCLES_COUNTER)
++                              val |= FIELD_PREP(CNTL_CP_MASK, 0xf0);
++              }
++
+               writel(val, pmu->base + reg);
+       } else {
+               /* Disable counter */
+@@ -468,6 +483,12 @@ static void ddr_perf_event_update(struct perf_event *event)
+       int ret;
+       new_raw_count = ddr_perf_read_counter(pmu, counter);
++      /* Remove the bias applied in ddr_perf_counter_enable(). */
++      if (pmu->devtype_data->quirks & DDR_CAP_AXI_ID_FILTER_ENHANCED) {
++              if (counter == EVENT_CYCLES_COUNTER)
++                      new_raw_count &= CYCLES_COUNTER_MASK;
++      }
++
+       local64_add(new_raw_count, &event->count);
+       /*
+-- 
+2.40.1
+
diff --git a/queue-5.15/perf-jevents-switch-build-to-use-jevents.py.patch b/queue-5.15/perf-jevents-switch-build-to-use-jevents.py.patch
new file mode 100644 (file)
index 0000000..614eb89
--- /dev/null
@@ -0,0 +1,295 @@
+From f7508f92cf16375b4050a2c74c7be05e7ed58f1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Jun 2022 11:25:04 -0700
+Subject: perf jevents: Switch build to use jevents.py
+
+From: Ian Rogers <rogers.email@gmail.com>
+
+[ Upstream commit 00facc760903be6675870c2749e2cd72140e396e ]
+
+Generate pmu-events.c using jevents.py rather than the binary built from
+jevents.c.
+
+Add a new config variable NO_JEVENTS that is set when there is no
+architecture json or an appropriate python interpreter isn't present.
+
+When NO_JEVENTS is defined the file pmu-events/empty-pmu-events.c is
+copied and used as the pmu-events.c file.
+
+Signed-off-by: Ian Rogers <irogers@google.com>
+Tested-by: John Garry <john.garry@huawei.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Ananth Narayan <ananth.narayan@amd.com>
+Cc: Andi Kleen <ak@linux.intel.com>
+Cc: Andrew Kilroy <andrew.kilroy@arm.com>
+Cc: Caleb Biggers <caleb.biggers@intel.com>
+Cc: Felix Fietkau <nbd@nbd.name>
+Cc: Ian Rogers <rogers.email@gmail.com>
+Cc: Ingo Molnar <mingo@redhat.com>
+Cc: James Clark <james.clark@arm.com>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Kajol Jain <kjain@linux.ibm.com>
+Cc: Kan Liang <kan.liang@linux.intel.com>
+Cc: Kshipra Bopardikar <kshipra.bopardikar@intel.com>
+Cc: Like Xu <likexu@tencent.com>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Nick Forrington <nick.forrington@arm.com>
+Cc: Paul Clarke <pc@us.ibm.com>
+Cc: Perry Taylor <perry.taylor@intel.com>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: Qi Liu <liuqi115@huawei.com>
+Cc: Ravi Bangoria <ravi.bangoria@amd.com>
+Cc: Sandipan Das <sandipan.das@amd.com>
+Cc: Santosh Shukla <santosh.shukla@amd.com>
+Cc: Stephane Eranian <eranian@google.com>
+Cc: Will Deacon <will@kernel.org>
+Cc: Xing Zhengjun <zhengjun.xing@linux.intel.com>
+Link: https://lore.kernel.org/r/20220629182505.406269-4-irogers@google.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: 7822a8913f4c ("perf build: Update build rule for generated files")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/Makefile.config               |  19 +++
+ tools/perf/Makefile.perf                 |   1 +
+ tools/perf/pmu-events/Build              |  13 +-
+ tools/perf/pmu-events/empty-pmu-events.c | 158 +++++++++++++++++++++++
+ 4 files changed, 189 insertions(+), 2 deletions(-)
+ create mode 100644 tools/perf/pmu-events/empty-pmu-events.c
+
+diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
+index 973c0d5ed8d8b..e1077c4d30fff 100644
+--- a/tools/perf/Makefile.config
++++ b/tools/perf/Makefile.config
+@@ -857,6 +857,25 @@ else
+   endif
+ endif
++ifneq ($(NO_JEVENTS),1)
++  ifeq ($(wildcard pmu-events/arch/$(SRCARCH)/mapfile.csv),)
++    NO_JEVENTS := 1
++  endif
++endif
++ifneq ($(NO_JEVENTS),1)
++  NO_JEVENTS := 0
++  ifndef PYTHON
++    $(warning No python interpreter disabling jevent generation)
++    NO_JEVENTS := 1
++  else
++    # jevents.py uses f-strings present in Python 3.6 released in Dec. 2016.
++    JEVENTS_PYTHON_GOOD := $(shell $(PYTHON) -c 'import sys;print("1" if(sys.version_info.major >= 3 and sys.version_info.minor >= 6) else "0")' 2> /dev/null)
++    ifneq ($(JEVENTS_PYTHON_GOOD), 1)
++      $(warning Python interpreter too old (older than 3.6) disabling jevent generation)
++      NO_JEVENTS := 1
++    endif
++  endif
++endif
+ ifndef NO_LIBBFD
+   ifeq ($(feature-libbfd), 1)
+diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
+index b856afa6eb52e..b82f2d89d74c4 100644
+--- a/tools/perf/Makefile.perf
++++ b/tools/perf/Makefile.perf
+@@ -649,6 +649,7 @@ JEVENTS       := $(OUTPUT)pmu-events/jevents
+ JEVENTS_IN    := $(OUTPUT)pmu-events/jevents-in.o
+ PMU_EVENTS_IN := $(OUTPUT)pmu-events/pmu-events-in.o
++export NO_JEVENTS
+ export JEVENTS
+diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
+index a055dee6a46af..5ec5ce8c31bab 100644
+--- a/tools/perf/pmu-events/Build
++++ b/tools/perf/pmu-events/Build
+@@ -9,10 +9,19 @@ JSON         =  $(shell [ -d $(JDIR) ] &&                            \
+ JDIR_TEST     =  pmu-events/arch/test
+ JSON_TEST     =  $(shell [ -d $(JDIR_TEST) ] &&                       \
+                       find $(JDIR_TEST) -name '*.json')
++JEVENTS_PY    =  pmu-events/jevents.py
+ #
+ # Locate/process JSON files in pmu-events/arch/
+ # directory and create tables in pmu-events.c.
+ #
+-$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JSON_TEST) $(JEVENTS)
+-      $(Q)$(call echo-cmd,gen)$(JEVENTS) $(SRCARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V)
++
++ifeq ($(NO_JEVENTS),1)
++$(OUTPUT)pmu-events/pmu-events.c: pmu-events/empty-pmu-events.c
++      $(call rule_mkdir)
++      $(Q)$(call echo-cmd,gen)cp $< $@
++else
++$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JSON_TEST) $(JEVENTS_PY)
++      $(call rule_mkdir)
++      $(Q)$(call echo-cmd,gen)$(PYTHON) $(JEVENTS_PY) $(SRCARCH) pmu-events/arch $@
++endif
+diff --git a/tools/perf/pmu-events/empty-pmu-events.c b/tools/perf/pmu-events/empty-pmu-events.c
+new file mode 100644
+index 0000000000000..77e655c6f1162
+--- /dev/null
++++ b/tools/perf/pmu-events/empty-pmu-events.c
+@@ -0,0 +1,158 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * An empty pmu-events.c file used when there is no architecture json files in
++ * arch or when the jevents.py script cannot be run.
++ *
++ * The test cpu/soc is provided for testing.
++ */
++#include "pmu-events/pmu-events.h"
++
++static const struct pmu_event pme_test_soc_cpu[] = {
++      {
++              .name = "l3_cache_rd",
++              .event = "event=0x40",
++              .desc = "L3 cache access, read",
++              .topic = "cache",
++              .long_desc = "Attributable Level 3 cache access, read",
++      },
++      {
++              .name = "segment_reg_loads.any",
++              .event = "event=0x6,period=200000,umask=0x80",
++              .desc = "Number of segment register loads",
++              .topic = "other",
++      },
++      {
++              .name = "dispatch_blocked.any",
++              .event = "event=0x9,period=200000,umask=0x20",
++              .desc = "Memory cluster signals to block micro-op dispatch for any reason",
++              .topic = "other",
++      },
++      {
++              .name = "eist_trans",
++              .event = "event=0x3a,period=200000,umask=0x0",
++              .desc = "Number of Enhanced Intel SpeedStep(R) Technology (EIST) transitions",
++              .topic = "other",
++      },
++      {
++              .name = "uncore_hisi_ddrc.flux_wcmd",
++              .event = "event=0x2",
++              .desc = "DDRC write commands. Unit: hisi_sccl,ddrc ",
++              .topic = "uncore",
++              .long_desc = "DDRC write commands",
++              .pmu = "hisi_sccl,ddrc",
++      },
++      {
++              .name = "unc_cbo_xsnp_response.miss_eviction",
++              .event = "event=0x22,umask=0x81",
++              .desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core. Unit: uncore_cbox ",
++              .topic = "uncore",
++              .long_desc = "A cross-core snoop resulted from L3 Eviction which misses in some processor core",
++              .pmu = "uncore_cbox",
++      },
++      {
++              .name = "event-hyphen",
++              .event = "event=0xe0,umask=0x00",
++              .desc = "UNC_CBO_HYPHEN. Unit: uncore_cbox ",
++              .topic = "uncore",
++              .long_desc = "UNC_CBO_HYPHEN",
++              .pmu = "uncore_cbox",
++      },
++      {
++              .name = "event-two-hyph",
++              .event = "event=0xc0,umask=0x00",
++              .desc = "UNC_CBO_TWO_HYPH. Unit: uncore_cbox ",
++              .topic = "uncore",
++              .long_desc = "UNC_CBO_TWO_HYPH",
++              .pmu = "uncore_cbox",
++      },
++      {
++              .name = "uncore_hisi_l3c.rd_hit_cpipe",
++              .event = "event=0x7",
++              .desc = "Total read hits. Unit: hisi_sccl,l3c ",
++              .topic = "uncore",
++              .long_desc = "Total read hits",
++              .pmu = "hisi_sccl,l3c",
++      },
++      {
++              .name = "uncore_imc_free_running.cache_miss",
++              .event = "event=0x12",
++              .desc = "Total cache misses. Unit: uncore_imc_free_running ",
++              .topic = "uncore",
++              .long_desc = "Total cache misses",
++              .pmu = "uncore_imc_free_running",
++      },
++      {
++              .name = "uncore_imc.cache_hits",
++              .event = "event=0x34",
++              .desc = "Total cache hits. Unit: uncore_imc ",
++              .topic = "uncore",
++              .long_desc = "Total cache hits",
++              .pmu = "uncore_imc",
++      },
++      {
++              .name = "bp_l1_btb_correct",
++              .event = "event=0x8a",
++              .desc = "L1 BTB Correction",
++              .topic = "branch",
++      },
++      {
++              .name = "bp_l2_btb_correct",
++              .event = "event=0x8b",
++              .desc = "L2 BTB Correction",
++              .topic = "branch",
++      },
++      {
++              .name = 0,
++              .event = 0,
++              .desc = 0,
++      },
++};
++
++const struct pmu_events_map pmu_events_map[] = {
++      {
++              .cpuid = "testcpu",
++              .version = "v1",
++              .type = "core",
++              .table = pme_test_soc_cpu,
++      },
++      {
++              .cpuid = 0,
++              .version = 0,
++              .type = 0,
++              .table = 0,
++      },
++};
++
++static const struct pmu_event pme_test_soc_sys[] = {
++      {
++              .name = "sys_ddr_pmu.write_cycles",
++              .event = "event=0x2b",
++              .desc = "ddr write-cycles event. Unit: uncore_sys_ddr_pmu ",
++              .compat = "v8",
++              .topic = "uncore",
++              .pmu = "uncore_sys_ddr_pmu",
++      },
++      {
++              .name = "sys_ccn_pmu.read_cycles",
++              .event = "config=0x2c",
++              .desc = "ccn read-cycles event. Unit: uncore_sys_ccn_pmu ",
++              .compat = "0x01",
++              .topic = "uncore",
++              .pmu = "uncore_sys_ccn_pmu",
++      },
++      {
++              .name = 0,
++              .event = 0,
++              .desc = 0,
++      },
++};
++
++const struct pmu_sys_events pmu_sys_event_tables[] = {
++      {
++              .table = pme_test_soc_sys,
++              .name = "pme_test_soc_sys",
++      },
++      {
++              .table = 0
++      },
++};
+-- 
+2.40.1
+
diff --git a/queue-5.15/perf-smmuv3-enable-hisilicon-erratum-162001900-quirk.patch b/queue-5.15/perf-smmuv3-enable-hisilicon-erratum-162001900-quirk.patch
new file mode 100644 (file)
index 0000000..814b522
--- /dev/null
@@ -0,0 +1,160 @@
+From 85cb3ee14bcadb7ed4040069bc86ebd5c13878ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Aug 2023 20:40:12 +0800
+Subject: perf/smmuv3: Enable HiSilicon Erratum 162001900 quirk for HIP08/09
+
+From: Yicong Yang <yangyicong@hisilicon.com>
+
+[ Upstream commit 0242737dc4eb9f6e9a5ea594b3f93efa0b12f28d ]
+
+Some HiSilicon SMMU PMCG suffers the erratum 162001900 that the PMU
+disable control sometimes fail to disable the counters. This will lead
+to error or inaccurate data since before we enable the counters the
+counter's still counting for the event used in last perf session.
+
+This patch tries to fix this by hardening the global disable process.
+Before disable the PMU, writing an invalid event type (0xffff) to
+focibly stop the counters. Correspondingly restore each events on
+pmu::pmu_enable().
+
+Signed-off-by: Yicong Yang <yangyicong@hisilicon.com>
+Link: https://lore.kernel.org/r/20230814124012.58013-1-yangyicong@huawei.com
+Signed-off-by: Will Deacon <will@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ Documentation/arm64/silicon-errata.rst |  3 ++
+ drivers/acpi/arm64/iort.c              |  5 ++-
+ drivers/perf/arm_smmuv3_pmu.c          | 46 +++++++++++++++++++++++++-
+ include/linux/acpi_iort.h              |  1 +
+ 4 files changed, 53 insertions(+), 2 deletions(-)
+
+diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst
+index 83a75e16e54de..d2f90ecc426f9 100644
+--- a/Documentation/arm64/silicon-errata.rst
++++ b/Documentation/arm64/silicon-errata.rst
+@@ -172,6 +172,9 @@ stable kernels.
+ +----------------+-----------------+-----------------+-----------------------------+
+ | Hisilicon      | Hip08 SMMU PMCG | #162001800      | N/A                         |
+ +----------------+-----------------+-----------------+-----------------------------+
++| Hisilicon      | Hip08 SMMU PMCG | #162001900      | N/A                         |
++|                | Hip09 SMMU PMCG |                 |                             |
+++----------------+-----------------+-----------------+-----------------------------+
+ +----------------+-----------------+-----------------+-----------------------------+
+ | Qualcomm Tech. | Kryo/Falkor v1  | E1003           | QCOM_FALKOR_ERRATUM_1003    |
+ +----------------+-----------------+-----------------+-----------------------------+
+diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
+index f2f8f05662deb..3dd74ad95d01b 100644
+--- a/drivers/acpi/arm64/iort.c
++++ b/drivers/acpi/arm64/iort.c
+@@ -1381,7 +1381,10 @@ static void __init arm_smmu_v3_pmcg_init_resources(struct resource *res,
+ static struct acpi_platform_list pmcg_plat_info[] __initdata = {
+       /* HiSilicon Hip08 Platform */
+       {"HISI  ", "HIP08   ", 0, ACPI_SIG_IORT, greater_than_or_equal,
+-       "Erratum #162001800", IORT_SMMU_V3_PMCG_HISI_HIP08},
++       "Erratum #162001800, Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP08},
++      /* HiSilicon Hip09 Platform */
++      {"HISI  ", "HIP09   ", 0, ACPI_SIG_IORT, greater_than_or_equal,
++       "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
+       { }
+ };
+diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
+index 5933ad151f869..1ef683bb40b64 100644
+--- a/drivers/perf/arm_smmuv3_pmu.c
++++ b/drivers/perf/arm_smmuv3_pmu.c
+@@ -96,6 +96,7 @@
+ #define SMMU_PMCG_PA_SHIFT              12
+ #define SMMU_PMCG_EVCNTR_RDONLY         BIT(0)
++#define SMMU_PMCG_HARDEN_DISABLE        BIT(1)
+ static int cpuhp_state_num;
+@@ -140,6 +141,20 @@ static inline void smmu_pmu_enable(struct pmu *pmu)
+       writel(SMMU_PMCG_CR_ENABLE, smmu_pmu->reg_base + SMMU_PMCG_CR);
+ }
++static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu,
++                                     struct perf_event *event, int idx);
++
++static inline void smmu_pmu_enable_quirk_hip08_09(struct pmu *pmu)
++{
++      struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
++      unsigned int idx;
++
++      for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
++              smmu_pmu_apply_event_filter(smmu_pmu, smmu_pmu->events[idx], idx);
++
++      smmu_pmu_enable(pmu);
++}
++
+ static inline void smmu_pmu_disable(struct pmu *pmu)
+ {
+       struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
+@@ -148,6 +163,22 @@ static inline void smmu_pmu_disable(struct pmu *pmu)
+       writel(0, smmu_pmu->reg_base + SMMU_PMCG_IRQ_CTRL);
+ }
++static inline void smmu_pmu_disable_quirk_hip08_09(struct pmu *pmu)
++{
++      struct smmu_pmu *smmu_pmu = to_smmu_pmu(pmu);
++      unsigned int idx;
++
++      /*
++       * The global disable of PMU sometimes fail to stop the counting.
++       * Harden this by writing an invalid event type to each used counter
++       * to forcibly stop counting.
++       */
++      for_each_set_bit(idx, smmu_pmu->used_counters, smmu_pmu->num_counters)
++              writel(0xffff, smmu_pmu->reg_base + SMMU_PMCG_EVTYPER(idx));
++
++      smmu_pmu_disable(pmu);
++}
++
+ static inline void smmu_pmu_counter_set_value(struct smmu_pmu *smmu_pmu,
+                                             u32 idx, u64 value)
+ {
+@@ -747,7 +778,10 @@ static void smmu_pmu_get_acpi_options(struct smmu_pmu *smmu_pmu)
+       switch (model) {
+       case IORT_SMMU_V3_PMCG_HISI_HIP08:
+               /* HiSilicon Erratum 162001800 */
+-              smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY;
++              smmu_pmu->options |= SMMU_PMCG_EVCNTR_RDONLY | SMMU_PMCG_HARDEN_DISABLE;
++              break;
++      case IORT_SMMU_V3_PMCG_HISI_HIP09:
++              smmu_pmu->options |= SMMU_PMCG_HARDEN_DISABLE;
+               break;
+       }
+@@ -836,6 +870,16 @@ static int smmu_pmu_probe(struct platform_device *pdev)
+       smmu_pmu_get_acpi_options(smmu_pmu);
++      /*
++       * For platforms suffer this quirk, the PMU disable sometimes fails to
++       * stop the counters. This will leads to inaccurate or error counting.
++       * Forcibly disable the counters with these quirk handler.
++       */
++      if (smmu_pmu->options & SMMU_PMCG_HARDEN_DISABLE) {
++              smmu_pmu->pmu.pmu_enable = smmu_pmu_enable_quirk_hip08_09;
++              smmu_pmu->pmu.pmu_disable = smmu_pmu_disable_quirk_hip08_09;
++      }
++
+       /* Pick one CPU to be the preferred one to use */
+       smmu_pmu->on_cpu = raw_smp_processor_id();
+       WARN_ON(irq_set_affinity(smmu_pmu->irq, cpumask_of(smmu_pmu->on_cpu)));
+diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
+index f1f0842a2cb2b..43082bd44a999 100644
+--- a/include/linux/acpi_iort.h
++++ b/include/linux/acpi_iort.h
+@@ -21,6 +21,7 @@
+  */
+ #define IORT_SMMU_V3_PMCG_GENERIC        0x00000000 /* Generic SMMUv3 PMCG */
+ #define IORT_SMMU_V3_PMCG_HISI_HIP08     0x00000001 /* HiSilicon HIP08 PMCG */
++#define IORT_SMMU_V3_PMCG_HISI_HIP09     0x00000002 /* HiSilicon HIP09 PMCG */
+ int iort_register_domain_token(int trans_id, phys_addr_t base,
+                              struct fwnode_handle *fw_node);
+-- 
+2.40.1
+
diff --git a/queue-5.15/perf-test-remove-bash-construct-from-stat_bpf_counte.patch b/queue-5.15/perf-test-remove-bash-construct-from-stat_bpf_counte.patch
new file mode 100644 (file)
index 0000000..2028e7b
--- /dev/null
@@ -0,0 +1,75 @@
+From a0f13f5935ec64accd11b32b3a25c7b8aeff9c06 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Oct 2021 14:48:25 +0100
+Subject: perf test: Remove bash construct from stat_bpf_counters.sh test
+
+From: James Clark <james.clark@arm.com>
+
+[ Upstream commit c8b947642d2339ce74c6a1ce56726089539f48d9 ]
+
+Currently the test skips with an error because == only works in bash:
+
+  $ ./perf test 91 -v
+  Couldn't bump rlimit(MEMLOCK), failures may take place when creating BPF maps, etc
+  91: perf stat --bpf-counters test                                   :
+  --- start ---
+  test child forked, pid 44586
+  ./tests/shell/stat_bpf_counters.sh: 26: [: -v: unexpected operator
+  test child finished with -2
+  ---- end ----
+  perf stat --bpf-counters test: Skip
+
+Changing == to = does the same thing, but doesn't result in an error:
+
+  ./perf test 91 -v
+  Couldn't bump rlimit(MEMLOCK), failures may take place when creating BPF maps, etc
+  91: perf stat --bpf-counters test                                   :
+  --- start ---
+  test child forked, pid 45833
+  Skipping: --bpf-counters not supported
+    Error: unknown option `bpf-counters'
+  [...]
+  test child finished with -2
+  ---- end ----
+  perf stat --bpf-counters test: Skip
+
+Signed-off-by: James Clark <james.clark@arm.com>
+Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: Florian Fainelli <f.fainelli@gmail.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Jiri Olsa <jolsa@redhat.com>
+Cc: John Fastabend <john.fastabend@gmail.com>
+Cc: KP Singh <kpsingh@kernel.org>
+Cc: Mark Rutland <mark.rutland@arm.com>
+Cc: Martin KaFai Lau <kafai@fb.com>
+Cc: Namhyung Kim <namhyung@kernel.org>
+Cc: Song Liu <songliubraving@fb.com>
+Cc: Sumanth Korikkar <sumanthk@linux.ibm.com>
+Cc: Thomas Richter <tmricht@linux.ibm.com>
+Cc: Yonghong Song <yhs@fb.com>
+Cc: bpf@vger.kernel.org
+Cc: netdev@vger.kernel.org
+Link: https://lore.kernel.org/r/20211028134828.65774-2-james.clark@arm.com
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Stable-dep-of: 68ca249c964f ("perf test shell stat_bpf_counters: Fix test on Intel")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/shell/stat_bpf_counters.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tools/perf/tests/shell/stat_bpf_counters.sh b/tools/perf/tests/shell/stat_bpf_counters.sh
+index 2aed20dc22625..13473aeba489c 100755
+--- a/tools/perf/tests/shell/stat_bpf_counters.sh
++++ b/tools/perf/tests/shell/stat_bpf_counters.sh
+@@ -23,7 +23,7 @@ compare_number()
+ # skip if --bpf-counters is not supported
+ if ! perf stat --bpf-counters true > /dev/null 2>&1; then
+-      if [ "$1" == "-v" ]; then
++      if [ "$1" = "-v" ]; then
+               echo "Skipping: --bpf-counters not supported"
+               perf --no-pager stat --bpf-counters true || true
+       fi
+-- 
+2.40.1
+
diff --git a/queue-5.15/perf-test-shell-stat_bpf_counters-fix-test-on-intel.patch b/queue-5.15/perf-test-shell-stat_bpf_counters-fix-test-on-intel.patch
new file mode 100644 (file)
index 0000000..83932e2
--- /dev/null
@@ -0,0 +1,56 @@
+From 30a27a0a95ceb6a10eb8c175ed71d1878008a9eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 25 Aug 2023 09:41:51 -0700
+Subject: perf test shell stat_bpf_counters: Fix test on Intel
+
+From: Namhyung Kim <namhyung@kernel.org>
+
+[ Upstream commit 68ca249c964f520af7f8763e22f12bd26b57b870 ]
+
+As of now, bpf counters (bperf) don't support event groups.  But the
+default perf stat includes topdown metrics if supported (on recent Intel
+machines) which require groups.  That makes perf stat exiting.
+
+  $ sudo perf stat --bpf-counter true
+  bpf managed perf events do not yet support groups.
+
+Actually the test explicitly uses cycles event only, but it missed to
+pass the option when it checks the availability of the command.
+
+Fixes: 2c0cb9f56020d2ea ("perf test: Add a shell test for 'perf stat --bpf-counters' new option")
+Reviewed-by: Song Liu <song@kernel.org>
+Signed-off-by: Namhyung Kim <namhyung@kernel.org>
+Cc: Adrian Hunter <adrian.hunter@intel.com>
+Cc: Ian Rogers <irogers@google.com>
+Cc: Ingo Molnar <mingo@kernel.org>
+Cc: Jiri Olsa <jolsa@kernel.org>
+Cc: Peter Zijlstra <peterz@infradead.org>
+Cc: bpf@vger.kernel.org
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230825164152.165610-2-namhyung@kernel.org
+Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/perf/tests/shell/stat_bpf_counters.sh | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/perf/tests/shell/stat_bpf_counters.sh b/tools/perf/tests/shell/stat_bpf_counters.sh
+index 13473aeba489c..6bf24b85294c7 100755
+--- a/tools/perf/tests/shell/stat_bpf_counters.sh
++++ b/tools/perf/tests/shell/stat_bpf_counters.sh
+@@ -22,10 +22,10 @@ compare_number()
+ }
+ # skip if --bpf-counters is not supported
+-if ! perf stat --bpf-counters true > /dev/null 2>&1; then
++if ! perf stat -e cycles --bpf-counters true > /dev/null 2>&1; then
+       if [ "$1" = "-v" ]; then
+               echo "Skipping: --bpf-counters not supported"
+-              perf --no-pager stat --bpf-counters true || true
++              perf --no-pager stat -e cycles --bpf-counters true || true
+       fi
+       exit 2
+ fi
+-- 
+2.40.1
+
diff --git a/queue-5.15/powerpc-pseries-fix-possible-memory-leak-in-ibmebus_.patch b/queue-5.15/powerpc-pseries-fix-possible-memory-leak-in-ibmebus_.patch
new file mode 100644 (file)
index 0000000..9148446
--- /dev/null
@@ -0,0 +1,39 @@
+From baa0650bc2b54f5a01a62511cbdd93472c8150ea Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Nov 2022 09:19:29 +0800
+Subject: powerpc/pseries: fix possible memory leak in ibmebus_bus_init()
+
+From: ruanjinjie <ruanjinjie@huawei.com>
+
+[ Upstream commit afda85b963c12947e298ad85d757e333aa40fd74 ]
+
+If device_register() returns error in ibmebus_bus_init(), name of kobject
+which is allocated in dev_set_name() called in device_add() is leaked.
+
+As comment of device_add() says, it should call put_device() to drop
+the reference count that was set in device_initialize() when it fails,
+so the name can be freed in kobject_cleanup().
+
+Signed-off-by: ruanjinjie <ruanjinjie@huawei.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://msgid.link/20221110011929.3709774-1-ruanjinjie@huawei.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/platforms/pseries/ibmebus.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c
+index 7ee3ed7d6cc21..6936ffee253b2 100644
+--- a/arch/powerpc/platforms/pseries/ibmebus.c
++++ b/arch/powerpc/platforms/pseries/ibmebus.c
+@@ -451,6 +451,7 @@ static int __init ibmebus_bus_init(void)
+       if (err) {
+               printk(KERN_WARNING "%s: device_register returned %i\n",
+                      __func__, err);
++              put_device(&ibmebus_bus_device);
+               bus_unregister(&ibmebus_bus_type);
+               return err;
+-- 
+2.40.1
+
diff --git a/queue-5.15/printk-consolidate-console-deferred-printing.patch b/queue-5.15/printk-consolidate-console-deferred-printing.patch
new file mode 100644 (file)
index 0000000..f828e07
--- /dev/null
@@ -0,0 +1,126 @@
+From 84c248b03e6537eba02569b796651cd9656dc9ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 17 Jul 2023 21:52:05 +0206
+Subject: printk: Consolidate console deferred printing
+
+From: John Ogness <john.ogness@linutronix.de>
+
+[ Upstream commit 696ffaf50e1f8dbc66223ff614473f945f5fb8d8 ]
+
+Printing to consoles can be deferred for several reasons:
+
+- explicitly with printk_deferred()
+- printk() in NMI context
+- recursive printk() calls
+
+The current implementation is not consistent. For printk_deferred(),
+irq work is scheduled twice. For NMI und recursive, panic CPU
+suppression and caller delays are not properly enforced.
+
+Correct these inconsistencies by consolidating the deferred printing
+code so that vprintk_deferred() is the top-level function for
+deferred printing and vprintk_emit() will perform whichever irq_work
+queueing is appropriate.
+
+Also add kerneldoc for wake_up_klogd() and defer_console_output() to
+clarify their differences and appropriate usage.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+Link: https://lore.kernel.org/r/20230717194607.145135-6-john.ogness@linutronix.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/printk/printk.c      | 35 ++++++++++++++++++++++++++++-------
+ kernel/printk/printk_safe.c |  9 ++-------
+ 2 files changed, 30 insertions(+), 14 deletions(-)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 8d856b7c2e5af..8b110b245d92c 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -2269,7 +2269,11 @@ asmlinkage int vprintk_emit(int facility, int level,
+               preempt_enable();
+       }
+-      wake_up_klogd();
++      if (in_sched)
++              defer_console_output();
++      else
++              wake_up_klogd();
++
+       return printed_len;
+ }
+ EXPORT_SYMBOL(vprintk_emit);
+@@ -3277,11 +3281,33 @@ static void __wake_up_klogd(int val)
+       preempt_enable();
+ }
++/**
++ * wake_up_klogd - Wake kernel logging daemon
++ *
++ * Use this function when new records have been added to the ringbuffer
++ * and the console printing of those records has already occurred or is
++ * known to be handled by some other context. This function will only
++ * wake the logging daemon.
++ *
++ * Context: Any context.
++ */
+ void wake_up_klogd(void)
+ {
+       __wake_up_klogd(PRINTK_PENDING_WAKEUP);
+ }
++/**
++ * defer_console_output - Wake kernel logging daemon and trigger
++ *    console printing in a deferred context
++ *
++ * Use this function when new records have been added to the ringbuffer,
++ * this context is responsible for console printing those records, but
++ * the current context is not allowed to perform the console printing.
++ * Trigger an irq_work context to perform the console printing. This
++ * function also wakes the logging daemon.
++ *
++ * Context: Any context.
++ */
+ void defer_console_output(void)
+ {
+       /*
+@@ -3298,12 +3324,7 @@ void printk_trigger_flush(void)
+ int vprintk_deferred(const char *fmt, va_list args)
+ {
+-      int r;
+-
+-      r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args);
+-      defer_console_output();
+-
+-      return r;
++      return vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args);
+ }
+ int _printk_deferred(const char *fmt, ...)
+diff --git a/kernel/printk/printk_safe.c b/kernel/printk/printk_safe.c
+index ef0f9a2044da1..6d10927a07d83 100644
+--- a/kernel/printk/printk_safe.c
++++ b/kernel/printk/printk_safe.c
+@@ -38,13 +38,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
+        * Use the main logbuf even in NMI. But avoid calling console
+        * drivers that might have their own locks.
+        */
+-      if (this_cpu_read(printk_context) || in_nmi()) {
+-              int len;
+-
+-              len = vprintk_store(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
+-              defer_console_output();
+-              return len;
+-      }
++      if (this_cpu_read(printk_context) || in_nmi())
++              return vprintk_deferred(fmt, args);
+       /* No obstacles. */
+       return vprintk_default(fmt, args);
+-- 
+2.40.1
+
diff --git a/queue-5.15/rcuscale-move-rcu_scale_writer-schedule_timeout_unin.patch b/queue-5.15/rcuscale-move-rcu_scale_writer-schedule_timeout_unin.patch
new file mode 100644 (file)
index 0000000..77a8e8f
--- /dev/null
@@ -0,0 +1,71 @@
+From bc8e449cb13f7633dd7d1ff5c5303cdc5e5b727d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Jun 2023 15:39:26 +0800
+Subject: rcuscale: Move rcu_scale_writer() schedule_timeout_uninterruptible()
+ to _idle()
+
+From: Zqiang <qiang.zhang1211@gmail.com>
+
+[ Upstream commit e60c122a1614b4f65b29a7bef9d83b9fd30e937a ]
+
+The rcuscale.holdoff module parameter can be used to delay the start
+of rcu_scale_writer() kthread.  However, the hung-task timeout will
+trigger when the timeout specified by rcuscale.holdoff is greater than
+hung_task_timeout_secs:
+
+runqemu kvm nographic slirp qemuparams="-smp 4 -m 2048M"
+bootparams="rcuscale.shutdown=0 rcuscale.holdoff=300"
+
+[  247.071753] INFO: task rcu_scale_write:59 blocked for more than 122 seconds.
+[  247.072529]       Not tainted 6.4.0-rc1-00134-gb9ed6de8d4ff #7
+[  247.073400] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
+[  247.074331] task:rcu_scale_write state:D stack:30144 pid:59    ppid:2      flags:0x00004000
+[  247.075346] Call Trace:
+[  247.075660]  <TASK>
+[  247.075965]  __schedule+0x635/0x1280
+[  247.076448]  ? __pfx___schedule+0x10/0x10
+[  247.076967]  ? schedule_timeout+0x2dc/0x4d0
+[  247.077471]  ? __pfx_lock_release+0x10/0x10
+[  247.078018]  ? enqueue_timer+0xe2/0x220
+[  247.078522]  schedule+0x84/0x120
+[  247.078957]  schedule_timeout+0x2e1/0x4d0
+[  247.079447]  ? __pfx_schedule_timeout+0x10/0x10
+[  247.080032]  ? __pfx_rcu_scale_writer+0x10/0x10
+[  247.080591]  ? __pfx_process_timeout+0x10/0x10
+[  247.081163]  ? __pfx_sched_set_fifo_low+0x10/0x10
+[  247.081760]  ? __pfx_rcu_scale_writer+0x10/0x10
+[  247.082287]  rcu_scale_writer+0x6b1/0x7f0
+[  247.082773]  ? mark_held_locks+0x29/0xa0
+[  247.083252]  ? __pfx_rcu_scale_writer+0x10/0x10
+[  247.083865]  ? __pfx_rcu_scale_writer+0x10/0x10
+[  247.084412]  kthread+0x179/0x1c0
+[  247.084759]  ? __pfx_kthread+0x10/0x10
+[  247.085098]  ret_from_fork+0x2c/0x50
+[  247.085433]  </TASK>
+
+This commit therefore replaces schedule_timeout_uninterruptible() with
+schedule_timeout_idle().
+
+Signed-off-by: Zqiang <qiang.zhang1211@gmail.com>
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/rcu/rcuscale.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/kernel/rcu/rcuscale.c b/kernel/rcu/rcuscale.c
+index 57ec414710bbc..a83cb29d37607 100644
+--- a/kernel/rcu/rcuscale.c
++++ b/kernel/rcu/rcuscale.c
+@@ -402,7 +402,7 @@ rcu_scale_writer(void *arg)
+       sched_set_fifo_low(current);
+       if (holdoff)
+-              schedule_timeout_uninterruptible(holdoff * HZ);
++              schedule_timeout_idle(holdoff * HZ);
+       /*
+        * Wait until rcu_end_inkernel_boot() is called for normal GP tests
+-- 
+2.40.1
+
diff --git a/queue-5.15/samples-hw_breakpoint-fix-building-without-module-un.patch b/queue-5.15/samples-hw_breakpoint-fix-building-without-module-un.patch
new file mode 100644 (file)
index 0000000..06d8204
--- /dev/null
@@ -0,0 +1,48 @@
+From 1692fd16fe41eb5f0f378ce83ef42d3e6a166cbf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jul 2023 10:25:36 +0200
+Subject: samples/hw_breakpoint: fix building without module unloading
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit b9080468caeddc58a91edd1c3a7d212ea82b0d1d ]
+
+__symbol_put() is really meant as an internal helper and is not available
+when module unloading is disabled, unlike the previously used symbol_put():
+
+samples/hw_breakpoint/data_breakpoint.c: In function 'hw_break_module_exit':
+samples/hw_breakpoint/data_breakpoint.c:73:9: error: implicit declaration of function '__symbol_put'; did you mean '__symbol_get'? [-Werror=implicit-function-declaration]
+
+The hw_break_module_exit() function is not actually used when module
+unloading is disabled, but it still causes the build failure for an
+undefined identifier. Enclose this one call in an appropriate #ifdef to
+clarify what the requirement is. Leaving out the entire exit function
+would also work but feels less clar in this case.
+
+Fixes: 910e230d5f1bb ("samples/hw_breakpoint: Fix kernel BUG 'invalid opcode: 0000'")
+Fixes: d8a84d33a4954 ("samples/hw_breakpoint: drop use of kallsyms_lookup_name()")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ samples/hw_breakpoint/data_breakpoint.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
+index 9debd128b2ab8..b99322f188e59 100644
+--- a/samples/hw_breakpoint/data_breakpoint.c
++++ b/samples/hw_breakpoint/data_breakpoint.c
+@@ -70,7 +70,9 @@ static int __init hw_break_module_init(void)
+ static void __exit hw_break_module_exit(void)
+ {
+       unregister_wide_hw_breakpoint(sample_hbp);
++#ifdef CONFIG_MODULE_UNLOAD
+       __symbol_put(ksym_name);
++#endif
+       printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/samples-hw_breakpoint-fix-kernel-bug-invalid-opcode-.patch b/queue-5.15/samples-hw_breakpoint-fix-kernel-bug-invalid-opcode-.patch
new file mode 100644 (file)
index 0000000..afc60cb
--- /dev/null
@@ -0,0 +1,77 @@
+From e876a323e61b3d5ceb9623daecd910fe1d32319b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 16 Apr 2023 23:05:17 +0800
+Subject: samples/hw_breakpoint: Fix kernel BUG 'invalid opcode: 0000'
+
+From: Rong Tao <rongtao@cestc.cn>
+
+[ Upstream commit 910e230d5f1bb72c54532e94fbb1705095c7bab6 ]
+
+Macro symbol_put() is defined as __symbol_put(__stringify(x))
+
+    ksym_name = "jiffies"
+    symbol_put(ksym_name)
+
+will be resolved as
+
+    __symbol_put("ksym_name")
+
+which is clearly wrong. So symbol_put must be replaced with __symbol_put.
+
+When we uninstall hw_breakpoint.ko (rmmod), a kernel bug occurs with the
+following error:
+
+[11381.854152] kernel BUG at kernel/module/main.c:779!
+[11381.854159] invalid opcode: 0000 [#2] PREEMPT SMP PTI
+[11381.854163] CPU: 8 PID: 59623 Comm: rmmod Tainted: G      D    OE      6.2.9-200.fc37.x86_64 #1
+[11381.854167] Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./B360M-HDV, BIOS P3.20 10/23/2018
+[11381.854169] RIP: 0010:__symbol_put+0xa2/0xb0
+[11381.854175] Code: 00 e8 92 d2 f7 ff 65 8b 05 c3 2f e6 78 85 c0 74 1b 48 8b 44 24 30 65 48 2b 04 25 28 00 00 00 75 12 48 83 c4 38 c3 cc cc cc cc <0f> 0b 0f 1f 44 00 00 eb de e8 c0 df d8 00 90 90 90 90 90 90 90 90
+[11381.854178] RSP: 0018:ffffad8ec6ae7dd0 EFLAGS: 00010246
+[11381.854181] RAX: 0000000000000000 RBX: ffffffffc1fd1240 RCX: 000000000000000c
+[11381.854184] RDX: 000000000000006b RSI: ffffffffc02bf7c7 RDI: ffffffffc1fd001c
+[11381.854186] RBP: 000055a38b76e7c8 R08: ffffffff871ccfe0 R09: 0000000000000000
+[11381.854188] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
+[11381.854190] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
+[11381.854192] FS:  00007fbf7c62c740(0000) GS:ffff8c5badc00000(0000) knlGS:0000000000000000
+[11381.854195] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[11381.854197] CR2: 000055a38b7793f8 CR3: 0000000363e1e001 CR4: 00000000003726e0
+[11381.854200] DR0: ffffffffb3407980 DR1: 0000000000000000 DR2: 0000000000000000
+[11381.854202] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
+[11381.854204] Call Trace:
+[11381.854207]  <TASK>
+[11381.854212]  s_module_exit+0xc/0xff0 [symbol_getput]
+[11381.854219]  __do_sys_delete_module.constprop.0+0x198/0x2f0
+[11381.854225]  do_syscall_64+0x58/0x80
+[11381.854231]  ? exit_to_user_mode_prepare+0x180/0x1f0
+[11381.854237]  ? syscall_exit_to_user_mode+0x17/0x40
+[11381.854241]  ? do_syscall_64+0x67/0x80
+[11381.854245]  ? syscall_exit_to_user_mode+0x17/0x40
+[11381.854248]  ? do_syscall_64+0x67/0x80
+[11381.854252]  ? exc_page_fault+0x70/0x170
+[11381.854256]  entry_SYSCALL_64_after_hwframe+0x72/0xdc
+
+Signed-off-by: Rong Tao <rongtao@cestc.cn>
+Reviewed-by: Petr Mladek <pmladek@suse.com>
+Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ samples/hw_breakpoint/data_breakpoint.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/samples/hw_breakpoint/data_breakpoint.c b/samples/hw_breakpoint/data_breakpoint.c
+index 418c46fe5ffc3..9debd128b2ab8 100644
+--- a/samples/hw_breakpoint/data_breakpoint.c
++++ b/samples/hw_breakpoint/data_breakpoint.c
+@@ -70,7 +70,7 @@ static int __init hw_break_module_init(void)
+ static void __exit hw_break_module_exit(void)
+ {
+       unregister_wide_hw_breakpoint(sample_hbp);
+-      symbol_put(ksym_name);
++      __symbol_put(ksym_name);
+       printk(KERN_INFO "HW Breakpoint for %s write uninstalled\n", ksym_name);
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/scftorture-forgive-memory-allocation-failure-if-kasa.patch b/queue-5.15/scftorture-forgive-memory-allocation-failure-if-kasa.patch
new file mode 100644 (file)
index 0000000..84f48df
--- /dev/null
@@ -0,0 +1,49 @@
+From b217c5b5d1862463d4b21ed41224dfdbf8ffdece Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 15 May 2023 19:00:10 -0700
+Subject: scftorture: Forgive memory-allocation failure if KASAN
+
+From: Paul E. McKenney <paulmck@kernel.org>
+
+[ Upstream commit 013608cd0812bdb21fc26d39ed8fdd2fc76e8b9b ]
+
+Kernels built with CONFIG_KASAN=y quarantine newly freed memory in order
+to better detect use-after-free errors.  However, this can exhaust memory
+more quickly in allocator-heavy tests, which can result in spurious
+scftorture failure.  This commit therefore forgives memory-allocation
+failure in kernels built with CONFIG_KASAN=y, but continues counting
+the errors for use in detailed test-result analyses.
+
+Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/scftorture.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/kernel/scftorture.c b/kernel/scftorture.c
+index 27286d99e0c28..41006eef003f6 100644
+--- a/kernel/scftorture.c
++++ b/kernel/scftorture.c
+@@ -175,7 +175,8 @@ static void scf_torture_stats_print(void)
+               scfs.n_all_wait += scf_stats_p[i].n_all_wait;
+       }
+       if (atomic_read(&n_errs) || atomic_read(&n_mb_in_errs) ||
+-          atomic_read(&n_mb_out_errs) || atomic_read(&n_alloc_errs))
++          atomic_read(&n_mb_out_errs) ||
++          (!IS_ENABLED(CONFIG_KASAN) && atomic_read(&n_alloc_errs)))
+               bangstr = "!!! ";
+       pr_alert("%s %sscf_invoked_count %s: %lld resched: %lld single: %lld/%lld single_ofl: %lld/%lld single_rpc: %lld single_rpc_ofl: %lld many: %lld/%lld all: %lld/%lld ",
+                SCFTORT_FLAG, bangstr, isdone ? "VER" : "ver", invoked_count, scfs.n_resched,
+@@ -327,7 +328,8 @@ static void scftorture_invoke_one(struct scf_statistics *scfp, struct torture_ra
+               preempt_disable();
+       if (scfsp->scfs_prim == SCF_PRIM_SINGLE || scfsp->scfs_wait) {
+               scfcp = kmalloc(sizeof(*scfcp), GFP_ATOMIC);
+-              if (WARN_ON_ONCE(!scfcp)) {
++              if (!scfcp) {
++                      WARN_ON_ONCE(!IS_ENABLED(CONFIG_KASAN));
+                       atomic_inc(&n_alloc_errs);
+               } else {
+                       scfcp->scfc_cpu = -1;
+-- 
+2.40.1
+
diff --git a/queue-5.15/scsi-lpfc-fix-the-null-vs-is_err-bug-for-debugfs_cre.patch b/queue-5.15/scsi-lpfc-fix-the-null-vs-is_err-bug-for-debugfs_cre.patch
new file mode 100644 (file)
index 0000000..7d49bf4
--- /dev/null
@@ -0,0 +1,97 @@
+From 796193c62c3b6127cb823c45e1c020378882a923 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Sep 2023 11:08:09 +0800
+Subject: scsi: lpfc: Fix the NULL vs IS_ERR() bug for debugfs_create_file()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit 7dcc683db3639eadd11bf0d59a09088a43de5e22 ]
+
+Since debugfs_create_file() returns ERR_PTR and never NULL, use IS_ERR() to
+check the return value.
+
+Fixes: 2fcbc569b9f5 ("scsi: lpfc: Make debugfs ktime stats generic for NVME and SCSI")
+Fixes: 4c47efc140fa ("scsi: lpfc: Move SCSI and NVME Stats to hardware queue structures")
+Fixes: 6a828b0f6192 ("scsi: lpfc: Support non-uniform allocation of MSIX vectors to hardware queues")
+Fixes: 95bfc6d8ad86 ("scsi: lpfc: Make FW logging dynamically configurable")
+Fixes: 9f77870870d8 ("scsi: lpfc: Add debugfs support for cm framework buffers")
+Fixes: c490850a0947 ("scsi: lpfc: Adapt partitioned XRI lists to efficient sharing")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Link: https://lore.kernel.org/r/20230906030809.2847970-1-ruanjinjie@huawei.com
+Reviewed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/lpfc/lpfc_debugfs.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
+index 560b2504e674d..a15ad76aee211 100644
+--- a/drivers/scsi/lpfc/lpfc_debugfs.c
++++ b/drivers/scsi/lpfc/lpfc_debugfs.c
+@@ -6058,7 +6058,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+                                           phba->hba_debugfs_root,
+                                           phba,
+                                           &lpfc_debugfs_op_multixripools);
+-              if (!phba->debug_multixri_pools) {
++              if (IS_ERR(phba->debug_multixri_pools)) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                        "0527 Cannot create debugfs multixripools\n");
+                       goto debug_failed;
+@@ -6070,7 +6070,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+                       debugfs_create_file(name, S_IFREG | 0644,
+                                           phba->hba_debugfs_root,
+                                           phba, &lpfc_cgn_buffer_op);
+-              if (!phba->debug_cgn_buffer) {
++              if (IS_ERR(phba->debug_cgn_buffer)) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                        "6527 Cannot create debugfs "
+                                        "cgn_buffer\n");
+@@ -6083,7 +6083,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+                       debugfs_create_file(name, S_IFREG | 0644,
+                                           phba->hba_debugfs_root,
+                                           phba, &lpfc_rx_monitor_op);
+-              if (!phba->debug_rx_monitor) {
++              if (IS_ERR(phba->debug_rx_monitor)) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                        "6528 Cannot create debugfs "
+                                        "rx_monitor\n");
+@@ -6096,7 +6096,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+                       debugfs_create_file(name, 0644,
+                                           phba->hba_debugfs_root,
+                                           phba, &lpfc_debugfs_ras_log);
+-              if (!phba->debug_ras_log) {
++              if (IS_ERR(phba->debug_ras_log)) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                        "6148 Cannot create debugfs"
+                                        " ras_log\n");
+@@ -6117,7 +6117,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+                       debugfs_create_file(name, S_IFREG | 0644,
+                                           phba->hba_debugfs_root,
+                                           phba, &lpfc_debugfs_op_lockstat);
+-              if (!phba->debug_lockstat) {
++              if (IS_ERR(phba->debug_lockstat)) {
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                        "4610 Can't create debugfs lockstat\n");
+                       goto debug_failed;
+@@ -6346,7 +6346,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+               debugfs_create_file(name, 0644,
+                                   vport->vport_debugfs_root,
+                                   vport, &lpfc_debugfs_op_scsistat);
+-      if (!vport->debug_scsistat) {
++      if (IS_ERR(vport->debug_scsistat)) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                "4611 Cannot create debugfs scsistat\n");
+               goto debug_failed;
+@@ -6357,7 +6357,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport)
+               debugfs_create_file(name, 0644,
+                                   vport->vport_debugfs_root,
+                                   vport, &lpfc_debugfs_op_ioktime);
+-      if (!vport->debug_ioktime) {
++      if (IS_ERR(vport->debug_ioktime)) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+                                "0815 Cannot create debugfs ioktime\n");
+               goto debug_failed;
+-- 
+2.40.1
+
diff --git a/queue-5.15/scsi-qla2xxx-fix-null-vs-is_err-bug-for-debugfs_crea.patch b/queue-5.15/scsi-qla2xxx-fix-null-vs-is_err-bug-for-debugfs_crea.patch
new file mode 100644 (file)
index 0000000..149d9d3
--- /dev/null
@@ -0,0 +1,54 @@
+From ccf6db45307662f3463c155999d7e501dce3e80e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 31 Aug 2023 22:09:29 +0800
+Subject: scsi: qla2xxx: Fix NULL vs IS_ERR() bug for debugfs_create_dir()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit d0b0822e32dbae80bbcb3cc86f34d28539d913df ]
+
+Since both debugfs_create_dir() and debugfs_create_file() return ERR_PTR
+and never NULL, use IS_ERR() instead of checking for NULL.
+
+Fixes: 1e98fb0f9208 ("scsi: qla2xxx: Setup debugfs entries for remote ports")
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Link: https://lore.kernel.org/r/20230831140930.3166359-1-ruanjinjie@huawei.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_dfs.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
+index aa9d69e5274d8..af921fd150d1e 100644
+--- a/drivers/scsi/qla2xxx/qla_dfs.c
++++ b/drivers/scsi/qla2xxx/qla_dfs.c
+@@ -116,7 +116,7 @@ qla2x00_dfs_create_rport(scsi_qla_host_t *vha, struct fc_port *fp)
+       sprintf(wwn, "pn-%016llx", wwn_to_u64(fp->port_name));
+       fp->dfs_rport_dir = debugfs_create_dir(wwn, vha->dfs_rport_root);
+-      if (!fp->dfs_rport_dir)
++      if (IS_ERR(fp->dfs_rport_dir))
+               return;
+       if (NVME_TARGET(vha->hw, fp))
+               debugfs_create_file("dev_loss_tmo", 0600, fp->dfs_rport_dir,
+@@ -615,14 +615,14 @@ qla2x00_dfs_setup(scsi_qla_host_t *vha)
+       if (IS_QLA27XX(ha) || IS_QLA83XX(ha) || IS_QLA28XX(ha)) {
+               ha->tgt.dfs_naqp = debugfs_create_file("naqp",
+                   0400, ha->dfs_dir, vha, &dfs_naqp_ops);
+-              if (!ha->tgt.dfs_naqp) {
++              if (IS_ERR(ha->tgt.dfs_naqp)) {
+                       ql_log(ql_log_warn, vha, 0xd011,
+                              "Unable to create debugFS naqp node.\n");
+                       goto out;
+               }
+       }
+       vha->dfs_rport_root = debugfs_create_dir("rports", ha->dfs_dir);
+-      if (!vha->dfs_rport_root) {
++      if (IS_ERR(vha->dfs_rport_root)) {
+               ql_log(ql_log_warn, vha, 0xd012,
+                      "Unable to create debugFS rports node.\n");
+               goto out;
+-- 
+2.40.1
+
diff --git a/queue-5.15/scsi-target-iscsi-fix-buffer-overflow-in-lio_target_.patch b/queue-5.15/scsi-target-iscsi-fix-buffer-overflow-in-lio_target_.patch
new file mode 100644 (file)
index 0000000..7858e5b
--- /dev/null
@@ -0,0 +1,163 @@
+From 5da520c60a584e654fa9174685776429fe5c8a2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 22 Jul 2023 18:26:37 +0300
+Subject: scsi: target: iscsi: Fix buffer overflow in
+ lio_target_nacl_info_show()
+
+From: Konstantin Shelekhin <k.shelekhin@yadro.com>
+
+[ Upstream commit 801f287c93ff95582b0a2d2163f12870a2f076d4 ]
+
+The function lio_target_nacl_info_show() uses sprintf() in a loop to print
+details for every iSCSI connection in a session without checking for the
+buffer length. With enough iSCSI connections it's possible to overflow the
+buffer provided by configfs and corrupt the memory.
+
+This patch replaces sprintf() with sysfs_emit_at() that checks for buffer
+boundries.
+
+Signed-off-by: Konstantin Shelekhin <k.shelekhin@yadro.com>
+Link: https://lore.kernel.org/r/20230722152657.168859-2-k.shelekhin@yadro.com
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/target/iscsi/iscsi_target_configfs.c | 54 ++++++++++----------
+ 1 file changed, 27 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
+index f4a24fa5058e6..df399110fbf11 100644
+--- a/drivers/target/iscsi/iscsi_target_configfs.c
++++ b/drivers/target/iscsi/iscsi_target_configfs.c
+@@ -507,102 +507,102 @@ static ssize_t lio_target_nacl_info_show(struct config_item *item, char *page)
+       spin_lock_bh(&se_nacl->nacl_sess_lock);
+       se_sess = se_nacl->nacl_sess;
+       if (!se_sess) {
+-              rb += sprintf(page+rb, "No active iSCSI Session for Initiator"
++              rb += sysfs_emit_at(page, rb, "No active iSCSI Session for Initiator"
+                       " Endpoint: %s\n", se_nacl->initiatorname);
+       } else {
+               sess = se_sess->fabric_sess_ptr;
+-              rb += sprintf(page+rb, "InitiatorName: %s\n",
++              rb += sysfs_emit_at(page, rb, "InitiatorName: %s\n",
+                       sess->sess_ops->InitiatorName);
+-              rb += sprintf(page+rb, "InitiatorAlias: %s\n",
++              rb += sysfs_emit_at(page, rb, "InitiatorAlias: %s\n",
+                       sess->sess_ops->InitiatorAlias);
+-              rb += sprintf(page+rb,
++              rb += sysfs_emit_at(page, rb,
+                             "LIO Session ID: %u   ISID: 0x%6ph  TSIH: %hu  ",
+                             sess->sid, sess->isid, sess->tsih);
+-              rb += sprintf(page+rb, "SessionType: %s\n",
++              rb += sysfs_emit_at(page, rb, "SessionType: %s\n",
+                               (sess->sess_ops->SessionType) ?
+                               "Discovery" : "Normal");
+-              rb += sprintf(page+rb, "Session State: ");
++              rb += sysfs_emit_at(page, rb, "Session State: ");
+               switch (sess->session_state) {
+               case TARG_SESS_STATE_FREE:
+-                      rb += sprintf(page+rb, "TARG_SESS_FREE\n");
++                      rb += sysfs_emit_at(page, rb, "TARG_SESS_FREE\n");
+                       break;
+               case TARG_SESS_STATE_ACTIVE:
+-                      rb += sprintf(page+rb, "TARG_SESS_STATE_ACTIVE\n");
++                      rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_ACTIVE\n");
+                       break;
+               case TARG_SESS_STATE_LOGGED_IN:
+-                      rb += sprintf(page+rb, "TARG_SESS_STATE_LOGGED_IN\n");
++                      rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_LOGGED_IN\n");
+                       break;
+               case TARG_SESS_STATE_FAILED:
+-                      rb += sprintf(page+rb, "TARG_SESS_STATE_FAILED\n");
++                      rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_FAILED\n");
+                       break;
+               case TARG_SESS_STATE_IN_CONTINUE:
+-                      rb += sprintf(page+rb, "TARG_SESS_STATE_IN_CONTINUE\n");
++                      rb += sysfs_emit_at(page, rb, "TARG_SESS_STATE_IN_CONTINUE\n");
+                       break;
+               default:
+-                      rb += sprintf(page+rb, "ERROR: Unknown Session"
++                      rb += sysfs_emit_at(page, rb, "ERROR: Unknown Session"
+                                       " State!\n");
+                       break;
+               }
+-              rb += sprintf(page+rb, "---------------------[iSCSI Session"
++              rb += sysfs_emit_at(page, rb, "---------------------[iSCSI Session"
+                               " Values]-----------------------\n");
+-              rb += sprintf(page+rb, "  CmdSN/WR  :  CmdSN/WC  :  ExpCmdSN"
++              rb += sysfs_emit_at(page, rb, "  CmdSN/WR  :  CmdSN/WC  :  ExpCmdSN"
+                               "  :  MaxCmdSN  :     ITT    :     TTT\n");
+               max_cmd_sn = (u32) atomic_read(&sess->max_cmd_sn);
+-              rb += sprintf(page+rb, " 0x%08x   0x%08x   0x%08x   0x%08x"
++              rb += sysfs_emit_at(page, rb, " 0x%08x   0x%08x   0x%08x   0x%08x"
+                               "   0x%08x   0x%08x\n",
+                       sess->cmdsn_window,
+                       (max_cmd_sn - sess->exp_cmd_sn) + 1,
+                       sess->exp_cmd_sn, max_cmd_sn,
+                       sess->init_task_tag, sess->targ_xfer_tag);
+-              rb += sprintf(page+rb, "----------------------[iSCSI"
++              rb += sysfs_emit_at(page, rb, "----------------------[iSCSI"
+                               " Connections]-------------------------\n");
+               spin_lock(&sess->conn_lock);
+               list_for_each_entry(conn, &sess->sess_conn_list, conn_list) {
+-                      rb += sprintf(page+rb, "CID: %hu  Connection"
++                      rb += sysfs_emit_at(page, rb, "CID: %hu  Connection"
+                                       " State: ", conn->cid);
+                       switch (conn->conn_state) {
+                       case TARG_CONN_STATE_FREE:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "TARG_CONN_STATE_FREE\n");
+                               break;
+                       case TARG_CONN_STATE_XPT_UP:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "TARG_CONN_STATE_XPT_UP\n");
+                               break;
+                       case TARG_CONN_STATE_IN_LOGIN:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "TARG_CONN_STATE_IN_LOGIN\n");
+                               break;
+                       case TARG_CONN_STATE_LOGGED_IN:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "TARG_CONN_STATE_LOGGED_IN\n");
+                               break;
+                       case TARG_CONN_STATE_IN_LOGOUT:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "TARG_CONN_STATE_IN_LOGOUT\n");
+                               break;
+                       case TARG_CONN_STATE_LOGOUT_REQUESTED:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "TARG_CONN_STATE_LOGOUT_REQUESTED\n");
+                               break;
+                       case TARG_CONN_STATE_CLEANUP_WAIT:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "TARG_CONN_STATE_CLEANUP_WAIT\n");
+                               break;
+                       default:
+-                              rb += sprintf(page+rb,
++                              rb += sysfs_emit_at(page, rb,
+                                       "ERROR: Unknown Connection State!\n");
+                               break;
+                       }
+-                      rb += sprintf(page+rb, "   Address %pISc %s", &conn->login_sockaddr,
++                      rb += sysfs_emit_at(page, rb, "   Address %pISc %s", &conn->login_sockaddr,
+                               (conn->network_transport == ISCSI_TCP) ?
+                               "TCP" : "SCTP");
+-                      rb += sprintf(page+rb, "  StatSN: 0x%08x\n",
++                      rb += sysfs_emit_at(page, rb, "  StatSN: 0x%08x\n",
+                               conn->stat_sn);
+               }
+               spin_unlock(&sess->conn_lock);
+-- 
+2.40.1
+
diff --git a/queue-5.15/selftests-tracing-fix-to-unmount-tracefs-for-recover.patch b/queue-5.15/selftests-tracing-fix-to-unmount-tracefs-for-recover.patch
new file mode 100644 (file)
index 0000000..f9bf171
--- /dev/null
@@ -0,0 +1,65 @@
+From a280b038ebeb0d770cd931c221cb703f2a4ede01 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Sep 2023 10:10:39 +0900
+Subject: selftests: tracing: Fix to unmount tracefs for recovering environment
+
+From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+
+[ Upstream commit 7e021da80f48582171029714f8a487347f29dddb ]
+
+Fix to unmount the tracefs if the ftracetest mounted it for recovering
+system environment. If the tracefs is already mounted, this does nothing.
+
+Suggested-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/all/29fce076-746c-4650-8358-b4e0fa215cf7@sirena.org.uk/
+Fixes: cbd965bde74c ("ftrace/selftests: Return the skip code when tracing directory not configured in kernel")
+Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
+Reviewed-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Reviewed-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/ftrace/ftracetest | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
+index 8ec1922e974eb..55314cd197ab9 100755
+--- a/tools/testing/selftests/ftrace/ftracetest
++++ b/tools/testing/selftests/ftrace/ftracetest
+@@ -30,6 +30,9 @@ err_ret=1
+ # kselftest skip code is 4
+ err_skip=4
++# umount required
++UMOUNT_DIR=""
++
+ # cgroup RT scheduling prevents chrt commands from succeeding, which
+ # induces failures in test wakeup tests.  Disable for the duration of
+ # the tests.
+@@ -44,6 +47,9 @@ setup() {
+ cleanup() {
+   echo $sched_rt_runtime_orig > $sched_rt_runtime
++  if [ -n "${UMOUNT_DIR}" ]; then
++    umount ${UMOUNT_DIR} ||:
++  fi
+ }
+ errexit() { # message
+@@ -155,11 +161,13 @@ if [ -z "$TRACING_DIR" ]; then
+           mount -t tracefs nodev /sys/kernel/tracing ||
+             errexit "Failed to mount /sys/kernel/tracing"
+           TRACING_DIR="/sys/kernel/tracing"
++          UMOUNT_DIR=${TRACING_DIR}
+       # If debugfs exists, then so does /sys/kernel/debug
+       elif [ -d "/sys/kernel/debug" ]; then
+           mount -t debugfs nodev /sys/kernel/debug ||
+             errexit "Failed to mount /sys/kernel/debug"
+           TRACING_DIR="/sys/kernel/debug/tracing"
++          UMOUNT_DIR=${TRACING_DIR}
+       else
+           err_ret=$err_skip
+           errexit "debugfs and tracefs are not configured in this kernel"
+-- 
+2.40.1
+
diff --git a/queue-5.15/serial-cpm_uart-avoid-suspicious-locking.patch b/queue-5.15/serial-cpm_uart-avoid-suspicious-locking.patch
new file mode 100644 (file)
index 0000000..331d7d6
--- /dev/null
@@ -0,0 +1,80 @@
+From 64dfb41cde8b231df8bf1cee63bd6e3b7bbc70a7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Aug 2023 15:56:42 +0200
+Subject: serial: cpm_uart: Avoid suspicious locking
+
+From: Christophe Leroy <christophe.leroy@csgroup.eu>
+
+[ Upstream commit 36ef11d311f405e55ad8e848c19b212ff71ef536 ]
+
+  CHECK   drivers/tty/serial/cpm_uart/cpm_uart_core.c
+drivers/tty/serial/cpm_uart/cpm_uart_core.c:1271:39: warning: context imbalance in 'cpm_uart_console_write' - unexpected unlock
+
+Allthough 'nolock' is not expected to change, sparse find the following
+form suspicious:
+
+       if (unlikely(nolock)) {
+               local_irq_save(flags);
+       } else {
+               spin_lock_irqsave(&pinfo->port.lock, flags);
+       }
+
+       cpm_uart_early_write(pinfo, s, count, true);
+
+       if (unlikely(nolock)) {
+               local_irq_restore(flags);
+       } else {
+               spin_unlock_irqrestore(&pinfo->port.lock, flags);
+       }
+
+Rewrite it a more obvious form:
+
+       if (unlikely(oops_in_progress)) {
+               local_irq_save(flags);
+               cpm_uart_early_write(pinfo, s, count, true);
+               local_irq_restore(flags);
+       } else {
+               spin_lock_irqsave(&pinfo->port.lock, flags);
+               cpm_uart_early_write(pinfo, s, count, true);
+               spin_unlock_irqrestore(&pinfo->port.lock, flags);
+       }
+
+Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
+Link: https://lore.kernel.org/r/f7da5cdc9287960185829cfef681a7d8614efa1f.1691068700.git.christophe.leroy@csgroup.eu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/cpm_uart/cpm_uart_core.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+index db07d6a5d764d..2335edd516847 100644
+--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
++++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+@@ -1276,19 +1276,14 @@ static void cpm_uart_console_write(struct console *co, const char *s,
+ {
+       struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
+       unsigned long flags;
+-      int nolock = oops_in_progress;
+-      if (unlikely(nolock)) {
++      if (unlikely(oops_in_progress)) {
+               local_irq_save(flags);
+-      } else {
+-              spin_lock_irqsave(&pinfo->port.lock, flags);
+-      }
+-
+-      cpm_uart_early_write(pinfo, s, count, true);
+-
+-      if (unlikely(nolock)) {
++              cpm_uart_early_write(pinfo, s, count, true);
+               local_irq_restore(flags);
+       } else {
++              spin_lock_irqsave(&pinfo->port.lock, flags);
++              cpm_uart_early_write(pinfo, s, count, true);
+               spin_unlock_irqrestore(&pinfo->port.lock, flags);
+       }
+ }
+-- 
+2.40.1
+
diff --git a/queue-5.15/series b/queue-5.15/series
new file mode 100644 (file)
index 0000000..68e572a
--- /dev/null
@@ -0,0 +1,91 @@
+autofs-fix-memory-leak-of-waitqueues-in-autofs_catat.patch
+btrfs-output-extra-debug-info-if-we-failed-to-find-a.patch
+locks-fix-kasan-use-after-free-in-trace_event_raw_ev.patch
+acpica-add-aml_no_operand_resolve-flag-to-timer.patch
+kernel-fork-beware-of-__put_task_struct-calling-cont.patch
+rcuscale-move-rcu_scale_writer-schedule_timeout_unin.patch
+scftorture-forgive-memory-allocation-failure-if-kasa.patch
+acpi-video-add-backlight-native-dmi-quirk-for-lenovo.patch
+perf-smmuv3-enable-hisilicon-erratum-162001900-quirk.patch
+perf-imx_ddr-speed-up-overflow-frequency-of-cycle.patch
+hw_breakpoint-fix-single-stepping-when-using-bpf_ove.patch
+acpi-x86-s2idle-catch-multiple-acpi_type_package-obj.patch
+devlink-remove-reload-failed-checks-in-params-get-se.patch
+crypto-lrw-xts-replace-strlcpy-with-strscpy.patch
+wifi-ath9k-fix-fortify-warnings.patch
+wifi-ath9k-fix-printk-specifier.patch
+wifi-mwifiex-fix-fortify-warning.patch
+wifi-wil6210-fix-fortify-warnings.patch
+crypto-lib-mpi-avoid-null-pointer-deref-in-mpi_cmp_u.patch
+tpm_tis-resend-command-to-recover-from-data-transfer.patch
+mmc-sdhci-esdhc-imx-improve-esdhc_flag_err010450.patch
+alx-fix-oob-read-compiler-warning.patch
+wifi-mac80211-check-s1g-action-frame-size.patch
+netfilter-ebtables-fix-fortify-warnings-in-size_entr.patch
+wifi-mac80211_hwsim-drop-short-frames.patch
+libbpf-free-btf_vmlinux-when-closing-bpf_object.patch
+drm-bridge-tc358762-instruct-dsi-host-to-generate-hs.patch
+arm64-dts-qcom-sm6125-pdx201-correct-ramoops-pmsg-si.patch
+arm64-dts-qcom-sm8150-kumano-correct-ramoops-pmsg-si.patch
+arm64-dts-qcom-sm8250-edo-correct-ramoops-pmsg-size.patch
+samples-hw_breakpoint-fix-kernel-bug-invalid-opcode-.patch
+alsa-hda-intel-dsp-cfg-add-lunarlake-support.patch
+drm-amd-display-blocking-invalid-420-modes-on-hdmi-t.patch
+drm-exynos-fix-a-possible-null-pointer-dereference-d.patch
+bus-ti-sysc-configure-uart-quirks-for-k3-soc.patch
+md-raid1-fix-potential-oob-in-raid1_remove_disk.patch
+ext2-fix-datatype-of-block-number-in-ext2_xattr_set2.patch
+fs-jfs-prevent-double-free-in-dbunmount-after-failed.patch
+jfs-fix-invalid-free-of-jfs_ip-ipimap-i_imap-in-diun.patch
+arm-9317-1-kexec-make-smp-stop-calls-asynchronous.patch
+powerpc-pseries-fix-possible-memory-leak-in-ibmebus_.patch
+pci-fu740-set-the-number-of-msi-vectors.patch
+media-dvb-usb-v2-af9035-fix-null-ptr-deref-in-af9035.patch
+media-dw2102-fix-null-ptr-deref-in-dw2102_i2c_transf.patch
+media-af9005-fix-null-ptr-deref-in-af9005_i2c_xfer.patch
+media-anysee-fix-null-ptr-deref-in-anysee_master_xfe.patch
+media-az6007-fix-null-ptr-deref-in-az6007_i2c_xfer.patch
+media-dvb-usb-v2-gl861-fix-null-ptr-deref-in-gl861_i.patch
+media-tuners-qt1010-replace-bug_on-with-a-regular-er.patch
+media-pci-cx23885-replace-bug-with-error-return.patch
+usb-cdns3-put-the-cdns-set-active-part-outside-the-s.patch
+usb-gadget-fsl_qe_udc-validate-endpoint-index-for-ch.patch
+tools-iio-iio_generic_buffer-fix-some-integer-type-a.patch
+scsi-target-iscsi-fix-buffer-overflow-in-lio_target_.patch
+serial-cpm_uart-avoid-suspicious-locking.patch
+usb-ehci-add-workaround-for-chipidea-portsc.pec-bug.patch
+media-pci-ipu3-cio2-initialise-timing-struct-to-avoi.patch
+kobject-add-sanity-check-for-kset-kobj.ktype-in-kset.patch
+interconnect-fix-locking-for-runpm-vs-reclaim.patch
+printk-consolidate-console-deferred-printing.patch
+jbd2-refactor-wait-logic-for-transaction-updates-int.patch
+jbd2-fix-use-after-free-of-transaction_t-race.patch
+jbd2-kill-t_handle_lock-transaction-spinlock.patch
+jbd2-rename-jbd_debug-to-jbd2_debug.patch
+jbd2-correct-the-end-of-the-journal-recovery-scan-ra.patch
+mtd-rawnand-brcmnand-allow-soc-to-provide-i-o-operat.patch
+mtd-rawnand-brcmnand-fix-ecc-level-field-setting-for.patch
+mips-use-grep-e-instead-of-egrep.patch
+perf-jevents-switch-build-to-use-jevents.py.patch
+perf-build-update-build-rule-for-generated-files.patch
+perf-test-remove-bash-construct-from-stat_bpf_counte.patch
+perf-test-shell-stat_bpf_counters-fix-test-on-intel.patch
+btrfs-move-btrfs_pinned_by_swapfile-prototype-into-v.patch
+btrfs-add-a-helper-to-read-the-superblock-metadata_u.patch
+btrfs-compare-the-correct-fsid-metadata_uuid-in-btrf.patch
+drm-gm12u320-fix-the-timeout-usage-for-usb_bulk_msg.patch
+scsi-qla2xxx-fix-null-vs-is_err-bug-for-debugfs_crea.patch
+selftests-tracing-fix-to-unmount-tracefs-for-recover.patch
+scsi-lpfc-fix-the-null-vs-is_err-bug-for-debugfs_cre.patch
+x86-boot-compressed-reserve-more-memory-for-page-tab.patch
+x86-purgatory-remove-lto-flags.patch
+netfilter-nf_tables-make-validation-state-per-table.patch
+netfilter-nf_tables-gc-transaction-api-to-avoid-race.patch
+netfilter-nf_tables-adapt-set-backend-to-use-gc-tran.patch
+netfilter-nft_set_hash-mark-set-element-as-dead-when.patch
+netfilter-nf_tables-remove-busy-mark-and-gc-batch-ap.patch
+netfilter-nf_tables-fix-kdoc-warnings-after-gc-rewor.patch
+netfilter-nf_tables-fix-gc-transaction-races-with-ne.patch
+netfilter-nf_tables-gc-transaction-race-with-netns-d.patch
+samples-hw_breakpoint-fix-building-without-module-un.patch
+md-raid1-fix-error-iso-c90-forbids-mixed-declaration.patch
diff --git a/queue-5.15/tools-iio-iio_generic_buffer-fix-some-integer-type-a.patch b/queue-5.15/tools-iio-iio_generic_buffer-fix-some-integer-type-a.patch
new file mode 100644 (file)
index 0000000..47c134a
--- /dev/null
@@ -0,0 +1,73 @@
+From 24e0efae4d98b5e3b17384c79612d755dbccc647 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 25 Jul 2023 09:24:07 +0000
+Subject: tools: iio: iio_generic_buffer: Fix some integer type and calculation
+
+From: Chenyuan Mi <michenyuan@huawei.com>
+
+[ Upstream commit 49d736313d0975ddeb156f4f59801da833f78b30 ]
+
+In function size_from_channelarray(), the return value 'bytes' is defined
+as int type. However, the calcution of 'bytes' in this function is designed
+to use the unsigned int type. So it is necessary to change 'bytes' type to
+unsigned int to avoid integer overflow.
+
+The size_from_channelarray() is called in main() function, its return value
+is directly multipled by 'buf_len' and then used as the malloc() parameter.
+The 'buf_len' is completely controllable by user, thus a multiplication
+overflow may occur here. This could allocate an unexpected small area.
+
+Signed-off-by: Chenyuan Mi <michenyuan@huawei.com>
+Link: https://lore.kernel.org/r/20230725092407.62545-1-michenyuan@huawei.com
+Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/iio/iio_generic_buffer.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+diff --git a/tools/iio/iio_generic_buffer.c b/tools/iio/iio_generic_buffer.c
+index f8deae4e26a15..44bbf80f0cfdd 100644
+--- a/tools/iio/iio_generic_buffer.c
++++ b/tools/iio/iio_generic_buffer.c
+@@ -51,9 +51,9 @@ enum autochan {
+  * Has the side effect of filling the channels[i].location values used
+  * in processing the buffer output.
+  **/
+-static int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
++static unsigned int size_from_channelarray(struct iio_channel_info *channels, int num_channels)
+ {
+-      int bytes = 0;
++      unsigned int bytes = 0;
+       int i = 0;
+       while (i < num_channels) {
+@@ -348,7 +348,7 @@ int main(int argc, char **argv)
+       ssize_t read_size;
+       int dev_num = -1, trig_num = -1;
+       char *buffer_access = NULL;
+-      int scan_size;
++      unsigned int scan_size;
+       int noevents = 0;
+       int notrigger = 0;
+       char *dummy;
+@@ -674,7 +674,16 @@ int main(int argc, char **argv)
+       }
+       scan_size = size_from_channelarray(channels, num_channels);
+-      data = malloc(scan_size * buf_len);
++
++      size_t total_buf_len = scan_size * buf_len;
++
++      if (scan_size > 0 && total_buf_len / scan_size != buf_len) {
++              ret = -EFAULT;
++              perror("Integer overflow happened when calculate scan_size * buf_len");
++              goto error;
++      }
++
++      data = malloc(total_buf_len);
+       if (!data) {
+               ret = -ENOMEM;
+               goto error;
+-- 
+2.40.1
+
diff --git a/queue-5.15/tpm_tis-resend-command-to-recover-from-data-transfer.patch b/queue-5.15/tpm_tis-resend-command-to-recover-from-data-transfer.patch
new file mode 100644 (file)
index 0000000..efbf144
--- /dev/null
@@ -0,0 +1,50 @@
+From 6d2110d42ae332a997e50ec0f81c91c1363bfadd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 13 Jun 2023 20:02:59 +0200
+Subject: tpm_tis: Resend command to recover from data transfer errors
+
+From: Alexander Steffen <Alexander.Steffen@infineon.com>
+
+[ Upstream commit 280db21e153d8810ce3b93640c63ae922bcb9e8e ]
+
+Similar to the transmission of TPM responses, also the transmission of TPM
+commands may become corrupted. Instead of aborting when detecting such
+issues, try resending the command again.
+
+Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index d7c440ac465f3..b3452259d6e0b 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -469,10 +469,17 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
+       int rc;
+       u32 ordinal;
+       unsigned long dur;
+-
+-      rc = tpm_tis_send_data(chip, buf, len);
+-      if (rc < 0)
+-              return rc;
++      unsigned int try;
++
++      for (try = 0; try < TPM_RETRY; try++) {
++              rc = tpm_tis_send_data(chip, buf, len);
++              if (rc >= 0)
++                      /* Data transfer done successfully */
++                      break;
++              else if (rc != -EIO)
++                      /* Data transfer failed, not recoverable */
++                      return rc;
++      }
+       /* go and do it */
+       rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO);
+-- 
+2.40.1
+
diff --git a/queue-5.15/usb-cdns3-put-the-cdns-set-active-part-outside-the-s.patch b/queue-5.15/usb-cdns3-put-the-cdns-set-active-part-outside-the-s.patch
new file mode 100644 (file)
index 0000000..6b08110
--- /dev/null
@@ -0,0 +1,143 @@
+From 291b17c9c2ed70386f7a6d6d73bf937f27c5df11 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 16 Jun 2023 10:19:51 +0800
+Subject: usb: cdns3: Put the cdns set active part outside the spin lock
+
+From: Xiaolei Wang <xiaolei.wang@windriver.com>
+
+[ Upstream commit 2319b9c87fe243327285f2fefd7374ffd75a65fc ]
+
+The device may be scheduled during the resume process,
+so this cannot appear in atomic operations. Since
+pm_runtime_set_active will resume suppliers, put set
+active outside the spin lock, which is only used to
+protect the struct cdns data structure, otherwise the
+kernel will report the following warning:
+
+  BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1163
+  in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 651, name: sh
+  preempt_count: 1, expected: 0
+  RCU nest depth: 0, expected: 0
+  CPU: 0 PID: 651 Comm: sh Tainted: G        WC         6.1.20 #1
+  Hardware name: Freescale i.MX8QM MEK (DT)
+  Call trace:
+    dump_backtrace.part.0+0xe0/0xf0
+    show_stack+0x18/0x30
+    dump_stack_lvl+0x64/0x80
+    dump_stack+0x1c/0x38
+    __might_resched+0x1fc/0x240
+    __might_sleep+0x68/0xc0
+    __pm_runtime_resume+0x9c/0xe0
+    rpm_get_suppliers+0x68/0x1b0
+    __pm_runtime_set_status+0x298/0x560
+    cdns_resume+0xb0/0x1c0
+    cdns3_controller_resume.isra.0+0x1e0/0x250
+    cdns3_plat_resume+0x28/0x40
+
+Signed-off-by: Xiaolei Wang <xiaolei.wang@windriver.com>
+Acked-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20230616021952.1025854-1-xiaolei.wang@windriver.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/cdns3/cdns3-plat.c |  3 ++-
+ drivers/usb/cdns3/cdnsp-pci.c  |  3 ++-
+ drivers/usb/cdns3/core.c       | 15 +++++++++++----
+ drivers/usb/cdns3/core.h       |  7 +++++--
+ 4 files changed, 20 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c
+index 4d0f027e5bd3a..9cb647203dcf2 100644
+--- a/drivers/usb/cdns3/cdns3-plat.c
++++ b/drivers/usb/cdns3/cdns3-plat.c
+@@ -256,9 +256,10 @@ static int cdns3_controller_resume(struct device *dev, pm_message_t msg)
+       cdns3_set_platform_suspend(cdns->dev, false, false);
+       spin_lock_irqsave(&cdns->lock, flags);
+-      cdns_resume(cdns, !PMSG_IS_AUTO(msg));
++      cdns_resume(cdns);
+       cdns->in_lpm = false;
+       spin_unlock_irqrestore(&cdns->lock, flags);
++      cdns_set_active(cdns, !PMSG_IS_AUTO(msg));
+       if (cdns->wakeup_pending) {
+               cdns->wakeup_pending = false;
+               enable_irq(cdns->wakeup_irq);
+diff --git a/drivers/usb/cdns3/cdnsp-pci.c b/drivers/usb/cdns3/cdnsp-pci.c
+index 29f433c5a6f3f..a85db23fa19f2 100644
+--- a/drivers/usb/cdns3/cdnsp-pci.c
++++ b/drivers/usb/cdns3/cdnsp-pci.c
+@@ -210,8 +210,9 @@ static int __maybe_unused cdnsp_pci_resume(struct device *dev)
+       int ret;
+       spin_lock_irqsave(&cdns->lock, flags);
+-      ret = cdns_resume(cdns, 1);
++      ret = cdns_resume(cdns);
+       spin_unlock_irqrestore(&cdns->lock, flags);
++      cdns_set_active(cdns, 1);
+       return ret;
+ }
+diff --git a/drivers/usb/cdns3/core.c b/drivers/usb/cdns3/core.c
+index dbcdf3b24b477..7b20d2d5c262e 100644
+--- a/drivers/usb/cdns3/core.c
++++ b/drivers/usb/cdns3/core.c
+@@ -522,9 +522,8 @@ int cdns_suspend(struct cdns *cdns)
+ }
+ EXPORT_SYMBOL_GPL(cdns_suspend);
+-int cdns_resume(struct cdns *cdns, u8 set_active)
++int cdns_resume(struct cdns *cdns)
+ {
+-      struct device *dev = cdns->dev;
+       enum usb_role real_role;
+       bool role_changed = false;
+       int ret = 0;
+@@ -556,15 +555,23 @@ int cdns_resume(struct cdns *cdns, u8 set_active)
+       if (cdns->roles[cdns->role]->resume)
+               cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns));
++      return 0;
++}
++EXPORT_SYMBOL_GPL(cdns_resume);
++
++void cdns_set_active(struct cdns *cdns, u8 set_active)
++{
++      struct device *dev = cdns->dev;
++
+       if (set_active) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+       }
+-      return 0;
++      return;
+ }
+-EXPORT_SYMBOL_GPL(cdns_resume);
++EXPORT_SYMBOL_GPL(cdns_set_active);
+ #endif /* CONFIG_PM_SLEEP */
+ MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>");
+diff --git a/drivers/usb/cdns3/core.h b/drivers/usb/cdns3/core.h
+index ab0cb68acd239..1b6631cdf5dec 100644
+--- a/drivers/usb/cdns3/core.h
++++ b/drivers/usb/cdns3/core.h
+@@ -125,10 +125,13 @@ int cdns_init(struct cdns *cdns);
+ int cdns_remove(struct cdns *cdns);
+ #ifdef CONFIG_PM_SLEEP
+-int cdns_resume(struct cdns *cdns, u8 set_active);
++int cdns_resume(struct cdns *cdns);
+ int cdns_suspend(struct cdns *cdns);
++void cdns_set_active(struct cdns *cdns, u8 set_active);
+ #else /* CONFIG_PM_SLEEP */
+-static inline int cdns_resume(struct cdns *cdns, u8 set_active)
++static inline int cdns_resume(struct cdns *cdns)
++{ return 0; }
++static inline int cdns_set_active(struct cdns *cdns, u8 set_active)
+ { return 0; }
+ static inline int cdns_suspend(struct cdns *cdns)
+ { return 0; }
+-- 
+2.40.1
+
diff --git a/queue-5.15/usb-ehci-add-workaround-for-chipidea-portsc.pec-bug.patch b/queue-5.15/usb-ehci-add-workaround-for-chipidea-portsc.pec-bug.patch
new file mode 100644 (file)
index 0000000..b223e64
--- /dev/null
@@ -0,0 +1,119 @@
+From 8aff0e03fc6684495129f13cfa21898c3c991bba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 9 Aug 2023 10:44:31 +0800
+Subject: usb: ehci: add workaround for chipidea PORTSC.PEC bug
+
+From: Xu Yang <xu.yang_2@nxp.com>
+
+[ Upstream commit dda4b60ed70bd670eefda081f70c0cb20bbeb1fa ]
+
+Some NXP processor using chipidea IP has a bug when frame babble is
+detected.
+
+As per 4.15.1.1.1 Serial Bus Babble:
+  A babble condition also exists if IN transaction is in progress at
+High-speed SOF2 point. This is called frame babble. The host controller
+must disable the port to which the frame babble is detected.
+
+The USB controller has disabled the port (PE cleared) and has asserted
+USBERRINT when frame babble is detected, but PEC is not asserted.
+Therefore, the SW isn't aware that port has been disabled. Then the
+SW keeps sending packets to this port, but all of the transfers will
+fail.
+
+This workaround will firstly assert PCD by SW when USBERRINT is detected
+and then judge whether port change has really occurred or not by polling
+roothub status. Because the PEC doesn't get asserted in our case, this
+patch will also assert it by SW when specific conditions are satisfied.
+
+Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
+Acked-by: Peter Chen <peter.chen@kernel.org>
+Link: https://lore.kernel.org/r/20230809024432.535160-1-xu.yang_2@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/host/ehci-hcd.c |  8 ++++++--
+ drivers/usb/host/ehci-hub.c | 10 +++++++++-
+ drivers/usb/host/ehci.h     | 10 ++++++++++
+ 3 files changed, 25 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 1440803216297..02044d45edded 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -755,10 +755,14 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+       /* normal [4.15.1.2] or error [4.15.1.1] completion */
+       if (likely ((status & (STS_INT|STS_ERR)) != 0)) {
+-              if (likely ((status & STS_ERR) == 0))
++              if (likely ((status & STS_ERR) == 0)) {
+                       INCR(ehci->stats.normal);
+-              else
++              } else {
++                      /* Force to check port status */
++                      if (ehci->has_ci_pec_bug)
++                              status |= STS_PCD;
+                       INCR(ehci->stats.error);
++              }
+               bh = 1;
+       }
+diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
+index c4f6a2559a987..0350c03dc97a1 100644
+--- a/drivers/usb/host/ehci-hub.c
++++ b/drivers/usb/host/ehci-hub.c
+@@ -674,7 +674,8 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
+               if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend)
+                               || (ehci->reset_done[i] && time_after_eq(
+-                                      jiffies, ehci->reset_done[i]))) {
++                                      jiffies, ehci->reset_done[i]))
++                              || ehci_has_ci_pec_bug(ehci, temp)) {
+                       if (i < 7)
+                           buf [0] |= 1 << (i + 1);
+                       else
+@@ -874,6 +875,13 @@ int ehci_hub_control(
+               if (temp & PORT_PEC)
+                       status |= USB_PORT_STAT_C_ENABLE << 16;
++              if (ehci_has_ci_pec_bug(ehci, temp)) {
++                      status |= USB_PORT_STAT_C_ENABLE << 16;
++                      ehci_info(ehci,
++                              "PE is cleared by HW port:%d PORTSC:%08x\n",
++                              wIndex + 1, temp);
++              }
++
+               if ((temp & PORT_OCC) && (!ignore_oc && !ehci->spurious_oc)){
+                       status |= USB_PORT_STAT_C_OVERCURRENT << 16;
+diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
+index fdd073cc053b8..9888ca5f5f36f 100644
+--- a/drivers/usb/host/ehci.h
++++ b/drivers/usb/host/ehci.h
+@@ -207,6 +207,7 @@ struct ehci_hcd {                  /* one per controller */
+       unsigned                has_fsl_port_bug:1; /* FreeScale */
+       unsigned                has_fsl_hs_errata:1;    /* Freescale HS quirk */
+       unsigned                has_fsl_susp_errata:1;  /* NXP SUSP quirk */
++      unsigned                has_ci_pec_bug:1;       /* ChipIdea PEC bug */
+       unsigned                big_endian_mmio:1;
+       unsigned                big_endian_desc:1;
+       unsigned                big_endian_capbase:1;
+@@ -706,6 +707,15 @@ ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
+  */
+ #define ehci_has_fsl_susp_errata(e)   ((e)->has_fsl_susp_errata)
++/*
++ * Some Freescale/NXP processors using ChipIdea IP have a bug in which
++ * disabling the port (PE is cleared) does not cause PEC to be asserted
++ * when frame babble is detected.
++ */
++#define ehci_has_ci_pec_bug(e, portsc) \
++      ((e)->has_ci_pec_bug && ((e)->command & CMD_PSE) \
++       && !(portsc & PORT_PEC) && !(portsc & PORT_PE))
++
+ /*
+  * While most USB host controllers implement their registers in
+  * little-endian format, a minority (celleb companion chip) implement
+-- 
+2.40.1
+
diff --git a/queue-5.15/usb-gadget-fsl_qe_udc-validate-endpoint-index-for-ch.patch b/queue-5.15/usb-gadget-fsl_qe_udc-validate-endpoint-index-for-ch.patch
new file mode 100644 (file)
index 0000000..f669b61
--- /dev/null
@@ -0,0 +1,37 @@
+From bbcaf4e578c3501723c298e2aeac36c5f68059f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 28 Jun 2023 16:15:11 +0800
+Subject: usb: gadget: fsl_qe_udc: validate endpoint index for ch9 udc
+
+From: Ma Ke <make_ruc2021@163.com>
+
+[ Upstream commit ce9daa2efc0872a9a68ea51dc8000df05893ef2e ]
+
+We should verify the bound of the array to assure that host
+may not manipulate the index to point past endpoint array.
+
+Signed-off-by: Ma Ke <make_ruc2021@163.com>
+Acked-by: Li Yang <leoyang.li@nxp.com>
+Link: https://lore.kernel.org/r/20230628081511.186850-1-make_ruc2021@163.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/gadget/udc/fsl_qe_udc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
+index 15db7a3868fe4..aff4050f96dd6 100644
+--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
++++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
+@@ -1956,6 +1956,8 @@ static void ch9getstatus(struct qe_udc *udc, u8 request_type, u16 value,
+       } else if ((request_type & USB_RECIP_MASK) == USB_RECIP_ENDPOINT) {
+               /* Get endpoint status */
+               int pipe = index & USB_ENDPOINT_NUMBER_MASK;
++              if (pipe >= USB_MAX_ENDPOINTS)
++                      goto stall;
+               struct qe_ep *target_ep = &udc->eps[pipe];
+               u16 usep;
+-- 
+2.40.1
+
diff --git a/queue-5.15/wifi-ath9k-fix-fortify-warnings.patch b/queue-5.15/wifi-ath9k-fix-fortify-warnings.patch
new file mode 100644 (file)
index 0000000..5f61296
--- /dev/null
@@ -0,0 +1,97 @@
+From 3ba5683d96edd6b9a405403a24d05e6373bce2fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 24 Jul 2023 13:11:07 +0300
+Subject: wifi: ath9k: fix fortify warnings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 810e41cebb6c6e394f2068f839e1a3fc745a5dcc ]
+
+When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y,
+I've noticed the following:
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘ath_tx_complete_aggr’ at drivers/net/wireless/ath/ath9k/xmit.c:556:4,
+    inlined from ‘ath_tx_process_buffer’ at drivers/net/wireless/ath/ath9k/xmit.c:773:3:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+  529 |                         __read_overflow2_field(q_size_field, size);
+      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘ath_tx_count_frames’ at drivers/net/wireless/ath/ath9k/xmit.c:473:3,
+    inlined from ‘ath_tx_complete_aggr’ at drivers/net/wireless/ath/ath9k/xmit.c:572:2,
+    inlined from ‘ath_tx_process_buffer’ at drivers/net/wireless/ath/ath9k/xmit.c:773:3:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+  529 |                         __read_overflow2_field(q_size_field, size);
+      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In both cases, the compiler complains on:
+
+memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
+
+which is the legal way to copy both 'ba_low' and following 'ba_high'
+members of 'struct ath_tx_status' at once (that is, issue one 8-byte
+'memcpy()' for two 4-byte fields). Since the fortification logic seems
+interprets this trick as an attempt to overread 4-byte 'ba_low', silence
+relevant warnings by using the convenient 'struct_group()' quirk.
+
+Suggested-by: Johannes Berg <johannes@sipsolutions.net>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230620080855.396851-2-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath9k/mac.h  | 6 ++++--
+ drivers/net/wireless/ath/ath9k/xmit.c | 4 ++--
+ 2 files changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
+index fd6aa49adadfe..9b00e77a6fc3c 100644
+--- a/drivers/net/wireless/ath/ath9k/mac.h
++++ b/drivers/net/wireless/ath/ath9k/mac.h
+@@ -113,8 +113,10 @@ struct ath_tx_status {
+       u8 qid;
+       u16 desc_id;
+       u8 tid;
+-      u32 ba_low;
+-      u32 ba_high;
++      struct_group(ba,
++              u32 ba_low;
++              u32 ba_high;
++      );
+       u32 evm0;
+       u32 evm1;
+       u32 evm2;
+diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
+index 6555abf02f18b..84c68aefc171a 100644
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -421,7 +421,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
+       isaggr = bf_isaggr(bf);
+       if (isaggr) {
+               seq_st = ts->ts_seqnum;
+-              memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
++              memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
+       }
+       while (bf) {
+@@ -504,7 +504,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
+       if (isaggr && txok) {
+               if (ts->ts_flags & ATH9K_TX_BA) {
+                       seq_st = ts->ts_seqnum;
+-                      memcpy(ba, &ts->ba_low, WME_BA_BMP_SIZE >> 3);
++                      memcpy(ba, &ts->ba, WME_BA_BMP_SIZE >> 3);
+               } else {
+                       /*
+                        * AR5416 can become deaf/mute when BA
+-- 
+2.40.1
+
diff --git a/queue-5.15/wifi-ath9k-fix-printk-specifier.patch b/queue-5.15/wifi-ath9k-fix-printk-specifier.patch
new file mode 100644 (file)
index 0000000..40b824e
--- /dev/null
@@ -0,0 +1,68 @@
+From 5564f030ec93576017186a4da25830cb95e0c92c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 23 Jul 2023 12:04:02 +0800
+Subject: wifi: ath9k: fix printk specifier
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dongliang Mu <dzm91@hust.edu.cn>
+
+[ Upstream commit 061115fbfb2ce5870c9a004d68dc63138c07c782 ]
+
+Smatch reports:
+
+ath_pci_probe() warn: argument 4 to %lx specifier is cast from pointer
+ath_ahb_probe() warn: argument 4 to %lx specifier is cast from pointer
+
+Fix it by modifying %lx to %p in the printk format string.
+
+Note that with this change, the pointer address will be printed as a
+hashed value by default. This is appropriate because the kernel
+should not leak kernel pointers to user space in an informational
+message. If someone wants to see the real address for debugging
+purposes, this can be achieved with the no_hash_pointers kernel option.
+
+Signed-off-by: Dongliang Mu <dzm91@hust.edu.cn>
+Acked-by: Toke Høiland-Jørgensen <toke@toke.dk>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230723040403.296723-1-dzm91@hust.edu.cn
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/ath9k/ahb.c | 4 ++--
+ drivers/net/wireless/ath/ath9k/pci.c | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
+index cdefb8e2daf14..05fb76a4e144e 100644
+--- a/drivers/net/wireless/ath/ath9k/ahb.c
++++ b/drivers/net/wireless/ath/ath9k/ahb.c
+@@ -136,8 +136,8 @@ static int ath_ahb_probe(struct platform_device *pdev)
+       ah = sc->sc_ah;
+       ath9k_hw_name(ah, hw_name, sizeof(hw_name));
+-      wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+-                 hw_name, (unsigned long)mem, irq);
++      wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
++                 hw_name, mem, irq);
+       return 0;
+diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
+index a074e23013c58..f0e3901e8182a 100644
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -988,8 +988,8 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+       sc->sc_ah->msi_reg = 0;
+       ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
+-      wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+-                 hw_name, (unsigned long)sc->mem, pdev->irq);
++      wiphy_info(hw->wiphy, "%s mem=0x%p, irq=%d\n",
++                 hw_name, sc->mem, pdev->irq);
+       return 0;
+-- 
+2.40.1
+
diff --git a/queue-5.15/wifi-mac80211-check-s1g-action-frame-size.patch b/queue-5.15/wifi-mac80211-check-s1g-action-frame-size.patch
new file mode 100644 (file)
index 0000000..8d4975f
--- /dev/null
@@ -0,0 +1,37 @@
+From 130cd99b4ccd465c5cac6c5acb28a94c1f0d20f6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 17:51:05 +0200
+Subject: wifi: mac80211: check S1G action frame size
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 19e4a47ee74718a22e963e8a647c8c3bfe8bb05c ]
+
+Before checking the action code, check that it even
+exists in the frame.
+
+Reported-by: syzbot+be9c824e6f269d608288@syzkaller.appspotmail.com
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/mac80211/rx.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index 175ead6b19cb4..26943c93f14c4 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -3557,6 +3557,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
+                       break;
+               goto queue;
+       case WLAN_CATEGORY_S1G:
++              if (len < offsetofend(typeof(*mgmt),
++                                    u.action.u.s1g.action_code))
++                      break;
++
+               switch (mgmt->u.action.u.s1g.action_code) {
+               case WLAN_S1G_TWT_SETUP:
+               case WLAN_S1G_TWT_TEARDOWN:
+-- 
+2.40.1
+
diff --git a/queue-5.15/wifi-mac80211_hwsim-drop-short-frames.patch b/queue-5.15/wifi-mac80211_hwsim-drop-short-frames.patch
new file mode 100644 (file)
index 0000000..ab62758
--- /dev/null
@@ -0,0 +1,49 @@
+From 981c077dbc0a164dbc34d85fb21cfaee2f0de3d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Aug 2023 21:28:01 +0200
+Subject: wifi: mac80211_hwsim: drop short frames
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit fba360a047d5eeeb9d4b7c3a9b1c8308980ce9a6 ]
+
+While technically some control frames like ACK are shorter and
+end after Address 1, such frames shouldn't be forwarded through
+wmediumd or similar userspace, so require the full 3-address
+header to avoid accessing invalid memory if shorter frames are
+passed in.
+
+Reported-by: syzbot+b2645b5bf1512b81fa22@syzkaller.appspotmail.com
+Reviewed-by: Jeff Johnson <quic_jjohnson@quicinc.com>
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/mac80211_hwsim.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
+index c3c3b5aa87b0d..6eb3c845640bd 100644
+--- a/drivers/net/wireless/mac80211_hwsim.c
++++ b/drivers/net/wireless/mac80211_hwsim.c
+@@ -3693,14 +3693,15 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
+       frame_data_len = nla_len(info->attrs[HWSIM_ATTR_FRAME]);
+       frame_data = (void *)nla_data(info->attrs[HWSIM_ATTR_FRAME]);
++      if (frame_data_len < sizeof(struct ieee80211_hdr_3addr) ||
++          frame_data_len > IEEE80211_MAX_DATA_LEN)
++              goto err;
++
+       /* Allocate new skb here */
+       skb = alloc_skb(frame_data_len, GFP_KERNEL);
+       if (skb == NULL)
+               goto err;
+-      if (frame_data_len > IEEE80211_MAX_DATA_LEN)
+-              goto err;
+-
+       /* Copy the data */
+       skb_put_data(skb, frame_data, frame_data_len);
+-- 
+2.40.1
+
diff --git a/queue-5.15/wifi-mwifiex-fix-fortify-warning.patch b/queue-5.15/wifi-mwifiex-fix-fortify-warning.patch
new file mode 100644 (file)
index 0000000..59afc4f
--- /dev/null
@@ -0,0 +1,87 @@
+From 136fbf5b961de47165d42542c6fac9df68037ae7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 29 Jun 2023 11:51:01 +0300
+Subject: wifi: mwifiex: fix fortify warning
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit dcce94b80a954a8968ff29fafcfb066d6197fa9a ]
+
+When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y,
+I've noticed the following:
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘mwifiex_construct_tdls_action_frame’ at drivers/net/wireless/marvell/mwifiex/tdls.c:765:3,
+    inlined from ‘mwifiex_send_tdls_action_frame’ at drivers/net/wireless/marvell/mwifiex/tdls.c:856:6:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+  529 |                         __read_overflow2_field(q_size_field, size);
+      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The compiler actually complains on:
+
+memmove(pos + ETH_ALEN, &mgmt->u.action.category,
+       sizeof(mgmt->u.action.u.tdls_discover_resp));
+
+and it happens because the fortification logic interprets this
+as an attempt to overread 1-byte 'u.action.category' member of
+'struct ieee80211_mgmt'. To silence this warning, it's enough
+to pass an address of 'u.action' itself instead of an address
+of its first member.
+
+This also fixes an improper usage of 'sizeof()'. Since 'skb' is
+extended with 'sizeof(mgmt->u.action.u.tdls_discover_resp) + 1'
+bytes (where 1 is actually 'sizeof(mgmt->u.action.category)'),
+I assume that the same number of bytes should be copied.
+
+Suggested-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Reviewed-by: Brian Norris <briannorris@chromium.org>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230629085115.180499-2-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/marvell/mwifiex/tdls.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/wireless/marvell/mwifiex/tdls.c b/drivers/net/wireless/marvell/mwifiex/tdls.c
+index 97bb87c3676bb..6c60621b6cccb 100644
+--- a/drivers/net/wireless/marvell/mwifiex/tdls.c
++++ b/drivers/net/wireless/marvell/mwifiex/tdls.c
+@@ -735,6 +735,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+       int ret;
+       u16 capab;
+       struct ieee80211_ht_cap *ht_cap;
++      unsigned int extra;
+       u8 radio, *pos;
+       capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap;
+@@ -753,7 +754,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+       switch (action_code) {
+       case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+-              skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1);
++              /* See the layout of 'struct ieee80211_mgmt'. */
++              extra = sizeof(mgmt->u.action.u.tdls_discover_resp) +
++                      sizeof(mgmt->u.action.category);
++              skb_put(skb, extra);
+               mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+               mgmt->u.action.u.tdls_discover_resp.action_code =
+                                             WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+@@ -762,8 +766,7 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+               mgmt->u.action.u.tdls_discover_resp.capability =
+                                                            cpu_to_le16(capab);
+               /* move back for addr4 */
+-              memmove(pos + ETH_ALEN, &mgmt->u.action.category,
+-                      sizeof(mgmt->u.action.u.tdls_discover_resp));
++              memmove(pos + ETH_ALEN, &mgmt->u.action, extra);
+               /* init address 4 */
+               eth_broadcast_addr(pos);
+-- 
+2.40.1
+
diff --git a/queue-5.15/wifi-wil6210-fix-fortify-warnings.patch b/queue-5.15/wifi-wil6210-fix-fortify-warnings.patch
new file mode 100644 (file)
index 0000000..7388249
--- /dev/null
@@ -0,0 +1,127 @@
+From 3f4a013fc1640a99e74f3ab8be5dc0b819a922d2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Jun 2023 12:36:55 +0300
+Subject: wifi: wil6210: fix fortify warnings
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit 1ad8237e971630c66a1a6194491e0837b64d00e0 ]
+
+When compiling with gcc 13.1 and CONFIG_FORTIFY_SOURCE=y,
+I've noticed the following:
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘wil_rx_crypto_check_edma’ at drivers/net/wireless/ath/wil6210/txrx_edma.c:566:2:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+  529 |                         __read_overflow2_field(q_size_field, size);
+      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+where the compiler complains on:
+
+const u8 *pn;
+...
+pn = (u8 *)&st->ext.pn_15_0;
+...
+memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN);
+
+and:
+
+In function ‘fortify_memcpy_chk’,
+    inlined from ‘wil_rx_crypto_check’ at drivers/net/wireless/ath/wil6210/txrx.c:684:2:
+./include/linux/fortify-string.h:529:25: warning: call to ‘__read_overflow2_field’
+declared with attribute warning: detected read beyond size of field (2nd parameter);
+maybe use struct_group()? [-Wattribute-warning]
+  529 |                         __read_overflow2_field(q_size_field, size);
+      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+where the compiler complains on:
+
+const u8 *pn = (u8 *)&d->mac.pn_15_0;
+...
+memcpy(cc->pn, pn, IEEE80211_GCMP_PN_LEN);
+
+In both cases, the fortification logic interprets 'memcpy()' as 6-byte
+overread of 2-byte field 'pn_15_0' of 'struct wil_rx_status_extension'
+and 'pn_15_0' of 'struct vring_rx_mac', respectively. To silence
+these warnings, last two fields of the aforementioned structures
+are grouped using 'struct_group_attr(pn, __packed' quirk.
+
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230621093711.80118-1-dmantipov@yandex.ru
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/ath/wil6210/txrx.c      | 2 +-
+ drivers/net/wireless/ath/wil6210/txrx.h      | 6 ++++--
+ drivers/net/wireless/ath/wil6210/txrx_edma.c | 2 +-
+ drivers/net/wireless/ath/wil6210/txrx_edma.h | 6 ++++--
+ 4 files changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
+index cc830c795b33c..5b2de4f3fa0bd 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx.c
++++ b/drivers/net/wireless/ath/wil6210/txrx.c
+@@ -666,7 +666,7 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
+       struct wil_tid_crypto_rx *c = mc ? &s->group_crypto_rx :
+                                     &s->tid_crypto_rx[tid];
+       struct wil_tid_crypto_rx_single *cc = &c->key_id[key_id];
+-      const u8 *pn = (u8 *)&d->mac.pn_15_0;
++      const u8 *pn = (u8 *)&d->mac.pn;
+       if (!cc->key_set) {
+               wil_err_ratelimited(wil,
+diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
+index 1f4c8ec75be87..0f6f6b62bfc9a 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx.h
++++ b/drivers/net/wireless/ath/wil6210/txrx.h
+@@ -343,8 +343,10 @@ struct vring_rx_mac {
+       u32 d0;
+       u32 d1;
+       u16 w4;
+-      u16 pn_15_0;
+-      u32 pn_47_16;
++      struct_group_attr(pn, __packed,
++              u16 pn_15_0;
++              u32 pn_47_16;
++      );
+ } __packed;
+ /* Rx descriptor - DMA part
+diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.c b/drivers/net/wireless/ath/wil6210/txrx_edma.c
+index 201c8c35e0c9e..1ba1f21ebea26 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx_edma.c
++++ b/drivers/net/wireless/ath/wil6210/txrx_edma.c
+@@ -548,7 +548,7 @@ static int wil_rx_crypto_check_edma(struct wil6210_priv *wil,
+       s = &wil->sta[cid];
+       c = mc ? &s->group_crypto_rx : &s->tid_crypto_rx[tid];
+       cc = &c->key_id[key_id];
+-      pn = (u8 *)&st->ext.pn_15_0;
++      pn = (u8 *)&st->ext.pn;
+       if (!cc->key_set) {
+               wil_err_ratelimited(wil,
+diff --git a/drivers/net/wireless/ath/wil6210/txrx_edma.h b/drivers/net/wireless/ath/wil6210/txrx_edma.h
+index c736f7413a35f..ee90e225bb050 100644
+--- a/drivers/net/wireless/ath/wil6210/txrx_edma.h
++++ b/drivers/net/wireless/ath/wil6210/txrx_edma.h
+@@ -330,8 +330,10 @@ struct wil_rx_status_extension {
+       u32 d0;
+       u32 d1;
+       __le16 seq_num; /* only lower 12 bits */
+-      u16 pn_15_0;
+-      u32 pn_47_16;
++      struct_group_attr(pn, __packed,
++              u16 pn_15_0;
++              u32 pn_47_16;
++      );
+ } __packed;
+ struct wil_rx_status_extended {
+-- 
+2.40.1
+
diff --git a/queue-5.15/x86-boot-compressed-reserve-more-memory-for-page-tab.patch b/queue-5.15/x86-boot-compressed-reserve-more-memory-for-page-tab.patch
new file mode 100644 (file)
index 0000000..0d1478b
--- /dev/null
@@ -0,0 +1,123 @@
+From 8bacc9ae37ba50885b2e1c09203dbdea747cf1e8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Sep 2023 10:02:21 +0300
+Subject: x86/boot/compressed: Reserve more memory for page tables
+
+From: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+
+[ Upstream commit f530ee95b72e77b09c141c4b1a4b94d1199ffbd9 ]
+
+The decompressor has a hard limit on the number of page tables it can
+allocate. This limit is defined at compile-time and will cause boot
+failure if it is reached.
+
+The kernel is very strict and calculates the limit precisely for the
+worst-case scenario based on the current configuration. However, it is
+easy to forget to adjust the limit when a new use-case arises. The
+worst-case scenario is rarely encountered during sanity checks.
+
+In the case of enabling 5-level paging, a use-case was overlooked. The
+limit needs to be increased by one to accommodate the additional level.
+This oversight went unnoticed until Aaron attempted to run the kernel
+via kexec with 5-level paging and unaccepted memory enabled.
+
+Update wost-case calculations to include 5-level paging.
+
+To address this issue, let's allocate some extra space for page tables.
+128K should be sufficient for any use-case. The logic can be simplified
+by using a single value for all kernel configurations.
+
+[ Also add a warning, should this memory run low - by Dave Hansen. ]
+
+Fixes: 34bbb0009f3b ("x86/boot/compressed: Enable 5-level paging during decompression stage")
+Reported-by: Aaron Lu <aaron.lu@intel.com>
+Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Link: https://lore.kernel.org/r/20230915070221.10266-1-kirill.shutemov@linux.intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/boot/compressed/ident_map_64.c |  8 +++++
+ arch/x86/include/asm/boot.h             | 45 +++++++++++++++++--------
+ 2 files changed, 39 insertions(+), 14 deletions(-)
+
+diff --git a/arch/x86/boot/compressed/ident_map_64.c b/arch/x86/boot/compressed/ident_map_64.c
+index f7213d0943b82..575d881ff86e2 100644
+--- a/arch/x86/boot/compressed/ident_map_64.c
++++ b/arch/x86/boot/compressed/ident_map_64.c
+@@ -67,6 +67,14 @@ static void *alloc_pgt_page(void *context)
+               return NULL;
+       }
++      /* Consumed more tables than expected? */
++      if (pages->pgt_buf_offset == BOOT_PGT_SIZE_WARN) {
++              debug_putstr("pgt_buf running low in " __FILE__ "\n");
++              debug_putstr("Need to raise BOOT_PGT_SIZE?\n");
++              debug_putaddr(pages->pgt_buf_offset);
++              debug_putaddr(pages->pgt_buf_size);
++      }
++
+       entry = pages->pgt_buf + pages->pgt_buf_offset;
+       pages->pgt_buf_offset += PAGE_SIZE;
+diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h
+index 9191280d9ea31..215d37f7dde8a 100644
+--- a/arch/x86/include/asm/boot.h
++++ b/arch/x86/include/asm/boot.h
+@@ -40,23 +40,40 @@
+ #ifdef CONFIG_X86_64
+ # define BOOT_STACK_SIZE      0x4000
++/*
++ * Used by decompressor's startup_32() to allocate page tables for identity
++ * mapping of the 4G of RAM in 4-level paging mode:
++ * - 1 level4 table;
++ * - 1 level3 table;
++ * - 4 level2 table that maps everything with 2M pages;
++ *
++ * The additional level5 table needed for 5-level paging is allocated from
++ * trampoline_32bit memory.
++ */
+ # define BOOT_INIT_PGT_SIZE   (6*4096)
+-# ifdef CONFIG_RANDOMIZE_BASE
++
+ /*
+- * Assuming all cross the 512GB boundary:
+- * 1 page for level4
+- * (2+2)*4 pages for kernel, param, cmd_line, and randomized kernel
+- * 2 pages for first 2M (video RAM: CONFIG_X86_VERBOSE_BOOTUP).
+- * Total is 19 pages.
++ * Total number of page tables kernel_add_identity_map() can allocate,
++ * including page tables consumed by startup_32().
++ *
++ * Worst-case scenario:
++ *  - 5-level paging needs 1 level5 table;
++ *  - KASLR needs to map kernel, boot_params, cmdline and randomized kernel,
++ *    assuming all of them cross 256T boundary:
++ *    + 4*2 level4 table;
++ *    + 4*2 level3 table;
++ *    + 4*2 level2 table;
++ *  - X86_VERBOSE_BOOTUP needs to map the first 2M (video RAM):
++ *    + 1 level4 table;
++ *    + 1 level3 table;
++ *    + 1 level2 table;
++ * Total: 28 tables
++ *
++ * Add 4 spare table in case decompressor touches anything beyond what is
++ * accounted above. Warn if it happens.
+  */
+-#  ifdef CONFIG_X86_VERBOSE_BOOTUP
+-#   define BOOT_PGT_SIZE      (19*4096)
+-#  else /* !CONFIG_X86_VERBOSE_BOOTUP */
+-#   define BOOT_PGT_SIZE      (17*4096)
+-#  endif
+-# else /* !CONFIG_RANDOMIZE_BASE */
+-#  define BOOT_PGT_SIZE               BOOT_INIT_PGT_SIZE
+-# endif
++# define BOOT_PGT_SIZE_WARN   (28*4096)
++# define BOOT_PGT_SIZE                (32*4096)
+ #else /* !CONFIG_X86_64 */
+ # define BOOT_STACK_SIZE      0x1000
+-- 
+2.40.1
+
diff --git a/queue-5.15/x86-purgatory-remove-lto-flags.patch b/queue-5.15/x86-purgatory-remove-lto-flags.patch
new file mode 100644 (file)
index 0000000..b455318
--- /dev/null
@@ -0,0 +1,63 @@
+From c7114e3b4cb26973bc083984b73f4aa580ef946e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Sep 2023 10:01:38 -0700
+Subject: x86/purgatory: Remove LTO flags
+
+From: Song Liu <song@kernel.org>
+
+[ Upstream commit 75b2f7e4c9e0fd750a5a27ca9736d1daa7a3762a ]
+
+-flto* implies -ffunction-sections. With LTO enabled, ld.lld generates
+multiple .text sections for purgatory.ro:
+
+  $ readelf -S purgatory.ro  | grep " .text"
+    [ 1] .text             PROGBITS         0000000000000000  00000040
+    [ 7] .text.purgatory   PROGBITS         0000000000000000  000020e0
+    [ 9] .text.warn        PROGBITS         0000000000000000  000021c0
+    [13] .text.sha256_upda PROGBITS         0000000000000000  000022f0
+    [15] .text.sha224_upda PROGBITS         0000000000000000  00002be0
+    [17] .text.sha256_fina PROGBITS         0000000000000000  00002bf0
+    [19] .text.sha224_fina PROGBITS         0000000000000000  00002cc0
+
+This causes WARNING from kexec_purgatory_setup_sechdrs():
+
+  WARNING: CPU: 26 PID: 110894 at kernel/kexec_file.c:919
+  kexec_load_purgatory+0x37f/0x390
+
+Fix this by disabling LTO for purgatory.
+
+[ AFAICT, x86 is the only arch that supports LTO and purgatory. ]
+
+We could also fix this with an explicit linker script to rejoin .text.*
+sections back into .text. However, given the benefit of LTOing purgatory
+is small, simply disable the production of more .text.* sections for now.
+
+Fixes: b33fff07e3e3 ("x86, build: allow LTO to be selected")
+Signed-off-by: Song Liu <song@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Link: https://lore.kernel.org/r/20230914170138.995606-1-song@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/purgatory/Makefile | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/arch/x86/purgatory/Makefile b/arch/x86/purgatory/Makefile
+index dc0b91c1db04b..7a7701d1e18d0 100644
+--- a/arch/x86/purgatory/Makefile
++++ b/arch/x86/purgatory/Makefile
+@@ -19,6 +19,10 @@ CFLAGS_sha256.o := -D__DISABLE_EXPORTS
+ # optimization flags.
+ KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%,$(KBUILD_CFLAGS))
++# When LTO is enabled, llvm emits many text sections, which is not supported
++# by kexec. Remove -flto=* flags.
++KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO),$(KBUILD_CFLAGS))
++
+ # When linking purgatory.ro with -r unresolved symbols are not checked,
+ # also link a purgatory.chk binary without -r to check for unresolved symbols.
+ PURGATORY_LDFLAGS := -e purgatory_start -nostdlib -z nodefaultlib
+-- 
+2.40.1
+