From: Greg Kroah-Hartman Date: Fri, 19 Nov 2021 14:35:25 +0000 (+0100) Subject: 5.15-stable patches X-Git-Tag: v5.4.161~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=532edb4b477a782509a70bef697f68cb5fc19b1c;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: perf-core-avoid-put_page-when-gup-fails.patch thermal-fix-null-pointer-dereferences-in-of_thermal_-functions.patch --- diff --git a/queue-5.15/perf-core-avoid-put_page-when-gup-fails.patch b/queue-5.15/perf-core-avoid-put_page-when-gup-fails.patch new file mode 100644 index 00000000000..6dde4636276 --- /dev/null +++ b/queue-5.15/perf-core-avoid-put_page-when-gup-fails.patch @@ -0,0 +1,61 @@ +From 4716023a8f6a0f4a28047f14dd7ebdc319606b84 Mon Sep 17 00:00:00 2001 +From: Greg Thelen +Date: Wed, 10 Nov 2021 18:18:14 -0800 +Subject: perf/core: Avoid put_page() when GUP fails + +From: Greg Thelen + +commit 4716023a8f6a0f4a28047f14dd7ebdc319606b84 upstream. + +PEBS PERF_SAMPLE_PHYS_ADDR events use perf_virt_to_phys() to convert PMU +sampled virtual addresses to physical using get_user_page_fast_only() +and page_to_phys(). + +Some get_user_page_fast_only() error cases return false, indicating no +page reference, but still initialize the output page pointer with an +unreferenced page. In these error cases perf_virt_to_phys() calls +put_page(). This causes page reference count underflow, which can lead +to unintentional page sharing. + +Fix perf_virt_to_phys() to only put_page() if get_user_page_fast_only() +returns a referenced page. + +Fixes: fc7ce9c74c3ad ("perf/core, x86: Add PERF_SAMPLE_PHYS_ADDR") +Signed-off-by: Greg Thelen +Signed-off-by: Peter Zijlstra (Intel) +Link: https://lkml.kernel.org/r/20211111021814.757086-1-gthelen@google.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/events/core.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -7154,7 +7154,6 @@ void perf_output_sample(struct perf_outp + static u64 perf_virt_to_phys(u64 virt) + { + u64 phys_addr = 0; +- struct page *p = NULL; + + if (!virt) + return 0; +@@ -7173,14 +7172,15 @@ static u64 perf_virt_to_phys(u64 virt) + * If failed, leave phys_addr as 0. + */ + if (current->mm != NULL) { ++ struct page *p; ++ + pagefault_disable(); +- if (get_user_page_fast_only(virt, 0, &p)) ++ if (get_user_page_fast_only(virt, 0, &p)) { + phys_addr = page_to_phys(p) + virt % PAGE_SIZE; ++ put_page(p); ++ } + pagefault_enable(); + } +- +- if (p) +- put_page(p); + } + + return phys_addr; diff --git a/queue-5.15/series b/queue-5.15/series index e236be94c49..a2307119828 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -15,3 +15,5 @@ bluetooth-btusb-add-support-for-tp-link-ub500-adapter.patch parisc-entry-fix-trace-test-in-syscall-exit-path.patch pci-msi-deal-with-devices-lying-about-their-msi-mask-capability.patch pci-add-msi-masking-quirk-for-nvidia-ion-ahci.patch +perf-core-avoid-put_page-when-gup-fails.patch +thermal-fix-null-pointer-dereferences-in-of_thermal_-functions.patch diff --git a/queue-5.15/thermal-fix-null-pointer-dereferences-in-of_thermal_-functions.patch b/queue-5.15/thermal-fix-null-pointer-dereferences-in-of_thermal_-functions.patch new file mode 100644 index 00000000000..7429bf0981f --- /dev/null +++ b/queue-5.15/thermal-fix-null-pointer-dereferences-in-of_thermal_-functions.patch @@ -0,0 +1,86 @@ +From 96cfe05051fd8543cdedd6807ec59a0e6c409195 Mon Sep 17 00:00:00 2001 +From: Subbaraman Narayanamurthy +Date: Thu, 4 Nov 2021 16:57:07 -0700 +Subject: thermal: Fix NULL pointer dereferences in of_thermal_ functions + +From: Subbaraman Narayanamurthy + +commit 96cfe05051fd8543cdedd6807ec59a0e6c409195 upstream. + +of_parse_thermal_zones() parses the thermal-zones node and registers a +thermal_zone device for each subnode. However, if a thermal zone is +consuming a thermal sensor and that thermal sensor device hasn't probed +yet, an attempt to set trip_point_*_temp for that thermal zone device +can cause a NULL pointer dereference. Fix it. + + console:/sys/class/thermal/thermal_zone87 # echo 120000 > trip_point_0_temp + ... + Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020 + ... + Call trace: + of_thermal_set_trip_temp+0x40/0xc4 + trip_point_temp_store+0xc0/0x1dc + dev_attr_store+0x38/0x88 + sysfs_kf_write+0x64/0xc0 + kernfs_fop_write_iter+0x108/0x1d0 + vfs_write+0x2f4/0x368 + ksys_write+0x7c/0xec + __arm64_sys_write+0x20/0x30 + el0_svc_common.llvm.7279915941325364641+0xbc/0x1bc + do_el0_svc+0x28/0xa0 + el0_svc+0x14/0x24 + el0_sync_handler+0x88/0xec + el0_sync+0x1c0/0x200 + +While at it, fix the possible NULL pointer dereference in other +functions as well: of_thermal_get_temp(), of_thermal_set_emul_temp(), +of_thermal_get_trend(). + +Suggested-by: David Collins +Signed-off-by: Subbaraman Narayanamurthy +Acked-by: Daniel Lezcano +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman +--- + drivers/thermal/thermal_of.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/drivers/thermal/thermal_of.c ++++ b/drivers/thermal/thermal_of.c +@@ -89,7 +89,7 @@ static int of_thermal_get_temp(struct th + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_temp) ++ if (!data->ops || !data->ops->get_temp) + return -EINVAL; + + return data->ops->get_temp(data->sensor_data, temp); +@@ -186,6 +186,9 @@ static int of_thermal_set_emul_temp(stru + { + struct __thermal_zone *data = tz->devdata; + ++ if (!data->ops || !data->ops->set_emul_temp) ++ return -EINVAL; ++ + return data->ops->set_emul_temp(data->sensor_data, temp); + } + +@@ -194,7 +197,7 @@ static int of_thermal_get_trend(struct t + { + struct __thermal_zone *data = tz->devdata; + +- if (!data->ops->get_trend) ++ if (!data->ops || !data->ops->get_trend) + return -EINVAL; + + return data->ops->get_trend(data->sensor_data, trip, trend); +@@ -301,7 +304,7 @@ static int of_thermal_set_trip_temp(stru + if (trip >= data->ntrips || trip < 0) + return -EDOM; + +- if (data->ops->set_trip_temp) { ++ if (data->ops && data->ops->set_trip_temp) { + int ret; + + ret = data->ops->set_trip_temp(data->sensor_data, trip, temp);