From e98d7973451ba7333825888f010fa52c027fe8cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 3 Nov 2020 15:44:38 +0100 Subject: [PATCH] 5.4-stable patches added patches: acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch acpi-extlog-check-for-rdmsr-failure.patch acpi-video-use-acpi-backlight-for-hp-635-notebook.patch btrfs-cleanup-cow-block-on-error.patch btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch btrfs-improve-device-scanning-messages.patch btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch btrfs-reschedule-if-necessary-when-logging-directory-items.patch btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch leds-bcm6328-bcm6358-use-devres-led-registering-function.patch media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch nfs-fix-nfs_path-in-case-of-a-rename-retry.patch nfsd-add-missing-nfsv2-.pc_func-methods.patch nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch powerpc-drmem-make-lmb_size-64-bit.patch powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch powerpc-memhotplug-make-lmb-size-64bit.patch powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch powerpc-rtas-restrict-rtas-requests-from-userspace.patch powerpc-warn-about-use-of-smt_snooze_delay.patch s390-stp-add-locking-to-sysfs-functions.patch scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch udf-fix-memory-leak-when-mounting.patch usb-cdc-acm-fix-cooldown-mechanism.patch usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch usb-dwc3-gadget-check-mps-of-the-request-length.patch usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch vt-keyboard-extend-func_buf_lock-to-readers.patch vt-keyboard-simplify-vt_kdgkbsent.patch w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch --- ...ate-changes-when-input-device-closed.patch | 88 +++ ...r-_psd-table-setting-on-new-amd-cpus.patch | 37 + ...llow-debugging-when-acpi-is-disabled.patch | 68 ++ ...keup-check-from-acpi_ec_dispatch_gpe.patch | 36 + ...ec-work-unconditionally-after-wakeup.patch | 46 ++ .../acpi-extlog-check-for-rdmsr-failure.patch | 42 ++ ...e-acpi-backlight-for-hp-635-notebook.patch | 42 ++ .../btrfs-cleanup-cow-block-on-error.patch | 135 ++++ ...e-after-free-after-removing-a-device.patch | 678 ++++++++++++++++++ ...ad-extent-after-failure-to-create-it.patch | 139 ++++ ...rfs-improve-device-scanning-messages.patch | 59 ++ ...p-metadata-reserve-for-delayed-inode.patch | 66 ++ ...cessary-when-logging-directory-items.patch | 111 +++ ...ng-inodes-when-processing-references.patch | 273 +++++++ ...h-after-orphanization-of-a-directory.patch | 244 +++++++ ...ert-caused-by-legacy-btrfs-root-item.patch | 102 +++ ...e-number-of-chunk-stripes-and-parity.patch | 64 ++ ...cate-clone_roots-in-btrfs_ioctl_send.patch | 37 + ...780-fix-race-in-jz4780_dma_tx_status.patch | 57 ++ ...rkarounds-when-running-as-a-guest-os.patch | 55 ++ ...atomic-gpio-with-sleeping-gpio-chips.patch | 57 ++ ...age-buffers-in-block_write_full_page.patch | 94 +++ ...wacom_wac_pen_report-for-pad-battery.patch | 61 ++ ...adc-fix-leak-of-device-node-iterator.patch | 98 +++ ...2-fix-alignment-issue-with-timestamp.patch | 75 ++ ...8-fix-alignment-issue-with-timestamp.patch | 87 +++ ...tamp-alignment-and-prevent-data-leak.patch | 60 ++ ...tamp-alignment-and-prevent-data-leak.patch | 94 +++ ...-use-devres-led-registering-function.patch | 53 ++ ..._fixup_xu_info-not-having-any-effect.patch | 65 ++ ...ion-for-firmware-working-memory-area.patch | 140 ++++ ...x-nfs_path-in-case-of-a-rename-retry.patch | 58 ++ ...d-add-missing-nfsv2-.pc_func-methods.patch | 72 ++ ...d-updates-after-close-open_downgrade.patch | 231 ++++++ ..._supp_fence_ops-4.2-exchange_id-flag.patch | 71 ++ ...orts-for-d3-if-power-managed-by-acpi.patch | 65 ++ ...state-checks-in-rpm_get-put_supplier.patch | 84 +++ .../powerpc-drmem-make-lmb_size-64-bit.patch | 45 ++ ...with-p9n-dd2.1-vsx-ci-load-emulation.patch | 53 ++ ...werpc-memhotplug-make-lmb-size-64bit.patch | 119 +++ ...low_sleep_handler-with-kuap-and-kuep.patch | 56 ++ ...hile-processing-opal-error-log-event.patch | 128 ++++ ...estrict-rtas-requests-from-userspace.patch | 264 +++++++ ...c-warn-about-use-of-smt_snooze_delay.patch | 104 +++ ...0-stp-add-locking-to-sysfs-functions.patch | 236 ++++++ ...nter-dereferences-in-mptscsih_remove.patch | 77 ++ ...crash-on-session-cleanup-with-unload.patch | 49 ++ queue-5.4/series | 68 ++ ...memory-leaks-while-iterating-entries.patch | 33 + ...ion-mount-options-in-remount-process.patch | 55 ++ ...dumping-authentication-mount-options.patch | 62 ++ ...re-to-not-dirty-twice-for-auth-nodes.patch | 46 ++ ...tion-resource-in-error-handling-path.patch | 65 ++ ...memory-leaks-while-iterating-entries.patch | 107 +++ .../udf-fix-memory-leak-when-mounting.patch | 83 +++ .../usb-cdc-acm-fix-cooldown-mechanism.patch | 126 ++++ ...phy-cleanup-for-probe-error-handling.patch | 42 ++ ...rigger-runtime-pm-when-remove-driver.patch | 106 +++ ...wc3-ep0-fix-zlp-for-out-ep0-requests.patch | 63 ++ ...dget-check-mps-of-the-request-length.patch | 43 ++ ..._transfer-before-clear_stall-command.patch | 145 ++++ ...e-pending-requests-after-clear_stall.patch | 66 ++ ...lize-dsm-method-for-pm-functionality.patch | 40 ++ ...h-dr-of-check-return-of-dma_set_mask.patch | 42 ++ ...-hard_reset_count-for-any-disconnect.patch | 99 +++ ...und-for-s3-issue-on-amd-snps-3.0-xhc.patch | 81 +++ ...oard-extend-func_buf_lock-to-readers.patch | 94 +++ .../vt-keyboard-simplify-vt_kdgkbsent.patch | 73 ++ ...olution-problem-leading-to-bus-error.patch | 90 +++ 69 files changed, 6604 insertions(+) create mode 100644 queue-5.4/acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch create mode 100644 queue-5.4/acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch create mode 100644 queue-5.4/acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch create mode 100644 queue-5.4/acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch create mode 100644 queue-5.4/acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch create mode 100644 queue-5.4/acpi-extlog-check-for-rdmsr-failure.patch create mode 100644 queue-5.4/acpi-video-use-acpi-backlight-for-hp-635-notebook.patch create mode 100644 queue-5.4/btrfs-cleanup-cow-block-on-error.patch create mode 100644 queue-5.4/btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch create mode 100644 queue-5.4/btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch create mode 100644 queue-5.4/btrfs-improve-device-scanning-messages.patch create mode 100644 queue-5.4/btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch create mode 100644 queue-5.4/btrfs-reschedule-if-necessary-when-logging-directory-items.patch create mode 100644 queue-5.4/btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch create mode 100644 queue-5.4/btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch create mode 100644 queue-5.4/btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch create mode 100644 queue-5.4/btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch create mode 100644 queue-5.4/btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch create mode 100644 queue-5.4/dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch create mode 100644 queue-5.4/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch create mode 100644 queue-5.4/extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch create mode 100644 queue-5.4/fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch create mode 100644 queue-5.4/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch create mode 100644 queue-5.4/iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch create mode 100644 queue-5.4/iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch create mode 100644 queue-5.4/iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch create mode 100644 queue-5.4/iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch create mode 100644 queue-5.4/iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch create mode 100644 queue-5.4/leds-bcm6328-bcm6358-use-devres-led-registering-function.patch create mode 100644 queue-5.4/media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch create mode 100644 queue-5.4/mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch create mode 100644 queue-5.4/nfs-fix-nfs_path-in-case-of-a-rename-retry.patch create mode 100644 queue-5.4/nfsd-add-missing-nfsv2-.pc_func-methods.patch create mode 100644 queue-5.4/nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch create mode 100644 queue-5.4/nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch create mode 100644 queue-5.4/pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch create mode 100644 queue-5.4/pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch create mode 100644 queue-5.4/powerpc-drmem-make-lmb_size-64-bit.patch create mode 100644 queue-5.4/powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch create mode 100644 queue-5.4/powerpc-memhotplug-make-lmb-size-64bit.patch create mode 100644 queue-5.4/powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch create mode 100644 queue-5.4/powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch create mode 100644 queue-5.4/powerpc-rtas-restrict-rtas-requests-from-userspace.patch create mode 100644 queue-5.4/powerpc-warn-about-use-of-smt_snooze_delay.patch create mode 100644 queue-5.4/s390-stp-add-locking-to-sysfs-functions.patch create mode 100644 queue-5.4/scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch create mode 100644 queue-5.4/scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch create mode 100644 queue-5.4/ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch create mode 100644 queue-5.4/ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch create mode 100644 queue-5.4/ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch create mode 100644 queue-5.4/ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch create mode 100644 queue-5.4/ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch create mode 100644 queue-5.4/ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch create mode 100644 queue-5.4/udf-fix-memory-leak-when-mounting.patch create mode 100644 queue-5.4/usb-cdc-acm-fix-cooldown-mechanism.patch create mode 100644 queue-5.4/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch create mode 100644 queue-5.4/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch create mode 100644 queue-5.4/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch create mode 100644 queue-5.4/usb-dwc3-gadget-check-mps-of-the-request-length.patch create mode 100644 queue-5.4/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch create mode 100644 queue-5.4/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch create mode 100644 queue-5.4/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch create mode 100644 queue-5.4/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch create mode 100644 queue-5.4/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch create mode 100644 queue-5.4/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch create mode 100644 queue-5.4/vt-keyboard-extend-func_buf_lock-to-readers.patch create mode 100644 queue-5.4/vt-keyboard-simplify-vt_kdgkbsent.patch create mode 100644 queue-5.4/w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch diff --git a/queue-5.4/acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch b/queue-5.4/acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch new file mode 100644 index 00000000000..7df61762ee2 --- /dev/null +++ b/queue-5.4/acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch @@ -0,0 +1,88 @@ +From 21988a8e51479ceffe7b0568b170effabb708dfe Mon Sep 17 00:00:00 2001 +From: "dmitry.torokhov@gmail.com" +Date: Sun, 4 Oct 2020 22:11:25 -0700 +Subject: ACPI: button: fix handling lid state changes when input device closed + +From: dmitry.torokhov@gmail.com + +commit 21988a8e51479ceffe7b0568b170effabb708dfe upstream. + +The original intent of 84d3f6b76447 was to delay evaluating lid state until +all drivers have been loaded, with input device being opened from userspace +serving as a signal for this condition. Let's ensure that state updates +happen even if userspace closed (or in the future inhibited) input device. + +Note that if we go through suspend/resume cycle we assume the system has +been fully initialized even if LID input device has not been opened yet. + +This has a side-effect of fixing access to input->users outside of +input->mutex protections by the way of eliminating said accesses and using +driver private flag. + +Fixes: 84d3f6b76447 ("ACPI / button: Delay acpi_lid_initialize_state() until first user space open") +Signed-off-by: Dmitry Torokhov +Reviewed-by: Hans de Goede +Cc: 4.15+ # 4.15+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/button.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/acpi/button.c ++++ b/drivers/acpi/button.c +@@ -136,6 +136,7 @@ struct acpi_button { + int last_state; + ktime_t last_time; + bool suspended; ++ bool lid_state_initialized; + }; + + static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); +@@ -391,6 +392,8 @@ static int acpi_lid_update_state(struct + + static void acpi_lid_initialize_state(struct acpi_device *device) + { ++ struct acpi_button *button = acpi_driver_data(device); ++ + switch (lid_init_state) { + case ACPI_BUTTON_LID_INIT_OPEN: + (void)acpi_lid_notify_state(device, 1); +@@ -402,13 +405,14 @@ static void acpi_lid_initialize_state(st + default: + break; + } ++ ++ button->lid_state_initialized = true; + } + + static void acpi_button_notify(struct acpi_device *device, u32 event) + { + struct acpi_button *button = acpi_driver_data(device); + struct input_dev *input; +- int users; + + switch (event) { + case ACPI_FIXED_HARDWARE_EVENT: +@@ -417,10 +421,7 @@ static void acpi_button_notify(struct ac + case ACPI_BUTTON_NOTIFY_STATUS: + input = button->input; + if (button->type == ACPI_BUTTON_TYPE_LID) { +- mutex_lock(&button->input->mutex); +- users = button->input->users; +- mutex_unlock(&button->input->mutex); +- if (users) ++ if (button->lid_state_initialized) + acpi_lid_update_state(device, true); + } else { + int keycode; +@@ -465,7 +466,7 @@ static int acpi_button_resume(struct dev + struct acpi_button *button = acpi_driver_data(device); + + button->suspended = false; +- if (button->type == ACPI_BUTTON_TYPE_LID && button->input->users) { ++ if (button->type == ACPI_BUTTON_TYPE_LID) { + button->last_state = !!acpi_lid_evaluate_state(device); + button->last_time = ktime_get(); + acpi_lid_initialize_state(device); diff --git a/queue-5.4/acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch b/queue-5.4/acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch new file mode 100644 index 00000000000..f4226b9ec8a --- /dev/null +++ b/queue-5.4/acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch @@ -0,0 +1,37 @@ +From 5368512abe08a28525d9b24abbfc2a72493e8dba Mon Sep 17 00:00:00 2001 +From: Wei Huang +Date: Sun, 18 Oct 2020 22:57:41 -0500 +Subject: acpi-cpufreq: Honor _PSD table setting on new AMD CPUs + +From: Wei Huang + +commit 5368512abe08a28525d9b24abbfc2a72493e8dba upstream. + +acpi-cpufreq has a old quirk that overrides the _PSD table supplied by +BIOS on AMD CPUs. However the _PSD table of new AMD CPUs (Family 19h+) +now accurately reports the P-state dependency of CPU cores. Hence this +quirk needs to be fixed in order to support new CPUs' frequency control. + +Fixes: acd316248205 ("acpi-cpufreq: Add quirk to disable _PSD usage on all AMD CPUs") +Signed-off-by: Wei Huang +[ rjw: Subject edit ] +Cc: 3.10+ # 3.10+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/cpufreq/acpi-cpufreq.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/cpufreq/acpi-cpufreq.c ++++ b/drivers/cpufreq/acpi-cpufreq.c +@@ -688,7 +688,8 @@ static int acpi_cpufreq_cpu_init(struct + cpumask_copy(policy->cpus, topology_core_cpumask(cpu)); + } + +- if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) { ++ if (check_amd_hwpstate_cpu(cpu) && boot_cpu_data.x86 < 0x19 && ++ !acpi_pstate_strict) { + cpumask_clear(policy->cpus); + cpumask_set_cpu(cpu, policy->cpus); + cpumask_copy(data->freqdomain_cpus, diff --git a/queue-5.4/acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch b/queue-5.4/acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch new file mode 100644 index 00000000000..e6059189ca2 --- /dev/null +++ b/queue-5.4/acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch @@ -0,0 +1,68 @@ +From 0fada277147ffc6d694aa32162f51198d4f10d94 Mon Sep 17 00:00:00 2001 +From: Jamie Iles +Date: Mon, 12 Oct 2020 14:04:46 +0100 +Subject: ACPI: debug: don't allow debugging when ACPI is disabled + +From: Jamie Iles + +commit 0fada277147ffc6d694aa32162f51198d4f10d94 upstream. + +If ACPI is disabled then loading the acpi_dbg module will result in the +following splat when lock debugging is enabled. + + DEBUG_LOCKS_WARN_ON(lock->magic != lock) + WARNING: CPU: 0 PID: 1 at kernel/locking/mutex.c:938 __mutex_lock+0xa10/0x1290 + Kernel panic - not syncing: panic_on_warn set ... + CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.9.0-rc8+ #103 + Hardware name: linux,dummy-virt (DT) + Call trace: + dump_backtrace+0x0/0x4d8 + show_stack+0x34/0x48 + dump_stack+0x174/0x1f8 + panic+0x360/0x7a0 + __warn+0x244/0x2ec + report_bug+0x240/0x398 + bug_handler+0x50/0xc0 + call_break_hook+0x160/0x1d8 + brk_handler+0x30/0xc0 + do_debug_exception+0x184/0x340 + el1_dbg+0x48/0xb0 + el1_sync_handler+0x170/0x1c8 + el1_sync+0x80/0x100 + __mutex_lock+0xa10/0x1290 + mutex_lock_nested+0x6c/0xc0 + acpi_register_debugger+0x40/0x88 + acpi_aml_init+0xc4/0x114 + do_one_initcall+0x24c/0xb10 + kernel_init_freeable+0x690/0x728 + kernel_init+0x20/0x1e8 + ret_from_fork+0x10/0x18 + +This is because acpi_debugger.lock has not been initialized as +acpi_debugger_init() is not called when ACPI is disabled. Fail module +loading to avoid this and any subsequent problems that might arise by +trying to debug AML when ACPI is disabled. + +Fixes: 8cfb0cdf07e2 ("ACPI / debugger: Add IO interface to access debugger functionalities") +Reviewed-by: Hanjun Guo +Signed-off-by: Jamie Iles +Cc: 4.10+ # 4.10+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/acpi_dbg.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/acpi/acpi_dbg.c ++++ b/drivers/acpi/acpi_dbg.c +@@ -749,6 +749,9 @@ int __init acpi_aml_init(void) + { + int ret; + ++ if (acpi_disabled) ++ return -ENODEV; ++ + /* Initialize AML IO interface */ + mutex_init(&acpi_aml_io.lock); + init_waitqueue_head(&acpi_aml_io.wait); diff --git a/queue-5.4/acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch b/queue-5.4/acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch new file mode 100644 index 00000000000..1fc5d60940e --- /dev/null +++ b/queue-5.4/acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch @@ -0,0 +1,36 @@ +From e0e9ce390d7bc6a705653d4a8aa4ea92c9a65e53 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Mon, 5 Oct 2020 19:13:46 +0200 +Subject: ACPI: EC: PM: Drop ec_no_wakeup check from acpi_ec_dispatch_gpe() + +From: Rafael J. Wysocki + +commit e0e9ce390d7bc6a705653d4a8aa4ea92c9a65e53 upstream. + +It turns out that in some cases there are EC events to flush in +acpi_ec_dispatch_gpe() even though the ec_no_wakeup kernel parameter +is set and the EC GPE is disabled while sleeping, so drop the +ec_no_wakeup check that prevents those events from being processed +from acpi_ec_dispatch_gpe(). + +Reported-by: Todd Brandt +Cc: 5.4+ # 5.4+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/ec.c | 3 --- + 1 file changed, 3 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1968,9 +1968,6 @@ bool acpi_ec_dispatch_gpe(void) + if (acpi_any_gpe_status_set(first_ec->gpe)) + return true; + +- if (ec_no_wakeup) +- return false; +- + /* + * Dispatch the EC GPE in-band, but do not report wakeup in any case + * to allow the caller to process events properly after that. diff --git a/queue-5.4/acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch b/queue-5.4/acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch new file mode 100644 index 00000000000..d339f346ba3 --- /dev/null +++ b/queue-5.4/acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch @@ -0,0 +1,46 @@ +From 5e92442bb4121562231e6daf8a2d1306cb5f8805 Mon Sep 17 00:00:00 2001 +From: "Rafael J. Wysocki" +Date: Mon, 5 Oct 2020 19:13:15 +0200 +Subject: ACPI: EC: PM: Flush EC work unconditionally after wakeup + +From: Rafael J. Wysocki + +commit 5e92442bb4121562231e6daf8a2d1306cb5f8805 upstream. + +Commit 607b9df63057 ("ACPI: EC: PM: Avoid flushing EC work when EC +GPE is inactive") has been reported to cause some power button wakeup +events to be missed on some systems, so modify acpi_ec_dispatch_gpe() +to call acpi_ec_flush_work() unconditionally to effectively reverse +the changes made by that commit. + +Also note that the problem which prompted commit 607b9df63057 is not +reproducible any more on the affected machine. + +Fixes: 607b9df63057 ("ACPI: EC: PM: Avoid flushing EC work when EC GPE is inactive") +Reported-by: Raymond Tan +Cc: 5.4+ # 5.4+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/ec.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +--- a/drivers/acpi/ec.c ++++ b/drivers/acpi/ec.c +@@ -1976,12 +1976,11 @@ bool acpi_ec_dispatch_gpe(void) + * to allow the caller to process events properly after that. + */ + ret = acpi_dispatch_gpe(NULL, first_ec->gpe); +- if (ret == ACPI_INTERRUPT_HANDLED) { ++ if (ret == ACPI_INTERRUPT_HANDLED) + pm_pr_dbg("EC GPE dispatched\n"); + +- /* Flush the event and query workqueues. */ +- acpi_ec_flush_work(); +- } ++ /* Flush the event and query workqueues. */ ++ acpi_ec_flush_work(); + + return false; + } diff --git a/queue-5.4/acpi-extlog-check-for-rdmsr-failure.patch b/queue-5.4/acpi-extlog-check-for-rdmsr-failure.patch new file mode 100644 index 00000000000..77ab16eeb4c --- /dev/null +++ b/queue-5.4/acpi-extlog-check-for-rdmsr-failure.patch @@ -0,0 +1,42 @@ +From 7cecb47f55e00282f972a1e0b09136c8cd938221 Mon Sep 17 00:00:00 2001 +From: Ben Hutchings +Date: Sun, 27 Sep 2020 22:50:42 +0100 +Subject: ACPI / extlog: Check for RDMSR failure + +From: Ben Hutchings + +commit 7cecb47f55e00282f972a1e0b09136c8cd938221 upstream. + +extlog_init() uses rdmsrl() to read an MSR, which on older CPUs +provokes a error message at boot: + + unchecked MSR access error: RDMSR from 0x179 at rIP: 0xcd047307 (native_read_msr+0x7/0x40) + +Use rdmsrl_safe() instead, and return -ENODEV if it fails. + +Reported-by: jim@photojim.ca +References: https://bugs.debian.org/971058 +Cc: All applicable +Signed-off-by: Ben Hutchings +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/acpi_extlog.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/acpi/acpi_extlog.c ++++ b/drivers/acpi/acpi_extlog.c +@@ -223,9 +223,9 @@ static int __init extlog_init(void) + u64 cap; + int rc; + +- rdmsrl(MSR_IA32_MCG_CAP, cap); +- +- if (!(cap & MCG_ELOG_P) || !extlog_get_l1addr()) ++ if (rdmsrl_safe(MSR_IA32_MCG_CAP, &cap) || ++ !(cap & MCG_ELOG_P) || ++ !extlog_get_l1addr()) + return -ENODEV; + + if (edac_get_report_status() == EDAC_REPORTING_FORCE) { diff --git a/queue-5.4/acpi-video-use-acpi-backlight-for-hp-635-notebook.patch b/queue-5.4/acpi-video-use-acpi-backlight-for-hp-635-notebook.patch new file mode 100644 index 00000000000..a705a93f0c9 --- /dev/null +++ b/queue-5.4/acpi-video-use-acpi-backlight-for-hp-635-notebook.patch @@ -0,0 +1,42 @@ +From b226faab4e7890bbbccdf794e8b94276414f9058 Mon Sep 17 00:00:00 2001 +From: Alex Hung +Date: Sun, 13 Sep 2020 16:34:03 -0600 +Subject: ACPI: video: use ACPI backlight for HP 635 Notebook + +From: Alex Hung + +commit b226faab4e7890bbbccdf794e8b94276414f9058 upstream. + +The default backlight interface is AMD's radeon_bl0 which does not +work on this system, so use the ACPI backlight interface on it +instead. + +BugLink: https://bugs.launchpad.net/bugs/1894667 +Cc: All applicable +Signed-off-by: Alex Hung +[ rjw: Changelog edits ] +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/acpi/video_detect.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/acpi/video_detect.c ++++ b/drivers/acpi/video_detect.c +@@ -282,6 +282,15 @@ static const struct dmi_system_id video_ + DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"), + }, + }, ++ /* https://bugs.launchpad.net/bugs/1894667 */ ++ { ++ .callback = video_detect_force_video, ++ .ident = "HP 635 Notebook", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), ++ DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"), ++ }, ++ }, + + /* Non win8 machines which need native backlight nevertheless */ + { diff --git a/queue-5.4/btrfs-cleanup-cow-block-on-error.patch b/queue-5.4/btrfs-cleanup-cow-block-on-error.patch new file mode 100644 index 00000000000..2d04200332d --- /dev/null +++ b/queue-5.4/btrfs-cleanup-cow-block-on-error.patch @@ -0,0 +1,135 @@ +From 572c83acdcdafeb04e70aa46be1fa539310be20c Mon Sep 17 00:00:00 2001 +From: Josef Bacik +Date: Tue, 29 Sep 2020 08:53:54 -0400 +Subject: btrfs: cleanup cow block on error + +From: Josef Bacik + +commit 572c83acdcdafeb04e70aa46be1fa539310be20c upstream. + +In fstest btrfs/064 a transaction abort in __btrfs_cow_block could lead +to a system lockup. It gets stuck trying to write back inodes, and the +write back thread was trying to lock an extent buffer: + + $ cat /proc/2143497/stack + [<0>] __btrfs_tree_lock+0x108/0x250 + [<0>] lock_extent_buffer_for_io+0x35e/0x3a0 + [<0>] btree_write_cache_pages+0x15a/0x3b0 + [<0>] do_writepages+0x28/0xb0 + [<0>] __writeback_single_inode+0x54/0x5c0 + [<0>] writeback_sb_inodes+0x1e8/0x510 + [<0>] wb_writeback+0xcc/0x440 + [<0>] wb_workfn+0xd7/0x650 + [<0>] process_one_work+0x236/0x560 + [<0>] worker_thread+0x55/0x3c0 + [<0>] kthread+0x13a/0x150 + [<0>] ret_from_fork+0x1f/0x30 + +This is because we got an error while COWing a block, specifically here + + if (test_bit(BTRFS_ROOT_SHAREABLE, &root->state)) { + ret = btrfs_reloc_cow_block(trans, root, buf, cow); + if (ret) { + btrfs_abort_transaction(trans, ret); + return ret; + } + } + + [16402.241552] BTRFS: Transaction aborted (error -2) + [16402.242362] WARNING: CPU: 1 PID: 2563188 at fs/btrfs/ctree.c:1074 __btrfs_cow_block+0x376/0x540 + [16402.249469] CPU: 1 PID: 2563188 Comm: fsstress Not tainted 5.9.0-rc6+ #8 + [16402.249936] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014 + [16402.250525] RIP: 0010:__btrfs_cow_block+0x376/0x540 + [16402.252417] RSP: 0018:ffff9cca40e578b0 EFLAGS: 00010282 + [16402.252787] RAX: 0000000000000025 RBX: 0000000000000002 RCX: ffff9132bbd19388 + [16402.253278] RDX: 00000000ffffffd8 RSI: 0000000000000027 RDI: ffff9132bbd19380 + [16402.254063] RBP: ffff9132b41a49c0 R08: 0000000000000000 R09: 0000000000000000 + [16402.254887] R10: 0000000000000000 R11: ffff91324758b080 R12: ffff91326ef17ce0 + [16402.255694] R13: ffff91325fc0f000 R14: ffff91326ef176b0 R15: ffff9132815e2000 + [16402.256321] FS: 00007f542c6d7b80(0000) GS:ffff9132bbd00000(0000) knlGS:0000000000000000 + [16402.256973] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + [16402.257374] CR2: 00007f127b83f250 CR3: 0000000133480002 CR4: 0000000000370ee0 + [16402.257867] Call Trace: + [16402.258072] btrfs_cow_block+0x109/0x230 + [16402.258356] btrfs_search_slot+0x530/0x9d0 + [16402.258655] btrfs_lookup_file_extent+0x37/0x40 + [16402.259155] __btrfs_drop_extents+0x13c/0xd60 + [16402.259628] ? btrfs_block_rsv_migrate+0x4f/0xb0 + [16402.259949] btrfs_replace_file_extents+0x190/0x820 + [16402.260873] btrfs_clone+0x9ae/0xc00 + [16402.261139] btrfs_extent_same_range+0x66/0x90 + [16402.261771] btrfs_remap_file_range+0x353/0x3b1 + [16402.262333] vfs_dedupe_file_range_one.part.0+0xd5/0x140 + [16402.262821] vfs_dedupe_file_range+0x189/0x220 + [16402.263150] do_vfs_ioctl+0x552/0x700 + [16402.263662] __x64_sys_ioctl+0x62/0xb0 + [16402.264023] do_syscall_64+0x33/0x40 + [16402.264364] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [16402.264862] RIP: 0033:0x7f542c7d15cb + [16402.266901] RSP: 002b:00007ffd35944ea8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 + [16402.267627] RAX: ffffffffffffffda RBX: 00000000009d1968 RCX: 00007f542c7d15cb + [16402.268298] RDX: 00000000009d2490 RSI: 00000000c0189436 RDI: 0000000000000003 + [16402.268958] RBP: 00000000009d2520 R08: 0000000000000036 R09: 00000000009d2e64 + [16402.269726] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000002 + [16402.270659] R13: 000000000001f000 R14: 00000000009d1970 R15: 00000000009d2e80 + [16402.271498] irq event stamp: 0 + [16402.271846] hardirqs last enabled at (0): [<0000000000000000>] 0x0 + [16402.272497] hardirqs last disabled at (0): [] copy_process+0x6b9/0x1ba0 + [16402.273343] softirqs last enabled at (0): [] copy_process+0x6b9/0x1ba0 + [16402.273905] softirqs last disabled at (0): [<0000000000000000>] 0x0 + [16402.274338] ---[ end trace 737874a5a41a8236 ]--- + [16402.274669] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry + [16402.276179] BTRFS info (device dm-9): forced readonly + [16402.277046] BTRFS: error (device dm-9) in btrfs_replace_file_extents:2723: errno=-2 No such entry + [16402.278744] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry + [16402.279968] BTRFS: error (device dm-9) in __btrfs_cow_block:1074: errno=-2 No such entry + [16402.280582] BTRFS info (device dm-9): balance: ended with status: -30 + +The problem here is that as soon as we allocate the new block it is +locked and marked dirty in the btree inode. This means that we could +attempt to writeback this block and need to lock the extent buffer. +However we're not unlocking it here and thus we deadlock. + +Fix this by unlocking the cow block if we have any errors inside of +__btrfs_cow_block, and also free it so we do not leak it. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Filipe Manana +Signed-off-by: Josef Bacik +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ctree.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/fs/btrfs/ctree.c ++++ b/fs/btrfs/ctree.c +@@ -1103,6 +1103,8 @@ static noinline int __btrfs_cow_block(st + + ret = update_ref_for_cow(trans, root, buf, cow, &last_ref); + if (ret) { ++ btrfs_tree_unlock(cow); ++ free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } +@@ -1110,6 +1112,8 @@ static noinline int __btrfs_cow_block(st + if (test_bit(BTRFS_ROOT_REF_COWS, &root->state)) { + ret = btrfs_reloc_cow_block(trans, root, buf, cow); + if (ret) { ++ btrfs_tree_unlock(cow); ++ free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } +@@ -1142,6 +1146,8 @@ static noinline int __btrfs_cow_block(st + if (last_ref) { + ret = tree_mod_log_free_eb(buf); + if (ret) { ++ btrfs_tree_unlock(cow); ++ free_extent_buffer(cow); + btrfs_abort_transaction(trans, ret); + return ret; + } diff --git a/queue-5.4/btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch b/queue-5.4/btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch new file mode 100644 index 00000000000..f48c70adabd --- /dev/null +++ b/queue-5.4/btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch @@ -0,0 +1,678 @@ +From 66d204a16c94f24ad08290a7663ab67e7fc04e82 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 12 Oct 2020 11:55:24 +0100 +Subject: btrfs: fix readahead hang and use-after-free after removing a device + +From: Filipe Manana + +commit 66d204a16c94f24ad08290a7663ab67e7fc04e82 upstream. + +Very sporadically I had test case btrfs/069 from fstests hanging (for +years, it is not a recent regression), with the following traces in +dmesg/syslog: + + [162301.160628] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg started + [162301.181196] BTRFS info (device sdc): scrub: finished on devid 4 with status: 0 + [162301.287162] BTRFS info (device sdc): dev_replace from /dev/sdd (devid 2) to /dev/sdg finished + [162513.513792] INFO: task btrfs-transacti:1356167 blocked for more than 120 seconds. + [162513.514318] Not tainted 5.9.0-rc6-btrfs-next-69 #1 + [162513.514522] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [162513.514747] task:btrfs-transacti state:D stack: 0 pid:1356167 ppid: 2 flags:0x00004000 + [162513.514751] Call Trace: + [162513.514761] __schedule+0x5ce/0xd00 + [162513.514765] ? _raw_spin_unlock_irqrestore+0x3c/0x60 + [162513.514771] schedule+0x46/0xf0 + [162513.514844] wait_current_trans+0xde/0x140 [btrfs] + [162513.514850] ? finish_wait+0x90/0x90 + [162513.514864] start_transaction+0x37c/0x5f0 [btrfs] + [162513.514879] transaction_kthread+0xa4/0x170 [btrfs] + [162513.514891] ? btrfs_cleanup_transaction+0x660/0x660 [btrfs] + [162513.514894] kthread+0x153/0x170 + [162513.514897] ? kthread_stop+0x2c0/0x2c0 + [162513.514902] ret_from_fork+0x22/0x30 + [162513.514916] INFO: task fsstress:1356184 blocked for more than 120 seconds. + [162513.515192] Not tainted 5.9.0-rc6-btrfs-next-69 #1 + [162513.515431] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [162513.515680] task:fsstress state:D stack: 0 pid:1356184 ppid:1356177 flags:0x00004000 + [162513.515682] Call Trace: + [162513.515688] __schedule+0x5ce/0xd00 + [162513.515691] ? _raw_spin_unlock_irqrestore+0x3c/0x60 + [162513.515697] schedule+0x46/0xf0 + [162513.515712] wait_current_trans+0xde/0x140 [btrfs] + [162513.515716] ? finish_wait+0x90/0x90 + [162513.515729] start_transaction+0x37c/0x5f0 [btrfs] + [162513.515743] btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs] + [162513.515753] btrfs_sync_fs+0x61/0x1c0 [btrfs] + [162513.515758] ? __ia32_sys_fdatasync+0x20/0x20 + [162513.515761] iterate_supers+0x87/0xf0 + [162513.515765] ksys_sync+0x60/0xb0 + [162513.515768] __do_sys_sync+0xa/0x10 + [162513.515771] do_syscall_64+0x33/0x80 + [162513.515774] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [162513.515781] RIP: 0033:0x7f5238f50bd7 + [162513.515782] Code: Bad RIP value. + [162513.515784] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2 + [162513.515786] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7 + [162513.515788] RDX: 00000000ffffffff RSI: 000000000daf0e74 RDI: 000000000000003a + [162513.515789] RBP: 0000000000000032 R08: 000000000000000a R09: 00007f5239019be0 + [162513.515791] R10: fffffffffffff24f R11: 0000000000000206 R12: 000000000000003a + [162513.515792] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340 + [162513.515804] INFO: task fsstress:1356185 blocked for more than 120 seconds. + [162513.516064] Not tainted 5.9.0-rc6-btrfs-next-69 #1 + [162513.516329] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [162513.516617] task:fsstress state:D stack: 0 pid:1356185 ppid:1356177 flags:0x00000000 + [162513.516620] Call Trace: + [162513.516625] __schedule+0x5ce/0xd00 + [162513.516628] ? _raw_spin_unlock_irqrestore+0x3c/0x60 + [162513.516634] schedule+0x46/0xf0 + [162513.516647] wait_current_trans+0xde/0x140 [btrfs] + [162513.516650] ? finish_wait+0x90/0x90 + [162513.516662] start_transaction+0x4d7/0x5f0 [btrfs] + [162513.516679] btrfs_setxattr_trans+0x3c/0x100 [btrfs] + [162513.516686] __vfs_setxattr+0x66/0x80 + [162513.516691] __vfs_setxattr_noperm+0x70/0x200 + [162513.516697] vfs_setxattr+0x6b/0x120 + [162513.516703] setxattr+0x125/0x240 + [162513.516709] ? lock_acquire+0xb1/0x480 + [162513.516712] ? mnt_want_write+0x20/0x50 + [162513.516721] ? rcu_read_lock_any_held+0x8e/0xb0 + [162513.516723] ? preempt_count_add+0x49/0xa0 + [162513.516725] ? __sb_start_write+0x19b/0x290 + [162513.516727] ? preempt_count_add+0x49/0xa0 + [162513.516732] path_setxattr+0xba/0xd0 + [162513.516739] __x64_sys_setxattr+0x27/0x30 + [162513.516741] do_syscall_64+0x33/0x80 + [162513.516743] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [162513.516745] RIP: 0033:0x7f5238f56d5a + [162513.516746] Code: Bad RIP value. + [162513.516748] RSP: 002b:00007fff67b97868 EFLAGS: 00000202 ORIG_RAX: 00000000000000bc + [162513.516750] RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f5238f56d5a + [162513.516751] RDX: 000055b1fbb0d5a0 RSI: 00007fff67b978a0 RDI: 000055b1fbb0d470 + [162513.516753] RBP: 000055b1fbb0d5a0 R08: 0000000000000001 R09: 00007fff67b97700 + [162513.516754] R10: 0000000000000004 R11: 0000000000000202 R12: 0000000000000004 + [162513.516756] R13: 0000000000000024 R14: 0000000000000001 R15: 00007fff67b978a0 + [162513.516767] INFO: task fsstress:1356196 blocked for more than 120 seconds. + [162513.517064] Not tainted 5.9.0-rc6-btrfs-next-69 #1 + [162513.517365] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [162513.517763] task:fsstress state:D stack: 0 pid:1356196 ppid:1356177 flags:0x00004000 + [162513.517780] Call Trace: + [162513.517786] __schedule+0x5ce/0xd00 + [162513.517789] ? _raw_spin_unlock_irqrestore+0x3c/0x60 + [162513.517796] schedule+0x46/0xf0 + [162513.517810] wait_current_trans+0xde/0x140 [btrfs] + [162513.517814] ? finish_wait+0x90/0x90 + [162513.517829] start_transaction+0x37c/0x5f0 [btrfs] + [162513.517845] btrfs_attach_transaction_barrier+0x1f/0x50 [btrfs] + [162513.517857] btrfs_sync_fs+0x61/0x1c0 [btrfs] + [162513.517862] ? __ia32_sys_fdatasync+0x20/0x20 + [162513.517865] iterate_supers+0x87/0xf0 + [162513.517869] ksys_sync+0x60/0xb0 + [162513.517872] __do_sys_sync+0xa/0x10 + [162513.517875] do_syscall_64+0x33/0x80 + [162513.517878] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [162513.517881] RIP: 0033:0x7f5238f50bd7 + [162513.517883] Code: Bad RIP value. + [162513.517885] RSP: 002b:00007fff67b978e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000a2 + [162513.517887] RAX: ffffffffffffffda RBX: 000055b1fad2c560 RCX: 00007f5238f50bd7 + [162513.517889] RDX: 0000000000000000 RSI: 000000007660add2 RDI: 0000000000000053 + [162513.517891] RBP: 0000000000000032 R08: 0000000000000067 R09: 00007f5239019be0 + [162513.517893] R10: fffffffffffff24f R11: 0000000000000206 R12: 0000000000000053 + [162513.517895] R13: 00007fff67b97950 R14: 00007fff67b97906 R15: 000055b1fad1a340 + [162513.517908] INFO: task fsstress:1356197 blocked for more than 120 seconds. + [162513.518298] Not tainted 5.9.0-rc6-btrfs-next-69 #1 + [162513.518672] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [162513.519157] task:fsstress state:D stack: 0 pid:1356197 ppid:1356177 flags:0x00000000 + [162513.519160] Call Trace: + [162513.519165] __schedule+0x5ce/0xd00 + [162513.519168] ? _raw_spin_unlock_irqrestore+0x3c/0x60 + [162513.519174] schedule+0x46/0xf0 + [162513.519190] wait_current_trans+0xde/0x140 [btrfs] + [162513.519193] ? finish_wait+0x90/0x90 + [162513.519206] start_transaction+0x4d7/0x5f0 [btrfs] + [162513.519222] btrfs_create+0x57/0x200 [btrfs] + [162513.519230] lookup_open+0x522/0x650 + [162513.519246] path_openat+0x2b8/0xa50 + [162513.519270] do_filp_open+0x91/0x100 + [162513.519275] ? find_held_lock+0x32/0x90 + [162513.519280] ? lock_acquired+0x33b/0x470 + [162513.519285] ? do_raw_spin_unlock+0x4b/0xc0 + [162513.519287] ? _raw_spin_unlock+0x29/0x40 + [162513.519295] do_sys_openat2+0x20d/0x2d0 + [162513.519300] do_sys_open+0x44/0x80 + [162513.519304] do_syscall_64+0x33/0x80 + [162513.519307] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [162513.519309] RIP: 0033:0x7f5238f4a903 + [162513.519310] Code: Bad RIP value. + [162513.519312] RSP: 002b:00007fff67b97758 EFLAGS: 00000246 ORIG_RAX: 0000000000000055 + [162513.519314] RAX: ffffffffffffffda RBX: 00000000ffffffff RCX: 00007f5238f4a903 + [162513.519316] RDX: 0000000000000000 RSI: 00000000000001b6 RDI: 000055b1fbb0d470 + [162513.519317] RBP: 00007fff67b978c0 R08: 0000000000000001 R09: 0000000000000002 + [162513.519319] R10: 00007fff67b974f7 R11: 0000000000000246 R12: 0000000000000013 + [162513.519320] R13: 00000000000001b6 R14: 00007fff67b97906 R15: 000055b1fad1c620 + [162513.519332] INFO: task btrfs:1356211 blocked for more than 120 seconds. + [162513.519727] Not tainted 5.9.0-rc6-btrfs-next-69 #1 + [162513.520115] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + [162513.520508] task:btrfs state:D stack: 0 pid:1356211 ppid:1356178 flags:0x00004002 + [162513.520511] Call Trace: + [162513.520516] __schedule+0x5ce/0xd00 + [162513.520519] ? _raw_spin_unlock_irqrestore+0x3c/0x60 + [162513.520525] schedule+0x46/0xf0 + [162513.520544] btrfs_scrub_pause+0x11f/0x180 [btrfs] + [162513.520548] ? finish_wait+0x90/0x90 + [162513.520562] btrfs_commit_transaction+0x45a/0xc30 [btrfs] + [162513.520574] ? start_transaction+0xe0/0x5f0 [btrfs] + [162513.520596] btrfs_dev_replace_finishing+0x6d8/0x711 [btrfs] + [162513.520619] btrfs_dev_replace_by_ioctl.cold+0x1cc/0x1fd [btrfs] + [162513.520639] btrfs_ioctl+0x2a25/0x36f0 [btrfs] + [162513.520643] ? do_sigaction+0xf3/0x240 + [162513.520645] ? find_held_lock+0x32/0x90 + [162513.520648] ? do_sigaction+0xf3/0x240 + [162513.520651] ? lock_acquired+0x33b/0x470 + [162513.520655] ? _raw_spin_unlock_irq+0x24/0x50 + [162513.520657] ? lockdep_hardirqs_on+0x7d/0x100 + [162513.520660] ? _raw_spin_unlock_irq+0x35/0x50 + [162513.520662] ? do_sigaction+0xf3/0x240 + [162513.520671] ? __x64_sys_ioctl+0x83/0xb0 + [162513.520672] __x64_sys_ioctl+0x83/0xb0 + [162513.520677] do_syscall_64+0x33/0x80 + [162513.520679] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [162513.520681] RIP: 0033:0x7fc3cd307d87 + [162513.520682] Code: Bad RIP value. + [162513.520684] RSP: 002b:00007ffe30a56bb8 EFLAGS: 00000202 ORIG_RAX: 0000000000000010 + [162513.520686] RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007fc3cd307d87 + [162513.520687] RDX: 00007ffe30a57a30 RSI: 00000000ca289435 RDI: 0000000000000003 + [162513.520689] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 + [162513.520690] R10: 0000000000000008 R11: 0000000000000202 R12: 0000000000000003 + [162513.520692] R13: 0000557323a212e0 R14: 00007ffe30a5a520 R15: 0000000000000001 + [162513.520703] + Showing all locks held in the system: + [162513.520712] 1 lock held by khungtaskd/54: + [162513.520713] #0: ffffffffb40a91a0 (rcu_read_lock){....}-{1:2}, at: debug_show_all_locks+0x15/0x197 + [162513.520728] 1 lock held by in:imklog/596: + [162513.520729] #0: ffff8f3f0d781400 (&f->f_pos_lock){+.+.}-{3:3}, at: __fdget_pos+0x4d/0x60 + [162513.520782] 1 lock held by btrfs-transacti/1356167: + [162513.520784] #0: ffff8f3d810cc848 (&fs_info->transaction_kthread_mutex){+.+.}-{3:3}, at: transaction_kthread+0x4a/0x170 [btrfs] + [162513.520798] 1 lock held by btrfs/1356190: + [162513.520800] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write_file+0x22/0x60 + [162513.520805] 1 lock held by fsstress/1356184: + [162513.520806] #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0 + [162513.520811] 3 locks held by fsstress/1356185: + [162513.520812] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50 + [162513.520815] #1: ffff8f3d80a650b8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: vfs_setxattr+0x50/0x120 + [162513.520820] #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs] + [162513.520833] 1 lock held by fsstress/1356196: + [162513.520834] #0: ffff8f3d576440e8 (&type->s_umount_key#62){++++}-{3:3}, at: iterate_supers+0x6f/0xf0 + [162513.520838] 3 locks held by fsstress/1356197: + [162513.520839] #0: ffff8f3d57644470 (sb_writers#15){.+.+}-{0:0}, at: mnt_want_write+0x20/0x50 + [162513.520843] #1: ffff8f3d506465e8 (&type->i_mutex_dir_key#10){++++}-{3:3}, at: path_openat+0x2a7/0xa50 + [162513.520846] #2: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs] + [162513.520858] 2 locks held by btrfs/1356211: + [162513.520859] #0: ffff8f3d810cde30 (&fs_info->dev_replace.lock_finishing_cancel_unmount){+.+.}-{3:3}, at: btrfs_dev_replace_finishing+0x52/0x711 [btrfs] + [162513.520877] #1: ffff8f3d57644690 (sb_internal#2){.+.+}-{0:0}, at: start_transaction+0x40e/0x5f0 [btrfs] + +This was weird because the stack traces show that a transaction commit, +triggered by a device replace operation, is blocking trying to pause any +running scrubs but there are no stack traces of blocked tasks doing a +scrub. + +After poking around with drgn, I noticed there was a scrub task that was +constantly running and blocking for shorts periods of time: + + >>> t = find_task(prog, 1356190) + >>> prog.stack_trace(t) + #0 __schedule+0x5ce/0xcfc + #1 schedule+0x46/0xe4 + #2 schedule_timeout+0x1df/0x475 + #3 btrfs_reada_wait+0xda/0x132 + #4 scrub_stripe+0x2a8/0x112f + #5 scrub_chunk+0xcd/0x134 + #6 scrub_enumerate_chunks+0x29e/0x5ee + #7 btrfs_scrub_dev+0x2d5/0x91b + #8 btrfs_ioctl+0x7f5/0x36e7 + #9 __x64_sys_ioctl+0x83/0xb0 + #10 do_syscall_64+0x33/0x77 + #11 entry_SYSCALL_64+0x7c/0x156 + +Which corresponds to: + +int btrfs_reada_wait(void *handle) +{ + struct reada_control *rc = handle; + struct btrfs_fs_info *fs_info = rc->fs_info; + + while (atomic_read(&rc->elems)) { + if (!atomic_read(&fs_info->reada_works_cnt)) + reada_start_machine(fs_info); + wait_event_timeout(rc->wait, atomic_read(&rc->elems) == 0, + (HZ + 9) / 10); + } +(...) + +So the counter "rc->elems" was set to 1 and never decreased to 0, causing +the scrub task to loop forever in that function. Then I used the following +script for drgn to check the readahead requests: + + $ cat dump_reada.py + import sys + import drgn + from drgn import NULL, Object, cast, container_of, execscript, \ + reinterpret, sizeof + from drgn.helpers.linux import * + + mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1" + + mnt = None + for mnt in for_each_mount(prog, dst = mnt_path): + pass + + if mnt is None: + sys.stderr.write(f'Error: mount point {mnt_path} not found\n') + sys.exit(1) + + fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info) + + def dump_re(re): + nzones = re.nzones.value_() + print(f're at {hex(re.value_())}') + print(f'\t logical {re.logical.value_()}') + print(f'\t refcnt {re.refcnt.value_()}') + print(f'\t nzones {nzones}') + for i in range(nzones): + dev = re.zones[i].device + name = dev.name.str.string_() + print(f'\t\t dev id {dev.devid.value_()} name {name}') + print() + + for _, e in radix_tree_for_each(fs_info.reada_tree): + re = cast('struct reada_extent *', e) + dump_re(re) + + $ drgn dump_reada.py + re at 0xffff8f3da9d25ad8 + logical 38928384 + refcnt 1 + nzones 1 + dev id 0 name b'/dev/sdd' + $ + +So there was one readahead extent with a single zone corresponding to the +source device of that last device replace operation logged in dmesg/syslog. +Also the ID of that zone's device was 0 which is a special value set in +the source device of a device replace operation when the operation finishes +(constant BTRFS_DEV_REPLACE_DEVID set at btrfs_dev_replace_finishing()), +confirming again that device /dev/sdd was the source of a device replace +operation. + +Normally there should be as many zones in the readahead extent as there are +devices, and I wasn't expecting the extent to be in a block group with a +'single' profile, so I went and confirmed with the following drgn script +that there weren't any single profile block groups: + + $ cat dump_block_groups.py + import sys + import drgn + from drgn import NULL, Object, cast, container_of, execscript, \ + reinterpret, sizeof + from drgn.helpers.linux import * + + mnt_path = b"/home/fdmanana/btrfs-tests/scratch_1" + + mnt = None + for mnt in for_each_mount(prog, dst = mnt_path): + pass + + if mnt is None: + sys.stderr.write(f'Error: mount point {mnt_path} not found\n') + sys.exit(1) + + fs_info = cast('struct btrfs_fs_info *', mnt.mnt.mnt_sb.s_fs_info) + + BTRFS_BLOCK_GROUP_DATA = (1 << 0) + BTRFS_BLOCK_GROUP_SYSTEM = (1 << 1) + BTRFS_BLOCK_GROUP_METADATA = (1 << 2) + BTRFS_BLOCK_GROUP_RAID0 = (1 << 3) + BTRFS_BLOCK_GROUP_RAID1 = (1 << 4) + BTRFS_BLOCK_GROUP_DUP = (1 << 5) + BTRFS_BLOCK_GROUP_RAID10 = (1 << 6) + BTRFS_BLOCK_GROUP_RAID5 = (1 << 7) + BTRFS_BLOCK_GROUP_RAID6 = (1 << 8) + BTRFS_BLOCK_GROUP_RAID1C3 = (1 << 9) + BTRFS_BLOCK_GROUP_RAID1C4 = (1 << 10) + + def bg_flags_string(bg): + flags = bg.flags.value_() + ret = '' + if flags & BTRFS_BLOCK_GROUP_DATA: + ret = 'data' + if flags & BTRFS_BLOCK_GROUP_METADATA: + if len(ret) > 0: + ret += '|' + ret += 'meta' + if flags & BTRFS_BLOCK_GROUP_SYSTEM: + if len(ret) > 0: + ret += '|' + ret += 'system' + if flags & BTRFS_BLOCK_GROUP_RAID0: + ret += ' raid0' + elif flags & BTRFS_BLOCK_GROUP_RAID1: + ret += ' raid1' + elif flags & BTRFS_BLOCK_GROUP_DUP: + ret += ' dup' + elif flags & BTRFS_BLOCK_GROUP_RAID10: + ret += ' raid10' + elif flags & BTRFS_BLOCK_GROUP_RAID5: + ret += ' raid5' + elif flags & BTRFS_BLOCK_GROUP_RAID6: + ret += ' raid6' + elif flags & BTRFS_BLOCK_GROUP_RAID1C3: + ret += ' raid1c3' + elif flags & BTRFS_BLOCK_GROUP_RAID1C4: + ret += ' raid1c4' + else: + ret += ' single' + + return ret + + def dump_bg(bg): + print() + print(f'block group at {hex(bg.value_())}') + print(f'\t start {bg.start.value_()} length {bg.length.value_()}') + print(f'\t flags {bg.flags.value_()} - {bg_flags_string(bg)}') + + bg_root = fs_info.block_group_cache_tree.address_of_() + for bg in rbtree_inorder_for_each_entry('struct btrfs_block_group', bg_root, 'cache_node'): + dump_bg(bg) + + $ drgn dump_block_groups.py + + block group at 0xffff8f3d673b0400 + start 22020096 length 16777216 + flags 258 - system raid6 + + block group at 0xffff8f3d53ddb400 + start 38797312 length 536870912 + flags 260 - meta raid6 + + block group at 0xffff8f3d5f4d9c00 + start 575668224 length 2147483648 + flags 257 - data raid6 + + block group at 0xffff8f3d08189000 + start 2723151872 length 67108864 + flags 258 - system raid6 + + block group at 0xffff8f3db70ff000 + start 2790260736 length 1073741824 + flags 260 - meta raid6 + + block group at 0xffff8f3d5f4dd800 + start 3864002560 length 67108864 + flags 258 - system raid6 + + block group at 0xffff8f3d67037000 + start 3931111424 length 2147483648 + flags 257 - data raid6 + $ + +So there were only 2 reasons left for having a readahead extent with a +single zone: reada_find_zone(), called when creating a readahead extent, +returned NULL either because we failed to find the corresponding block +group or because a memory allocation failed. With some additional and +custom tracing I figured out that on every further ocurrence of the +problem the block group had just been deleted when we were looping to +create the zones for the readahead extent (at reada_find_extent()), so we +ended up with only one zone in the readahead extent, corresponding to a +device that ends up getting replaced. + +So after figuring that out it became obvious why the hang happens: + +1) Task A starts a scrub on any device of the filesystem, except for + device /dev/sdd; + +2) Task B starts a device replace with /dev/sdd as the source device; + +3) Task A calls btrfs_reada_add() from scrub_stripe() and it is currently + starting to scrub a stripe from block group X. This call to + btrfs_reada_add() is the one for the extent tree. When btrfs_reada_add() + calls reada_add_block(), it passes the logical address of the extent + tree's root node as its 'logical' argument - a value of 38928384; + +4) Task A then enters reada_find_extent(), called from reada_add_block(). + It finds there isn't any existing readahead extent for the logical + address 38928384, so it proceeds to the path of creating a new one. + + It calls btrfs_map_block() to find out which stripes exist for the block + group X. On the first iteration of the for loop that iterates over the + stripes, it finds the stripe for device /dev/sdd, so it creates one + zone for that device and adds it to the readahead extent. Before getting + into the second iteration of the loop, the cleanup kthread deletes block + group X because it was empty. So in the iterations for the remaining + stripes it does not add more zones to the readahead extent, because the + calls to reada_find_zone() returned NULL because they couldn't find + block group X anymore. + + As a result the new readahead extent has a single zone, corresponding to + the device /dev/sdd; + +4) Before task A returns to btrfs_reada_add() and queues the readahead job + for the readahead work queue, task B finishes the device replace and at + btrfs_dev_replace_finishing() swaps the device /dev/sdd with the new + device /dev/sdg; + +5) Task A returns to reada_add_block(), which increments the counter + "->elems" of the reada_control structure allocated at btrfs_reada_add(). + + Then it returns back to btrfs_reada_add() and calls + reada_start_machine(). This queues a job in the readahead work queue to + run the function reada_start_machine_worker(), which calls + __reada_start_machine(). + + At __reada_start_machine() we take the device list mutex and for each + device found in the current device list, we call + reada_start_machine_dev() to start the readahead work. However at this + point the device /dev/sdd was already freed and is not in the device + list anymore. + + This means the corresponding readahead for the extent at 38928384 is + never started, and therefore the "->elems" counter of the reada_control + structure allocated at btrfs_reada_add() never goes down to 0, causing + the call to btrfs_reada_wait(), done by the scrub task, to wait forever. + +Note that the readahead request can be made either after the device replace +started or before it started, however in pratice it is very unlikely that a +device replace is able to start after a readahead request is made and is +able to complete before the readahead request completes - maybe only on a +very small and nearly empty filesystem. + +This hang however is not the only problem we can have with readahead and +device removals. When the readahead extent has other zones other than the +one corresponding to the device that is being removed (either by a device +replace or a device remove operation), we risk having a use-after-free on +the device when dropping the last reference of the readahead extent. + +For example if we create a readahead extent with two zones, one for the +device /dev/sdd and one for the device /dev/sde: + +1) Before the readahead worker starts, the device /dev/sdd is removed, + and the corresponding btrfs_device structure is freed. However the + readahead extent still has the zone pointing to the device structure; + +2) When the readahead worker starts, it only finds device /dev/sde in the + current device list of the filesystem; + +3) It starts the readahead work, at reada_start_machine_dev(), using the + device /dev/sde; + +4) Then when it finishes reading the extent from device /dev/sde, it calls + __readahead_hook() which ends up dropping the last reference on the + readahead extent through the last call to reada_extent_put(); + +5) At reada_extent_put() it iterates over each zone of the readahead extent + and attempts to delete an element from the device's 'reada_extents' + radix tree, resulting in a use-after-free, as the device pointer of the + zone for /dev/sdd is now stale. We can also access the device after + dropping the last reference of a zone, through reada_zone_release(), + also called by reada_extent_put(). + +And a device remove suffers the same problem, however since it shrinks the +device size down to zero before removing the device, it is very unlikely to +still have readahead requests not completed by the time we free the device, +the only possibility is if the device has a very little space allocated. + +While the hang problem is exclusive to scrub, since it is currently the +only user of btrfs_reada_add() and btrfs_reada_wait(), the use-after-free +problem affects any path that triggers readhead, which includes +btree_readahead_hook() and __readahead_hook() (a readahead worker can +trigger readahed for the children of a node) for example - any path that +ends up calling reada_add_block() can trigger the use-after-free after a +device is removed. + +So fix this by waiting for any readahead requests for a device to complete +before removing a device, ensuring that while waiting for existing ones no +new ones can be made. + +This problem has been around for a very long time - the readahead code was +added in 2011, device remove exists since 2008 and device replace was +introduced in 2013, hard to pick a specific commit for a git Fixes tag. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/ctree.h | 2 ++ + fs/btrfs/dev-replace.c | 5 +++++ + fs/btrfs/reada.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ + fs/btrfs/volumes.c | 3 +++ + fs/btrfs/volumes.h | 1 + + 5 files changed, 56 insertions(+) + +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -3404,6 +3404,8 @@ struct reada_control *btrfs_reada_add(st + int btrfs_reada_wait(void *handle); + void btrfs_reada_detach(void *handle); + int btree_readahead_hook(struct extent_buffer *eb, int err); ++void btrfs_reada_remove_dev(struct btrfs_device *dev); ++void btrfs_reada_undo_remove_dev(struct btrfs_device *dev); + + static inline int is_fstree(u64 rootid) + { +--- a/fs/btrfs/dev-replace.c ++++ b/fs/btrfs/dev-replace.c +@@ -631,6 +631,9 @@ static int btrfs_dev_replace_finishing(s + } + btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1); + ++ if (!scrub_ret) ++ btrfs_reada_remove_dev(src_device); ++ + /* + * We have to use this loop approach because at this point src_device + * has to be available for transaction commit to complete, yet new +@@ -639,6 +642,7 @@ static int btrfs_dev_replace_finishing(s + while (1) { + trans = btrfs_start_transaction(root, 0); + if (IS_ERR(trans)) { ++ btrfs_reada_undo_remove_dev(src_device); + mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); + return PTR_ERR(trans); + } +@@ -689,6 +693,7 @@ error: + up_write(&dev_replace->rwsem); + mutex_unlock(&fs_info->chunk_mutex); + mutex_unlock(&fs_info->fs_devices->device_list_mutex); ++ btrfs_reada_undo_remove_dev(src_device); + btrfs_rm_dev_replace_blocked(fs_info); + if (tgt_device) + btrfs_destroy_dev_replace_tgtdev(tgt_device); +--- a/fs/btrfs/reada.c ++++ b/fs/btrfs/reada.c +@@ -421,6 +421,9 @@ static struct reada_extent *reada_find_e + if (!dev->bdev) + continue; + ++ if (test_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state)) ++ continue; ++ + if (dev_replace_is_ongoing && + dev == fs_info->dev_replace.tgtdev) { + /* +@@ -1014,3 +1017,45 @@ void btrfs_reada_detach(void *handle) + + kref_put(&rc->refcnt, reada_control_release); + } ++ ++/* ++ * Before removing a device (device replace or device remove ioctls), call this ++ * function to wait for all existing readahead requests on the device and to ++ * make sure no one queues more readahead requests for the device. ++ * ++ * Must be called without holding neither the device list mutex nor the device ++ * replace semaphore, otherwise it will deadlock. ++ */ ++void btrfs_reada_remove_dev(struct btrfs_device *dev) ++{ ++ struct btrfs_fs_info *fs_info = dev->fs_info; ++ ++ /* Serialize with readahead extent creation at reada_find_extent(). */ ++ spin_lock(&fs_info->reada_lock); ++ set_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state); ++ spin_unlock(&fs_info->reada_lock); ++ ++ /* ++ * There might be readahead requests added to the radix trees which ++ * were not yet added to the readahead work queue. We need to start ++ * them and wait for their completion, otherwise we can end up with ++ * use-after-free problems when dropping the last reference on the ++ * readahead extents and their zones, as they need to access the ++ * device structure. ++ */ ++ reada_start_machine(fs_info); ++ btrfs_flush_workqueue(fs_info->readahead_workers); ++} ++ ++/* ++ * If when removing a device (device replace or device remove ioctls) an error ++ * happens after calling btrfs_reada_remove_dev(), call this to undo what that ++ * function did. This is safe to call even if btrfs_reada_remove_dev() was not ++ * called before. ++ */ ++void btrfs_reada_undo_remove_dev(struct btrfs_device *dev) ++{ ++ spin_lock(&dev->fs_info->reada_lock); ++ clear_bit(BTRFS_DEV_STATE_NO_READA, &dev->dev_state); ++ spin_unlock(&dev->fs_info->reada_lock); ++} +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -2208,6 +2208,8 @@ int btrfs_rm_device(struct btrfs_fs_info + + mutex_unlock(&uuid_mutex); + ret = btrfs_shrink_device(device, 0); ++ if (!ret) ++ btrfs_reada_remove_dev(device); + mutex_lock(&uuid_mutex); + if (ret) + goto error_undo; +@@ -2294,6 +2296,7 @@ out: + return ret; + + error_undo: ++ btrfs_reada_undo_remove_dev(device); + if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) { + mutex_lock(&fs_info->chunk_mutex); + list_add(&device->dev_alloc_list, +--- a/fs/btrfs/volumes.h ++++ b/fs/btrfs/volumes.h +@@ -56,6 +56,7 @@ struct btrfs_io_geometry { + #define BTRFS_DEV_STATE_MISSING (2) + #define BTRFS_DEV_STATE_REPLACE_TGT (3) + #define BTRFS_DEV_STATE_FLUSH_SENT (4) ++#define BTRFS_DEV_STATE_NO_READA (5) + + struct btrfs_device { + struct list_head dev_list; /* device_list_mutex */ diff --git a/queue-5.4/btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch b/queue-5.4/btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch new file mode 100644 index 00000000000..3435a0d9f6e --- /dev/null +++ b/queue-5.4/btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch @@ -0,0 +1,139 @@ +From 83bc1560e02e25c6439341352024ebe8488f4fbd Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 12 Oct 2020 11:55:23 +0100 +Subject: btrfs: fix use-after-free on readahead extent after failure to create it + +From: Filipe Manana + +commit 83bc1560e02e25c6439341352024ebe8488f4fbd upstream. + +If we fail to find suitable zones for a new readahead extent, we end up +leaving a stale pointer in the global readahead extents radix tree +(fs_info->reada_tree), which can trigger the following trace later on: + + [13367.696354] BUG: kernel NULL pointer dereference, address: 00000000000000b0 + [13367.696802] #PF: supervisor read access in kernel mode + [13367.697249] #PF: error_code(0x0000) - not-present page + [13367.697721] PGD 0 P4D 0 + [13367.698171] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC PTI + [13367.698632] CPU: 6 PID: 851214 Comm: btrfs Tainted: G W 5.9.0-rc6-btrfs-next-69 #1 + [13367.699100] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014 + [13367.700069] RIP: 0010:__lock_acquire+0x20a/0x3970 + [13367.700562] Code: ff 1f 0f b7 c0 48 0f (...) + [13367.701609] RSP: 0018:ffffb14448f57790 EFLAGS: 00010046 + [13367.702140] RAX: 0000000000000000 RBX: 29b935140c15e8cf RCX: 0000000000000000 + [13367.702698] RDX: 0000000000000002 RSI: ffffffffb3d66bd0 RDI: 0000000000000046 + [13367.703240] RBP: ffff8a52ba8ac040 R08: 00000c2866ad9288 R09: 0000000000000001 + [13367.703783] R10: 0000000000000001 R11: 00000000b66d9b53 R12: ffff8a52ba8ac9b0 + [13367.704330] R13: 0000000000000000 R14: ffff8a532b6333e8 R15: 0000000000000000 + [13367.704880] FS: 00007fe1df6b5700(0000) GS:ffff8a5376600000(0000) knlGS:0000000000000000 + [13367.705438] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + [13367.705995] CR2: 00000000000000b0 CR3: 000000022cca8004 CR4: 00000000003706e0 + [13367.706565] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + [13367.707127] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + [13367.707686] Call Trace: + [13367.708246] ? ___slab_alloc+0x395/0x740 + [13367.708820] ? reada_add_block+0xae/0xee0 [btrfs] + [13367.709383] lock_acquire+0xb1/0x480 + [13367.709955] ? reada_add_block+0xe0/0xee0 [btrfs] + [13367.710537] ? reada_add_block+0xae/0xee0 [btrfs] + [13367.711097] ? rcu_read_lock_sched_held+0x5d/0x90 + [13367.711659] ? kmem_cache_alloc_trace+0x8d2/0x990 + [13367.712221] ? lock_acquired+0x33b/0x470 + [13367.712784] _raw_spin_lock+0x34/0x80 + [13367.713356] ? reada_add_block+0xe0/0xee0 [btrfs] + [13367.713966] reada_add_block+0xe0/0xee0 [btrfs] + [13367.714529] ? btrfs_root_node+0x15/0x1f0 [btrfs] + [13367.715077] btrfs_reada_add+0x117/0x170 [btrfs] + [13367.715620] scrub_stripe+0x21e/0x10d0 [btrfs] + [13367.716141] ? kvm_sched_clock_read+0x5/0x10 + [13367.716657] ? __lock_acquire+0x41e/0x3970 + [13367.717184] ? scrub_chunk+0x60/0x140 [btrfs] + [13367.717697] ? find_held_lock+0x32/0x90 + [13367.718254] ? scrub_chunk+0x60/0x140 [btrfs] + [13367.718773] ? lock_acquired+0x33b/0x470 + [13367.719278] ? scrub_chunk+0xcd/0x140 [btrfs] + [13367.719786] scrub_chunk+0xcd/0x140 [btrfs] + [13367.720291] scrub_enumerate_chunks+0x270/0x5c0 [btrfs] + [13367.720787] ? finish_wait+0x90/0x90 + [13367.721281] btrfs_scrub_dev+0x1ee/0x620 [btrfs] + [13367.721762] ? rcu_read_lock_any_held+0x8e/0xb0 + [13367.722235] ? preempt_count_add+0x49/0xa0 + [13367.722710] ? __sb_start_write+0x19b/0x290 + [13367.723192] btrfs_ioctl+0x7f5/0x36f0 [btrfs] + [13367.723660] ? __fget_files+0x101/0x1d0 + [13367.724118] ? find_held_lock+0x32/0x90 + [13367.724559] ? __fget_files+0x101/0x1d0 + [13367.724982] ? __x64_sys_ioctl+0x83/0xb0 + [13367.725399] __x64_sys_ioctl+0x83/0xb0 + [13367.725802] do_syscall_64+0x33/0x80 + [13367.726188] entry_SYSCALL_64_after_hwframe+0x44/0xa9 + [13367.726574] RIP: 0033:0x7fe1df7add87 + [13367.726948] Code: 00 00 00 48 8b 05 09 91 (...) + [13367.727763] RSP: 002b:00007fe1df6b4d48 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 + [13367.728179] RAX: ffffffffffffffda RBX: 000055ce1fb596a0 RCX: 00007fe1df7add87 + [13367.728604] RDX: 000055ce1fb596a0 RSI: 00000000c400941b RDI: 0000000000000003 + [13367.729021] RBP: 0000000000000000 R08: 00007fe1df6b5700 R09: 0000000000000000 + [13367.729431] R10: 00007fe1df6b5700 R11: 0000000000000246 R12: 00007ffd922b07de + [13367.729842] R13: 00007ffd922b07df R14: 00007fe1df6b4e40 R15: 0000000000802000 + [13367.730275] Modules linked in: btrfs blake2b_generic xor (...) + [13367.732638] CR2: 00000000000000b0 + [13367.733166] ---[ end trace d298b6805556acd9 ]--- + +What happens is the following: + +1) At reada_find_extent() we don't find any existing readahead extent for + the metadata extent starting at logical address X; + +2) So we proceed to create a new one. We then call btrfs_map_block() to get + information about which stripes contain extent X; + +3) After that we iterate over the stripes and create only one zone for the + readahead extent - only one because reada_find_zone() returned NULL for + all iterations except for one, either because a memory allocation failed + or it couldn't find the block group of the extent (it may have just been + deleted); + +4) We then add the new readahead extent to the readahead extents radix + tree at fs_info->reada_tree; + +5) Then we iterate over each zone of the new readahead extent, and find + that the device used for that zone no longer exists, because it was + removed or it was the source device of a device replace operation. + Since this left 'have_zone' set to 0, after finishing the loop we jump + to the 'error' label, call kfree() on the new readahead extent and + return without removing it from the radix tree at fs_info->reada_tree; + +6) Any future call to reada_find_extent() for the logical address X will + find the stale pointer in the readahead extents radix tree, increment + its reference counter, which can trigger the use-after-free right + away or return it to the caller reada_add_block() that results in the + use-after-free of the example trace above. + +So fix this by making sure we delete the readahead extent from the radix +tree if we fail to setup zones for it (when 'have_zone = 0'). + +Fixes: 319450211842ba ("btrfs: reada: bypass adding extent when all zone failed") +CC: stable@vger.kernel.org # 4.9+ +Reviewed-by: Johannes Thumshirn +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/reada.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/btrfs/reada.c ++++ b/fs/btrfs/reada.c +@@ -445,6 +445,8 @@ static struct reada_extent *reada_find_e + } + have_zone = 1; + } ++ if (!have_zone) ++ radix_tree_delete(&fs_info->reada_tree, index); + spin_unlock(&fs_info->reada_lock); + up_read(&fs_info->dev_replace.rwsem); + diff --git a/queue-5.4/btrfs-improve-device-scanning-messages.patch b/queue-5.4/btrfs-improve-device-scanning-messages.patch new file mode 100644 index 00000000000..3766d004826 --- /dev/null +++ b/queue-5.4/btrfs-improve-device-scanning-messages.patch @@ -0,0 +1,59 @@ +From 79dae17d8d44b2d15779e332180080af45df5352 Mon Sep 17 00:00:00 2001 +From: Anand Jain +Date: Thu, 3 Sep 2020 21:30:12 +0800 +Subject: btrfs: improve device scanning messages + +From: Anand Jain + +commit 79dae17d8d44b2d15779e332180080af45df5352 upstream. + +Systems booting without the initramfs seems to scan an unusual kind +of device path (/dev/root). And at a later time, the device is updated +to the correct path. We generally print the process name and PID of the +process scanning the device but we don't capture the same information if +the device path is rescanned with a different pathname. + +The current message is too long, so drop the unnecessary UUID and add +process name and PID. + +While at this also update the duplicate device warning to include the +process name and PID so the messages are consistent + +CC: stable@vger.kernel.org # 4.19+ +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=89721 +Signed-off-by: Anand Jain +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/volumes.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -1123,16 +1123,18 @@ static noinline struct btrfs_device *dev + bdput(path_bdev); + mutex_unlock(&fs_devices->device_list_mutex); + btrfs_warn_in_rcu(device->fs_info, +- "duplicate device fsid:devid for %pU:%llu old:%s new:%s", +- disk_super->fsid, devid, +- rcu_str_deref(device->name), path); ++ "duplicate device %s devid %llu generation %llu scanned by %s (%d)", ++ path, devid, found_transid, ++ current->comm, ++ task_pid_nr(current)); + return ERR_PTR(-EEXIST); + } + bdput(path_bdev); + btrfs_info_in_rcu(device->fs_info, +- "device fsid %pU devid %llu moved old:%s new:%s", +- disk_super->fsid, devid, +- rcu_str_deref(device->name), path); ++ "devid %llu device path %s changed to %s scanned by %s (%d)", ++ devid, rcu_str_deref(device->name), ++ path, current->comm, ++ task_pid_nr(current)); + } + + name = rcu_string_strdup(path, GFP_NOFS); diff --git a/queue-5.4/btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch b/queue-5.4/btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch new file mode 100644 index 00000000000..9bbba89a2b8 --- /dev/null +++ b/queue-5.4/btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch @@ -0,0 +1,66 @@ +From b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Fri, 24 Jul 2020 14:46:09 +0800 +Subject: btrfs: qgroup: fix wrong qgroup metadata reserve for delayed inode + +From: Qu Wenruo + +commit b4c5d8fdfff3e2b6c4fa4a5043e8946dff500f8c upstream. + +For delayed inode facility, qgroup metadata is reserved for it, and +later freed. + +However we're freeing more bytes than we reserved. +In btrfs_delayed_inode_reserve_metadata(): + + num_bytes = btrfs_calc_metadata_size(fs_info, 1); + ... + ret = btrfs_qgroup_reserve_meta_prealloc(root, + fs_info->nodesize, true); + ... + if (!ret) { + node->bytes_reserved = num_bytes; + +But in btrfs_delayed_inode_release_metadata(): + + if (qgroup_free) + btrfs_qgroup_free_meta_prealloc(node->root, + node->bytes_reserved); + else + btrfs_qgroup_convert_reserved_meta(node->root, + node->bytes_reserved); + +This means, we're always releasing more qgroup metadata rsv than we have +reserved. + +This won't trigger selftest warning, as btrfs qgroup metadata rsv has +extra protection against cases like quota enabled half-way. + +But we still need to fix this problem any way. + +This patch will use the same num_bytes for qgroup metadata rsv so we +could handle it correctly. + +Fixes: f218ea6c4792 ("btrfs: delayed-inode: Remove wrong qgroup meta reservation calls") +CC: stable@vger.kernel.org # 4.19+ +Reviewed-by: Josef Bacik +Signed-off-by: Qu Wenruo +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/delayed-inode.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/fs/btrfs/delayed-inode.c ++++ b/fs/btrfs/delayed-inode.c +@@ -627,8 +627,7 @@ static int btrfs_delayed_inode_reserve_m + */ + if (!src_rsv || (!trans->bytes_reserved && + src_rsv->type != BTRFS_BLOCK_RSV_DELALLOC)) { +- ret = btrfs_qgroup_reserve_meta_prealloc(root, +- fs_info->nodesize, true); ++ ret = btrfs_qgroup_reserve_meta_prealloc(root, num_bytes, true); + if (ret < 0) + return ret; + ret = btrfs_block_rsv_add(root, dst_rsv, num_bytes, diff --git a/queue-5.4/btrfs-reschedule-if-necessary-when-logging-directory-items.patch b/queue-5.4/btrfs-reschedule-if-necessary-when-logging-directory-items.patch new file mode 100644 index 00000000000..5feafbd92e6 --- /dev/null +++ b/queue-5.4/btrfs-reschedule-if-necessary-when-logging-directory-items.patch @@ -0,0 +1,111 @@ +From bb56f02f26fe23798edb1b2175707419b28c752a Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 14 Sep 2020 15:27:50 +0100 +Subject: btrfs: reschedule if necessary when logging directory items + +From: Filipe Manana + +commit bb56f02f26fe23798edb1b2175707419b28c752a upstream. + +Logging directories with many entries can take a significant amount of +time, and in some cases monopolize a cpu/core for a long time if the +logging task doesn't happen to block often enough. + +Johannes and Lu Fengqi reported test case generic/041 triggering a soft +lockup when the kernel has CONFIG_SOFTLOCKUP_DETECTOR=y. For this test +case we log an inode with 3002 hard links, and because the test removed +one hard link before fsyncing the file, the inode logging causes the +parent directory do be logged as well, which has 6004 directory items to +log (3002 BTRFS_DIR_ITEM_KEY items plus 3002 BTRFS_DIR_INDEX_KEY items), +so it can take a significant amount of time and trigger the soft lockup. + +So just make tree-log.c:log_dir_items() reschedule when necessary, +releasing the current search path before doing so and then resume from +where it was before the reschedule. + +The stack trace produced when the soft lockup happens is the following: + +[10480.277653] watchdog: BUG: soft lockup - CPU#2 stuck for 22s! [xfs_io:28172] +[10480.279418] Modules linked in: dm_thin_pool dm_persistent_data (...) +[10480.284915] irq event stamp: 29646366 +[10480.285987] hardirqs last enabled at (29646365): [] __slab_alloc.constprop.0+0x56/0x60 +[10480.288482] hardirqs last disabled at (29646366): [] irqentry_enter+0x1d/0x50 +[10480.290856] softirqs last enabled at (4612): [] __do_softirq+0x323/0x56c +[10480.293615] softirqs last disabled at (4483): [] asm_call_on_stack+0xf/0x20 +[10480.296428] CPU: 2 PID: 28172 Comm: xfs_io Not tainted 5.9.0-rc4-default+ #1248 +[10480.298948] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-59-gc9ba527-rebuilt.opensuse.org 04/01/2014 +[10480.302455] RIP: 0010:__slab_alloc.constprop.0+0x19/0x60 +[10480.304151] Code: 86 e8 31 75 21 00 66 66 2e 0f 1f 84 00 00 00 (...) +[10480.309558] RSP: 0018:ffffadbe09397a58 EFLAGS: 00000282 +[10480.311179] RAX: ffff8a495ab92840 RBX: 0000000000000282 RCX: 0000000000000006 +[10480.313242] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff85249b66 +[10480.315260] RBP: ffff8a497d04b740 R08: 0000000000000001 R09: 0000000000000001 +[10480.317229] R10: ffff8a497d044800 R11: ffff8a495ab93c40 R12: 0000000000000000 +[10480.319169] R13: 0000000000000000 R14: 0000000000000c40 R15: ffffffffc01daf70 +[10480.321104] FS: 00007fa1dc5c0e40(0000) GS:ffff8a497da00000(0000) knlGS:0000000000000000 +[10480.323559] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[10480.325235] CR2: 00007fa1dc5befb8 CR3: 0000000004f8a006 CR4: 0000000000170ea0 +[10480.327259] Call Trace: +[10480.328286] ? overwrite_item+0x1f0/0x5a0 [btrfs] +[10480.329784] __kmalloc+0x831/0xa20 +[10480.331009] ? btrfs_get_32+0xb0/0x1d0 [btrfs] +[10480.332464] overwrite_item+0x1f0/0x5a0 [btrfs] +[10480.333948] log_dir_items+0x2ee/0x570 [btrfs] +[10480.335413] log_directory_changes+0x82/0xd0 [btrfs] +[10480.336926] btrfs_log_inode+0xc9b/0xda0 [btrfs] +[10480.338374] ? init_once+0x20/0x20 [btrfs] +[10480.339711] btrfs_log_inode_parent+0x8d3/0xd10 [btrfs] +[10480.341257] ? dget_parent+0x97/0x2e0 +[10480.342480] btrfs_log_dentry_safe+0x3a/0x50 [btrfs] +[10480.343977] btrfs_sync_file+0x24b/0x5e0 [btrfs] +[10480.345381] do_fsync+0x38/0x70 +[10480.346483] __x64_sys_fsync+0x10/0x20 +[10480.347703] do_syscall_64+0x2d/0x70 +[10480.348891] entry_SYSCALL_64_after_hwframe+0x44/0xa9 +[10480.350444] RIP: 0033:0x7fa1dc80970b +[10480.351642] Code: 0f 05 48 3d 00 f0 ff ff 77 45 c3 0f 1f 40 00 48 (...) +[10480.356952] RSP: 002b:00007fffb3d081d0 EFLAGS: 00000293 ORIG_RAX: 000000000000004a +[10480.359458] RAX: ffffffffffffffda RBX: 0000562d93d45e40 RCX: 00007fa1dc80970b +[10480.361426] RDX: 0000562d93d44ab0 RSI: 0000562d93d45e60 RDI: 0000000000000003 +[10480.363367] RBP: 0000000000000001 R08: 0000000000000000 R09: 00007fa1dc7b2a40 +[10480.365317] R10: 0000562d93d0e366 R11: 0000000000000293 R12: 0000000000000001 +[10480.367299] R13: 0000562d93d45290 R14: 0000562d93d45e40 R15: 0000562d93d45e60 + +Link: https://lore.kernel.org/linux-btrfs/20180713090216.GC575@fnst.localdomain/ +Reported-by: Johannes Thumshirn +CC: stable@vger.kernel.org # 4.4+ +Tested-by: Johannes Thumshirn +Reviewed-by: Johannes Thumshirn +Signed-off-by: Filipe Manana +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-log.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -3639,6 +3639,7 @@ static noinline int log_dir_items(struct + * search and this search we'll not find the key again and can just + * bail. + */ ++search: + ret = btrfs_search_slot(NULL, root, &min_key, path, 0, 0); + if (ret != 0) + goto done; +@@ -3658,6 +3659,13 @@ static noinline int log_dir_items(struct + + if (min_key.objectid != ino || min_key.type != key_type) + goto done; ++ ++ if (need_resched()) { ++ btrfs_release_path(path); ++ cond_resched(); ++ goto search; ++ } ++ + ret = overwrite_item(trans, log, dst_path, src, i, + &min_key); + if (ret) { diff --git a/queue-5.4/btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch b/queue-5.4/btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch new file mode 100644 index 00000000000..af4cb8ceb33 --- /dev/null +++ b/queue-5.4/btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch @@ -0,0 +1,273 @@ +From 98272bb77bf4cc20ed1ffca89832d713e70ebf09 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 21 Sep 2020 14:13:29 +0100 +Subject: btrfs: send, orphanize first all conflicting inodes when processing references + +From: Filipe Manana + +commit 98272bb77bf4cc20ed1ffca89832d713e70ebf09 upstream. + +When doing an incremental send it is possible that when processing the new +references for an inode we end up issuing rename or link operations that +have an invalid path, which contains the orphanized name of a directory +before we actually orphanized it, causing the receiver to fail. + +The following reproducer triggers such scenario: + + $ cat reproducer.sh + #!/bin/bash + + mkfs.btrfs -f /dev/sdi >/dev/null + mount /dev/sdi /mnt/sdi + + touch /mnt/sdi/a + touch /mnt/sdi/b + mkdir /mnt/sdi/testdir + # We want "a" to have a lower inode number then "testdir" (257 vs 259). + mv /mnt/sdi/a /mnt/sdi/testdir/a + + # Filesystem looks like: + # + # . (ino 256) + # |----- testdir/ (ino 259) + # | |----- a (ino 257) + # | + # |----- b (ino 258) + + btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1 + btrfs send -f /tmp/snap1.send /mnt/sdi/snap1 + + # Now rename 259 to "testdir_2", then change the name of 257 to + # "testdir" and make it a direct descendant of the root inode (256). + # Also create a new link for inode 257 with the old name of inode 258. + # By swapping the names and location of several inodes and create a + # nasty dependency chain of rename and link operations. + mv /mnt/sdi/testdir/a /mnt/sdi/a2 + touch /mnt/sdi/testdir/a + mv /mnt/sdi/b /mnt/sdi/b2 + ln /mnt/sdi/a2 /mnt/sdi/b + mv /mnt/sdi/testdir /mnt/sdi/testdir_2 + mv /mnt/sdi/a2 /mnt/sdi/testdir + + # Filesystem now looks like: + # + # . (ino 256) + # |----- testdir_2/ (ino 259) + # | |----- a (ino 260) + # | + # |----- testdir (ino 257) + # |----- b (ino 257) + # |----- b2 (ino 258) + + btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2 + btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2 + + mkfs.btrfs -f /dev/sdj >/dev/null + mount /dev/sdj /mnt/sdj + + btrfs receive -f /tmp/snap1.send /mnt/sdj + btrfs receive -f /tmp/snap2.send /mnt/sdj + + umount /mnt/sdi + umount /mnt/sdj + +When running the reproducer, the receive of the incremental send stream +fails: + + $ ./reproducer.sh + Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1' + At subvol /mnt/sdi/snap1 + Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2' + At subvol /mnt/sdi/snap2 + At subvol snap1 + At snapshot snap2 + ERROR: link b -> o259-6-0/a failed: No such file or directory + +The problem happens because of the following: + +1) Before we start iterating the list of new references for inode 257, + we generate its current path and store it at @valid_path, done at + the very beginning of process_recorded_refs(). The generated path + is "o259-6-0/a", containing the orphanized name for inode 259; + +2) Then we iterate over the list of new references, which has the + references "b" and "testdir" in that specific order; + +3) We process reference "b" first, because it is in the list before + reference "testdir". We then issue a link operation to create + the new reference "b" using a target path corresponding to the + content at @valid_path, which corresponds to "o259-6-0/a". + However we haven't yet orphanized inode 259, its name is still + "testdir", and not "o259-6-0". The orphanization of 259 did not + happen yet because we will process the reference named "testdir" + for inode 257 only in the next iteration of the loop that goes + over the list of new references. + +Fix the issue by having a preliminar iteration over all the new references +at process_recorded_refs(). This iteration is responsible only for doing +the orphanization of other inodes that have and old reference that +conflicts with one of the new references of the inode we are currently +processing. The emission of rename and link operations happen now in the +next iteration of the new references. + +A test case for fstests will follow soon. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/send.c | 127 ++++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 87 insertions(+), 40 deletions(-) + +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -3880,52 +3880,56 @@ static int process_recorded_refs(struct + goto out; + } + ++ /* ++ * Before doing any rename and link operations, do a first pass on the ++ * new references to orphanize any unprocessed inodes that may have a ++ * reference that conflicts with one of the new references of the current ++ * inode. This needs to happen first because a new reference may conflict ++ * with the old reference of a parent directory, so we must make sure ++ * that the path used for link and rename commands don't use an ++ * orphanized name when an ancestor was not yet orphanized. ++ * ++ * Example: ++ * ++ * Parent snapshot: ++ * ++ * . (ino 256) ++ * |----- testdir/ (ino 259) ++ * | |----- a (ino 257) ++ * | ++ * |----- b (ino 258) ++ * ++ * Send snapshot: ++ * ++ * . (ino 256) ++ * |----- testdir_2/ (ino 259) ++ * | |----- a (ino 260) ++ * | ++ * |----- testdir (ino 257) ++ * |----- b (ino 257) ++ * |----- b2 (ino 258) ++ * ++ * Processing the new reference for inode 257 with name "b" may happen ++ * before processing the new reference with name "testdir". If so, we ++ * must make sure that by the time we send a link command to create the ++ * hard link "b", inode 259 was already orphanized, since the generated ++ * path in "valid_path" already contains the orphanized name for 259. ++ * We are processing inode 257, so only later when processing 259 we do ++ * the rename operation to change its temporary (orphanized) name to ++ * "testdir_2". ++ */ + list_for_each_entry(cur, &sctx->new_refs, list) { +- /* +- * We may have refs where the parent directory does not exist +- * yet. This happens if the parent directories inum is higher +- * than the current inum. To handle this case, we create the +- * parent directory out of order. But we need to check if this +- * did already happen before due to other refs in the same dir. +- */ + ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen); + if (ret < 0) + goto out; +- if (ret == inode_state_will_create) { +- ret = 0; +- /* +- * First check if any of the current inodes refs did +- * already create the dir. +- */ +- list_for_each_entry(cur2, &sctx->new_refs, list) { +- if (cur == cur2) +- break; +- if (cur2->dir == cur->dir) { +- ret = 1; +- break; +- } +- } +- +- /* +- * If that did not happen, check if a previous inode +- * did already create the dir. +- */ +- if (!ret) +- ret = did_create_dir(sctx, cur->dir); +- if (ret < 0) +- goto out; +- if (!ret) { +- ret = send_create_inode(sctx, cur->dir); +- if (ret < 0) +- goto out; +- } +- } ++ if (ret == inode_state_will_create) ++ continue; + + /* +- * Check if this new ref would overwrite the first ref of +- * another unprocessed inode. If yes, orphanize the +- * overwritten inode. If we find an overwritten ref that is +- * not the first ref, simply unlink it. ++ * Check if this new ref would overwrite the first ref of another ++ * unprocessed inode. If yes, orphanize the overwritten inode. ++ * If we find an overwritten ref that is not the first ref, ++ * simply unlink it. + */ + ret = will_overwrite_ref(sctx, cur->dir, cur->dir_gen, + cur->name, cur->name_len, +@@ -4002,6 +4006,49 @@ static int process_recorded_refs(struct + if (ret < 0) + goto out; + } ++ } ++ ++ } ++ ++ list_for_each_entry(cur, &sctx->new_refs, list) { ++ /* ++ * We may have refs where the parent directory does not exist ++ * yet. This happens if the parent directories inum is higher ++ * than the current inum. To handle this case, we create the ++ * parent directory out of order. But we need to check if this ++ * did already happen before due to other refs in the same dir. ++ */ ++ ret = get_cur_inode_state(sctx, cur->dir, cur->dir_gen); ++ if (ret < 0) ++ goto out; ++ if (ret == inode_state_will_create) { ++ ret = 0; ++ /* ++ * First check if any of the current inodes refs did ++ * already create the dir. ++ */ ++ list_for_each_entry(cur2, &sctx->new_refs, list) { ++ if (cur == cur2) ++ break; ++ if (cur2->dir == cur->dir) { ++ ret = 1; ++ break; ++ } ++ } ++ ++ /* ++ * If that did not happen, check if a previous inode ++ * did already create the dir. ++ */ ++ if (!ret) ++ ret = did_create_dir(sctx, cur->dir); ++ if (ret < 0) ++ goto out; ++ if (!ret) { ++ ret = send_create_inode(sctx, cur->dir); ++ if (ret < 0) ++ goto out; ++ } + } + + if (S_ISDIR(sctx->cur_inode_mode) && sctx->parent_root) { diff --git a/queue-5.4/btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch b/queue-5.4/btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch new file mode 100644 index 00000000000..40bb11410ef --- /dev/null +++ b/queue-5.4/btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch @@ -0,0 +1,244 @@ +From 9c2b4e0347067396ceb3ae929d6888c81d610259 Mon Sep 17 00:00:00 2001 +From: Filipe Manana +Date: Mon, 21 Sep 2020 14:13:30 +0100 +Subject: btrfs: send, recompute reference path after orphanization of a directory + +From: Filipe Manana + +commit 9c2b4e0347067396ceb3ae929d6888c81d610259 upstream. + +During an incremental send, when an inode has multiple new references we +might end up emitting rename operations for orphanizations that have a +source path that is no longer valid due to a previous orphanization of +some directory inode. This causes the receiver to fail since it tries +to rename a path that does not exists. + +Example reproducer: + + $ cat reproducer.sh + #!/bin/bash + + mkfs.btrfs -f /dev/sdi >/dev/null + mount /dev/sdi /mnt/sdi + + touch /mnt/sdi/f1 + touch /mnt/sdi/f2 + mkdir /mnt/sdi/d1 + mkdir /mnt/sdi/d1/d2 + + # Filesystem looks like: + # + # . (ino 256) + # |----- f1 (ino 257) + # |----- f2 (ino 258) + # |----- d1/ (ino 259) + # |----- d2/ (ino 260) + + btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap1 + btrfs send -f /tmp/snap1.send /mnt/sdi/snap1 + + # Now do a series of changes such that: + # + # *) inode 258 has one new hardlink and the previous name changed + # + # *) both names conflict with the old names of two other inodes: + # + # 1) the new name "d1" conflicts with the old name of inode 259, + # under directory inode 256 (root) + # + # 2) the new name "d2" conflicts with the old name of inode 260 + # under directory inode 259 + # + # *) inodes 259 and 260 now have the old names of inode 258 + # + # *) inode 257 is now located under inode 260 - an inode with a number + # smaller than the inode (258) for which we created a second hard + # link and swapped its names with inodes 259 and 260 + # + ln /mnt/sdi/f2 /mnt/sdi/d1/f2_link + mv /mnt/sdi/f1 /mnt/sdi/d1/d2/f1 + + # Swap d1 and f2. + mv /mnt/sdi/d1 /mnt/sdi/tmp + mv /mnt/sdi/f2 /mnt/sdi/d1 + mv /mnt/sdi/tmp /mnt/sdi/f2 + + # Swap d2 and f2_link + mv /mnt/sdi/f2/d2 /mnt/sdi/tmp + mv /mnt/sdi/f2/f2_link /mnt/sdi/f2/d2 + mv /mnt/sdi/tmp /mnt/sdi/f2/f2_link + + # Filesystem now looks like: + # + # . (ino 256) + # |----- d1 (ino 258) + # |----- f2/ (ino 259) + # |----- f2_link/ (ino 260) + # | |----- f1 (ino 257) + # | + # |----- d2 (ino 258) + + btrfs subvolume snapshot -r /mnt/sdi /mnt/sdi/snap2 + btrfs send -f /tmp/snap2.send -p /mnt/sdi/snap1 /mnt/sdi/snap2 + + mkfs.btrfs -f /dev/sdj >/dev/null + mount /dev/sdj /mnt/sdj + + btrfs receive -f /tmp/snap1.send /mnt/sdj + btrfs receive -f /tmp/snap2.send /mnt/sdj + + umount /mnt/sdi + umount /mnt/sdj + +When executed the receive of the incremental stream fails: + + $ ./reproducer.sh + Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap1' + At subvol /mnt/sdi/snap1 + Create a readonly snapshot of '/mnt/sdi' in '/mnt/sdi/snap2' + At subvol /mnt/sdi/snap2 + At subvol snap1 + At snapshot snap2 + ERROR: rename d1/d2 -> o260-6-0 failed: No such file or directory + +This happens because: + +1) When processing inode 257 we end up computing the name for inode 259 + because it is an ancestor in the send snapshot, and at that point it + still has its old name, "d1", from the parent snapshot because inode + 259 was not yet processed. We then cache that name, which is valid + until we start processing inode 259 (or set the progress to 260 after + processing its references); + +2) Later we start processing inode 258 and collecting all its new + references into the list sctx->new_refs. The first reference in the + list happens to be the reference for name "d1" while the reference for + name "d2" is next (the last element of the list). + We compute the full path "d1/d2" for this second reference and store + it in the reference (its ->full_path member). The path used for the + new parent directory was "d1" and not "f2" because inode 259, the + new parent, was not yet processed; + +3) When we start processing the new references at process_recorded_refs() + we start with the first reference in the list, for the new name "d1". + Because there is a conflicting inode that was not yet processed, which + is directory inode 259, we orphanize it, renaming it from "d1" to + "o259-6-0"; + +4) Then we start processing the new reference for name "d2", and we + realize it conflicts with the reference of inode 260 in the parent + snapshot. So we issue an orphanization operation for inode 260 by + emitting a rename operation with a destination path of "o260-6-0" + and a source path of "d1/d2" - this source path is the value we + stored in the reference earlier at step 2), corresponding to the + ->full_path member of the reference, however that path is no longer + valid due to the orphanization of the directory inode 259 in step 3). + This makes the receiver fail since the path does not exists, it should + have been "o259-6-0/d2". + +Fix this by recomputing the full path of a reference before emitting an +orphanization if we previously orphanized any directory, since that +directory could be a parent in the new path. This is a rare scenario so +keeping it simple and not checking if that previously orphanized directory +is in fact an ancestor of the inode we are trying to orphanize. + +A test case for fstests follows soon. + +CC: stable@vger.kernel.org # 4.4+ +Reviewed-by: Josef Bacik +Signed-off-by: Filipe Manana +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/send.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 72 insertions(+) + +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -3813,6 +3813,72 @@ static int update_ref_path(struct send_c + } + + /* ++ * When processing the new references for an inode we may orphanize an existing ++ * directory inode because its old name conflicts with one of the new references ++ * of the current inode. Later, when processing another new reference of our ++ * inode, we might need to orphanize another inode, but the path we have in the ++ * reference reflects the pre-orphanization name of the directory we previously ++ * orphanized. For example: ++ * ++ * parent snapshot looks like: ++ * ++ * . (ino 256) ++ * |----- f1 (ino 257) ++ * |----- f2 (ino 258) ++ * |----- d1/ (ino 259) ++ * |----- d2/ (ino 260) ++ * ++ * send snapshot looks like: ++ * ++ * . (ino 256) ++ * |----- d1 (ino 258) ++ * |----- f2/ (ino 259) ++ * |----- f2_link/ (ino 260) ++ * | |----- f1 (ino 257) ++ * | ++ * |----- d2 (ino 258) ++ * ++ * When processing inode 257 we compute the name for inode 259 as "d1", and we ++ * cache it in the name cache. Later when we start processing inode 258, when ++ * collecting all its new references we set a full path of "d1/d2" for its new ++ * reference with name "d2". When we start processing the new references we ++ * start by processing the new reference with name "d1", and this results in ++ * orphanizing inode 259, since its old reference causes a conflict. Then we ++ * move on the next new reference, with name "d2", and we find out we must ++ * orphanize inode 260, as its old reference conflicts with ours - but for the ++ * orphanization we use a source path corresponding to the path we stored in the ++ * new reference, which is "d1/d2" and not "o259-6-0/d2" - this makes the ++ * receiver fail since the path component "d1/" no longer exists, it was renamed ++ * to "o259-6-0/" when processing the previous new reference. So in this case we ++ * must recompute the path in the new reference and use it for the new ++ * orphanization operation. ++ */ ++static int refresh_ref_path(struct send_ctx *sctx, struct recorded_ref *ref) ++{ ++ char *name; ++ int ret; ++ ++ name = kmemdup(ref->name, ref->name_len, GFP_KERNEL); ++ if (!name) ++ return -ENOMEM; ++ ++ fs_path_reset(ref->full_path); ++ ret = get_cur_path(sctx, ref->dir, ref->dir_gen, ref->full_path); ++ if (ret < 0) ++ goto out; ++ ++ ret = fs_path_add(ref->full_path, name, ref->name_len); ++ if (ret < 0) ++ goto out; ++ ++ /* Update the reference's base name pointer. */ ++ set_ref_path(ref, ref->full_path); ++out: ++ kfree(name); ++ return ret; ++} ++ ++/* + * This does all the move/link/unlink/rmdir magic. + */ + static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) +@@ -3946,6 +4012,12 @@ static int process_recorded_refs(struct + struct name_cache_entry *nce; + struct waiting_dir_move *wdm; + ++ if (orphanized_dir) { ++ ret = refresh_ref_path(sctx, cur); ++ if (ret < 0) ++ goto out; ++ } ++ + ret = orphanize_inode(sctx, ow_inode, ow_gen, + cur->full_path); + if (ret < 0) diff --git a/queue-5.4/btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch b/queue-5.4/btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch new file mode 100644 index 00000000000..6b016693a43 --- /dev/null +++ b/queue-5.4/btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch @@ -0,0 +1,102 @@ +From 1465af12e254a68706e110846f59cf0f09683184 Mon Sep 17 00:00:00 2001 +From: Qu Wenruo +Date: Tue, 22 Sep 2020 10:37:01 +0800 +Subject: btrfs: tree-checker: fix false alert caused by legacy btrfs root item + +From: Qu Wenruo + +commit 1465af12e254a68706e110846f59cf0f09683184 upstream. + +Commit 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check") +introduced btrfs root item size check, however btrfs root item has two +versions, the legacy one which just ends before generation_v2 member, is +smaller than current btrfs root item size. + +This caused btrfs kernel to reject valid but old tree root leaves. + +Fix this problem by also allowing legacy root item, since kernel can +already handle them pretty well and upgrade to newer root item format +when needed. + +Reported-by: Martin Steigerwald +Fixes: 259ee7754b67 ("btrfs: tree-checker: Add ROOT_ITEM check") +CC: stable@vger.kernel.org # 5.4+ +Tested-By: Martin Steigerwald +Reviewed-by: Josef Bacik +Signed-off-by: Qu Wenruo +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-checker.c | 17 ++++++++++++----- + include/uapi/linux/btrfs_tree.h | 14 ++++++++++++++ + 2 files changed, 26 insertions(+), 5 deletions(-) + +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -869,7 +869,7 @@ static int check_root_item(struct extent + int slot) + { + struct btrfs_fs_info *fs_info = leaf->fs_info; +- struct btrfs_root_item ri; ++ struct btrfs_root_item ri = { 0 }; + const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY | + BTRFS_ROOT_SUBVOL_DEAD; + +@@ -889,14 +889,21 @@ static int check_root_item(struct extent + return -EUCLEAN; + } + +- if (btrfs_item_size_nr(leaf, slot) != sizeof(ri)) { ++ if (btrfs_item_size_nr(leaf, slot) != sizeof(ri) && ++ btrfs_item_size_nr(leaf, slot) != btrfs_legacy_root_item_size()) { + generic_err(leaf, slot, +- "invalid root item size, have %u expect %zu", +- btrfs_item_size_nr(leaf, slot), sizeof(ri)); ++ "invalid root item size, have %u expect %zu or %u", ++ btrfs_item_size_nr(leaf, slot), sizeof(ri), ++ btrfs_legacy_root_item_size()); + } + ++ /* ++ * For legacy root item, the members starting at generation_v2 will be ++ * all filled with 0. ++ * And since we allow geneartion_v2 as 0, it will still pass the check. ++ */ + read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot), +- sizeof(ri)); ++ btrfs_item_size_nr(leaf, slot)); + + /* Generation related */ + if (btrfs_root_generation(&ri) > +--- a/include/uapi/linux/btrfs_tree.h ++++ b/include/uapi/linux/btrfs_tree.h +@@ -4,6 +4,11 @@ + + #include + #include ++#ifdef __KERNEL__ ++#include ++#else ++#include ++#endif + + /* + * This header contains the structure definitions and constants used +@@ -651,6 +656,15 @@ struct btrfs_root_item { + } __attribute__ ((__packed__)); + + /* ++ * Btrfs root item used to be smaller than current size. The old format ends ++ * at where member generation_v2 is. ++ */ ++static inline __u32 btrfs_legacy_root_item_size(void) ++{ ++ return offsetof(struct btrfs_root_item, generation_v2); ++} ++ ++/* + * this is used for both forward and backward root refs + */ + struct btrfs_root_ref { diff --git a/queue-5.4/btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch b/queue-5.4/btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch new file mode 100644 index 00000000000..118c3851244 --- /dev/null +++ b/queue-5.4/btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch @@ -0,0 +1,64 @@ +From 85d07fbe09efd1c529ff3e025e2f0d2c6c96a1b7 Mon Sep 17 00:00:00 2001 +From: Daniel Xu +Date: Thu, 8 Oct 2020 18:09:10 -0700 +Subject: btrfs: tree-checker: validate number of chunk stripes and parity + +From: Daniel Xu + +commit 85d07fbe09efd1c529ff3e025e2f0d2c6c96a1b7 upstream. + +If there's no parity and num_stripes < ncopies, a crafted image can +trigger a division by zero in calc_stripe_length(). + +The image was generated through fuzzing. + +CC: stable@vger.kernel.org # 5.4+ +Reviewed-by: Qu Wenruo +Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=209587 +Signed-off-by: Daniel Xu +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/tree-checker.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/fs/btrfs/tree-checker.c ++++ b/fs/btrfs/tree-checker.c +@@ -577,18 +577,36 @@ int btrfs_check_chunk_valid(struct exten + u64 type; + u64 features; + bool mixed = false; ++ int raid_index; ++ int nparity; ++ int ncopies; + + length = btrfs_chunk_length(leaf, chunk); + stripe_len = btrfs_chunk_stripe_len(leaf, chunk); + num_stripes = btrfs_chunk_num_stripes(leaf, chunk); + sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); + type = btrfs_chunk_type(leaf, chunk); ++ raid_index = btrfs_bg_flags_to_raid_index(type); ++ ncopies = btrfs_raid_array[raid_index].ncopies; ++ nparity = btrfs_raid_array[raid_index].nparity; + + if (!num_stripes) { + chunk_err(leaf, chunk, logical, + "invalid chunk num_stripes, have %u", num_stripes); + return -EUCLEAN; + } ++ if (num_stripes < ncopies) { ++ chunk_err(leaf, chunk, logical, ++ "invalid chunk num_stripes < ncopies, have %u < %d", ++ num_stripes, ncopies); ++ return -EUCLEAN; ++ } ++ if (nparity && num_stripes == nparity) { ++ chunk_err(leaf, chunk, logical, ++ "invalid chunk num_stripes == nparity, have %u == %d", ++ num_stripes, nparity); ++ return -EUCLEAN; ++ } + if (!IS_ALIGNED(logical, fs_info->sectorsize)) { + chunk_err(leaf, chunk, logical, + "invalid chunk logical, have %llu should aligned to %u", diff --git a/queue-5.4/btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch b/queue-5.4/btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch new file mode 100644 index 00000000000..932f9a089b0 --- /dev/null +++ b/queue-5.4/btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch @@ -0,0 +1,37 @@ +From 8eb2fd00153a3a96a19c62ac9c6d48c2efebe5e8 Mon Sep 17 00:00:00 2001 +From: Denis Efremov +Date: Mon, 21 Sep 2020 20:03:35 +0300 +Subject: btrfs: use kvzalloc() to allocate clone_roots in btrfs_ioctl_send() + +From: Denis Efremov + +commit 8eb2fd00153a3a96a19c62ac9c6d48c2efebe5e8 upstream. + +btrfs_ioctl_send() used open-coded kvzalloc implementation earlier. +The code was accidentally replaced with kzalloc() call [1]. Restore +the original code by using kvzalloc() to allocate sctx->clone_roots. + +[1] https://patchwork.kernel.org/patch/9757891/#20529627 + +Fixes: 818e010bf9d0 ("btrfs: replace opencoded kvzalloc with the helper") +CC: stable@vger.kernel.org # 4.14+ +Signed-off-by: Denis Efremov +Reviewed-by: David Sterba +Signed-off-by: David Sterba +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/send.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/fs/btrfs/send.c ++++ b/fs/btrfs/send.c +@@ -7352,7 +7352,7 @@ long btrfs_ioctl_send(struct file *mnt_f + + alloc_size = sizeof(struct clone_root) * (arg->clone_sources_count + 1); + +- sctx->clone_roots = kzalloc(alloc_size, GFP_KERNEL); ++ sctx->clone_roots = kvzalloc(alloc_size, GFP_KERNEL); + if (!sctx->clone_roots) { + ret = -ENOMEM; + goto out; diff --git a/queue-5.4/dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch b/queue-5.4/dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch new file mode 100644 index 00000000000..97ddaff9604 --- /dev/null +++ b/queue-5.4/dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch @@ -0,0 +1,57 @@ +From baf6fd97b16ea8f981b8a8b04039596f32fc2972 Mon Sep 17 00:00:00 2001 +From: Paul Cercueil +Date: Sun, 4 Oct 2020 16:03:07 +0200 +Subject: dmaengine: dma-jz4780: Fix race in jz4780_dma_tx_status + +From: Paul Cercueil + +commit baf6fd97b16ea8f981b8a8b04039596f32fc2972 upstream. + +The jz4780_dma_tx_status() function would check if a channel's cookie +state was set to 'completed', and if not, it would enter the critical +section. However, in that time frame, the jz4780_dma_chan_irq() function +was able to set the cookie to 'completed', and clear the jzchan->vchan +pointer, which was deferenced in the critical section of the first +function. + +Fix this race by checking the channel's cookie state after entering the +critical function and not before. + +Fixes: d894fc6046fe ("dmaengine: jz4780: add driver for the Ingenic JZ4780 DMA controller") +Cc: stable@vger.kernel.org # v4.0 +Signed-off-by: Paul Cercueil +Reported-by: Artur Rojek +Tested-by: Artur Rojek +Link: https://lore.kernel.org/r/20201004140307.885556-1-paul@crapouillou.net +Signed-off-by: Vinod Koul +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/dma/dma-jz4780.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +--- a/drivers/dma/dma-jz4780.c ++++ b/drivers/dma/dma-jz4780.c +@@ -639,11 +639,11 @@ static enum dma_status jz4780_dma_tx_sta + unsigned long flags; + unsigned long residue = 0; + ++ spin_lock_irqsave(&jzchan->vchan.lock, flags); ++ + status = dma_cookie_status(chan, cookie, txstate); + if ((status == DMA_COMPLETE) || (txstate == NULL)) +- return status; +- +- spin_lock_irqsave(&jzchan->vchan.lock, flags); ++ goto out_unlock_irqrestore; + + vdesc = vchan_find_desc(&jzchan->vchan, cookie); + if (vdesc) { +@@ -660,6 +660,7 @@ static enum dma_status jz4780_dma_tx_sta + && jzchan->desc->status & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT)) + status = DMA_ERROR; + ++out_unlock_irqrestore: + spin_unlock_irqrestore(&jzchan->vchan.lock, flags); + return status; + } diff --git a/queue-5.4/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch b/queue-5.4/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch new file mode 100644 index 00000000000..4ee6f34f3fd --- /dev/null +++ b/queue-5.4/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch @@ -0,0 +1,55 @@ +From 8195400f7ea95399f721ad21f4d663a62c65036f Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Mon, 19 Oct 2020 11:15:23 +0100 +Subject: drm/i915: Force VT'd workarounds when running as a guest OS + +From: Chris Wilson + +commit 8195400f7ea95399f721ad21f4d663a62c65036f upstream. + +If i915.ko is being used as a passthrough device, it does not know if +the host is using intel_iommu. Mixing the iommu and gfx causes a few +issues (such as scanout overfetch) which we need to workaround inside +the driver, so if we detect we are running under a hypervisor, also +assume the device access is being virtualised. + +Reported-by: Stefan Fritsch +Suggested-by: Stefan Fritsch +Signed-off-by: Chris Wilson +Cc: Zhenyu Wang +Cc: Joonas Lahtinen +Cc: Stefan Fritsch +Cc: stable@vger.kernel.org +Tested-by: Stefan Fritsch +Reviewed-by: Zhenyu Wang +Link: https://patchwork.freedesktop.org/patch/msgid/20201019101523.4145-1-chris@chris-wilson.co.uk +(cherry picked from commit f566fdcd6cc49a9d5b5d782f56e3e7cb243f01b8) +Signed-off-by: Rodrigo Vivi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/i915/i915_drv.h | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -33,6 +33,8 @@ + #include + #include + ++#include ++ + #include + #include + #include +@@ -2197,7 +2199,9 @@ static inline bool intel_vtd_active(void + if (intel_iommu_gfx_mapped) + return true; + #endif +- return false; ++ ++ /* Running as a guest, we assume the host is enforcing VT'd */ ++ return !hypervisor_is_type(X86_HYPER_NATIVE); + } + + static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv) diff --git a/queue-5.4/extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch b/queue-5.4/extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch new file mode 100644 index 00000000000..dddb7d6a311 --- /dev/null +++ b/queue-5.4/extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch @@ -0,0 +1,57 @@ +From 6aaad58c872db062f7ea2761421ca748bd0931cc Mon Sep 17 00:00:00 2001 +From: Krzysztof Kozlowski +Date: Mon, 17 Aug 2020 09:00:00 +0200 +Subject: extcon: ptn5150: Fix usage of atomic GPIO with sleeping GPIO chips + +From: Krzysztof Kozlowski + +commit 6aaad58c872db062f7ea2761421ca748bd0931cc upstream. + +The driver uses atomic version of gpiod_set_value() without any real +reason. It is called in a workqueue under mutex so it could sleep +there. Changing it to "can_sleep" flavor allows to use the driver with +all GPIO chips. + +Fixes: 4ed754de2d66 ("extcon: Add support for ptn5150 extcon driver") +Cc: +Signed-off-by: Krzysztof Kozlowski +Reviewed-by: Vijai Kumar K +Signed-off-by: Chanwoo Choi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/extcon/extcon-ptn5150.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/extcon/extcon-ptn5150.c ++++ b/drivers/extcon/extcon-ptn5150.c +@@ -127,7 +127,7 @@ static void ptn5150_irq_work(struct work + case PTN5150_DFP_ATTACHED: + extcon_set_state_sync(info->edev, + EXTCON_USB_HOST, false); +- gpiod_set_value(info->vbus_gpiod, 0); ++ gpiod_set_value_cansleep(info->vbus_gpiod, 0); + extcon_set_state_sync(info->edev, EXTCON_USB, + true); + break; +@@ -138,9 +138,9 @@ static void ptn5150_irq_work(struct work + PTN5150_REG_CC_VBUS_DETECTION_MASK) >> + PTN5150_REG_CC_VBUS_DETECTION_SHIFT); + if (vbus) +- gpiod_set_value(info->vbus_gpiod, 0); ++ gpiod_set_value_cansleep(info->vbus_gpiod, 0); + else +- gpiod_set_value(info->vbus_gpiod, 1); ++ gpiod_set_value_cansleep(info->vbus_gpiod, 1); + + extcon_set_state_sync(info->edev, + EXTCON_USB_HOST, true); +@@ -156,7 +156,7 @@ static void ptn5150_irq_work(struct work + EXTCON_USB_HOST, false); + extcon_set_state_sync(info->edev, + EXTCON_USB, false); +- gpiod_set_value(info->vbus_gpiod, 0); ++ gpiod_set_value_cansleep(info->vbus_gpiod, 0); + } + } + diff --git a/queue-5.4/fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch b/queue-5.4/fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch new file mode 100644 index 00000000000..43fcb9d3afd --- /dev/null +++ b/queue-5.4/fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch @@ -0,0 +1,94 @@ +From 6dbf7bb555981fb5faf7b691e8f6169fc2b2e63b Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Fri, 4 Sep 2020 10:58:51 +0200 +Subject: fs: Don't invalidate page buffers in block_write_full_page() + +From: Jan Kara + +commit 6dbf7bb555981fb5faf7b691e8f6169fc2b2e63b upstream. + +If block_write_full_page() is called for a page that is beyond current +inode size, it will truncate page buffers for the page and return 0. +This logic has been added in 2.5.62 in commit 81eb69062588 ("fix ext3 +BUG due to race with truncate") in history.git tree to fix a problem +with ext3 in data=ordered mode. This particular problem doesn't exist +anymore because ext3 is long gone and ext4 handles ordered data +differently. Also normally buffers are invalidated by truncate code and +there's no need to specially handle this in ->writepage() code. + +This invalidation of page buffers in block_write_full_page() is causing +issues to filesystems (e.g. ext4 or ocfs2) when block device is shrunk +under filesystem's hands and metadata buffers get discarded while being +tracked by the journalling layer. Although it is obviously "not +supported" it can cause kernel crashes like: + +[ 7986.689400] BUG: unable to handle kernel NULL pointer dereference at ++0000000000000008 +[ 7986.697197] PGD 0 P4D 0 +[ 7986.699724] Oops: 0002 [#1] SMP PTI +[ 7986.703200] CPU: 4 PID: 203778 Comm: jbd2/dm-3-8 Kdump: loaded Tainted: G ++O --------- - - 4.18.0-147.5.0.5.h126.eulerosv2r9.x86_64 #1 +[ 7986.716438] Hardware name: Huawei RH2288H V3/BC11HGSA0, BIOS 1.57 08/11/2015 +[ 7986.723462] RIP: 0010:jbd2_journal_grab_journal_head+0x1b/0x40 [jbd2] +... +[ 7986.810150] Call Trace: +[ 7986.812595] __jbd2_journal_insert_checkpoint+0x23/0x70 [jbd2] +[ 7986.818408] jbd2_journal_commit_transaction+0x155f/0x1b60 [jbd2] +[ 7986.836467] kjournald2+0xbd/0x270 [jbd2] + +which is not great. The crash happens because bh->b_private is suddently +NULL although BH_JBD flag is still set (this is because +block_invalidatepage() cleared BH_Mapped flag and subsequent bh lookup +found buffer without BH_Mapped set, called init_page_buffers() which has +rewritten bh->b_private). So just remove the invalidation in +block_write_full_page(). + +Note that the buffer cache invalidation when block device changes size +is already careful to avoid similar problems by using +invalidate_mapping_pages() which skips busy buffers so it was only this +odd block_write_full_page() behavior that could tear down bdev buffers +under filesystem's hands. + +Reported-by: Ye Bin +Signed-off-by: Jan Kara +Reviewed-by: Christoph Hellwig +CC: stable@vger.kernel.org +Signed-off-by: Jens Axboe +Signed-off-by: Greg Kroah-Hartman + +--- + fs/buffer.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +--- a/fs/buffer.c ++++ b/fs/buffer.c +@@ -2739,16 +2739,6 @@ int nobh_writepage(struct page *page, ge + /* Is the page fully outside i_size? (truncate in progress) */ + offset = i_size & (PAGE_SIZE-1); + if (page->index >= end_index+1 || !offset) { +- /* +- * The page may have dirty, unmapped buffers. For example, +- * they may have been added in ext3_writepage(). Make them +- * freeable here, so the page does not leak. +- */ +-#if 0 +- /* Not really sure about this - do we need this ? */ +- if (page->mapping->a_ops->invalidatepage) +- page->mapping->a_ops->invalidatepage(page, offset); +-#endif + unlock_page(page); + return 0; /* don't care */ + } +@@ -2943,12 +2933,6 @@ int block_write_full_page(struct page *p + /* Is the page fully outside i_size? (truncate in progress) */ + offset = i_size & (PAGE_SIZE-1); + if (page->index >= end_index+1 || !offset) { +- /* +- * The page may have dirty, unmapped buffers. For example, +- * they may have been added in ext3_writepage(). Make them +- * freeable here, so the page does not leak. +- */ +- do_invalidatepage(page, 0, PAGE_SIZE); + unlock_page(page); + return 0; /* don't care */ + } diff --git a/queue-5.4/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch b/queue-5.4/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch new file mode 100644 index 00000000000..7de8bc3a0cb --- /dev/null +++ b/queue-5.4/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch @@ -0,0 +1,61 @@ +From d9216d753b2b1406b801243b12aaf00a5ce5b861 Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Wed, 23 Sep 2020 13:14:56 -0700 +Subject: HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery + +From: Jason Gerecke + +commit d9216d753b2b1406b801243b12aaf00a5ce5b861 upstream. + +It has recently been reported that the "heartbeat" report from devices +like the 2nd-gen Intuos Pro (PTH-460, PTH-660, PTH-860) or the 2nd-gen +Bluetooth-enabled Intuos tablets (CTL-4100WL, CTL-6100WL) can cause the +driver to send a spurious BTN_TOUCH=0 once per second in the middle of +drawing. This can result in broken lines while drawing on Chrome OS. + +The source of the issue has been traced back to a change which modified +the driver to only call `wacom_wac_pad_report()` once per report instead +of once per collection. As part of this change, pad-handling code was +removed from `wacom_wac_collection()` under the assumption that the +`WACOM_PEN_FIELD` and `WACOM_TOUCH_FIELD` checks would not be satisfied +when a pad or battery collection was being processed. + +To be clear, the macros `WACOM_PAD_FIELD` and `WACOM_PEN_FIELD` do not +currently check exclusive conditions. In fact, most "pad" fields will +also appear to be "pen" fields simply due to their presence inside of +a Digitizer application collection. Because of this, the removal of +the check from `wacom_wac_collection()` just causes pad / battery +collections to instead trigger a call to `wacom_wac_pen_report()` +instead. The pen report function in turn resets the tip switch state +just prior to exiting, resulting in the observed BTN_TOUCH=0 symptom. + +To correct this, we restore a version of the `WACOM_PAD_FIELD` check +in `wacom_wac_collection()` and return early. This effectively prevents +pad / battery collections from being reported until the very end of the +report as originally intended. + +Fixes: d4b8efeb46d9 ("HID: wacom: generic: Correct pad syncing") +Cc: stable@vger.kernel.org # v4.17+ +Signed-off-by: Jason Gerecke +Reviewed-by: Ping Cheng +Tested-by: Ping Cheng +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/wacom_wac.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/hid/wacom_wac.c ++++ b/drivers/hid/wacom_wac.c +@@ -2773,7 +2773,9 @@ static int wacom_wac_collection(struct h + if (report->type != HID_INPUT_REPORT) + return -1; + +- if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) ++ if (WACOM_PAD_FIELD(field)) ++ return 0; ++ else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input) + wacom_wac_pen_report(hdev, report); + else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input) + wacom_wac_finger_report(hdev, report); diff --git a/queue-5.4/iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch b/queue-5.4/iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch new file mode 100644 index 00000000000..177a9e363aa --- /dev/null +++ b/queue-5.4/iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch @@ -0,0 +1,98 @@ +From da4410d4078ba4ead9d6f1027d6db77c5a74ecee Mon Sep 17 00:00:00 2001 +From: Tobias Jordan +Date: Sat, 26 Sep 2020 18:19:46 +0200 +Subject: iio: adc: gyroadc: fix leak of device node iterator + +From: Tobias Jordan + +commit da4410d4078ba4ead9d6f1027d6db77c5a74ecee upstream. + +Add missing of_node_put calls when exiting the for_each_child_of_node +loop in rcar_gyroadc_parse_subdevs early. + +Also add goto-exception handling for the error paths in that loop. + +Fixes: 059c53b32329 ("iio: adc: Add Renesas GyroADC driver") +Signed-off-by: Tobias Jordan +Link: https://lore.kernel.org/r/20200926161946.GA10240@agrajag.zerfleddert.de +Cc: +Signed-off-by: Jonathan Cameron +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/adc/rcar-gyroadc.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +--- a/drivers/iio/adc/rcar-gyroadc.c ++++ b/drivers/iio/adc/rcar-gyroadc.c +@@ -357,7 +357,7 @@ static int rcar_gyroadc_parse_subdevs(st + num_channels = ARRAY_SIZE(rcar_gyroadc_iio_channels_3); + break; + default: +- return -EINVAL; ++ goto err_e_inval; + } + + /* +@@ -374,7 +374,7 @@ static int rcar_gyroadc_parse_subdevs(st + dev_err(dev, + "Failed to get child reg property of ADC \"%pOFn\".\n", + child); +- return ret; ++ goto err_of_node_put; + } + + /* Channel number is too high. */ +@@ -382,7 +382,7 @@ static int rcar_gyroadc_parse_subdevs(st + dev_err(dev, + "Only %i channels supported with %pOFn, but reg = <%i>.\n", + num_channels, child, reg); +- return -EINVAL; ++ goto err_e_inval; + } + } + +@@ -391,7 +391,7 @@ static int rcar_gyroadc_parse_subdevs(st + dev_err(dev, + "Channel %i uses different ADC mode than the rest.\n", + reg); +- return -EINVAL; ++ goto err_e_inval; + } + + /* Channel is valid, grab the regulator. */ +@@ -401,7 +401,8 @@ static int rcar_gyroadc_parse_subdevs(st + if (IS_ERR(vref)) { + dev_dbg(dev, "Channel %i 'vref' supply not connected.\n", + reg); +- return PTR_ERR(vref); ++ ret = PTR_ERR(vref); ++ goto err_of_node_put; + } + + priv->vref[reg] = vref; +@@ -425,8 +426,10 @@ static int rcar_gyroadc_parse_subdevs(st + * attached to the GyroADC at a time, so if we found it, + * we can stop parsing here. + */ +- if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) ++ if (childmode == RCAR_GYROADC_MODE_SELECT_1_MB88101A) { ++ of_node_put(child); + break; ++ } + } + + if (first) { +@@ -435,6 +438,12 @@ static int rcar_gyroadc_parse_subdevs(st + } + + return 0; ++ ++err_e_inval: ++ ret = -EINVAL; ++err_of_node_put: ++ of_node_put(child); ++ return ret; + } + + static void rcar_gyroadc_deinit_supplies(struct iio_dev *indio_dev) diff --git a/queue-5.4/iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch b/queue-5.4/iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch new file mode 100644 index 00000000000..ab8d6b36d4d --- /dev/null +++ b/queue-5.4/iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch @@ -0,0 +1,75 @@ +From 39e91f3be4cba51c1560bcda3a343ed1f64dc916 Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Wed, 22 Jul 2020 16:51:00 +0100 +Subject: iio:adc:ti-adc0832 Fix alignment issue with timestamp + +From: Jonathan Cameron + +commit 39e91f3be4cba51c1560bcda3a343ed1f64dc916 upstream. + +One of a class of bugs pointed out by Lars in a recent review. +iio_push_to_buffers_with_timestamp assumes the buffer used is aligned +to the size of the timestamp (8 bytes). This is not guaranteed in +this driver which uses an array of smaller elements on the stack. + +We fix this issues by moving to a suitable structure in the iio_priv() +data with alignment explicitly requested. This data is allocated +with kzalloc so no data can leak apart from previous readings. +Note that previously no data could leak 'including' previous readings +but I don't think it is an issue to potentially leak them like +this now does. + +In this case the postioning of the timestamp is depends on what +other channels are enabled. As such we cannot use a structure to +make the alignment explicit as it would be missleading by suggesting +only one possible location for the timestamp. + +Fixes: 815bbc87462a ("iio: ti-adc0832: add triggered buffer support") +Reported-by: Lars-Peter Clausen +Signed-off-by: Jonathan Cameron +Reviewed-by: Andy Shevchenko +Cc: Akinobu Mita +Cc: +Link: https://lore.kernel.org/r/20200722155103.979802-25-jic23@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/adc/ti-adc0832.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +--- a/drivers/iio/adc/ti-adc0832.c ++++ b/drivers/iio/adc/ti-adc0832.c +@@ -28,6 +28,12 @@ struct adc0832 { + struct regulator *reg; + struct mutex lock; + u8 mux_bits; ++ /* ++ * Max size needed: 16x 1 byte ADC data + 8 bytes timestamp ++ * May be shorter if not all channels are enabled subject ++ * to the timestamp remaining 8 byte aligned. ++ */ ++ u8 data[24] __aligned(8); + + u8 tx_buf[2] ____cacheline_aligned; + u8 rx_buf[2]; +@@ -199,7 +205,6 @@ static irqreturn_t adc0832_trigger_handl + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc0832 *adc = iio_priv(indio_dev); +- u8 data[24] = { }; /* 16x 1 byte ADC data + 8 bytes timestamp */ + int scan_index; + int i = 0; + +@@ -217,10 +222,10 @@ static irqreturn_t adc0832_trigger_handl + goto out; + } + +- data[i] = ret; ++ adc->data[i] = ret; + i++; + } +- iio_push_to_buffers_with_timestamp(indio_dev, data, ++ iio_push_to_buffers_with_timestamp(indio_dev, adc->data, + iio_get_time_ns(indio_dev)); + out: + mutex_unlock(&adc->lock); diff --git a/queue-5.4/iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch b/queue-5.4/iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch new file mode 100644 index 00000000000..bb4419785a4 --- /dev/null +++ b/queue-5.4/iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch @@ -0,0 +1,87 @@ +From 293e809b2e8e608b65a949101aaf7c0bd1224247 Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Wed, 22 Jul 2020 16:51:01 +0100 +Subject: iio:adc:ti-adc12138 Fix alignment issue with timestamp + +From: Jonathan Cameron + +commit 293e809b2e8e608b65a949101aaf7c0bd1224247 upstream. + +One of a class of bugs pointed out by Lars in a recent review. +iio_push_to_buffers_with_timestamp assumes the buffer used is aligned +to the size of the timestamp (8 bytes). This is not guaranteed in +this driver which uses an array of smaller elements on the stack. + +We move to a suitable structure in the iio_priv() data with alignment +explicitly requested. This data is allocated with kzalloc so no +data can leak apart from previous readings. Note that previously +no leak at all could occur, but previous readings should never +be a problem. + +In this case the timestamp location depends on what other channels +are enabled. As such we can't use a structure without misleading +by suggesting only one possible timestamp location. + +Fixes: 50a6edb1b6e0 ("iio: adc: add ADC12130/ADC12132/ADC12138 ADC driver") +Reported-by: Lars-Peter Clausen +Signed-off-by: Jonathan Cameron +Reviewed-by: Andy Shevchenko +Cc: Akinobu Mita +Cc: +Link: https://lore.kernel.org/r/20200722155103.979802-26-jic23@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/adc/ti-adc12138.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +--- a/drivers/iio/adc/ti-adc12138.c ++++ b/drivers/iio/adc/ti-adc12138.c +@@ -47,6 +47,12 @@ struct adc12138 { + struct completion complete; + /* The number of cclk periods for the S/H's acquisition time */ + unsigned int acquisition_time; ++ /* ++ * Maximum size needed: 16x 2 bytes ADC data + 8 bytes timestamp. ++ * Less may be need if not all channels are enabled, as long as ++ * the 8 byte alignment of the timestamp is maintained. ++ */ ++ __be16 data[20] __aligned(8); + + u8 tx_buf[2] ____cacheline_aligned; + u8 rx_buf[2]; +@@ -329,7 +335,6 @@ static irqreturn_t adc12138_trigger_hand + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct adc12138 *adc = iio_priv(indio_dev); +- __be16 data[20] = { }; /* 16x 2 bytes ADC data + 8 bytes timestamp */ + __be16 trash; + int ret; + int scan_index; +@@ -345,7 +350,7 @@ static irqreturn_t adc12138_trigger_hand + reinit_completion(&adc->complete); + + ret = adc12138_start_and_read_conv(adc, scan_chan, +- i ? &data[i - 1] : &trash); ++ i ? &adc->data[i - 1] : &trash); + if (ret) { + dev_warn(&adc->spi->dev, + "failed to start conversion\n"); +@@ -362,7 +367,7 @@ static irqreturn_t adc12138_trigger_hand + } + + if (i) { +- ret = adc12138_read_conv_data(adc, &data[i - 1]); ++ ret = adc12138_read_conv_data(adc, &adc->data[i - 1]); + if (ret) { + dev_warn(&adc->spi->dev, + "failed to get conversion data\n"); +@@ -370,7 +375,7 @@ static irqreturn_t adc12138_trigger_hand + } + } + +- iio_push_to_buffers_with_timestamp(indio_dev, data, ++ iio_push_to_buffers_with_timestamp(indio_dev, adc->data, + iio_get_time_ns(indio_dev)); + out: + mutex_unlock(&adc->lock); diff --git a/queue-5.4/iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch b/queue-5.4/iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch new file mode 100644 index 00000000000..a793b3c1ed1 --- /dev/null +++ b/queue-5.4/iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch @@ -0,0 +1,60 @@ +From 10ab7cfd5522f0041028556dac864a003e158556 Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Wed, 22 Jul 2020 16:50:41 +0100 +Subject: iio:gyro:itg3200: Fix timestamp alignment and prevent data leak. + +From: Jonathan Cameron + +commit 10ab7cfd5522f0041028556dac864a003e158556 upstream. + +One of a class of bugs pointed out by Lars in a recent review. +iio_push_to_buffers_with_timestamp assumes the buffer used is aligned +to the size of the timestamp (8 bytes). This is not guaranteed in +this driver which uses a 16 byte array of smaller elements on the stack. +This is fixed by using an explicit c structure. As there are no +holes in the structure, there is no possiblity of data leakage +in this case. + +The explicit alignment of ts is not strictly necessary but potentially +makes the code slightly less fragile. It also removes the possibility +of this being cut and paste into another driver where the alignment +isn't already true. + +Fixes: 36e0371e7764 ("iio:itg3200: Use iio_push_to_buffers_with_timestamp()") +Reported-by: Lars-Peter Clausen +Signed-off-by: Jonathan Cameron +Reviewed-by: Andy Shevchenko +Cc: +Link: https://lore.kernel.org/r/20200722155103.979802-6-jic23@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/gyro/itg3200_buffer.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/iio/gyro/itg3200_buffer.c ++++ b/drivers/iio/gyro/itg3200_buffer.c +@@ -46,13 +46,20 @@ static irqreturn_t itg3200_trigger_handl + struct iio_poll_func *pf = p; + struct iio_dev *indio_dev = pf->indio_dev; + struct itg3200 *st = iio_priv(indio_dev); +- __be16 buf[ITG3200_SCAN_ELEMENTS + sizeof(s64)/sizeof(u16)]; ++ /* ++ * Ensure correct alignment and padding including for the ++ * timestamp that may be inserted. ++ */ ++ struct { ++ __be16 buf[ITG3200_SCAN_ELEMENTS]; ++ s64 ts __aligned(8); ++ } scan; + +- int ret = itg3200_read_all_channels(st->i2c, buf); ++ int ret = itg3200_read_all_channels(st->i2c, scan.buf); + if (ret < 0) + goto error_ret; + +- iio_push_to_buffers_with_timestamp(indio_dev, buf, pf->timestamp); ++ iio_push_to_buffers_with_timestamp(indio_dev, &scan, pf->timestamp); + + iio_trigger_notify_done(indio_dev->trig); + diff --git a/queue-5.4/iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch b/queue-5.4/iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch new file mode 100644 index 00000000000..956c6aa2bd0 --- /dev/null +++ b/queue-5.4/iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch @@ -0,0 +1,94 @@ +From 0456ecf34d466261970e0ff92b2b9c78a4908637 Mon Sep 17 00:00:00 2001 +From: Jonathan Cameron +Date: Wed, 22 Jul 2020 16:50:44 +0100 +Subject: iio:light:si1145: Fix timestamp alignment and prevent data leak. + +From: Jonathan Cameron + +commit 0456ecf34d466261970e0ff92b2b9c78a4908637 upstream. + +One of a class of bugs pointed out by Lars in a recent review. +iio_push_to_buffers_with_timestamp assumes the buffer used is aligned +to the size of the timestamp (8 bytes). This is not guaranteed in +this driver which uses a 24 byte array of smaller elements on the stack. +As Lars also noted this anti pattern can involve a leak of data to +userspace and that indeed can happen here. We close both issues by +moving to a suitable array in the iio_priv() data with alignment +explicitly requested. This data is allocated with kzalloc so no +data can leak appart from previous readings. + +Depending on the enabled channels, the location of the timestamp +can be at various aligned offsets through the buffer. As such we +any use of a structure to enforce this alignment would incorrectly +suggest a single location for the timestamp. Comments adjusted to +express this clearly in the code. + +Fixes: ac45e57f1590 ("iio: light: Add driver for Silabs si1132, si1141/2/3 and si1145/6/7 ambient light, uv index and proximity sensors") +Reported-by: Lars-Peter Clausen +Signed-off-by: Jonathan Cameron +Reviewed-by: Andy Shevchenko +Cc: Peter Meerwald-Stadler +Cc: +Link: https://lore.kernel.org/r/20200722155103.979802-9-jic23@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iio/light/si1145.c | 19 +++++++++++-------- + 1 file changed, 11 insertions(+), 8 deletions(-) + +--- a/drivers/iio/light/si1145.c ++++ b/drivers/iio/light/si1145.c +@@ -169,6 +169,7 @@ struct si1145_part_info { + * @part_info: Part information + * @trig: Pointer to iio trigger + * @meas_rate: Value of MEAS_RATE register. Only set in HW in auto mode ++ * @buffer: Used to pack data read from sensor. + */ + struct si1145_data { + struct i2c_client *client; +@@ -180,6 +181,14 @@ struct si1145_data { + bool autonomous; + struct iio_trigger *trig; + int meas_rate; ++ /* ++ * Ensure timestamp will be naturally aligned if present. ++ * Maximum buffer size (may be only partly used if not all ++ * channels are enabled): ++ * 6*2 bytes channels data + 4 bytes alignment + ++ * 8 bytes timestamp ++ */ ++ u8 buffer[24] __aligned(8); + }; + + /** +@@ -441,12 +450,6 @@ static irqreturn_t si1145_trigger_handle + struct iio_poll_func *pf = private; + struct iio_dev *indio_dev = pf->indio_dev; + struct si1145_data *data = iio_priv(indio_dev); +- /* +- * Maximum buffer size: +- * 6*2 bytes channels data + 4 bytes alignment + +- * 8 bytes timestamp +- */ +- u8 buffer[24]; + int i, j = 0; + int ret; + u8 irq_status = 0; +@@ -479,7 +482,7 @@ static irqreturn_t si1145_trigger_handle + + ret = i2c_smbus_read_i2c_block_data_or_emulated( + data->client, indio_dev->channels[i].address, +- sizeof(u16) * run, &buffer[j]); ++ sizeof(u16) * run, &data->buffer[j]); + if (ret < 0) + goto done; + j += run * sizeof(u16); +@@ -494,7 +497,7 @@ static irqreturn_t si1145_trigger_handle + goto done; + } + +- iio_push_to_buffers_with_timestamp(indio_dev, buffer, ++ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_get_time_ns(indio_dev)); + + done: diff --git a/queue-5.4/leds-bcm6328-bcm6358-use-devres-led-registering-function.patch b/queue-5.4/leds-bcm6328-bcm6358-use-devres-led-registering-function.patch new file mode 100644 index 00000000000..315a123dcc6 --- /dev/null +++ b/queue-5.4/leds-bcm6328-bcm6358-use-devres-led-registering-function.patch @@ -0,0 +1,53 @@ +From ff5c89d44453e7ad99502b04bf798a3fc32c758b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marek=20Beh=C3=BAn?= +Date: Fri, 18 Sep 2020 00:32:58 +0200 +Subject: leds: bcm6328, bcm6358: use devres LED registering function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +commit ff5c89d44453e7ad99502b04bf798a3fc32c758b upstream. + +These two drivers do not provide remove method and use devres for +allocation of other resources, yet they use led_classdev_register +instead of the devres variant, devm_led_classdev_register. + +Fix this. + +Signed-off-by: Marek Behún +Cc: Álvaro Fernández Rojas +Cc: Kevin Cernekee +Cc: Jaedon Shin +Signed-off-by: Pavel Machek +Cc: stable@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/leds/leds-bcm6328.c | 2 +- + drivers/leds/leds-bcm6358.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/leds/leds-bcm6328.c ++++ b/drivers/leds/leds-bcm6328.c +@@ -332,7 +332,7 @@ static int bcm6328_led(struct device *de + led->cdev.brightness_set = bcm6328_led_set; + led->cdev.blink_set = bcm6328_blink_set; + +- rc = led_classdev_register(dev, &led->cdev); ++ rc = devm_led_classdev_register(dev, &led->cdev); + if (rc < 0) + return rc; + +--- a/drivers/leds/leds-bcm6358.c ++++ b/drivers/leds/leds-bcm6358.c +@@ -137,7 +137,7 @@ static int bcm6358_led(struct device *de + + led->cdev.brightness_set = bcm6358_led_set; + +- rc = led_classdev_register(dev, &led->cdev); ++ rc = devm_led_classdev_register(dev, &led->cdev); + if (rc < 0) + return rc; + diff --git a/queue-5.4/media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch b/queue-5.4/media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch new file mode 100644 index 00000000000..42305544390 --- /dev/null +++ b/queue-5.4/media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch @@ -0,0 +1,65 @@ +From 93df48d37c3f03886d84831992926333e7810640 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Tue, 28 Jul 2020 13:22:08 +0200 +Subject: media: uvcvideo: Fix uvc_ctrl_fixup_xu_info() not having any effect + +From: Hans de Goede + +commit 93df48d37c3f03886d84831992926333e7810640 upstream. + +uvc_ctrl_add_info() calls uvc_ctrl_get_flags() which will override +the fixed-up flags set by uvc_ctrl_fixup_xu_info(). + +uvc_ctrl_init_xu_ctrl() already calls uvc_ctrl_get_flags() before +calling uvc_ctrl_add_info(), so the uvc_ctrl_get_flags() call in +uvc_ctrl_add_info() is not necessary for xu ctrls. + +This commit moves the uvc_ctrl_get_flags() call for normal controls +from uvc_ctrl_add_info() to uvc_ctrl_init_ctrl(), so that we no longer +call uvc_ctrl_get_flags() twice for xu controls and so that we no longer +override the fixed-up flags set by uvc_ctrl_fixup_xu_info(). + +This fixes the xu motor controls not working properly on a Logitech +046d:08cc, and presumably also on the other Logitech models which have +a quirk for this in the uvc_ctrl_fixup_xu_info() function. + +Cc: stable@vger.kernel.org +Signed-off-by: Hans de Goede +Signed-off-by: Laurent Pinchart +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/usb/uvc/uvc_ctrl.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/media/usb/uvc/uvc_ctrl.c ++++ b/drivers/media/usb/uvc/uvc_ctrl.c +@@ -2033,13 +2033,6 @@ static int uvc_ctrl_add_info(struct uvc_ + goto done; + } + +- /* +- * Retrieve control flags from the device. Ignore errors and work with +- * default flag values from the uvc_ctrl array when the device doesn't +- * properly implement GET_INFO on standard controls. +- */ +- uvc_ctrl_get_flags(dev, ctrl, &ctrl->info); +- + ctrl->initialized = 1; + + uvc_trace(UVC_TRACE_CONTROL, "Added control %pUl/%u to device %s " +@@ -2262,6 +2255,13 @@ static void uvc_ctrl_init_ctrl(struct uv + if (uvc_entity_match_guid(ctrl->entity, info->entity) && + ctrl->index == info->index) { + uvc_ctrl_add_info(dev, ctrl, info); ++ /* ++ * Retrieve control flags from the device. Ignore errors ++ * and work with default flag values from the uvc_ctrl ++ * array when the device doesn't properly implement ++ * GET_INFO on standard controls. ++ */ ++ uvc_ctrl_get_flags(dev, ctrl, &ctrl->info); + break; + } + } diff --git a/queue-5.4/mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch b/queue-5.4/mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch new file mode 100644 index 00000000000..fcc436e8fdb --- /dev/null +++ b/queue-5.4/mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch @@ -0,0 +1,140 @@ +From cf3af0a4d3b62ab48e0b90180ea161d0f5d4953f Mon Sep 17 00:00:00 2001 +From: "Maciej W. Rozycki" +Date: Wed, 14 Oct 2020 22:34:56 +0100 +Subject: MIPS: DEC: Restore bootmem reservation for firmware working memory area + +From: Maciej W. Rozycki + +commit cf3af0a4d3b62ab48e0b90180ea161d0f5d4953f upstream. + +Fix a crash on DEC platforms starting with: + +VFS: Mounted root (nfs filesystem) on device 0:11. +Freeing unused PROM memory: 124k freed +BUG: Bad page state in process swapper pfn:00001 +page:(ptrval) refcount:0 mapcount:-128 mapping:00000000 index:0x1 pfn:0x1 +flags: 0x0() +raw: 00000000 00000100 00000122 00000000 00000001 00000000 ffffff7f 00000000 +page dumped because: nonzero mapcount +Modules linked in: +CPU: 0 PID: 1 Comm: swapper Not tainted 5.9.0-00858-g865c50e1d279 #1 +Stack : 8065dc48 0000000b 8065d2b8 9bc27dcc 80645bfc 9bc259a4 806a1b97 80703124 + 80710000 8064a900 00000001 80099574 806b116c 1000ec00 9bc27d88 806a6f30 + 00000000 00000000 80645bfc 00000000 31232039 80706ba4 2e392e35 8039f348 + 2d383538 00000070 0000000a 35363867 00000000 806c2830 80710000 806b0000 + 80710000 8064a900 00000001 81000000 00000000 00000000 8035af2c 80700000 + ... +Call Trace: +[<8004bc5c>] show_stack+0x34/0x104 +[<8015675c>] bad_page+0xfc/0x128 +[<80157714>] free_pcppages_bulk+0x1f4/0x5dc +[<801591cc>] free_unref_page+0xc0/0x130 +[<8015cb04>] free_reserved_area+0x144/0x1d8 +[<805abd78>] kernel_init+0x20/0x100 +[<80046070>] ret_from_kernel_thread+0x14/0x1c +Disabling lock debugging due to kernel taint + +caused by an attempt to free bootmem space that as from +commit b93ddc4f9156 ("mips: Reserve memory for the kernel image resources") +has not been anymore reserved due to the removal of generic MIPS arch code +that used to reserve all the memory from the beginning of RAM up to the +kernel load address. + +This memory does need to be reserved on DEC platforms however as it is +used by REX firmware as working area, as per the TURBOchannel firmware +specification[1]: + +Table 2-2 REX Memory Regions +------------------------------------------------------------------------- + Starting Ending +Region Address Address Use +------------------------------------------------------------------------- +0 0xa0000000 0xa000ffff Restart block, exception vectors, + REX stack and bss +1 0xa0010000 0xa0017fff Keyboard or tty drivers + +2 0xa0018000 0xa001f3ff 1) CRT driver + +3 0xa0020000 0xa002ffff boot, cnfg, init and t objects + +4 0xa0020000 0xa002ffff 64KB scratch space +------------------------------------------------------------------------- +1) Note that the last 3 Kbytes of region 2 are reserved for backward +compatibility with previous system software. +------------------------------------------------------------------------- + +(this table uses KSEG2 unmapped virtual addresses, which in the MIPS +architecture are offset from physical addresses by a fixed value of +0xa0000000 and therefore the regions referred do correspond to the +beginning of the physical address space) and we call into the firmware +on several occasions throughout the bootstrap process. It is believed +that pre-REX firmware used with non-TURBOchannel DEC platforms has the +same requirements, as hinted by note #1 cited. + +Recreate the discarded reservation then, in DEC platform code, removing +the crash. + +References: + +[1] "TURBOchannel Firmware Specification", On-line version, + EK-TCAAD-FS-004, Digital Equipment Corporation, January 1993, + Chapter 2 "System Module Firmware", p. 2-5 + +Signed-off-by: Maciej W. Rozycki +Fixes: b93ddc4f9156 ("mips: Reserve memory for the kernel image resources") +Cc: stable@vger.kernel.org # v5.2+ +Signed-off-by: Greg Kroah-Hartman + +Signed-off-by: Thomas Bogendoerfer + +--- + arch/mips/dec/setup.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +--- a/arch/mips/dec/setup.c ++++ b/arch/mips/dec/setup.c +@@ -6,7 +6,7 @@ + * for more details. + * + * Copyright (C) 1998 Harald Koerfgen +- * Copyright (C) 2000, 2001, 2002, 2003, 2005 Maciej W. Rozycki ++ * Copyright (C) 2000, 2001, 2002, 2003, 2005, 2020 Maciej W. Rozycki + */ + #include + #include +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -22,6 +23,7 @@ + #include + #include + ++#include + #include + #include + #include +@@ -29,7 +31,9 @@ + #include + #include + #include ++#include + #include ++#include + #include + #include + #include +@@ -166,6 +170,9 @@ void __init plat_mem_setup(void) + + ioport_resource.start = ~0UL; + ioport_resource.end = 0UL; ++ ++ /* Stay away from the firmware working memory area for now. */ ++ memblock_reserve(PHYS_OFFSET, __pa_symbol(&_text) - PHYS_OFFSET); + } + + /* diff --git a/queue-5.4/nfs-fix-nfs_path-in-case-of-a-rename-retry.patch b/queue-5.4/nfs-fix-nfs_path-in-case-of-a-rename-retry.patch new file mode 100644 index 00000000000..183c298ea3e --- /dev/null +++ b/queue-5.4/nfs-fix-nfs_path-in-case-of-a-rename-retry.patch @@ -0,0 +1,58 @@ +From 247db73560bc3e5aef6db50c443c3c0db115bc93 Mon Sep 17 00:00:00 2001 +From: Ashish Sangwan +Date: Mon, 5 Oct 2020 02:22:43 -0700 +Subject: NFS: fix nfs_path in case of a rename retry + +From: Ashish Sangwan + +commit 247db73560bc3e5aef6db50c443c3c0db115bc93 upstream. + +We are generating incorrect path in case of rename retry because +we are restarting from wrong dentry. We should restart from the +dentry which was received in the call to nfs_path. + +CC: stable@vger.kernel.org +Signed-off-by: Ashish Sangwan +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/namespace.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +--- a/fs/nfs/namespace.c ++++ b/fs/nfs/namespace.c +@@ -31,9 +31,9 @@ int nfs_mountpoint_expiry_timeout = 500 + /* + * nfs_path - reconstruct the path given an arbitrary dentry + * @base - used to return pointer to the end of devname part of path +- * @dentry - pointer to dentry ++ * @dentry_in - pointer to dentry + * @buffer - result buffer +- * @buflen - length of buffer ++ * @buflen_in - length of buffer + * @flags - options (see below) + * + * Helper function for constructing the server pathname +@@ -48,15 +48,19 @@ int nfs_mountpoint_expiry_timeout = 500 + * the original device (export) name + * (if unset, the original name is returned verbatim) + */ +-char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, +- unsigned flags) ++char *nfs_path(char **p, struct dentry *dentry_in, char *buffer, ++ ssize_t buflen_in, unsigned flags) + { + char *end; + int namelen; + unsigned seq; + const char *base; ++ struct dentry *dentry; ++ ssize_t buflen; + + rename_retry: ++ buflen = buflen_in; ++ dentry = dentry_in; + end = buffer+buflen; + *--end = '\0'; + buflen--; diff --git a/queue-5.4/nfsd-add-missing-nfsv2-.pc_func-methods.patch b/queue-5.4/nfsd-add-missing-nfsv2-.pc_func-methods.patch new file mode 100644 index 00000000000..182496aed54 --- /dev/null +++ b/queue-5.4/nfsd-add-missing-nfsv2-.pc_func-methods.patch @@ -0,0 +1,72 @@ +From 6b3dccd48de8a4c650b01499a0b09d1e2279649e Mon Sep 17 00:00:00 2001 +From: Chuck Lever +Date: Thu, 1 Oct 2020 18:58:56 -0400 +Subject: NFSD: Add missing NFSv2 .pc_func methods + +From: Chuck Lever + +commit 6b3dccd48de8a4c650b01499a0b09d1e2279649e upstream. + +There's no protection in nfsd_dispatch() against a NULL .pc_func +helpers. A malicious NFS client can trigger a crash by invoking the +unused/unsupported NFSv2 ROOT or WRITECACHE procedures. + +The current NFSD dispatcher does not support returning a void reply +to a non-NULL procedure, so the reply to both of these is wrong, for +the moment. + +Cc: +Signed-off-by: Chuck Lever +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfsproc.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +--- a/fs/nfsd/nfsproc.c ++++ b/fs/nfsd/nfsproc.c +@@ -118,6 +118,13 @@ done: + return nfsd_return_attrs(nfserr, resp); + } + ++/* Obsolete, replaced by MNTPROC_MNT. */ ++static __be32 ++nfsd_proc_root(struct svc_rqst *rqstp) ++{ ++ return nfs_ok; ++} ++ + /* + * Look up a path name component + * Note: the dentry in the resp->fh may be negative if the file +@@ -203,6 +210,13 @@ nfsd_proc_read(struct svc_rqst *rqstp) + return fh_getattr(&resp->fh, &resp->stat); + } + ++/* Reserved */ ++static __be32 ++nfsd_proc_writecache(struct svc_rqst *rqstp) ++{ ++ return nfs_ok; ++} ++ + /* + * Write data to a file + * N.B. After this call resp->fh needs an fh_put +@@ -617,6 +631,7 @@ static const struct svc_procedure nfsd_p + .pc_xdrressize = ST+AT, + }, + [NFSPROC_ROOT] = { ++ .pc_func = nfsd_proc_root, + .pc_decode = nfssvc_decode_void, + .pc_encode = nfssvc_encode_void, + .pc_argsize = sizeof(struct nfsd_void), +@@ -654,6 +669,7 @@ static const struct svc_procedure nfsd_p + .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4, + }, + [NFSPROC_WRITECACHE] = { ++ .pc_func = nfsd_proc_writecache, + .pc_decode = nfssvc_decode_void, + .pc_encode = nfssvc_encode_void, + .pc_argsize = sizeof(struct nfsd_void), diff --git a/queue-5.4/nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch b/queue-5.4/nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch new file mode 100644 index 00000000000..34170a2f9a7 --- /dev/null +++ b/queue-5.4/nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch @@ -0,0 +1,231 @@ +From b4868b44c5628995fdd8ef2e24dda73cef963a75 Mon Sep 17 00:00:00 2001 +From: Benjamin Coddington +Date: Fri, 25 Sep 2020 15:48:39 -0400 +Subject: NFSv4: Wait for stateid updates after CLOSE/OPEN_DOWNGRADE + +From: Benjamin Coddington + +commit b4868b44c5628995fdd8ef2e24dda73cef963a75 upstream. + +Since commit 0e0cb35b417f ("NFSv4: Handle NFS4ERR_OLD_STATEID in +CLOSE/OPEN_DOWNGRADE") the following livelock may occur if a CLOSE races +with the update of the nfs_state: + +Process 1 Process 2 Server +========= ========= ======== + OPEN file + OPEN file + Reply OPEN (1) + Reply OPEN (2) + Update state (1) + CLOSE file (1) + Reply OLD_STATEID (1) + CLOSE file (2) + Reply CLOSE (-1) + Update state (2) + wait for state change + OPEN file + wake + CLOSE file + OPEN file + wake + CLOSE file + ... + ... + +We can avoid this situation by not issuing an immediate retry with a bumped +seqid when CLOSE/OPEN_DOWNGRADE receives NFS4ERR_OLD_STATEID. Instead, +take the same approach used by OPEN and wait at least 5 seconds for +outstanding stateid updates to complete if we can detect that we're out of +sequence. + +Note that after this change it is still possible (though unlikely) that +CLOSE waits a full 5 seconds, bumps the seqid, and retries -- and that +attempt races with another OPEN at the same time. In order to avoid this +race (which would result in the livelock), update +nfs_need_update_open_stateid() to handle the case where: + - the state is NFS_OPEN_STATE, and + - the stateid doesn't match the current open stateid + +Finally, nfs_need_update_open_stateid() is modified to be idempotent and +renamed to better suit the purpose of signaling that the stateid passed +is the next stateid in sequence. + +Fixes: 0e0cb35b417f ("NFSv4: Handle NFS4ERR_OLD_STATEID in CLOSE/OPEN_DOWNGRADE") +Cc: stable@vger.kernel.org # v5.4+ +Signed-off-by: Benjamin Coddington +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4_fs.h | 8 +++++ + fs/nfs/nfs4proc.c | 81 ++++++++++++++++++++++++++++++----------------------- + fs/nfs/nfs4trace.h | 1 + 3 files changed, 56 insertions(+), 34 deletions(-) + +--- a/fs/nfs/nfs4_fs.h ++++ b/fs/nfs/nfs4_fs.h +@@ -570,6 +570,14 @@ static inline bool nfs4_stateid_is_newer + return (s32)(be32_to_cpu(s1->seqid) - be32_to_cpu(s2->seqid)) > 0; + } + ++static inline bool nfs4_stateid_is_next(const nfs4_stateid *s1, const nfs4_stateid *s2) ++{ ++ u32 seq1 = be32_to_cpu(s1->seqid); ++ u32 seq2 = be32_to_cpu(s2->seqid); ++ ++ return seq2 == seq1 + 1U || (seq2 == 1U && seq1 == 0xffffffffU); ++} ++ + static inline void nfs4_stateid_seqid_inc(nfs4_stateid *s1) + { + u32 seqid = be32_to_cpu(s1->seqid); +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -1515,19 +1515,6 @@ static void nfs_state_log_update_open_st + wake_up_all(&state->waitq); + } + +-static void nfs_state_log_out_of_order_open_stateid(struct nfs4_state *state, +- const nfs4_stateid *stateid) +-{ +- u32 state_seqid = be32_to_cpu(state->open_stateid.seqid); +- u32 stateid_seqid = be32_to_cpu(stateid->seqid); +- +- if (stateid_seqid == state_seqid + 1U || +- (stateid_seqid == 1U && state_seqid == 0xffffffffU)) +- nfs_state_log_update_open_stateid(state); +- else +- set_bit(NFS_STATE_CHANGE_WAIT, &state->flags); +-} +- + static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state) + { + struct nfs_client *clp = state->owner->so_server->nfs_client; +@@ -1553,21 +1540,19 @@ static void nfs_test_and_clear_all_open_ + * i.e. The stateid seqids have to be initialised to 1, and + * are then incremented on every state transition. + */ +-static bool nfs_need_update_open_stateid(struct nfs4_state *state, ++static bool nfs_stateid_is_sequential(struct nfs4_state *state, + const nfs4_stateid *stateid) + { +- if (test_bit(NFS_OPEN_STATE, &state->flags) == 0 || +- !nfs4_stateid_match_other(stateid, &state->open_stateid)) { ++ if (test_bit(NFS_OPEN_STATE, &state->flags)) { ++ /* The common case - we're updating to a new sequence number */ ++ if (nfs4_stateid_match_other(stateid, &state->open_stateid) && ++ nfs4_stateid_is_next(&state->open_stateid, stateid)) { ++ return true; ++ } ++ } else { ++ /* This is the first OPEN in this generation */ + if (stateid->seqid == cpu_to_be32(1)) +- nfs_state_log_update_open_stateid(state); +- else +- set_bit(NFS_STATE_CHANGE_WAIT, &state->flags); +- return true; +- } +- +- if (nfs4_stateid_is_newer(stateid, &state->open_stateid)) { +- nfs_state_log_out_of_order_open_stateid(state, stateid); +- return true; ++ return true; + } + return false; + } +@@ -1641,16 +1626,16 @@ static void nfs_set_open_stateid_locked( + int status = 0; + for (;;) { + +- if (!nfs_need_update_open_stateid(state, stateid)) +- return; +- if (!test_bit(NFS_STATE_CHANGE_WAIT, &state->flags)) ++ if (nfs_stateid_is_sequential(state, stateid)) + break; ++ + if (status) + break; + /* Rely on seqids for serialisation with NFSv4.0 */ + if (!nfs4_has_session(NFS_SERVER(state->inode)->nfs_client)) + break; + ++ set_bit(NFS_STATE_CHANGE_WAIT, &state->flags); + prepare_to_wait(&state->waitq, &wait, TASK_KILLABLE); + /* + * Ensure we process the state changes in the same order +@@ -1661,6 +1646,7 @@ static void nfs_set_open_stateid_locked( + spin_unlock(&state->owner->so_lock); + rcu_read_unlock(); + trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0); ++ + if (!signal_pending(current)) { + if (schedule_timeout(5*HZ) == 0) + status = -EAGAIN; +@@ -3397,7 +3383,8 @@ static bool nfs4_refresh_open_old_statei + __be32 seqid_open; + u32 dst_seqid; + bool ret; +- int seq; ++ int seq, status = -EAGAIN; ++ DEFINE_WAIT(wait); + + for (;;) { + ret = false; +@@ -3409,15 +3396,41 @@ static bool nfs4_refresh_open_old_statei + continue; + break; + } ++ ++ write_seqlock(&state->seqlock); + seqid_open = state->open_stateid.seqid; +- if (read_seqretry(&state->seqlock, seq)) +- continue; + + dst_seqid = be32_to_cpu(dst->seqid); +- if ((s32)(dst_seqid - be32_to_cpu(seqid_open)) >= 0) +- dst->seqid = cpu_to_be32(dst_seqid + 1); +- else ++ ++ /* Did another OPEN bump the state's seqid? try again: */ ++ if ((s32)(be32_to_cpu(seqid_open) - dst_seqid) > 0) { + dst->seqid = seqid_open; ++ write_sequnlock(&state->seqlock); ++ ret = true; ++ break; ++ } ++ ++ /* server says we're behind but we haven't seen the update yet */ ++ set_bit(NFS_STATE_CHANGE_WAIT, &state->flags); ++ prepare_to_wait(&state->waitq, &wait, TASK_KILLABLE); ++ write_sequnlock(&state->seqlock); ++ trace_nfs4_close_stateid_update_wait(state->inode, dst, 0); ++ ++ if (signal_pending(current)) ++ status = -EINTR; ++ else ++ if (schedule_timeout(5*HZ) != 0) ++ status = 0; ++ ++ finish_wait(&state->waitq, &wait); ++ ++ if (!status) ++ continue; ++ if (status == -EINTR) ++ break; ++ ++ /* we slept the whole 5 seconds, we must have lost a seqid */ ++ dst->seqid = cpu_to_be32(dst_seqid + 1); + ret = true; + break; + } +--- a/fs/nfs/nfs4trace.h ++++ b/fs/nfs/nfs4trace.h +@@ -1291,6 +1291,7 @@ DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_set + DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_delegreturn); + DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update); + DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_open_stateid_update_wait); ++DEFINE_NFS4_INODE_STATEID_EVENT(nfs4_close_stateid_update_wait); + + DECLARE_EVENT_CLASS(nfs4_getattr_event, + TP_PROTO( diff --git a/queue-5.4/nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch b/queue-5.4/nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch new file mode 100644 index 00000000000..3e523aca98e --- /dev/null +++ b/queue-5.4/nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch @@ -0,0 +1,71 @@ +From 8c39076c276be0b31982e44654e2c2357473258a Mon Sep 17 00:00:00 2001 +From: Olga Kornievskaia +Date: Fri, 16 Oct 2020 09:25:45 -0400 +Subject: NFSv4.2: support EXCHGID4_FLAG_SUPP_FENCE_OPS 4.2 EXCHANGE_ID flag + +From: Olga Kornievskaia + +commit 8c39076c276be0b31982e44654e2c2357473258a upstream. + +RFC 7862 introduced a new flag that either client or server is +allowed to set: EXCHGID4_FLAG_SUPP_FENCE_OPS. + +Client needs to update its bitmask to allow for this flag value. + +v2: changed minor version argument to unsigned int + +Signed-off-by: Olga Kornievskaia +CC: +Signed-off-by: Anna Schumaker +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfs/nfs4proc.c | 9 ++++++--- + include/uapi/linux/nfs4.h | 3 +++ + 2 files changed, 9 insertions(+), 3 deletions(-) + +--- a/fs/nfs/nfs4proc.c ++++ b/fs/nfs/nfs4proc.c +@@ -7859,9 +7859,11 @@ int nfs4_proc_secinfo(struct inode *dir, + * both PNFS and NON_PNFS flags set, and not having one of NON_PNFS, PNFS, or + * DS flags set. + */ +-static int nfs4_check_cl_exchange_flags(u32 flags) ++static int nfs4_check_cl_exchange_flags(u32 flags, u32 version) + { +- if (flags & ~EXCHGID4_FLAG_MASK_R) ++ if (version >= 2 && (flags & ~EXCHGID4_2_FLAG_MASK_R)) ++ goto out_inval; ++ else if (version < 2 && (flags & ~EXCHGID4_FLAG_MASK_R)) + goto out_inval; + if ((flags & EXCHGID4_FLAG_USE_PNFS_MDS) && + (flags & EXCHGID4_FLAG_USE_NON_PNFS)) +@@ -8274,7 +8276,8 @@ static int _nfs4_proc_exchange_id(struct + if (status != 0) + goto out; + +- status = nfs4_check_cl_exchange_flags(resp->flags); ++ status = nfs4_check_cl_exchange_flags(resp->flags, ++ clp->cl_mvops->minor_version); + if (status != 0) + goto out; + +--- a/include/uapi/linux/nfs4.h ++++ b/include/uapi/linux/nfs4.h +@@ -136,6 +136,8 @@ + + #define EXCHGID4_FLAG_UPD_CONFIRMED_REC_A 0x40000000 + #define EXCHGID4_FLAG_CONFIRMED_R 0x80000000 ++ ++#define EXCHGID4_FLAG_SUPP_FENCE_OPS 0x00000004 + /* + * Since the validity of these bits depends on whether + * they're set in the argument or response, have separate +@@ -143,6 +145,7 @@ + */ + #define EXCHGID4_FLAG_MASK_A 0x40070103 + #define EXCHGID4_FLAG_MASK_R 0x80070103 ++#define EXCHGID4_2_FLAG_MASK_R 0x80070107 + + #define SEQ4_STATUS_CB_PATH_DOWN 0x00000001 + #define SEQ4_STATUS_CB_GSS_CONTEXTS_EXPIRING 0x00000002 diff --git a/queue-5.4/pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch b/queue-5.4/pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch new file mode 100644 index 00000000000..9625257a13b --- /dev/null +++ b/queue-5.4/pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch @@ -0,0 +1,65 @@ +From c6e331312ebfb52b7186e5d82d517d68b4d2f2d8 Mon Sep 17 00:00:00 2001 +From: Lukas Wunner +Date: Fri, 2 Oct 2020 07:10:12 +0200 +Subject: PCI/ACPI: Whitelist hotplug ports for D3 if power managed by ACPI + +From: Lukas Wunner + +commit c6e331312ebfb52b7186e5d82d517d68b4d2f2d8 upstream. + +Recent laptops with dual AMD GPUs fail to suspend the discrete GPU, thus +causing lockups on system sleep and high power consumption at runtime. +The discrete GPU would normally be suspended to D3cold by turning off +ACPI _PR3 Power Resources of the Root Port above the GPU. + +However on affected systems, the Root Port is hotplug-capable and +pci_bridge_d3_possible() only allows hotplug ports to go to D3 if they +belong to a Thunderbolt device or if the Root Port possesses a +"HotPlugSupportInD3" ACPI property. Neither is the case on affected +laptops. The reason for whitelisting only specific, known to work +hotplug ports for D3 is that there have been reports of SkyLake Xeon-SP +systems raising Hardware Error NMIs upon suspending their hotplug ports: +https://lore.kernel.org/linux-pci/20170503180426.GA4058@otc-nc-03/ + +But if a hotplug port is power manageable by ACPI (as can be detected +through presence of Power Resources and corresponding _PS0 and _PS3 +methods) then it ought to be safe to suspend it to D3. To this end, +amend acpi_pci_bridge_d3() to whitelist such ports for D3. + +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1222 +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1252 +Link: https://gitlab.freedesktop.org/drm/amd/-/issues/1304 +Reported-and-tested-by: Arthur Borsboom +Reported-and-tested-by: matoro +Reported-by: Aaron Zakhrov +Reported-by: Michal Rostecki +Reported-by: Shai Coleman +Signed-off-by: Lukas Wunner +Acked-by: Alex Deucher +Cc: 5.4+ # 5.4+ +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/pci-acpi.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/pci/pci-acpi.c ++++ b/drivers/pci/pci-acpi.c +@@ -944,6 +944,16 @@ static bool acpi_pci_bridge_d3(struct pc + if (!dev->is_hotplug_bridge) + return false; + ++ /* Assume D3 support if the bridge is power-manageable by ACPI. */ ++ adev = ACPI_COMPANION(&dev->dev); ++ if (!adev && !pci_dev_is_added(dev)) { ++ adev = acpi_pci_find_companion(&dev->dev); ++ ACPI_COMPANION_SET(&dev->dev, adev); ++ } ++ ++ if (adev && acpi_device_power_manageable(adev)) ++ return true; ++ + /* + * Look for a special _DSD property for the root port and if it + * is set we know the hierarchy behind it supports D3 just fine. diff --git a/queue-5.4/pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch b/queue-5.4/pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch new file mode 100644 index 00000000000..bd775875560 --- /dev/null +++ b/queue-5.4/pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch @@ -0,0 +1,84 @@ +From d12544fb2aa9944b180c35914031a8384ab082c1 Mon Sep 17 00:00:00 2001 +From: Xiang Chen +Date: Tue, 22 Sep 2020 21:11:06 +0800 +Subject: PM: runtime: Remove link state checks in rpm_get/put_supplier() + +From: Xiang Chen + +commit d12544fb2aa9944b180c35914031a8384ab082c1 upstream. + +To support runtime PM for hisi SAS driver (the driver is in directory +drivers/scsi/hisi_sas), we add device link between scsi_device->sdev_gendev +(consumer device) and hisi_hba->dev(supplier device) with flags +DL_FLAG_PM_RUNTIME | DL_FLAG_RPM_ACTIVE. + +After runtime suspended consumers and supplier, unload the dirver which +causes a hung. + +We found that it called function device_release_driver_internal() to +release the supplier device (hisi_hba->dev), as the device link was +busy, it set the device link state to DL_STATE_SUPPLIER_UNBIND, and +then it called device_release_driver_internal() to release the consumer +device (scsi_device->sdev_gendev). + +Then it would try to call pm_runtime_get_sync() to resume the consumer +device, but because consumer-supplier relation existed, it would try +to resume the supplier first, but as the link state was already +DL_STATE_SUPPLIER_UNBIND, so it skipped resuming the supplier and only +resumed the consumer which hanged (it sends IOs to resume scsi_device +while the SAS controller is suspended). + +Simple flow is as follows: + +device_release_driver_internal -> (supplier device) + if device_links_busy -> + device_links_unbind_consumers -> + ... + WRITE_ONCE(link->status, DL_STATE_SUPPLIER_UNBIND) + device_release_driver_internal (consumer device) + pm_runtime_get_sync -> (consumer device) + ... + __rpm_callback -> + rpm_get_suppliers -> + if link->state == DL_STATE_SUPPLIER_UNBIND -> skip the action of resuming the supplier + ... + pm_runtime_clean_up_links + ... + +Correct suspend/resume ordering between a supplier device and its consumer +devices (resume the supplier device before resuming consumer devices, and +suspend consumer devices before suspending the supplier device) should be +guaranteed by runtime PM, but the state checks in rpm_get_supplier() and +rpm_put_supplier() break this rule, so remove them. + +Signed-off-by: Xiang Chen +[ rjw: Subject and changelog edits ] +Cc: All applicable +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/power/runtime.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +--- a/drivers/base/power/runtime.c ++++ b/drivers/base/power/runtime.c +@@ -291,8 +291,7 @@ static int rpm_get_suppliers(struct devi + device_links_read_lock_held()) { + int retval; + +- if (!(link->flags & DL_FLAG_PM_RUNTIME) || +- READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) ++ if (!(link->flags & DL_FLAG_PM_RUNTIME)) + continue; + + retval = pm_runtime_get_sync(link->supplier); +@@ -312,8 +311,6 @@ static void rpm_put_suppliers(struct dev + + list_for_each_entry_rcu(link, &dev->links.suppliers, c_node, + device_links_read_lock_held()) { +- if (READ_ONCE(link->status) == DL_STATE_SUPPLIER_UNBIND) +- continue; + + while (refcount_dec_not_one(&link->rpm_active)) + pm_runtime_put(link->supplier); diff --git a/queue-5.4/powerpc-drmem-make-lmb_size-64-bit.patch b/queue-5.4/powerpc-drmem-make-lmb_size-64-bit.patch new file mode 100644 index 00000000000..71f3de9ef1b --- /dev/null +++ b/queue-5.4/powerpc-drmem-make-lmb_size-64-bit.patch @@ -0,0 +1,45 @@ +From ec72024e35dddb88a81e40071c87ceb18b5ee835 Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Wed, 7 Oct 2020 17:18:33 +0530 +Subject: powerpc/drmem: Make lmb_size 64 bit + +From: Aneesh Kumar K.V + +commit ec72024e35dddb88a81e40071c87ceb18b5ee835 upstream. + +Similar to commit 89c140bbaeee ("pseries: Fix 64 bit logical memory block panic") +make sure different variables tracking lmb_size are updated to be 64 bit. + +This was found by code audit. + +Cc: stable@vger.kernel.org +Signed-off-by: Aneesh Kumar K.V +Acked-by: Nathan Lynch +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20201007114836.282468-2-aneesh.kumar@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/include/asm/drmem.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/powerpc/include/asm/drmem.h ++++ b/arch/powerpc/include/asm/drmem.h +@@ -20,7 +20,7 @@ struct drmem_lmb { + struct drmem_lmb_info { + struct drmem_lmb *lmbs; + int n_lmbs; +- u32 lmb_size; ++ u64 lmb_size; + }; + + extern struct drmem_lmb_info *drmem_info; +@@ -79,7 +79,7 @@ struct of_drconf_cell_v2 { + #define DRCONF_MEM_AI_INVALID 0x00000040 + #define DRCONF_MEM_RESERVED 0x00000080 + +-static inline u32 drmem_lmb_size(void) ++static inline u64 drmem_lmb_size(void) + { + return drmem_info->lmb_size; + } diff --git a/queue-5.4/powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch b/queue-5.4/powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch new file mode 100644 index 00000000000..ddf884cc660 --- /dev/null +++ b/queue-5.4/powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch @@ -0,0 +1,53 @@ +From 1da4a0272c5469169f78cd76cf175ff984f52f06 Mon Sep 17 00:00:00 2001 +From: Michael Neuling +Date: Tue, 13 Oct 2020 15:37:40 +1100 +Subject: powerpc: Fix undetected data corruption with P9N DD2.1 VSX CI load emulation + +From: Michael Neuling + +commit 1da4a0272c5469169f78cd76cf175ff984f52f06 upstream. + +__get_user_atomic_128_aligned() stores to kaddr using stvx which is a +VMX store instruction, hence kaddr must be 16 byte aligned otherwise +the store won't occur as expected. + +Unfortunately when we call __get_user_atomic_128_aligned() in +p9_hmi_special_emu(), the buffer we pass as kaddr (ie. vbuf) isn't +guaranteed to be 16B aligned. This means that the write to vbuf in +__get_user_atomic_128_aligned() has the bottom bits of the address +truncated. This results in other local variables being +overwritten. Also vbuf will not contain the correct data which results +in the userspace emulation being wrong and hence undetected user data +corruption. + +In the past we've been mostly lucky as vbuf has ended up aligned but +this is fragile and isn't always true. CONFIG_STACKPROTECTOR in +particular can change the stack arrangement enough that our luck runs +out. + +This issue only occurs on POWER9 Nimbus <= DD2.1 bare metal. + +The fix is to align vbuf to a 16 byte boundary. + +Fixes: 5080332c2c89 ("powerpc/64s: Add workaround for P9 vector CI load issue") +Cc: stable@vger.kernel.org # v4.15+ +Signed-off-by: Michael Neuling +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20201013043741.743413-1-mikey@neuling.org +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/traps.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/powerpc/kernel/traps.c ++++ b/arch/powerpc/kernel/traps.c +@@ -877,7 +877,7 @@ static void p9_hmi_special_emu(struct pt + { + unsigned int ra, rb, t, i, sel, instr, rc; + const void __user *addr; +- u8 vbuf[16], *vdst; ++ u8 vbuf[16] __aligned(16), *vdst; + unsigned long ea, msr, msr_mask; + bool swap; + diff --git a/queue-5.4/powerpc-memhotplug-make-lmb-size-64bit.patch b/queue-5.4/powerpc-memhotplug-make-lmb-size-64bit.patch new file mode 100644 index 00000000000..c6a9a204f75 --- /dev/null +++ b/queue-5.4/powerpc-memhotplug-make-lmb-size-64bit.patch @@ -0,0 +1,119 @@ +From 301d2ea6572386245c5d2d2dc85c3b5a737b85ac Mon Sep 17 00:00:00 2001 +From: "Aneesh Kumar K.V" +Date: Wed, 7 Oct 2020 17:18:34 +0530 +Subject: powerpc/memhotplug: Make lmb size 64bit + +From: Aneesh Kumar K.V + +commit 301d2ea6572386245c5d2d2dc85c3b5a737b85ac upstream. + +Similar to commit 89c140bbaeee ("pseries: Fix 64 bit logical memory block panic") +make sure different variables tracking lmb_size are updated to be 64 bit. + +This was found by code audit. + +Cc: stable@vger.kernel.org +Signed-off-by: Aneesh Kumar K.V +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20201007114836.282468-3-aneesh.kumar@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/platforms/pseries/hotplug-memory.c | 43 ++++++++++++++++-------- + 1 file changed, 29 insertions(+), 14 deletions(-) + +--- a/arch/powerpc/platforms/pseries/hotplug-memory.c ++++ b/arch/powerpc/platforms/pseries/hotplug-memory.c +@@ -279,7 +279,7 @@ static int dlpar_offline_lmb(struct drme + return dlpar_change_lmb_state(lmb, false); + } + +-static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size) ++static int pseries_remove_memblock(unsigned long base, unsigned long memblock_size) + { + unsigned long block_sz, start_pfn; + int sections_per_block; +@@ -310,10 +310,11 @@ out: + + static int pseries_remove_mem_node(struct device_node *np) + { +- const __be32 *regs; ++ const __be32 *prop; + unsigned long base; +- unsigned int lmb_size; ++ unsigned long lmb_size; + int ret = -EINVAL; ++ int addr_cells, size_cells; + + /* + * Check to see if we are actually removing memory +@@ -324,12 +325,19 @@ static int pseries_remove_mem_node(struc + /* + * Find the base address and size of the memblock + */ +- regs = of_get_property(np, "reg", NULL); +- if (!regs) ++ prop = of_get_property(np, "reg", NULL); ++ if (!prop) + return ret; + +- base = be64_to_cpu(*(unsigned long *)regs); +- lmb_size = be32_to_cpu(regs[3]); ++ addr_cells = of_n_addr_cells(np); ++ size_cells = of_n_size_cells(np); ++ ++ /* ++ * "reg" property represents (addr,size) tuple. ++ */ ++ base = of_read_number(prop, addr_cells); ++ prop += addr_cells; ++ lmb_size = of_read_number(prop, size_cells); + + pseries_remove_memblock(base, lmb_size); + return 0; +@@ -620,7 +628,7 @@ static int dlpar_memory_remove_by_ic(u32 + + #else + static inline int pseries_remove_memblock(unsigned long base, +- unsigned int memblock_size) ++ unsigned long memblock_size) + { + return -EOPNOTSUPP; + } +@@ -953,10 +961,11 @@ int dlpar_memory(struct pseries_hp_error + + static int pseries_add_mem_node(struct device_node *np) + { +- const __be32 *regs; ++ const __be32 *prop; + unsigned long base; +- unsigned int lmb_size; ++ unsigned long lmb_size; + int ret = -EINVAL; ++ int addr_cells, size_cells; + + /* + * Check to see if we are actually adding memory +@@ -967,12 +976,18 @@ static int pseries_add_mem_node(struct d + /* + * Find the base and size of the memblock + */ +- regs = of_get_property(np, "reg", NULL); +- if (!regs) ++ prop = of_get_property(np, "reg", NULL); ++ if (!prop) + return ret; + +- base = be64_to_cpu(*(unsigned long *)regs); +- lmb_size = be32_to_cpu(regs[3]); ++ addr_cells = of_n_addr_cells(np); ++ size_cells = of_n_size_cells(np); ++ /* ++ * "reg" property represents (addr,size) tuple. ++ */ ++ base = of_read_number(prop, addr_cells); ++ prop += addr_cells; ++ lmb_size = of_read_number(prop, size_cells); + + /* + * Update memory region to represent the memory add diff --git a/queue-5.4/powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch b/queue-5.4/powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch new file mode 100644 index 00000000000..e91ddceb5c2 --- /dev/null +++ b/queue-5.4/powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch @@ -0,0 +1,56 @@ +From 2c637d2df4ee4830e9d3eb2bd5412250522ce96e Mon Sep 17 00:00:00 2001 +From: Christophe Leroy +Date: Fri, 11 Sep 2020 10:29:15 +0000 +Subject: powerpc/powermac: Fix low_sleep_handler with KUAP and KUEP + +From: Christophe Leroy + +commit 2c637d2df4ee4830e9d3eb2bd5412250522ce96e upstream. + +low_sleep_handler() has an hardcoded restore of segment registers +that doesn't take KUAP and KUEP into account. + +Use head_32's load_segment_registers() routine instead. + +Fixes: a68c31fc01ef ("powerpc/32s: Implement Kernel Userspace Access Protection") +Fixes: 31ed2b13c48d ("powerpc/32s: Implement Kernel Userspace Execution Prevention.") +Cc: stable@vger.kernel.org +Signed-off-by: Christophe Leroy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/21b05f7298c1b18f73e6e5b4cd5005aafa24b6da.1599820109.git.christophe.leroy@csgroup.eu +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/head_32.S | 2 +- + arch/powerpc/platforms/powermac/sleep.S | 9 +-------- + 2 files changed, 2 insertions(+), 9 deletions(-) + +--- a/arch/powerpc/kernel/head_32.S ++++ b/arch/powerpc/kernel/head_32.S +@@ -843,7 +843,7 @@ BEGIN_MMU_FTR_SECTION + END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) + blr + +-load_segment_registers: ++_GLOBAL(load_segment_registers) + li r0, NUM_USER_SEGMENTS /* load up user segment register values */ + mtctr r0 /* for context 0 */ + li r3, 0 /* Kp = 0, Ks = 0, VSID = 0 */ +--- a/arch/powerpc/platforms/powermac/sleep.S ++++ b/arch/powerpc/platforms/powermac/sleep.S +@@ -293,14 +293,7 @@ grackle_wake_up: + * we do any r1 memory access as we are not sure they + * are in a sane state above the first 256Mb region + */ +- li r0,16 /* load up segment register values */ +- mtctr r0 /* for context 0 */ +- lis r3,0x2000 /* Ku = 1, VSID = 0 */ +- li r4,0 +-3: mtsrin r3,r4 +- addi r3,r3,0x111 /* increment VSID */ +- addis r4,r4,0x1000 /* address of next segment */ +- bdnz 3b ++ bl load_segment_registers + sync + isync + diff --git a/queue-5.4/powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch b/queue-5.4/powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch new file mode 100644 index 00000000000..3aea300ac6b --- /dev/null +++ b/queue-5.4/powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch @@ -0,0 +1,128 @@ +From aea948bb80b478ddc2448f7359d574387521a52d Mon Sep 17 00:00:00 2001 +From: Mahesh Salgaonkar +Date: Tue, 6 Oct 2020 13:02:18 +0530 +Subject: powerpc/powernv/elog: Fix race while processing OPAL error log event. + +From: Mahesh Salgaonkar + +commit aea948bb80b478ddc2448f7359d574387521a52d upstream. + +Every error log reported by OPAL is exported to userspace through a +sysfs interface and notified using kobject_uevent(). The userspace +daemon (opal_errd) then reads the error log and acknowledges the error +log is saved safely to disk. Once acknowledged the kernel removes the +respective sysfs file entry causing respective resources to be +released including kobject. + +However it's possible the userspace daemon may already be scanning +elog entries when a new sysfs elog entry is created by the kernel. +User daemon may read this new entry and ack it even before kernel can +notify userspace about it through kobject_uevent() call. If that +happens then we have a potential race between +elog_ack_store->kobject_put() and kobject_uevent which can lead to +use-after-free of a kernfs object resulting in a kernel crash. eg: + + BUG: Unable to handle kernel data access on read at 0x6b6b6b6b6b6b6bfb + Faulting instruction address: 0xc0000000008ff2a0 + Oops: Kernel access of bad area, sig: 11 [#1] + LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA PowerNV + CPU: 27 PID: 805 Comm: irq/29-opal-elo Not tainted 5.9.0-rc2-gcc-8.2.0-00214-g6f56a67bcbb5-dirty #363 + ... + NIP kobject_uevent_env+0xa0/0x910 + LR elog_event+0x1f4/0x2d0 + Call Trace: + 0x5deadbeef0000122 (unreliable) + elog_event+0x1f4/0x2d0 + irq_thread_fn+0x4c/0xc0 + irq_thread+0x1c0/0x2b0 + kthread+0x1c4/0x1d0 + ret_from_kernel_thread+0x5c/0x6c + +This patch fixes this race by protecting the sysfs file +creation/notification by holding a reference count on kobject until we +safely send kobject_uevent(). + +The function create_elog_obj() returns the elog object which if used +by caller function will end up in use-after-free problem again. +However, the return value of create_elog_obj() function isn't being +used today and there is no need as well. Hence change it to return +void to make this fix complete. + +Fixes: 774fea1a38c6 ("powerpc/powernv: Read OPAL error log and export it through sysfs") +Cc: stable@vger.kernel.org # v3.15+ +Reported-by: Oliver O'Halloran +Signed-off-by: Mahesh Salgaonkar +Signed-off-by: Aneesh Kumar K.V +Reviewed-by: Oliver O'Halloran +Reviewed-by: Vasant Hegde +[mpe: Rework the logic to use a single return, reword comments, add oops] +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20201006122051.190176-1-mpe@ellerman.id.au +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/platforms/powernv/opal-elog.c | 33 ++++++++++++++++++++++------- + 1 file changed, 26 insertions(+), 7 deletions(-) + +--- a/arch/powerpc/platforms/powernv/opal-elog.c ++++ b/arch/powerpc/platforms/powernv/opal-elog.c +@@ -179,14 +179,14 @@ static ssize_t raw_attr_read(struct file + return count; + } + +-static struct elog_obj *create_elog_obj(uint64_t id, size_t size, uint64_t type) ++static void create_elog_obj(uint64_t id, size_t size, uint64_t type) + { + struct elog_obj *elog; + int rc; + + elog = kzalloc(sizeof(*elog), GFP_KERNEL); + if (!elog) +- return NULL; ++ return; + + elog->kobj.kset = elog_kset; + +@@ -219,18 +219,37 @@ static struct elog_obj *create_elog_obj( + rc = kobject_add(&elog->kobj, NULL, "0x%llx", id); + if (rc) { + kobject_put(&elog->kobj); +- return NULL; ++ return; + } + ++ /* ++ * As soon as the sysfs file for this elog is created/activated there is ++ * a chance the opal_errd daemon (or any userspace) might read and ++ * acknowledge the elog before kobject_uevent() is called. If that ++ * happens then there is a potential race between ++ * elog_ack_store->kobject_put() and kobject_uevent() which leads to a ++ * use-after-free of a kernfs object resulting in a kernel crash. ++ * ++ * To avoid that, we need to take a reference on behalf of the bin file, ++ * so that our reference remains valid while we call kobject_uevent(). ++ * We then drop our reference before exiting the function, leaving the ++ * bin file to drop the last reference (if it hasn't already). ++ */ ++ ++ /* Take a reference for the bin file */ ++ kobject_get(&elog->kobj); + rc = sysfs_create_bin_file(&elog->kobj, &elog->raw_attr); +- if (rc) { ++ if (rc == 0) { ++ kobject_uevent(&elog->kobj, KOBJ_ADD); ++ } else { ++ /* Drop the reference taken for the bin file */ + kobject_put(&elog->kobj); +- return NULL; + } + +- kobject_uevent(&elog->kobj, KOBJ_ADD); ++ /* Drop our reference */ ++ kobject_put(&elog->kobj); + +- return elog; ++ return; + } + + static irqreturn_t elog_event(int irq, void *data) diff --git a/queue-5.4/powerpc-rtas-restrict-rtas-requests-from-userspace.patch b/queue-5.4/powerpc-rtas-restrict-rtas-requests-from-userspace.patch new file mode 100644 index 00000000000..dc60248ac1e --- /dev/null +++ b/queue-5.4/powerpc-rtas-restrict-rtas-requests-from-userspace.patch @@ -0,0 +1,264 @@ +From bd59380c5ba4147dcbaad3e582b55ccfd120b764 Mon Sep 17 00:00:00 2001 +From: Andrew Donnellan +Date: Thu, 20 Aug 2020 14:45:12 +1000 +Subject: powerpc/rtas: Restrict RTAS requests from userspace + +From: Andrew Donnellan + +commit bd59380c5ba4147dcbaad3e582b55ccfd120b764 upstream. + +A number of userspace utilities depend on making calls to RTAS to retrieve +information and update various things. + +The existing API through which we expose RTAS to userspace exposes more +RTAS functionality than we actually need, through the sys_rtas syscall, +which allows root (or anyone with CAP_SYS_ADMIN) to make any RTAS call they +want with arbitrary arguments. + +Many RTAS calls take the address of a buffer as an argument, and it's up to +the caller to specify the physical address of the buffer as an argument. We +allocate a buffer (the "RMO buffer") in the Real Memory Area that RTAS can +access, and then expose the physical address and size of this buffer in +/proc/powerpc/rtas/rmo_buffer. Userspace is expected to read this address, +poke at the buffer using /dev/mem, and pass an address in the RMO buffer to +the RTAS call. + +However, there's nothing stopping the caller from specifying whatever +address they want in the RTAS call, and it's easy to construct a series of +RTAS calls that can overwrite arbitrary bytes (even without /dev/mem +access). + +Additionally, there are some RTAS calls that do potentially dangerous +things and for which there are no legitimate userspace use cases. + +In the past, this would not have been a particularly big deal as it was +assumed that root could modify all system state freely, but with Secure +Boot and lockdown we need to care about this. + +We can't fundamentally change the ABI at this point, however we can address +this by implementing a filter that checks RTAS calls against a list +of permitted calls and forces the caller to use addresses within the RMO +buffer. + +The list is based off the list of calls that are used by the librtas +userspace library, and has been tested with a number of existing userspace +RTAS utilities. For compatibility with any applications we are not aware of +that require other calls, the filter can be turned off at build time. + +Cc: stable@vger.kernel.org +Reported-by: Daniel Axtens +Signed-off-by: Andrew Donnellan +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200820044512.7543-1-ajd@linux.ibm.com +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/Kconfig | 13 +++ + arch/powerpc/kernel/rtas.c | 153 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 166 insertions(+) + +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -1024,6 +1024,19 @@ config FSL_RIO + Include support for RapidIO controller on Freescale embedded + processors (MPC8548, MPC8641, etc). + ++config PPC_RTAS_FILTER ++ bool "Enable filtering of RTAS syscalls" ++ default y ++ depends on PPC_RTAS ++ help ++ The RTAS syscall API has security issues that could be used to ++ compromise system integrity. This option enforces restrictions on the ++ RTAS calls and arguments passed by userspace programs to mitigate ++ these issues. ++ ++ Say Y unless you know what you are doing and the filter is causing ++ problems for you. ++ + endmenu + + config NONSTATIC_KERNEL +--- a/arch/powerpc/kernel/rtas.c ++++ b/arch/powerpc/kernel/rtas.c +@@ -940,6 +940,147 @@ struct pseries_errorlog *get_pseries_err + return NULL; + } + ++#ifdef CONFIG_PPC_RTAS_FILTER ++ ++/* ++ * The sys_rtas syscall, as originally designed, allows root to pass ++ * arbitrary physical addresses to RTAS calls. A number of RTAS calls ++ * can be abused to write to arbitrary memory and do other things that ++ * are potentially harmful to system integrity, and thus should only ++ * be used inside the kernel and not exposed to userspace. ++ * ++ * All known legitimate users of the sys_rtas syscall will only ever ++ * pass addresses that fall within the RMO buffer, and use a known ++ * subset of RTAS calls. ++ * ++ * Accordingly, we filter RTAS requests to check that the call is ++ * permitted, and that provided pointers fall within the RMO buffer. ++ * The rtas_filters list contains an entry for each permitted call, ++ * with the indexes of the parameters which are expected to contain ++ * addresses and sizes of buffers allocated inside the RMO buffer. ++ */ ++struct rtas_filter { ++ const char *name; ++ int token; ++ /* Indexes into the args buffer, -1 if not used */ ++ int buf_idx1; ++ int size_idx1; ++ int buf_idx2; ++ int size_idx2; ++ ++ int fixed_size; ++}; ++ ++static struct rtas_filter rtas_filters[] __ro_after_init = { ++ { "ibm,activate-firmware", -1, -1, -1, -1, -1 }, ++ { "ibm,configure-connector", -1, 0, -1, 1, -1, 4096 }, /* Special cased */ ++ { "display-character", -1, -1, -1, -1, -1 }, ++ { "ibm,display-message", -1, 0, -1, -1, -1 }, ++ { "ibm,errinjct", -1, 2, -1, -1, -1, 1024 }, ++ { "ibm,close-errinjct", -1, -1, -1, -1, -1 }, ++ { "ibm,open-errinct", -1, -1, -1, -1, -1 }, ++ { "ibm,get-config-addr-info2", -1, -1, -1, -1, -1 }, ++ { "ibm,get-dynamic-sensor-state", -1, 1, -1, -1, -1 }, ++ { "ibm,get-indices", -1, 2, 3, -1, -1 }, ++ { "get-power-level", -1, -1, -1, -1, -1 }, ++ { "get-sensor-state", -1, -1, -1, -1, -1 }, ++ { "ibm,get-system-parameter", -1, 1, 2, -1, -1 }, ++ { "get-time-of-day", -1, -1, -1, -1, -1 }, ++ { "ibm,get-vpd", -1, 0, -1, 1, 2 }, ++ { "ibm,lpar-perftools", -1, 2, 3, -1, -1 }, ++ { "ibm,platform-dump", -1, 4, 5, -1, -1 }, ++ { "ibm,read-slot-reset-state", -1, -1, -1, -1, -1 }, ++ { "ibm,scan-log-dump", -1, 0, 1, -1, -1 }, ++ { "ibm,set-dynamic-indicator", -1, 2, -1, -1, -1 }, ++ { "ibm,set-eeh-option", -1, -1, -1, -1, -1 }, ++ { "set-indicator", -1, -1, -1, -1, -1 }, ++ { "set-power-level", -1, -1, -1, -1, -1 }, ++ { "set-time-for-power-on", -1, -1, -1, -1, -1 }, ++ { "ibm,set-system-parameter", -1, 1, -1, -1, -1 }, ++ { "set-time-of-day", -1, -1, -1, -1, -1 }, ++ { "ibm,suspend-me", -1, -1, -1, -1, -1 }, ++ { "ibm,update-nodes", -1, 0, -1, -1, -1, 4096 }, ++ { "ibm,update-properties", -1, 0, -1, -1, -1, 4096 }, ++ { "ibm,physical-attestation", -1, 0, 1, -1, -1 }, ++}; ++ ++static bool in_rmo_buf(u32 base, u32 end) ++{ ++ return base >= rtas_rmo_buf && ++ base < (rtas_rmo_buf + RTAS_RMOBUF_MAX) && ++ base <= end && ++ end >= rtas_rmo_buf && ++ end < (rtas_rmo_buf + RTAS_RMOBUF_MAX); ++} ++ ++static bool block_rtas_call(int token, int nargs, ++ struct rtas_args *args) ++{ ++ int i; ++ ++ for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) { ++ struct rtas_filter *f = &rtas_filters[i]; ++ u32 base, size, end; ++ ++ if (token != f->token) ++ continue; ++ ++ if (f->buf_idx1 != -1) { ++ base = be32_to_cpu(args->args[f->buf_idx1]); ++ if (f->size_idx1 != -1) ++ size = be32_to_cpu(args->args[f->size_idx1]); ++ else if (f->fixed_size) ++ size = f->fixed_size; ++ else ++ size = 1; ++ ++ end = base + size - 1; ++ if (!in_rmo_buf(base, end)) ++ goto err; ++ } ++ ++ if (f->buf_idx2 != -1) { ++ base = be32_to_cpu(args->args[f->buf_idx2]); ++ if (f->size_idx2 != -1) ++ size = be32_to_cpu(args->args[f->size_idx2]); ++ else if (f->fixed_size) ++ size = f->fixed_size; ++ else ++ size = 1; ++ end = base + size - 1; ++ ++ /* ++ * Special case for ibm,configure-connector where the ++ * address can be 0 ++ */ ++ if (!strcmp(f->name, "ibm,configure-connector") && ++ base == 0) ++ return false; ++ ++ if (!in_rmo_buf(base, end)) ++ goto err; ++ } ++ ++ return false; ++ } ++ ++err: ++ pr_err_ratelimited("sys_rtas: RTAS call blocked - exploit attempt?\n"); ++ pr_err_ratelimited("sys_rtas: token=0x%x, nargs=%d (called by %s)\n", ++ token, nargs, current->comm); ++ return true; ++} ++ ++#else ++ ++static bool block_rtas_call(int token, int nargs, ++ struct rtas_args *args) ++{ ++ return false; ++} ++ ++#endif /* CONFIG_PPC_RTAS_FILTER */ ++ + /* We assume to be passed big endian arguments */ + SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs) + { +@@ -977,6 +1118,9 @@ SYSCALL_DEFINE1(rtas, struct rtas_args _ + args.rets = &args.args[nargs]; + memset(args.rets, 0, nret * sizeof(rtas_arg_t)); + ++ if (block_rtas_call(token, nargs, &args)) ++ return -EINVAL; ++ + /* Need to handle ibm,suspend_me call specially */ + if (token == ibm_suspend_me_token) { + +@@ -1038,6 +1182,9 @@ void __init rtas_initialize(void) + unsigned long rtas_region = RTAS_INSTANTIATE_MAX; + u32 base, size, entry; + int no_base, no_size, no_entry; ++#ifdef CONFIG_PPC_RTAS_FILTER ++ int i; ++#endif + + /* Get RTAS dev node and fill up our "rtas" structure with infos + * about it. +@@ -1077,6 +1224,12 @@ void __init rtas_initialize(void) + #ifdef CONFIG_RTAS_ERROR_LOGGING + rtas_last_error_token = rtas_token("rtas-last-error"); + #endif ++ ++#ifdef CONFIG_PPC_RTAS_FILTER ++ for (i = 0; i < ARRAY_SIZE(rtas_filters); i++) { ++ rtas_filters[i].token = rtas_token(rtas_filters[i].name); ++ } ++#endif + } + + int __init early_init_dt_scan_rtas(unsigned long node, diff --git a/queue-5.4/powerpc-warn-about-use-of-smt_snooze_delay.patch b/queue-5.4/powerpc-warn-about-use-of-smt_snooze_delay.patch new file mode 100644 index 00000000000..8412c5aadbd --- /dev/null +++ b/queue-5.4/powerpc-warn-about-use-of-smt_snooze_delay.patch @@ -0,0 +1,104 @@ +From a02f6d42357acf6e5de6ffc728e6e77faf3ad217 Mon Sep 17 00:00:00 2001 +From: Joel Stanley +Date: Wed, 2 Sep 2020 09:30:11 +0930 +Subject: powerpc: Warn about use of smt_snooze_delay + +From: Joel Stanley + +commit a02f6d42357acf6e5de6ffc728e6e77faf3ad217 upstream. + +It's not done anything for a long time. Save the percpu variable, and +emit a warning to remind users to not expect it to do anything. + +This uses pr_warn_once instead of pr_warn_ratelimit as testing +'ppc64_cpu --smt=off' on a 24 core / 4 SMT system showed the warning +to be noisy, as the online/offline loop is slow. + +Fixes: 3fa8cad82b94 ("powerpc/pseries/cpuidle: smt-snooze-delay cleanup.") +Cc: stable@vger.kernel.org # v3.14 +Signed-off-by: Joel Stanley +Acked-by: Gautham R. Shenoy +Signed-off-by: Michael Ellerman +Link: https://lore.kernel.org/r/20200902000012.3440389-1-joel@jms.id.au +Signed-off-by: Greg Kroah-Hartman + +--- + arch/powerpc/kernel/sysfs.c | 42 +++++++++++++++++------------------------- + 1 file changed, 17 insertions(+), 25 deletions(-) + +--- a/arch/powerpc/kernel/sysfs.c ++++ b/arch/powerpc/kernel/sysfs.c +@@ -31,29 +31,27 @@ + + static DEFINE_PER_CPU(struct cpu, cpu_devices); + +-/* +- * SMT snooze delay stuff, 64-bit only for now +- */ +- + #ifdef CONFIG_PPC64 + +-/* Time in microseconds we delay before sleeping in the idle loop */ +-static DEFINE_PER_CPU(long, smt_snooze_delay) = { 100 }; ++/* ++ * Snooze delay has not been hooked up since 3fa8cad82b94 ("powerpc/pseries/cpuidle: ++ * smt-snooze-delay cleanup.") and has been broken even longer. As was foretold in ++ * 2014: ++ * ++ * "ppc64_util currently utilises it. Once we fix ppc64_util, propose to clean ++ * up the kernel code." ++ * ++ * powerpc-utils stopped using it as of 1.3.8. At some point in the future this ++ * code should be removed. ++ */ + + static ssize_t store_smt_snooze_delay(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) + { +- struct cpu *cpu = container_of(dev, struct cpu, dev); +- ssize_t ret; +- long snooze; +- +- ret = sscanf(buf, "%ld", &snooze); +- if (ret != 1) +- return -EINVAL; +- +- per_cpu(smt_snooze_delay, cpu->dev.id) = snooze; ++ pr_warn_once("%s (%d) stored to unsupported smt_snooze_delay, which has no effect.\n", ++ current->comm, current->pid); + return count; + } + +@@ -61,9 +59,9 @@ static ssize_t show_smt_snooze_delay(str + struct device_attribute *attr, + char *buf) + { +- struct cpu *cpu = container_of(dev, struct cpu, dev); +- +- return sprintf(buf, "%ld\n", per_cpu(smt_snooze_delay, cpu->dev.id)); ++ pr_warn_once("%s (%d) read from unsupported smt_snooze_delay\n", ++ current->comm, current->pid); ++ return sprintf(buf, "100\n"); + } + + static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay, +@@ -71,16 +69,10 @@ static DEVICE_ATTR(smt_snooze_delay, 064 + + static int __init setup_smt_snooze_delay(char *str) + { +- unsigned int cpu; +- long snooze; +- + if (!cpu_has_feature(CPU_FTR_SMT)) + return 1; + +- snooze = simple_strtol(str, NULL, 10); +- for_each_possible_cpu(cpu) +- per_cpu(smt_snooze_delay, cpu) = snooze; +- ++ pr_warn("smt-snooze-delay command line option has no effect\n"); + return 1; + } + __setup("smt-snooze-delay=", setup_smt_snooze_delay); diff --git a/queue-5.4/s390-stp-add-locking-to-sysfs-functions.patch b/queue-5.4/s390-stp-add-locking-to-sysfs-functions.patch new file mode 100644 index 00000000000..1b6c60ac702 --- /dev/null +++ b/queue-5.4/s390-stp-add-locking-to-sysfs-functions.patch @@ -0,0 +1,236 @@ +From b3bd02495cb339124f13135d51940cf48d83e5cb Mon Sep 17 00:00:00 2001 +From: Sven Schnelle +Date: Tue, 15 Sep 2020 08:53:50 +0200 +Subject: s390/stp: add locking to sysfs functions + +From: Sven Schnelle + +commit b3bd02495cb339124f13135d51940cf48d83e5cb upstream. + +The sysfs function might race with stp_work_fn. To prevent that, +add the required locking. Another issue is that the sysfs functions +are checking the stp_online flag, but this flag just holds the user +setting whether STP is enabled. Add a flag to clock_sync_flag whether +stp_info holds valid data and use that instead. + +Cc: stable@vger.kernel.org +Signed-off-by: Sven Schnelle +Reviewed-by: Alexander Egorenkov +Signed-off-by: Vasily Gorbik +Signed-off-by: Greg Kroah-Hartman + +--- + arch/s390/kernel/time.c | 118 ++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 85 insertions(+), 33 deletions(-) + +--- a/arch/s390/kernel/time.c ++++ b/arch/s390/kernel/time.c +@@ -354,8 +354,9 @@ static DEFINE_PER_CPU(atomic_t, clock_sy + static DEFINE_MUTEX(clock_sync_mutex); + static unsigned long clock_sync_flags; + +-#define CLOCK_SYNC_HAS_STP 0 +-#define CLOCK_SYNC_STP 1 ++#define CLOCK_SYNC_HAS_STP 0 ++#define CLOCK_SYNC_STP 1 ++#define CLOCK_SYNC_STPINFO_VALID 2 + + /* + * The get_clock function for the physical clock. It will get the current +@@ -592,6 +593,22 @@ void stp_queue_work(void) + queue_work(time_sync_wq, &stp_work); + } + ++static int __store_stpinfo(void) ++{ ++ int rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi)); ++ ++ if (rc) ++ clear_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags); ++ else ++ set_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags); ++ return rc; ++} ++ ++static int stpinfo_valid(void) ++{ ++ return stp_online && test_bit(CLOCK_SYNC_STPINFO_VALID, &clock_sync_flags); ++} ++ + static int stp_sync_clock(void *data) + { + struct clock_sync_data *sync = data; +@@ -613,8 +630,7 @@ static int stp_sync_clock(void *data) + if (rc == 0) { + sync->clock_delta = clock_delta; + clock_sync_global(clock_delta); +- rc = chsc_sstpi(stp_page, &stp_info, +- sizeof(struct stp_sstpi)); ++ rc = __store_stpinfo(); + if (rc == 0 && stp_info.tmd != 2) + rc = -EAGAIN; + } +@@ -659,7 +675,7 @@ static void stp_work_fn(struct work_stru + if (rc) + goto out_unlock; + +- rc = chsc_sstpi(stp_page, &stp_info, sizeof(struct stp_sstpi)); ++ rc = __store_stpinfo(); + if (rc || stp_info.c == 0) + goto out_unlock; + +@@ -696,10 +712,14 @@ static ssize_t stp_ctn_id_show(struct de + struct device_attribute *attr, + char *buf) + { +- if (!stp_online) +- return -ENODATA; +- return sprintf(buf, "%016llx\n", +- *(unsigned long long *) stp_info.ctnid); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid()) ++ ret = sprintf(buf, "%016llx\n", ++ *(unsigned long long *) stp_info.ctnid); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL); +@@ -708,9 +728,13 @@ static ssize_t stp_ctn_type_show(struct + struct device_attribute *attr, + char *buf) + { +- if (!stp_online) +- return -ENODATA; +- return sprintf(buf, "%i\n", stp_info.ctn); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid()) ++ ret = sprintf(buf, "%i\n", stp_info.ctn); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL); +@@ -719,9 +743,13 @@ static ssize_t stp_dst_offset_show(struc + struct device_attribute *attr, + char *buf) + { +- if (!stp_online || !(stp_info.vbits & 0x2000)) +- return -ENODATA; +- return sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid() && (stp_info.vbits & 0x2000)) ++ ret = sprintf(buf, "%i\n", (int)(s16) stp_info.dsto); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL); +@@ -730,9 +758,13 @@ static ssize_t stp_leap_seconds_show(str + struct device_attribute *attr, + char *buf) + { +- if (!stp_online || !(stp_info.vbits & 0x8000)) +- return -ENODATA; +- return sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid() && (stp_info.vbits & 0x8000)) ++ ret = sprintf(buf, "%i\n", (int)(s16) stp_info.leaps); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL); +@@ -741,9 +773,13 @@ static ssize_t stp_stratum_show(struct d + struct device_attribute *attr, + char *buf) + { +- if (!stp_online) +- return -ENODATA; +- return sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid()) ++ ret = sprintf(buf, "%i\n", (int)(s16) stp_info.stratum); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(stratum, 0400, stp_stratum_show, NULL); +@@ -752,9 +788,13 @@ static ssize_t stp_time_offset_show(stru + struct device_attribute *attr, + char *buf) + { +- if (!stp_online || !(stp_info.vbits & 0x0800)) +- return -ENODATA; +- return sprintf(buf, "%i\n", (int) stp_info.tto); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid() && (stp_info.vbits & 0x0800)) ++ ret = sprintf(buf, "%i\n", (int) stp_info.tto); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(time_offset, 0400, stp_time_offset_show, NULL); +@@ -763,9 +803,13 @@ static ssize_t stp_time_zone_offset_show + struct device_attribute *attr, + char *buf) + { +- if (!stp_online || !(stp_info.vbits & 0x4000)) +- return -ENODATA; +- return sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid() && (stp_info.vbits & 0x4000)) ++ ret = sprintf(buf, "%i\n", (int)(s16) stp_info.tzo); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(time_zone_offset, 0400, +@@ -775,9 +819,13 @@ static ssize_t stp_timing_mode_show(stru + struct device_attribute *attr, + char *buf) + { +- if (!stp_online) +- return -ENODATA; +- return sprintf(buf, "%i\n", stp_info.tmd); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid()) ++ ret = sprintf(buf, "%i\n", stp_info.tmd); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL); +@@ -786,9 +834,13 @@ static ssize_t stp_timing_state_show(str + struct device_attribute *attr, + char *buf) + { +- if (!stp_online) +- return -ENODATA; +- return sprintf(buf, "%i\n", stp_info.tst); ++ ssize_t ret = -ENODATA; ++ ++ mutex_lock(&stp_work_mutex); ++ if (stpinfo_valid()) ++ ret = sprintf(buf, "%i\n", stp_info.tst); ++ mutex_unlock(&stp_work_mutex); ++ return ret; + } + + static DEVICE_ATTR(timing_state, 0400, stp_timing_state_show, NULL); diff --git a/queue-5.4/scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch b/queue-5.4/scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch new file mode 100644 index 00000000000..f0fdcdbb9bd --- /dev/null +++ b/queue-5.4/scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch @@ -0,0 +1,77 @@ +From 2f4843b172c2c0360ee7792ad98025fae7baefde Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Thu, 22 Oct 2020 11:00:05 +0200 +Subject: scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove() + +From: Helge Deller + +commit 2f4843b172c2c0360ee7792ad98025fae7baefde upstream. + +The mptscsih_remove() function triggers a kernel oops if the Scsi_Host +pointer (ioc->sh) is NULL, as can be seen in this syslog: + + ioc0: LSI53C1030 B2: Capabilities={Initiator,Target} + Begin: Waiting for root file system ... + scsi host2: error handler thread failed to spawn, error = -4 + mptspi: ioc0: WARNING - Unable to register controller with SCSI subsystem + Backtrace: + [<000000001045b7cc>] mptspi_probe+0x248/0x3d0 [mptspi] + [<0000000040946470>] pci_device_probe+0x1ac/0x2d8 + [<0000000040add668>] really_probe+0x1bc/0x988 + [<0000000040ade704>] driver_probe_device+0x160/0x218 + [<0000000040adee24>] device_driver_attach+0x160/0x188 + [<0000000040adef90>] __driver_attach+0x144/0x320 + [<0000000040ad7c78>] bus_for_each_dev+0xd4/0x158 + [<0000000040adc138>] driver_attach+0x4c/0x80 + [<0000000040adb3ec>] bus_add_driver+0x3e0/0x498 + [<0000000040ae0130>] driver_register+0xf4/0x298 + [<00000000409450c4>] __pci_register_driver+0x78/0xa8 + [<000000000007d248>] mptspi_init+0x18c/0x1c4 [mptspi] + +This patch adds the necessary NULL-pointer checks. Successfully tested on +a HP C8000 parisc workstation with buggy SCSI drives. + +Link: https://lore.kernel.org/r/20201022090005.GA9000@ls3530.fritz.box +Cc: +Signed-off-by: Helge Deller +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/message/fusion/mptscsih.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +--- a/drivers/message/fusion/mptscsih.c ++++ b/drivers/message/fusion/mptscsih.c +@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev) + MPT_SCSI_HOST *hd; + int sz1; + +- if((hd = shost_priv(host)) == NULL) +- return; ++ if (host == NULL) ++ hd = NULL; ++ else ++ hd = shost_priv(host); + + mptscsih_shutdown(pdev); + +@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev) + "Free'd ScsiLookup (%d) memory\n", + ioc->name, sz1)); + +- kfree(hd->info_kbuf); ++ if (hd) ++ kfree(hd->info_kbuf); + + /* NULL the Scsi_Host pointer + */ + ioc->sh = NULL; + +- scsi_host_put(host); +- ++ if (host) ++ scsi_host_put(host); + mpt_detach(pdev); + + } diff --git a/queue-5.4/scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch b/queue-5.4/scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch new file mode 100644 index 00000000000..de61bfbcc3f --- /dev/null +++ b/queue-5.4/scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch @@ -0,0 +1,49 @@ +From 50457dab670f396557e60c07f086358460876353 Mon Sep 17 00:00:00 2001 +From: Quinn Tran +Date: Tue, 29 Sep 2020 03:21:50 -0700 +Subject: scsi: qla2xxx: Fix crash on session cleanup with unload + +From: Quinn Tran + +commit 50457dab670f396557e60c07f086358460876353 upstream. + +On unload, session cleanup prematurely gave the signal for driver unload +path to advance. + +Link: https://lore.kernel.org/r/20200929102152.32278-6-njavali@marvell.com +Fixes: 726b85487067 ("qla2xxx: Add framework for async fabric discovery") +Cc: stable@vger.kernel.org +Reviewed-by: Himanshu Madhani +Signed-off-by: Quinn Tran +Signed-off-by: Nilesh Javali +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/qla2xxx/qla_target.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/scsi/qla2xxx/qla_target.c ++++ b/drivers/scsi/qla2xxx/qla_target.c +@@ -1230,14 +1230,15 @@ void qlt_schedule_sess_for_deletion(stru + case DSC_DELETE_PEND: + return; + case DSC_DELETED: +- if (tgt && tgt->tgt_stop && (tgt->sess_count == 0)) +- wake_up_all(&tgt->waitQ); +- if (sess->vha->fcport_count == 0) +- wake_up_all(&sess->vha->fcport_waitQ); +- + if (!sess->plogi_link[QLT_PLOGI_LINK_SAME_WWN] && +- !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]) ++ !sess->plogi_link[QLT_PLOGI_LINK_CONFLICT]) { ++ if (tgt && tgt->tgt_stop && tgt->sess_count == 0) ++ wake_up_all(&tgt->waitQ); ++ ++ if (sess->vha->fcport_count == 0) ++ wake_up_all(&sess->vha->fcport_waitQ); + return; ++ } + break; + case DSC_UPD_FCPORT: + /* diff --git a/queue-5.4/series b/queue-5.4/series index b691b8f40cf..a367994ae0b 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -102,3 +102,71 @@ perf-x86-intel-fix-ice-lake-event-constraint-table.patch perf-x86-amd-ibs-don-t-include-randomized-bits-in-get_ibs_op_count.patch perf-x86-amd-ibs-fix-raw-sample-data-accumulation.patch spi-sprd-release-dma-channel-also-on-probe-deferral.patch +extcon-ptn5150-fix-usage-of-atomic-gpio-with-sleeping-gpio-chips.patch +leds-bcm6328-bcm6358-use-devres-led-registering-function.patch +media-uvcvideo-fix-uvc_ctrl_fixup_xu_info-not-having-any-effect.patch +fs-don-t-invalidate-page-buffers-in-block_write_full_page.patch +nfs-fix-nfs_path-in-case-of-a-rename-retry.patch +acpi-button-fix-handling-lid-state-changes-when-input-device-closed.patch +acpi-extlog-check-for-rdmsr-failure.patch +acpi-video-use-acpi-backlight-for-hp-635-notebook.patch +acpi-debug-don-t-allow-debugging-when-acpi-is-disabled.patch +pci-acpi-whitelist-hotplug-ports-for-d3-if-power-managed-by-acpi.patch +acpi-ec-pm-flush-ec-work-unconditionally-after-wakeup.patch +acpi-ec-pm-drop-ec_no_wakeup-check-from-acpi_ec_dispatch_gpe.patch +acpi-cpufreq-honor-_psd-table-setting-on-new-amd-cpus.patch +w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch +scsi-mptfusion-fix-null-pointer-dereferences-in-mptscsih_remove.patch +scsi-qla2xxx-fix-crash-on-session-cleanup-with-unload.patch +pm-runtime-remove-link-state-checks-in-rpm_get-put_supplier.patch +btrfs-qgroup-fix-wrong-qgroup-metadata-reserve-for-delayed-inode.patch +btrfs-improve-device-scanning-messages.patch +btrfs-reschedule-if-necessary-when-logging-directory-items.patch +btrfs-send-orphanize-first-all-conflicting-inodes-when-processing-references.patch +btrfs-send-recompute-reference-path-after-orphanization-of-a-directory.patch +btrfs-use-kvzalloc-to-allocate-clone_roots-in-btrfs_ioctl_send.patch +btrfs-tree-checker-fix-false-alert-caused-by-legacy-btrfs-root-item.patch +btrfs-cleanup-cow-block-on-error.patch +btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch +btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch +btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch +usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch +usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch +usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch +usb-dwc3-gadget-check-mps-of-the-request-length.patch +usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch +usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch +usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch +usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch +usb-cdc-acm-fix-cooldown-mechanism.patch +usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch +usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch +drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch +vt-keyboard-simplify-vt_kdgkbsent.patch +vt-keyboard-extend-func_buf_lock-to-readers.patch +hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch +udf-fix-memory-leak-when-mounting.patch +dmaengine-dma-jz4780-fix-race-in-jz4780_dma_tx_status.patch +iio-light-si1145-fix-timestamp-alignment-and-prevent-data-leak.patch +iio-adc-gyroadc-fix-leak-of-device-node-iterator.patch +iio-adc-ti-adc0832-fix-alignment-issue-with-timestamp.patch +iio-adc-ti-adc12138-fix-alignment-issue-with-timestamp.patch +iio-gyro-itg3200-fix-timestamp-alignment-and-prevent-data-leak.patch +powerpc-drmem-make-lmb_size-64-bit.patch +mips-dec-restore-bootmem-reservation-for-firmware-working-memory-area.patch +s390-stp-add-locking-to-sysfs-functions.patch +powerpc-rtas-restrict-rtas-requests-from-userspace.patch +powerpc-warn-about-use-of-smt_snooze_delay.patch +powerpc-memhotplug-make-lmb-size-64bit.patch +powerpc-powernv-elog-fix-race-while-processing-opal-error-log-event.patch +powerpc-powermac-fix-low_sleep_handler-with-kuap-and-kuep.patch +powerpc-fix-undetected-data-corruption-with-p9n-dd2.1-vsx-ci-load-emulation.patch +nfsv4-wait-for-stateid-updates-after-close-open_downgrade.patch +nfsv4.2-support-exchgid4_flag_supp_fence_ops-4.2-exchange_id-flag.patch +nfsd-add-missing-nfsv2-.pc_func-methods.patch +ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch +ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch +ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch +ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch +ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch +ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch diff --git a/queue-5.4/ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch b/queue-5.4/ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch new file mode 100644 index 00000000000..a9ba8ff106e --- /dev/null +++ b/queue-5.4/ubifs-dent-fix-some-potential-memory-leaks-while-iterating-entries.patch @@ -0,0 +1,33 @@ +From 58f6e78a65f1fcbf732f60a7478ccc99873ff3ba Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Mon, 1 Jun 2020 17:10:37 +0800 +Subject: ubifs: dent: Fix some potential memory leaks while iterating entries + +From: Zhihao Cheng + +commit 58f6e78a65f1fcbf732f60a7478ccc99873ff3ba upstream. + +Fix some potential memory leaks in error handling branches while +iterating dent entries. For example, function dbg_check_dir() +forgets to free pdent if it exists. + +Signed-off-by: Zhihao Cheng +Cc: +Fixes: 1e51764a3c2ac05a2 ("UBIFS: add new flash file system") +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/debug.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/fs/ubifs/debug.c ++++ b/fs/ubifs/debug.c +@@ -1123,6 +1123,7 @@ int dbg_check_dir(struct ubifs_info *c, + err = PTR_ERR(dent); + if (err == -ENOENT) + break; ++ kfree(pdent); + return err; + } + diff --git a/queue-5.4/ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch b/queue-5.4/ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch new file mode 100644 index 00000000000..2b2064c3e1d --- /dev/null +++ b/queue-5.4/ubifs-don-t-parse-authentication-mount-options-in-remount-process.patch @@ -0,0 +1,55 @@ +From bb674a4d4de1032837fcbf860a63939e66f0b7ad Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Tue, 29 Sep 2020 20:45:30 +0800 +Subject: ubifs: Don't parse authentication mount options in remount process + +From: Zhihao Cheng + +commit bb674a4d4de1032837fcbf860a63939e66f0b7ad upstream. + +There is no need to dump authentication options while remounting, +because authentication initialization can only be doing once in +the first mount process. Dumping authentication mount options in +remount process may cause memory leak if UBIFS has already been +mounted with old authentication mount options. + +Signed-off-by: Zhihao Cheng +Cc: # 4.20+ +Fixes: d8a22773a12c6d7 ("ubifs: Enable authentication support") +Reviewed-by: Sascha Hauer +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/super.c | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1092,14 +1092,20 @@ static int ubifs_parse_options(struct ub + break; + } + case Opt_auth_key: +- c->auth_key_name = kstrdup(args[0].from, GFP_KERNEL); +- if (!c->auth_key_name) +- return -ENOMEM; ++ if (!is_remount) { ++ c->auth_key_name = kstrdup(args[0].from, ++ GFP_KERNEL); ++ if (!c->auth_key_name) ++ return -ENOMEM; ++ } + break; + case Opt_auth_hash_name: +- c->auth_hash_name = kstrdup(args[0].from, GFP_KERNEL); +- if (!c->auth_hash_name) +- return -ENOMEM; ++ if (!is_remount) { ++ c->auth_hash_name = kstrdup(args[0].from, ++ GFP_KERNEL); ++ if (!c->auth_hash_name) ++ return -ENOMEM; ++ } + break; + case Opt_ignore: + break; diff --git a/queue-5.4/ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch b/queue-5.4/ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch new file mode 100644 index 00000000000..9a20ab4e579 --- /dev/null +++ b/queue-5.4/ubifs-fix-a-memleak-after-dumping-authentication-mount-options.patch @@ -0,0 +1,62 @@ +From 47f6d9ce45b03a40c34b668a9884754c58122b39 Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Tue, 29 Sep 2020 20:45:29 +0800 +Subject: ubifs: Fix a memleak after dumping authentication mount options + +From: Zhihao Cheng + +commit 47f6d9ce45b03a40c34b668a9884754c58122b39 upstream. + +Fix a memory leak after dumping authentication mount options in error +handling branch. + +Signed-off-by: Zhihao Cheng +Cc: # 4.20+ +Fixes: d8a22773a12c6d7 ("ubifs: Enable authentication support") +Reviewed-by: Sascha Hauer +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/super.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1123,6 +1123,18 @@ static int ubifs_parse_options(struct ub + return 0; + } + ++/* ++ * ubifs_release_options - release mount parameters which have been dumped. ++ * @c: UBIFS file-system description object ++ */ ++static void ubifs_release_options(struct ubifs_info *c) ++{ ++ kfree(c->auth_key_name); ++ c->auth_key_name = NULL; ++ kfree(c->auth_hash_name); ++ c->auth_hash_name = NULL; ++} ++ + /** + * destroy_journal - destroy journal data structures. + * @c: UBIFS file-system description object +@@ -1632,8 +1644,7 @@ static void ubifs_umount(struct ubifs_in + ubifs_lpt_free(c, 0); + ubifs_exit_authentication(c); + +- kfree(c->auth_key_name); +- kfree(c->auth_hash_name); ++ ubifs_release_options(c); + kfree(c->cbuf); + kfree(c->rcvrd_mst_node); + kfree(c->mst_node); +@@ -2201,6 +2212,7 @@ out_umount: + out_unlock: + mutex_unlock(&c->umount_mutex); + out_close: ++ ubifs_release_options(c); + ubi_close_volume(c->ubi); + out: + return err; diff --git a/queue-5.4/ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch b/queue-5.4/ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch new file mode 100644 index 00000000000..bed5467ed89 --- /dev/null +++ b/queue-5.4/ubifs-journal-make-sure-to-not-dirty-twice-for-auth-nodes.patch @@ -0,0 +1,46 @@ +From 78c7d49f55d8631b67c09f9bfbe8155211a9ea06 Mon Sep 17 00:00:00 2001 +From: Richard Weinberger +Date: Mon, 28 Sep 2020 20:58:59 +0200 +Subject: ubifs: journal: Make sure to not dirty twice for auth nodes + +From: Richard Weinberger + +commit 78c7d49f55d8631b67c09f9bfbe8155211a9ea06 upstream. + +When removing the last reference of an inode the size of an auth node +is already part of write_len. So we must not call ubifs_add_auth_dirt(). +Call it only when needed. + +Cc: +Cc: Sascha Hauer +Cc: Kristof Havasi +Fixes: 6a98bc4614de ("ubifs: Add authentication nodes to journal") +Reported-and-tested-by: Kristof Havasi +Reviewed-by: Sascha Hauer +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/journal.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/fs/ubifs/journal.c ++++ b/fs/ubifs/journal.c +@@ -938,8 +938,6 @@ int ubifs_jnl_write_inode(struct ubifs_i + inode->i_ino); + release_head(c, BASEHD); + +- ubifs_add_auth_dirt(c, lnum); +- + if (last_reference) { + err = ubifs_tnc_remove_ino(c, inode->i_ino); + if (err) +@@ -949,6 +947,8 @@ int ubifs_jnl_write_inode(struct ubifs_i + } else { + union ubifs_key key; + ++ ubifs_add_auth_dirt(c, lnum); ++ + ino_key_init(c, &key, inode->i_ino); + err = ubifs_tnc_add(c, &key, lnum, offs, ilen, hash); + } diff --git a/queue-5.4/ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch b/queue-5.4/ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch new file mode 100644 index 00000000000..8904515b996 --- /dev/null +++ b/queue-5.4/ubifs-mount_ubifs-release-authentication-resource-in-error-handling-path.patch @@ -0,0 +1,65 @@ +From e2a05cc7f8229e150243cdae40f2af9021d67a4a Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Tue, 29 Sep 2020 20:45:31 +0800 +Subject: ubifs: mount_ubifs: Release authentication resource in error handling path + +From: Zhihao Cheng + +commit e2a05cc7f8229e150243cdae40f2af9021d67a4a upstream. + +Release the authentication related resource in some error handling +branches in mount_ubifs(). + +Signed-off-by: Zhihao Cheng +Cc: # 4.20+ +Fixes: d8a22773a12c6d7 ("ubifs: Enable authentication support") +Reviewed-by: Sascha Hauer +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/super.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/fs/ubifs/super.c ++++ b/fs/ubifs/super.c +@@ -1313,7 +1313,7 @@ static int mount_ubifs(struct ubifs_info + + err = ubifs_read_superblock(c); + if (err) +- goto out_free; ++ goto out_auth; + + c->probing = 0; + +@@ -1325,18 +1325,18 @@ static int mount_ubifs(struct ubifs_info + ubifs_err(c, "'compressor \"%s\" is not compiled in", + ubifs_compr_name(c, c->default_compr)); + err = -ENOTSUPP; +- goto out_free; ++ goto out_auth; + } + + err = init_constants_sb(c); + if (err) +- goto out_free; ++ goto out_auth; + + sz = ALIGN(c->max_idx_node_sz, c->min_io_size) * 2; + c->cbuf = kmalloc(sz, GFP_NOFS); + if (!c->cbuf) { + err = -ENOMEM; +- goto out_free; ++ goto out_auth; + } + + err = alloc_wbufs(c); +@@ -1611,6 +1611,8 @@ out_wbufs: + free_wbufs(c); + out_cbuf: + kfree(c->cbuf); ++out_auth: ++ ubifs_exit_authentication(c); + out_free: + kfree(c->write_reserve_buf); + kfree(c->bu.buf); diff --git a/queue-5.4/ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch b/queue-5.4/ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch new file mode 100644 index 00000000000..6e35681f4e0 --- /dev/null +++ b/queue-5.4/ubifs-xattr-fix-some-potential-memory-leaks-while-iterating-entries.patch @@ -0,0 +1,107 @@ +From f2aae745b82c842221f4f233051f9ac641790959 Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Mon, 1 Jun 2020 17:10:36 +0800 +Subject: ubifs: xattr: Fix some potential memory leaks while iterating entries + +From: Zhihao Cheng + +commit f2aae745b82c842221f4f233051f9ac641790959 upstream. + +Fix some potential memory leaks in error handling branches while +iterating xattr entries. For example, function ubifs_tnc_remove_ino() +forgets to free pxent if it exists. Similar problems also exist in +ubifs_purge_xattrs(), ubifs_add_orphan() and ubifs_jnl_write_inode(). + +Signed-off-by: Zhihao Cheng +Cc: +Fixes: 1e51764a3c2ac05a2 ("UBIFS: add new flash file system") +Signed-off-by: Richard Weinberger +Signed-off-by: Greg Kroah-Hartman + +--- + fs/ubifs/journal.c | 2 ++ + fs/ubifs/orphan.c | 2 ++ + fs/ubifs/tnc.c | 3 +++ + fs/ubifs/xattr.c | 2 ++ + 4 files changed, 9 insertions(+) + +--- a/fs/ubifs/journal.c ++++ b/fs/ubifs/journal.c +@@ -894,6 +894,7 @@ int ubifs_jnl_write_inode(struct ubifs_i + if (err == -ENOENT) + break; + ++ kfree(pxent); + goto out_release; + } + +@@ -906,6 +907,7 @@ int ubifs_jnl_write_inode(struct ubifs_i + ubifs_err(c, "dead directory entry '%s', error %d", + xent->name, err); + ubifs_ro_mode(c, err); ++ kfree(pxent); + kfree(xent); + goto out_release; + } +--- a/fs/ubifs/orphan.c ++++ b/fs/ubifs/orphan.c +@@ -173,6 +173,7 @@ int ubifs_add_orphan(struct ubifs_info * + err = PTR_ERR(xent); + if (err == -ENOENT) + break; ++ kfree(pxent); + return err; + } + +@@ -182,6 +183,7 @@ int ubifs_add_orphan(struct ubifs_info * + + xattr_orphan = orphan_add(c, xattr_inum, orphan); + if (IS_ERR(xattr_orphan)) { ++ kfree(pxent); + kfree(xent); + return PTR_ERR(xattr_orphan); + } +--- a/fs/ubifs/tnc.c ++++ b/fs/ubifs/tnc.c +@@ -2885,6 +2885,7 @@ int ubifs_tnc_remove_ino(struct ubifs_in + err = PTR_ERR(xent); + if (err == -ENOENT) + break; ++ kfree(pxent); + return err; + } + +@@ -2898,6 +2899,7 @@ int ubifs_tnc_remove_ino(struct ubifs_in + fname_len(&nm) = le16_to_cpu(xent->nlen); + err = ubifs_tnc_remove_nm(c, &key1, &nm); + if (err) { ++ kfree(pxent); + kfree(xent); + return err; + } +@@ -2906,6 +2908,7 @@ int ubifs_tnc_remove_ino(struct ubifs_in + highest_ino_key(c, &key2, xattr_inum); + err = ubifs_tnc_remove_range(c, &key1, &key2); + if (err) { ++ kfree(pxent); + kfree(xent); + return err; + } +--- a/fs/ubifs/xattr.c ++++ b/fs/ubifs/xattr.c +@@ -522,6 +522,7 @@ int ubifs_purge_xattrs(struct inode *hos + xent->name, err); + ubifs_ro_mode(c, err); + kfree(pxent); ++ kfree(xent); + return err; + } + +@@ -531,6 +532,7 @@ int ubifs_purge_xattrs(struct inode *hos + err = remove_xattr(c, host, xino, &nm); + if (err) { + kfree(pxent); ++ kfree(xent); + iput(xino); + ubifs_err(c, "cannot remove xattr, error %d", err); + return err; diff --git a/queue-5.4/udf-fix-memory-leak-when-mounting.patch b/queue-5.4/udf-fix-memory-leak-when-mounting.patch new file mode 100644 index 00000000000..2ac9fc4fb1d --- /dev/null +++ b/queue-5.4/udf-fix-memory-leak-when-mounting.patch @@ -0,0 +1,83 @@ +From a7be300de800e755714c71103ae4a0d205e41e99 Mon Sep 17 00:00:00 2001 +From: Jan Kara +Date: Tue, 22 Sep 2020 12:20:14 +0200 +Subject: udf: Fix memory leak when mounting + +From: Jan Kara + +commit a7be300de800e755714c71103ae4a0d205e41e99 upstream. + +udf_process_sequence() allocates temporary array for processing +partition descriptors on volume which it fails to free. Free the array +when it is not needed anymore. + +Fixes: 7b78fd02fb19 ("udf: Fix handling of Partition Descriptors") +CC: stable@vger.kernel.org +Reported-by: syzbot+128f4dd6e796c98b3760@syzkaller.appspotmail.com +Signed-off-by: Jan Kara +Signed-off-by: Greg Kroah-Hartman + +--- + fs/udf/super.c | 21 +++++++++++++-------- + 1 file changed, 13 insertions(+), 8 deletions(-) + +--- a/fs/udf/super.c ++++ b/fs/udf/super.c +@@ -1703,7 +1703,8 @@ static noinline int udf_process_sequence + "Pointers (max %u supported)\n", + UDF_MAX_TD_NESTING); + brelse(bh); +- return -EIO; ++ ret = -EIO; ++ goto out; + } + + vdp = (struct volDescPtr *)bh->b_data; +@@ -1723,7 +1724,8 @@ static noinline int udf_process_sequence + curr = get_volume_descriptor_record(ident, bh, &data); + if (IS_ERR(curr)) { + brelse(bh); +- return PTR_ERR(curr); ++ ret = PTR_ERR(curr); ++ goto out; + } + /* Descriptor we don't care about? */ + if (!curr) +@@ -1745,28 +1747,31 @@ static noinline int udf_process_sequence + */ + if (!data.vds[VDS_POS_PRIMARY_VOL_DESC].block) { + udf_err(sb, "Primary Volume Descriptor not found!\n"); +- return -EAGAIN; ++ ret = -EAGAIN; ++ goto out; + } + ret = udf_load_pvoldesc(sb, data.vds[VDS_POS_PRIMARY_VOL_DESC].block); + if (ret < 0) +- return ret; ++ goto out; + + if (data.vds[VDS_POS_LOGICAL_VOL_DESC].block) { + ret = udf_load_logicalvol(sb, + data.vds[VDS_POS_LOGICAL_VOL_DESC].block, + fileset); + if (ret < 0) +- return ret; ++ goto out; + } + + /* Now handle prevailing Partition Descriptors */ + for (i = 0; i < data.num_part_descs; i++) { + ret = udf_load_partdesc(sb, data.part_descs_loc[i].rec.block); + if (ret < 0) +- return ret; ++ goto out; + } +- +- return 0; ++ ret = 0; ++out: ++ kfree(data.part_descs_loc); ++ return ret; + } + + /* diff --git a/queue-5.4/usb-cdc-acm-fix-cooldown-mechanism.patch b/queue-5.4/usb-cdc-acm-fix-cooldown-mechanism.patch new file mode 100644 index 00000000000..19be0b63535 --- /dev/null +++ b/queue-5.4/usb-cdc-acm-fix-cooldown-mechanism.patch @@ -0,0 +1,126 @@ +From 38203b8385bf6283537162bde7d499f830964711 Mon Sep 17 00:00:00 2001 +From: Jerome Brunet +Date: Mon, 19 Oct 2020 19:07:02 +0200 +Subject: usb: cdc-acm: fix cooldown mechanism + +From: Jerome Brunet + +commit 38203b8385bf6283537162bde7d499f830964711 upstream. + +Commit a4e7279cd1d1 ("cdc-acm: introduce a cool down") is causing +regression if there is some USB error, such as -EPROTO. + +This has been reported on some samples of the Odroid-N2 using the Combee II +Zibgee USB dongle. + +> struct acm *acm = container_of(work, struct acm, work) + +is incorrect in case of a delayed work and causes warnings, usually from +the workqueue: + +> WARNING: CPU: 0 PID: 0 at kernel/workqueue.c:1474 __queue_work+0x480/0x528. + +When this happens, USB eventually stops working completely after a while. +Also the ACM_ERROR_DELAY bit is never set, so the cooldown mechanism +previously introduced cannot be triggered and acm_submit_read_urb() is +never called. + +This changes makes the cdc-acm driver use a single delayed work, fixing the +pointer arithmetic in acm_softint() and set the ACM_ERROR_DELAY when the +cooldown mechanism appear to be needed. + +Fixes: a4e7279cd1d1 ("cdc-acm: introduce a cool down") +Cc: Oliver Neukum +Reported-by: Pascal Vizeli +Acked-by: Oliver Neukum +Signed-off-by: Jerome Brunet +Link: https://lore.kernel.org/r/20201019170702.150534-1-jbrunet@baylibre.com +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/cdc-acm.c | 12 +++++------- + drivers/usb/class/cdc-acm.h | 3 +-- + 2 files changed, 6 insertions(+), 9 deletions(-) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -507,6 +507,7 @@ static void acm_read_bulk_callback(struc + "%s - cooling babbling device\n", __func__); + usb_mark_last_busy(acm->dev); + set_bit(rb->index, &acm->urbs_in_error_delay); ++ set_bit(ACM_ERROR_DELAY, &acm->flags); + cooldown = true; + break; + default: +@@ -532,7 +533,7 @@ static void acm_read_bulk_callback(struc + + if (stopped || stalled || cooldown) { + if (stalled) +- schedule_work(&acm->work); ++ schedule_delayed_work(&acm->dwork, 0); + else if (cooldown) + schedule_delayed_work(&acm->dwork, HZ / 2); + return; +@@ -562,13 +563,13 @@ static void acm_write_bulk(struct urb *u + acm_write_done(acm, wb); + spin_unlock_irqrestore(&acm->write_lock, flags); + set_bit(EVENT_TTY_WAKEUP, &acm->flags); +- schedule_work(&acm->work); ++ schedule_delayed_work(&acm->dwork, 0); + } + + static void acm_softint(struct work_struct *work) + { + int i; +- struct acm *acm = container_of(work, struct acm, work); ++ struct acm *acm = container_of(work, struct acm, dwork.work); + + if (test_bit(EVENT_RX_STALL, &acm->flags)) { + smp_mb(); /* against acm_suspend() */ +@@ -584,7 +585,7 @@ static void acm_softint(struct work_stru + if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) { + for (i = 0; i < acm->rx_buflimit; i++) + if (test_and_clear_bit(i, &acm->urbs_in_error_delay)) +- acm_submit_read_urb(acm, i, GFP_NOIO); ++ acm_submit_read_urb(acm, i, GFP_KERNEL); + } + + if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags)) +@@ -1364,7 +1365,6 @@ made_compressed_probe: + acm->ctrlsize = ctrlsize; + acm->readsize = readsize; + acm->rx_buflimit = num_rx_buf; +- INIT_WORK(&acm->work, acm_softint); + INIT_DELAYED_WORK(&acm->dwork, acm_softint); + init_waitqueue_head(&acm->wioctl); + spin_lock_init(&acm->write_lock); +@@ -1574,7 +1574,6 @@ static void acm_disconnect(struct usb_in + } + + acm_kill_urbs(acm); +- cancel_work_sync(&acm->work); + cancel_delayed_work_sync(&acm->dwork); + + tty_unregister_device(acm_tty_driver, acm->minor); +@@ -1617,7 +1616,6 @@ static int acm_suspend(struct usb_interf + return 0; + + acm_kill_urbs(acm); +- cancel_work_sync(&acm->work); + cancel_delayed_work_sync(&acm->dwork); + acm->urbs_in_error_delay = 0; + +--- a/drivers/usb/class/cdc-acm.h ++++ b/drivers/usb/class/cdc-acm.h +@@ -112,8 +112,7 @@ struct acm { + # define ACM_ERROR_DELAY 3 + unsigned long urbs_in_error_delay; /* these need to be restarted after a delay */ + struct usb_cdc_line_coding line; /* bits, stop, parity */ +- struct work_struct work; /* work queue entry for various purposes*/ +- struct delayed_work dwork; /* for cool downs needed in error recovery */ ++ struct delayed_work dwork; /* work queue entry for various purposes */ + unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */ + unsigned int ctrlout; /* output control lines (DTR, RTS) */ + struct async_icount iocount; /* counters for control line changes */ diff --git a/queue-5.4/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch b/queue-5.4/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch new file mode 100644 index 00000000000..997b8688083 --- /dev/null +++ b/queue-5.4/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch @@ -0,0 +1,42 @@ +From 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb Mon Sep 17 00:00:00 2001 +From: Li Jun +Date: Tue, 28 Jul 2020 20:42:41 +0800 +Subject: usb: dwc3: core: add phy cleanup for probe error handling + +From: Li Jun + +commit 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb upstream. + +Add the phy cleanup if dwc3 mode init fail, which is the missing part of +de-init for dwc3 core init. + +Fixes: c499ff71ff2a ("usb: dwc3: core: re-factor init and exit paths") +Cc: +Signed-off-by: Li Jun +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/core.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1535,6 +1535,17 @@ static int dwc3_probe(struct platform_de + + err5: + dwc3_event_buffers_cleanup(dwc); ++ ++ usb_phy_shutdown(dwc->usb2_phy); ++ usb_phy_shutdown(dwc->usb3_phy); ++ phy_exit(dwc->usb2_generic_phy); ++ phy_exit(dwc->usb3_generic_phy); ++ ++ usb_phy_set_suspend(dwc->usb2_phy, 1); ++ usb_phy_set_suspend(dwc->usb3_phy, 1); ++ phy_power_off(dwc->usb2_generic_phy); ++ phy_power_off(dwc->usb3_generic_phy); ++ + dwc3_ulpi_exit(dwc); + + err4: diff --git a/queue-5.4/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch b/queue-5.4/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch new file mode 100644 index 00000000000..142a9db66e4 --- /dev/null +++ b/queue-5.4/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch @@ -0,0 +1,106 @@ +From 266d0493900ac5d6a21cdbe6b1624ed2da94d47a Mon Sep 17 00:00:00 2001 +From: Li Jun +Date: Tue, 28 Jul 2020 20:42:40 +0800 +Subject: usb: dwc3: core: don't trigger runtime pm when remove driver + +From: Li Jun + +commit 266d0493900ac5d6a21cdbe6b1624ed2da94d47a upstream. + +No need to trigger runtime pm in driver removal, otherwise if user +disable auto suspend via sys file, runtime suspend may be entered, +which will call dwc3_core_exit() again and there will be clock disable +not balance warning: + +[ 2026.820154] xhci-hcd xhci-hcd.0.auto: remove, state 4 +[ 2026.825268] usb usb2: USB disconnect, device number 1 +[ 2026.831017] xhci-hcd xhci-hcd.0.auto: USB bus 2 deregistered +[ 2026.836806] xhci-hcd xhci-hcd.0.auto: remove, state 4 +[ 2026.842029] usb usb1: USB disconnect, device number 1 +[ 2026.848029] xhci-hcd xhci-hcd.0.auto: USB bus 1 deregistered +[ 2026.865889] ------------[ cut here ]------------ +[ 2026.870506] usb2_ctrl_root_clk already disabled +[ 2026.875082] WARNING: CPU: 0 PID: 731 at drivers/clk/clk.c:958 +clk_core_disable+0xa0/0xa8 +[ 2026.883170] Modules linked in: dwc3(-) phy_fsl_imx8mq_usb [last +unloaded: dwc3] +[ 2026.890488] CPU: 0 PID: 731 Comm: rmmod Not tainted +5.8.0-rc7-00280-g9d08cca-dirty #245 +[ 2026.898489] Hardware name: NXP i.MX8MQ EVK (DT) +[ 2026.903020] pstate: 20000085 (nzCv daIf -PAN -UAO BTYPE=--) +[ 2026.908594] pc : clk_core_disable+0xa0/0xa8 +[ 2026.912777] lr : clk_core_disable+0xa0/0xa8 +[ 2026.916958] sp : ffff8000121b39a0 +[ 2026.920271] x29: ffff8000121b39a0 x28: ffff0000b11f3700 +[ 2026.925583] x27: 0000000000000000 x26: ffff0000b539c700 +[ 2026.930895] x25: 000001d7e44e1232 x24: ffff0000b76fa800 +[ 2026.936208] x23: ffff0000b76fa6f8 x22: ffff800008d01040 +[ 2026.941520] x21: ffff0000b539ce00 x20: ffff0000b7105000 +[ 2026.946832] x19: ffff0000b7105000 x18: 0000000000000010 +[ 2026.952144] x17: 0000000000000001 x16: 0000000000000000 +[ 2026.957456] x15: ffff0000b11f3b70 x14: ffffffffffffffff +[ 2026.962768] x13: ffff8000921b36f7 x12: ffff8000121b36ff +[ 2026.968080] x11: ffff8000119e1000 x10: ffff800011bf26d0 +[ 2026.973392] x9 : 0000000000000000 x8 : ffff800011bf3000 +[ 2026.978704] x7 : ffff800010695d68 x6 : 0000000000000252 +[ 2026.984016] x5 : ffff0000bb9881f0 x4 : 0000000000000000 +[ 2026.989327] x3 : 0000000000000027 x2 : 0000000000000023 +[ 2026.994639] x1 : ac2fa471aa7cab00 x0 : 0000000000000000 +[ 2026.999951] Call trace: +[ 2027.002401] clk_core_disable+0xa0/0xa8 +[ 2027.006238] clk_core_disable_lock+0x20/0x38 +[ 2027.010508] clk_disable+0x1c/0x28 +[ 2027.013911] clk_bulk_disable+0x34/0x50 +[ 2027.017758] dwc3_core_exit+0xec/0x110 [dwc3] +[ 2027.022122] dwc3_suspend_common+0x84/0x188 [dwc3] +[ 2027.026919] dwc3_runtime_suspend+0x74/0x9c [dwc3] +[ 2027.031712] pm_generic_runtime_suspend+0x28/0x40 +[ 2027.036419] genpd_runtime_suspend+0xa0/0x258 +[ 2027.040777] __rpm_callback+0x88/0x140 +[ 2027.044526] rpm_callback+0x20/0x80 +[ 2027.048015] rpm_suspend+0xd0/0x418 +[ 2027.051503] __pm_runtime_suspend+0x58/0xa0 +[ 2027.055693] dwc3_runtime_idle+0x7c/0x90 [dwc3] +[ 2027.060224] __rpm_callback+0x88/0x140 +[ 2027.063973] rpm_idle+0x78/0x150 +[ 2027.067201] __pm_runtime_idle+0x58/0xa0 +[ 2027.071130] dwc3_remove+0x64/0xc0 [dwc3] +[ 2027.075140] platform_drv_remove+0x28/0x48 +[ 2027.079239] device_release_driver_internal+0xf4/0x1c0 +[ 2027.084377] driver_detach+0x4c/0xd8 +[ 2027.087954] bus_remove_driver+0x54/0xa8 +[ 2027.091877] driver_unregister+0x2c/0x58 +[ 2027.095799] platform_driver_unregister+0x10/0x18 +[ 2027.100509] dwc3_driver_exit+0x14/0x1408 [dwc3] +[ 2027.105129] __arm64_sys_delete_module+0x178/0x218 +[ 2027.109922] el0_svc_common.constprop.0+0x68/0x160 +[ 2027.114714] do_el0_svc+0x20/0x80 +[ 2027.118031] el0_sync_handler+0x88/0x190 +[ 2027.121953] el0_sync+0x140/0x180 +[ 2027.125267] ---[ end trace 027f4f8189958f1f ]--- +[ 2027.129976] ------------[ cut here ]------------ + +Fixes: fc8bb91bc83e ("usb: dwc3: implement runtime PM") +Cc: +Signed-off-by: Li Jun +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/dwc3/core.c ++++ b/drivers/usb/dwc3/core.c +@@ -1581,9 +1581,9 @@ static int dwc3_remove(struct platform_d + dwc3_core_exit(dwc); + dwc3_ulpi_exit(dwc); + +- pm_runtime_put_sync(&pdev->dev); +- pm_runtime_allow(&pdev->dev); + pm_runtime_disable(&pdev->dev); ++ pm_runtime_put_noidle(&pdev->dev); ++ pm_runtime_set_suspended(&pdev->dev); + + dwc3_free_event_buffers(dwc); + dwc3_free_scratch_buffers(dwc); diff --git a/queue-5.4/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch b/queue-5.4/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch new file mode 100644 index 00000000000..705aae7377d --- /dev/null +++ b/queue-5.4/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch @@ -0,0 +1,63 @@ +From 66706077dc89c66a4777a4c6298273816afb848c Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 24 Sep 2020 01:21:43 -0700 +Subject: usb: dwc3: ep0: Fix ZLP for OUT ep0 requests + +From: Thinh Nguyen + +commit 66706077dc89c66a4777a4c6298273816afb848c upstream. + +The current ZLP handling for ep0 requests is only for control IN +requests. For OUT direction, DWC3 needs to check and setup for MPS +alignment. + +Usually, control OUT requests can indicate its transfer size via the +wLength field of the control message. So usb_request->zero is usually +not needed for OUT direction. To handle ZLP OUT for control endpoint, +make sure the TRB is MPS size. + +Cc: stable@vger.kernel.org +Fixes: c7fcdeb2627c ("usb: dwc3: ep0: simplify EP0 state machine") +Fixes: d6e5a549cc4d ("usb: dwc3: simplify ZLP handling") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/ep0.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -942,12 +942,16 @@ static void dwc3_ep0_xfer_complete(struc + static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, + struct dwc3_ep *dep, struct dwc3_request *req) + { ++ unsigned int trb_length = 0; + int ret; + + req->direction = !!dep->number; + + if (req->request.length == 0) { +- dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0, ++ if (!req->direction) ++ trb_length = dep->endpoint.maxpacket; ++ ++ dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, trb_length, + DWC3_TRBCTL_CONTROL_DATA, false); + ret = dwc3_ep0_start_trans(dep); + } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) +@@ -994,9 +998,12 @@ static void __dwc3_ep0_do_control_data(s + + req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1]; + ++ if (!req->direction) ++ trb_length = dep->endpoint.maxpacket; ++ + /* Now prepare one extra TRB to align transfer size */ + dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, +- 0, DWC3_TRBCTL_CONTROL_DATA, ++ trb_length, DWC3_TRBCTL_CONTROL_DATA, + false); + ret = dwc3_ep0_start_trans(dep); + } else { diff --git a/queue-5.4/usb-dwc3-gadget-check-mps-of-the-request-length.patch b/queue-5.4/usb-dwc3-gadget-check-mps-of-the-request-length.patch new file mode 100644 index 00000000000..70a0594b14c --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-check-mps-of-the-request-length.patch @@ -0,0 +1,43 @@ +From ca3df3468eec87f6374662f7de425bc44c3810c1 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 24 Sep 2020 01:21:18 -0700 +Subject: usb: dwc3: gadget: Check MPS of the request length + +From: Thinh Nguyen + +commit ca3df3468eec87f6374662f7de425bc44c3810c1 upstream. + +When preparing for SG, not all the entries are prepared at once. When +resume, don't use the remaining request length to calculate for MPS +alignment. Use the entire request->length to do that. + +Cc: stable@vger.kernel.org +Fixes: 5d187c0454ef ("usb: dwc3: gadget: Don't setup more than requested") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/gadget.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1057,6 +1057,8 @@ static void dwc3_prepare_one_trb_sg(stru + struct scatterlist *s; + int i; + unsigned int length = req->request.length; ++ unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); ++ unsigned int rem = length % maxp; + unsigned int remaining = req->request.num_mapped_sgs + - req->num_queued_sgs; + +@@ -1068,8 +1070,6 @@ static void dwc3_prepare_one_trb_sg(stru + length -= sg_dma_len(s); + + for_each_sg(sg, s, remaining, i) { +- unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); +- unsigned int rem = length % maxp; + unsigned int trb_length; + unsigned chain = true; + diff --git a/queue-5.4/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch b/queue-5.4/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch new file mode 100644 index 00000000000..bcae220e70b --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch @@ -0,0 +1,145 @@ +From d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Wed, 2 Sep 2020 18:43:04 -0700 +Subject: usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command + +From: Thinh Nguyen + +commit d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 upstream. + +According the programming guide (for all DWC3 IPs), when the driver +handles ClearFeature(halt) request, it should issue CLEAR_STALL command +_after_ the END_TRANSFER command completes. The END_TRANSFER command may +take some time to complete. So, delay the ClearFeature(halt) request +control status stage and wait for END_TRANSFER command completion +interrupt. Only after END_TRANSFER command completes that the driver +may issue CLEAR_STALL command. + +Cc: stable@vger.kernel.org +Fixes: cb11ea56f37a ("usb: dwc3: gadget: Properly handle ClearFeature(halt)") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/core.h | 1 + + drivers/usb/dwc3/ep0.c | 16 ++++++++++++++++ + drivers/usb/dwc3/gadget.c | 40 ++++++++++++++++++++++++++++++++-------- + drivers/usb/dwc3/gadget.h | 1 + + 4 files changed, 50 insertions(+), 8 deletions(-) + +--- a/drivers/usb/dwc3/core.h ++++ b/drivers/usb/dwc3/core.h +@@ -700,6 +700,7 @@ struct dwc3_ep { + #define DWC3_EP_END_TRANSFER_PENDING BIT(4) + #define DWC3_EP_PENDING_REQUEST BIT(5) + #define DWC3_EP_DELAY_START BIT(6) ++#define DWC3_EP_PENDING_CLEAR_STALL BIT(11) + + /* This last one is specific to EP0 */ + #define DWC3_EP0_DIR_IN BIT(31) +--- a/drivers/usb/dwc3/ep0.c ++++ b/drivers/usb/dwc3/ep0.c +@@ -524,6 +524,11 @@ static int dwc3_ep0_handle_endpoint(stru + ret = __dwc3_gadget_ep_set_halt(dep, set, true); + if (ret) + return -EINVAL; ++ ++ /* ClearFeature(Halt) may need delayed status */ ++ if (!set && (dep->flags & DWC3_EP_END_TRANSFER_PENDING)) ++ return USB_GADGET_DELAYED_STATUS; ++ + break; + default: + return -EINVAL; +@@ -1049,6 +1054,17 @@ static void dwc3_ep0_do_control_status(s + __dwc3_ep0_do_control_status(dwc, dep); + } + ++void dwc3_ep0_send_delayed_status(struct dwc3 *dwc) ++{ ++ unsigned int direction = !dwc->ep0_expect_in; ++ ++ if (dwc->ep0state != EP0_STATUS_PHASE) ++ return; ++ ++ dwc->delayed_status = false; ++ __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); ++} ++ + static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) + { + struct dwc3_gadget_ep_cmd_params params; +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1719,6 +1719,18 @@ int __dwc3_gadget_ep_set_halt(struct dwc + return 0; + } + ++ dwc3_stop_active_transfer(dep, true, true); ++ ++ list_for_each_entry_safe(req, tmp, &dep->started_list, list) ++ dwc3_gadget_move_cancelled_request(req); ++ ++ if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) { ++ dep->flags |= DWC3_EP_PENDING_CLEAR_STALL; ++ return 0; ++ } ++ ++ dwc3_gadget_ep_cleanup_cancelled_requests(dep); ++ + ret = dwc3_send_clear_stall_ep_cmd(dep); + if (ret) { + dev_err(dwc->dev, "failed to clear STALL on %s\n", +@@ -1728,14 +1740,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc + + dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); + +- dwc3_stop_active_transfer(dep, true, true); +- +- list_for_each_entry_safe(req, tmp, &dep->started_list, list) +- dwc3_gadget_move_cancelled_request(req); +- +- if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) +- dwc3_gadget_ep_cleanup_cancelled_requests(dep); +- + if ((dep->flags & DWC3_EP_DELAY_START) && + !usb_endpoint_xfer_isoc(dep->endpoint.desc)) + __dwc3_gadget_kick_transfer(dep); +@@ -2767,6 +2771,26 @@ static void dwc3_endpoint_interrupt(stru + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; + dep->flags &= ~DWC3_EP_TRANSFER_STARTED; + dwc3_gadget_ep_cleanup_cancelled_requests(dep); ++ ++ if (dep->flags & DWC3_EP_PENDING_CLEAR_STALL) { ++ struct dwc3 *dwc = dep->dwc; ++ ++ dep->flags &= ~DWC3_EP_PENDING_CLEAR_STALL; ++ if (dwc3_send_clear_stall_ep_cmd(dep)) { ++ struct usb_ep *ep0 = &dwc->eps[0]->endpoint; ++ ++ dev_err(dwc->dev, "failed to clear STALL on %s\n", ++ dep->name); ++ if (dwc->delayed_status) ++ __dwc3_gadget_ep0_set_halt(ep0, 1); ++ return; ++ } ++ ++ dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); ++ if (dwc->delayed_status) ++ dwc3_ep0_send_delayed_status(dwc); ++ } ++ + if ((dep->flags & DWC3_EP_DELAY_START) && + !usb_endpoint_xfer_isoc(dep->endpoint.desc)) + __dwc3_gadget_kick_transfer(dep); +--- a/drivers/usb/dwc3/gadget.h ++++ b/drivers/usb/dwc3/gadget.h +@@ -111,6 +111,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_ + int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, + gfp_t gfp_flags); + int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol); ++void dwc3_ep0_send_delayed_status(struct dwc3 *dwc); + + /** + * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW diff --git a/queue-5.4/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch b/queue-5.4/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch new file mode 100644 index 00000000000..e68b3725252 --- /dev/null +++ b/queue-5.4/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch @@ -0,0 +1,66 @@ +From c503672abe1348f10f5a54a662336358c6e1a297 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Wed, 2 Sep 2020 18:42:58 -0700 +Subject: usb: dwc3: gadget: Resume pending requests after CLEAR_STALL + +From: Thinh Nguyen + +commit c503672abe1348f10f5a54a662336358c6e1a297 upstream. + +The function driver may queue new requests right after halting the +endpoint (i.e. queue new requests while the endpoint is stalled). +There's no restriction preventing it from doing so. However, dwc3 +currently drops those requests after CLEAR_STALL. The driver should only +drop started requests. Keep the pending requests in the pending list to +resume and process them after the host issues ClearFeature(Halt) to the +endpoint. + +Cc: stable@vger.kernel.org +Fixes: cb11ea56f37a ("usb: dwc3: gadget: Properly handle ClearFeature(halt)") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/gadget.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1521,8 +1521,13 @@ static int __dwc3_gadget_ep_queue(struct + list_add_tail(&req->list, &dep->pending_list); + req->status = DWC3_REQUEST_STATUS_QUEUED; + +- /* Start the transfer only after the END_TRANSFER is completed */ +- if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) { ++ /* ++ * Start the transfer only after the END_TRANSFER is completed ++ * and endpoint STALL is cleared. ++ */ ++ if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) || ++ (dep->flags & DWC3_EP_WEDGE) || ++ (dep->flags & DWC3_EP_STALL)) { + dep->flags |= DWC3_EP_DELAY_START; + return 0; + } +@@ -1728,13 +1733,14 @@ int __dwc3_gadget_ep_set_halt(struct dwc + list_for_each_entry_safe(req, tmp, &dep->started_list, list) + dwc3_gadget_move_cancelled_request(req); + +- list_for_each_entry_safe(req, tmp, &dep->pending_list, list) +- dwc3_gadget_move_cancelled_request(req); +- +- if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) { +- dep->flags &= ~DWC3_EP_DELAY_START; ++ if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + dwc3_gadget_ep_cleanup_cancelled_requests(dep); +- } ++ ++ if ((dep->flags & DWC3_EP_DELAY_START) && ++ !usb_endpoint_xfer_isoc(dep->endpoint.desc)) ++ __dwc3_gadget_kick_transfer(dep); ++ ++ dep->flags &= ~DWC3_EP_DELAY_START; + } + + return ret; diff --git a/queue-5.4/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch b/queue-5.4/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch new file mode 100644 index 00000000000..b9b3dc2ebf1 --- /dev/null +++ b/queue-5.4/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch @@ -0,0 +1,40 @@ +From a609ce2a13360d639b384b6ca783b38c1247f2db Mon Sep 17 00:00:00 2001 +From: Raymond Tan +Date: Fri, 21 Aug 2020 16:11:01 +0300 +Subject: usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM functionality + +From: Raymond Tan + +commit a609ce2a13360d639b384b6ca783b38c1247f2db upstream. + +Similar to some other IA platforms, Elkhart Lake too depends on the +PMU register write to request transition of Dx power state. + +Thus, we add the PCI_DEVICE_ID_INTEL_EHLLP to the list of devices that +shall execute the ACPI _DSM method during D0/D3 sequence. + +[heikki.krogerus@linux.intel.com: included Fixes tag] + +Fixes: dbb0569de852 ("usb: dwc3: pci: Add Support for Intel Elkhart Lake Devices") +Cc: stable@vger.kernel.org +Signed-off-by: Raymond Tan +Signed-off-by: Heikki Krogerus +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/dwc3-pci.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -147,7 +147,8 @@ static int dwc3_pci_quirks(struct dwc3_p + + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { + if (pdev->device == PCI_DEVICE_ID_INTEL_BXT || +- pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) { ++ pdev->device == PCI_DEVICE_ID_INTEL_BXT_M || ++ pdev->device == PCI_DEVICE_ID_INTEL_EHLLP) { + guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid); + dwc->has_dsm_for_pm = true; + } diff --git a/queue-5.4/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch b/queue-5.4/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch new file mode 100644 index 00000000000..3aaecbfe6e8 --- /dev/null +++ b/queue-5.4/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch @@ -0,0 +1,42 @@ +From 3cd54a618834430a26a648d880dd83d740f2ae30 Mon Sep 17 00:00:00 2001 +From: Ran Wang +Date: Sat, 10 Oct 2020 14:03:08 +0800 +Subject: usb: host: fsl-mph-dr-of: check return of dma_set_mask() + +From: Ran Wang + +commit 3cd54a618834430a26a648d880dd83d740f2ae30 upstream. + +fsl_usb2_device_register() should stop init if dma_set_mask() return +error. + +Fixes: cae058610465 ("drivers/usb/host: fsl: Set DMA_MASK of usb platform device") +Reviewed-by: Peter Chen +Signed-off-by: Ran Wang +Link: https://lore.kernel.org/r/20201010060308.33693-1-ran.wang_1@nxp.com +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/fsl-mph-dr-of.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/fsl-mph-dr-of.c ++++ b/drivers/usb/host/fsl-mph-dr-of.c +@@ -94,10 +94,13 @@ static struct platform_device *fsl_usb2_ + + pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask; + +- if (!pdev->dev.dma_mask) ++ if (!pdev->dev.dma_mask) { + pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask; +- else +- dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ } else { ++ retval = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); ++ if (retval) ++ goto error; ++ } + + retval = platform_device_add_data(pdev, pdata, sizeof(*pdata)); + if (retval) diff --git a/queue-5.4/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch b/queue-5.4/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch new file mode 100644 index 00000000000..da8f21b3607 --- /dev/null +++ b/queue-5.4/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch @@ -0,0 +1,99 @@ +From 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d Mon Sep 17 00:00:00 2001 +From: Li Jun +Date: Mon, 12 Oct 2020 19:03:12 +0800 +Subject: usb: typec: tcpm: reset hard_reset_count for any disconnect +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Li Jun + +commit 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d upstream. + +Current tcpm_detach() only reset hard_reset_count if port->attached +is true, this may cause this counter clear is missed if the CC +disconnect event is generated after tcpm_port_reset() is done +by other events, e.g. VBUS off comes first before CC disconect for +a power sink, in that case the first tcpm_detach() will only clear +port->attached flag but leave hard_reset_count there because +tcpm_port_is_disconnected() is still false, then later tcpm_detach() +by CC disconnect will directly return due to port->attached is cleared, +finally this will result tcpm will not try hard reset or error recovery +for later attach. + +ChiYuan reported this issue on his platform with below tcpm trace: +After power sink session setup after hard reset 2 times, detach +from the power source and then attach: +[ 4848.046358] VBUS off +[ 4848.046384] state change SNK_READY -> SNK_UNATTACHED +[ 4848.050908] Setting voltage/current limit 0 mV 0 mA +[ 4848.050936] polarity 0 +[ 4848.052593] Requesting mux state 0, usb-role 0, orientation 0 +[ 4848.053222] Start toggling +[ 4848.086500] state change SNK_UNATTACHED -> TOGGLING +[ 4848.089983] CC1: 0 -> 0, CC2: 3 -> 3 [state TOGGLING, polarity 0, connected] +[ 4848.089993] state change TOGGLING -> SNK_ATTACH_WAIT +[ 4848.090031] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms +[ 4848.141162] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected] +[ 4848.141170] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT +[ 4848.141184] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms +[ 4848.163156] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed 20 ms] +[ 4848.163162] Start toggling +[ 4848.216918] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected] +[ 4848.216954] state change TOGGLING -> SNK_ATTACH_WAIT +[ 4848.217080] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms +[ 4848.231771] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected] +[ 4848.231800] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT +[ 4848.231857] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms +[ 4848.256022] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed20 ms] +[ 4848.256049] Start toggling +[ 4848.871148] VBUS on +[ 4848.885324] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected] +[ 4848.885372] state change TOGGLING -> SNK_ATTACH_WAIT +[ 4848.885548] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms +[ 4849.088240] state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED [delayed200 ms] +[ 4849.088284] state change SNK_DEBOUNCED -> SNK_ATTACHED +[ 4849.088291] polarity 1 +[ 4849.088769] Requesting mux state 1, usb-role 2, orientation 2 +[ 4849.088895] state change SNK_ATTACHED -> SNK_STARTUP +[ 4849.088907] state change SNK_STARTUP -> SNK_DISCOVERY +[ 4849.088915] Setting voltage/current limit 5000 mV 0 mA +[ 4849.088927] vbus=0 charge:=1 +[ 4849.090505] state change SNK_DISCOVERY -> SNK_WAIT_CAPABILITIES +[ 4849.090828] pending state change SNK_WAIT_CAPABILITIES -> SNK_READY @240 ms +[ 4849.335878] state change SNK_WAIT_CAPABILITIES -> SNK_READY [delayed240 ms] + +this patch fix this issue by clear hard_reset_count at any cases +of cc disconnect, í.e. don't check port->attached flag. + +Fixes: 4b4e02c83167 ("typec: tcpm: Move out of staging") +Cc: stable@vger.kernel.org +Reported-and-tested-by: ChiYuan Huang +Reviewed-by: Guenter Roeck +Reviewed-by: Heikki Krogerus +Signed-off-by: Li Jun +Link: https://lore.kernel.org/r/1602500592-3817-1-git-send-email-jun.li@nxp.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/typec/tcpm/tcpm.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -2723,12 +2723,12 @@ static void tcpm_reset_port(struct tcpm_ + + static void tcpm_detach(struct tcpm_port *port) + { +- if (!port->attached) +- return; +- + if (tcpm_port_is_disconnected(port)) + port->hard_reset_count = 0; + ++ if (!port->attached) ++ return; ++ + tcpm_reset_port(port); + } + diff --git a/queue-5.4/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch b/queue-5.4/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch new file mode 100644 index 00000000000..85bf1486e10 --- /dev/null +++ b/queue-5.4/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch @@ -0,0 +1,81 @@ +From 2a632815683d2d34df52b701a36fe5ac6654e719 Mon Sep 17 00:00:00 2001 +From: Sandeep Singh +Date: Wed, 28 Oct 2020 22:31:23 +0200 +Subject: usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC + +From: Sandeep Singh + +commit 2a632815683d2d34df52b701a36fe5ac6654e719 upstream. + +On some platform of AMD, S3 fails with HCE and SRE errors. To fix this, +need to disable a bit which is enable in sparse controller. + +Cc: stable@vger.kernel.org #v4.19+ +Signed-off-by: Sanket Goswami +Signed-off-by: Sandeep Singh +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20201028203124.375344-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-pci.c | 17 +++++++++++++++++ + drivers/usb/host/xhci.h | 1 + + 2 files changed, 18 insertions(+) + +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -21,6 +21,8 @@ + #define SSIC_PORT_CFG2_OFFSET 0x30 + #define PROG_DONE (1 << 30) + #define SSIC_PORT_UNUSED (1 << 31) ++#define SPARSE_DISABLE_BIT 17 ++#define SPARSE_CNTL_ENABLE 0xC12C + + /* Device for a quirk */ + #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 +@@ -149,6 +151,9 @@ static void xhci_pci_quirks(struct devic + (pdev->device == 0x15e0 || pdev->device == 0x15e1)) + xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND; + ++ if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5) ++ xhci->quirks |= XHCI_DISABLE_SPARSE; ++ + if (pdev->vendor == PCI_VENDOR_ID_AMD) + xhci->quirks |= XHCI_TRUST_TX_LENGTH; + +@@ -467,6 +472,15 @@ static void xhci_pme_quirk(struct usb_hc + readl(reg); + } + ++static void xhci_sparse_control_quirk(struct usb_hcd *hcd) ++{ ++ u32 reg; ++ ++ reg = readl(hcd->regs + SPARSE_CNTL_ENABLE); ++ reg &= ~BIT(SPARSE_DISABLE_BIT); ++ writel(reg, hcd->regs + SPARSE_CNTL_ENABLE); ++} ++ + static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) + { + struct xhci_hcd *xhci = hcd_to_xhci(hcd); +@@ -486,6 +500,9 @@ static int xhci_pci_suspend(struct usb_h + if (xhci->quirks & XHCI_SSIC_PORT_UNUSED) + xhci_ssic_port_unused_quirk(hcd, true); + ++ if (xhci->quirks & XHCI_DISABLE_SPARSE) ++ xhci_sparse_control_quirk(hcd); ++ + ret = xhci_suspend(xhci, do_wakeup); + if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED)) + xhci_ssic_port_unused_quirk(hcd, false); +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1873,6 +1873,7 @@ struct xhci_hcd { + #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33) + #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) + #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) ++#define XHCI_DISABLE_SPARSE BIT_ULL(38) + + unsigned int num_active_eps; + unsigned int limit_active_eps; diff --git a/queue-5.4/vt-keyboard-extend-func_buf_lock-to-readers.patch b/queue-5.4/vt-keyboard-extend-func_buf_lock-to-readers.patch new file mode 100644 index 00000000000..d54235614a5 --- /dev/null +++ b/queue-5.4/vt-keyboard-extend-func_buf_lock-to-readers.patch @@ -0,0 +1,94 @@ +From 82e61c3909db51d91b9d3e2071557b6435018b80 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Mon, 19 Oct 2020 10:55:17 +0200 +Subject: vt: keyboard, extend func_buf_lock to readers + +From: Jiri Slaby + +commit 82e61c3909db51d91b9d3e2071557b6435018b80 upstream. + +Both read-side users of func_table/func_buf need locking. Without that, +one can easily confuse the code by repeatedly setting altering strings +like: +while (1) + for (a = 0; a < 2; a++) { + struct kbsentry kbs = {}; + strcpy((char *)kbs.kb_string, a ? ".\n" : "88888\n"); + ioctl(fd, KDSKBSENT, &kbs); + } + +When that program runs, one can get unexpected output by holding F1 +(note the unxpected period on the last line): +. +88888 +.8888 + +So protect all accesses to 'func_table' (and func_buf) by preexisting +'func_buf_lock'. + +It is easy in 'k_fn' handler as 'puts_queue' is expected not to sleep. +On the other hand, KDGKBSENT needs a local (atomic) copy of the string +because copy_to_user can sleep. Use already allocated, but unused +'kbs->kb_string' for that purpose. + +Note that the program above needs at least CAP_SYS_TTY_CONFIG. + +This depends on the previous patch and on the func_buf_lock lock added +in commit 46ca3f735f34 (tty/vt: fix write/write race in ioctl(KDSKBSENT) +handler) in 5.2. + +Likely fixes CVE-2020-25656. + +Cc: +Reported-by: Minh Yuan +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20201019085517.10176-2-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/vt/keyboard.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +--- a/drivers/tty/vt/keyboard.c ++++ b/drivers/tty/vt/keyboard.c +@@ -742,8 +742,13 @@ static void k_fn(struct vc_data *vc, uns + return; + + if ((unsigned)value < ARRAY_SIZE(func_table)) { ++ unsigned long flags; ++ ++ spin_lock_irqsave(&func_buf_lock, flags); + if (func_table[value]) + puts_queue(vc, func_table[value]); ++ spin_unlock_irqrestore(&func_buf_lock, flags); ++ + } else + pr_err("k_fn called with value=%d\n", value); + } +@@ -1990,7 +1995,7 @@ out: + #undef s + #undef v + +-/* FIXME: This one needs untangling and locking */ ++/* FIXME: This one needs untangling */ + int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) + { + struct kbsentry *kbs; +@@ -2022,10 +2027,14 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb + switch (cmd) { + case KDGKBSENT: { + /* size should have been a struct member */ +- unsigned char *from = func_table[i] ? : ""; ++ ssize_t len = sizeof(user_kdgkb->kb_string); ++ ++ spin_lock_irqsave(&func_buf_lock, flags); ++ len = strlcpy(kbs->kb_string, func_table[i] ? : "", len); ++ spin_unlock_irqrestore(&func_buf_lock, flags); + +- ret = copy_to_user(user_kdgkb->kb_string, from, +- strlen(from) + 1) ? -EFAULT : 0; ++ ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string, ++ len + 1) ? -EFAULT : 0; + + goto reterr; + } diff --git a/queue-5.4/vt-keyboard-simplify-vt_kdgkbsent.patch b/queue-5.4/vt-keyboard-simplify-vt_kdgkbsent.patch new file mode 100644 index 00000000000..8e119c41286 --- /dev/null +++ b/queue-5.4/vt-keyboard-simplify-vt_kdgkbsent.patch @@ -0,0 +1,73 @@ +From 6ca03f90527e499dd5e32d6522909e2ad390896b Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Mon, 19 Oct 2020 10:55:16 +0200 +Subject: vt: keyboard, simplify vt_kdgkbsent + +From: Jiri Slaby + +commit 6ca03f90527e499dd5e32d6522909e2ad390896b upstream. + +Use 'strlen' of the string, add one for NUL terminator and simply do +'copy_to_user' instead of the explicit 'for' loop. This makes the +KDGKBSENT case more compact. + +The only thing we need to take care about is NULL 'func_table[i]'. Use +an empty string in that case. + +The original check for overflow could never trigger as the func_buf +strings are always shorter or equal to 'struct kbsentry's. + +Cc: +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20201019085517.10176-1-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/vt/keyboard.c | 28 +++++++++------------------- + 1 file changed, 9 insertions(+), 19 deletions(-) + +--- a/drivers/tty/vt/keyboard.c ++++ b/drivers/tty/vt/keyboard.c +@@ -1994,9 +1994,7 @@ out: + int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) + { + struct kbsentry *kbs; +- char *p; + u_char *q; +- u_char __user *up; + int sz, fnw_sz; + int delta; + char *first_free, *fj, *fnw; +@@ -2022,23 +2020,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb + i = kbs->kb_func; + + switch (cmd) { +- case KDGKBSENT: +- sz = sizeof(kbs->kb_string) - 1; /* sz should have been +- a struct member */ +- up = user_kdgkb->kb_string; +- p = func_table[i]; +- if(p) +- for ( ; *p && sz; p++, sz--) +- if (put_user(*p, up++)) { +- ret = -EFAULT; +- goto reterr; +- } +- if (put_user('\0', up)) { +- ret = -EFAULT; +- goto reterr; +- } +- kfree(kbs); +- return ((p && *p) ? -EOVERFLOW : 0); ++ case KDGKBSENT: { ++ /* size should have been a struct member */ ++ unsigned char *from = func_table[i] ? : ""; ++ ++ ret = copy_to_user(user_kdgkb->kb_string, from, ++ strlen(from) + 1) ? -EFAULT : 0; ++ ++ goto reterr; ++ } + case KDSKBSENT: + if (!perm) { + ret = -EPERM; diff --git a/queue-5.4/w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch b/queue-5.4/w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch new file mode 100644 index 00000000000..2c1fffb5957 --- /dev/null +++ b/queue-5.4/w1-mxc_w1-fix-timeout-resolution-problem-leading-to-bus-error.patch @@ -0,0 +1,90 @@ +From c9723750a699c3bd465493ac2be8992b72ccb105 Mon Sep 17 00:00:00 2001 +From: Martin Fuzzey +Date: Wed, 30 Sep 2020 10:36:46 +0200 +Subject: w1: mxc_w1: Fix timeout resolution problem leading to bus error + +From: Martin Fuzzey + +commit c9723750a699c3bd465493ac2be8992b72ccb105 upstream. + +On my platform (i.MX53) bus access sometimes fails with + w1_search: max_slave_count 64 reached, will continue next search. + +The reason is the use of jiffies to implement a 200us timeout in +mxc_w1_ds2_touch_bit(). +On some platforms the jiffies timer resolution is insufficient for this. + +Fix by replacing jiffies by ktime_get(). + +For consistency apply the same change to the other use of jiffies in +mxc_w1_ds2_reset_bus(). + +Fixes: f80b2581a706 ("w1: mxc_w1: Optimize mxc_w1_ds2_touch_bit()") +Cc: stable +Signed-off-by: Martin Fuzzey +Link: https://lore.kernel.org/r/1601455030-6607-1-git-send-email-martin.fuzzey@flowbird.group +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/w1/masters/mxc_w1.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +--- a/drivers/w1/masters/mxc_w1.c ++++ b/drivers/w1/masters/mxc_w1.c +@@ -7,7 +7,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +@@ -40,12 +40,12 @@ struct mxc_w1_device { + static u8 mxc_w1_ds2_reset_bus(void *data) + { + struct mxc_w1_device *dev = data; +- unsigned long timeout; ++ ktime_t timeout; + + writeb(MXC_W1_CONTROL_RPP, dev->regs + MXC_W1_CONTROL); + + /* Wait for reset sequence 511+512us, use 1500us for sure */ +- timeout = jiffies + usecs_to_jiffies(1500); ++ timeout = ktime_add_us(ktime_get(), 1500); + + udelay(511 + 512); + +@@ -55,7 +55,7 @@ static u8 mxc_w1_ds2_reset_bus(void *dat + /* PST bit is valid after the RPP bit is self-cleared */ + if (!(ctrl & MXC_W1_CONTROL_RPP)) + return !(ctrl & MXC_W1_CONTROL_PST); +- } while (time_is_after_jiffies(timeout)); ++ } while (ktime_before(ktime_get(), timeout)); + + return 1; + } +@@ -68,12 +68,12 @@ static u8 mxc_w1_ds2_reset_bus(void *dat + static u8 mxc_w1_ds2_touch_bit(void *data, u8 bit) + { + struct mxc_w1_device *dev = data; +- unsigned long timeout; ++ ktime_t timeout; + + writeb(MXC_W1_CONTROL_WR(bit), dev->regs + MXC_W1_CONTROL); + + /* Wait for read/write bit (60us, Max 120us), use 200us for sure */ +- timeout = jiffies + usecs_to_jiffies(200); ++ timeout = ktime_add_us(ktime_get(), 200); + + udelay(60); + +@@ -83,7 +83,7 @@ static u8 mxc_w1_ds2_touch_bit(void *dat + /* RDST bit is valid after the WR1/RD bit is self-cleared */ + if (!(ctrl & MXC_W1_CONTROL_WR(bit))) + return !!(ctrl & MXC_W1_CONTROL_RDST); +- } while (time_is_after_jiffies(timeout)); ++ } while (ktime_before(ktime_get(), timeout)); + + return 0; + } -- 2.47.3