| From f01e22081ecf2a1856656bafa68870c5cf34ef4e Mon Sep 17 00:00:00 2001 |
| From: Guenter Roeck <linux@roeck-us.net> |
| Date: Mon, 17 Oct 2022 06:09:04 -0700 |
| Subject: [PATCH] BACKPORT: FROMLIST: thermal/core: Ensure that thermal device |
| is registered in thermal_zone_get_temp |
| |
| Calls to thermal_zone_get_temp() are not protected against thermal zone |
| device removal. As result, it is possible that the thermal zone operations |
| callbacks are no longer valid when thermal_zone_get_temp() is called. |
| This may result in crashes such as |
| |
| BUG: unable to handle page fault for address: ffffffffc04ef420 |
| #PF: supervisor read access in kernel mode |
| #PF: error_code(0x0000) - not-present page |
| PGD 5d60e067 P4D 5d60e067 PUD 5d610067 PMD 110197067 PTE 0 |
| Oops: 0000 [#1] PREEMPT SMP NOPTI |
| CPU: 1 PID: 3209 Comm: cat Tainted: G W 5.10.136-19389-g615abc6eb807 #1 02df41ac0b12f3a64f4b34245188d8875bb3bce1 |
| Hardware name: Google Coral/Coral, BIOS Google_Coral.10068.92.0 11/27/2018 |
| RIP: 0010:thermal_zone_get_temp+0x26/0x73 |
| Code: 89 c3 eb d3 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 53 48 85 ff 74 50 48 89 fb 48 81 ff 00 f0 ff ff 77 44 48 8b 83 98 03 00 00 <48> 83 78 10 00 74 36 49 89 f6 4c 8d bb d8 03 00 00 4c 89 ff e8 9f |
| RSP: 0018:ffffb3758138fd38 EFLAGS: 00010287 |
| RAX: ffffffffc04ef410 RBX: ffff98f14d7fb000 RCX: 0000000000000000 |
| RDX: ffff98f17cf90000 RSI: ffffb3758138fd64 RDI: ffff98f14d7fb000 |
| RBP: ffffb3758138fd50 R08: 0000000000001000 R09: ffff98f17cf90000 |
| R10: 0000000000000000 R11: ffffffff8dacad28 R12: 0000000000001000 |
| R13: ffff98f1793a7d80 R14: ffff98f143231708 R15: ffff98f14d7fb018 |
| FS: 00007ec166097800(0000) GS:ffff98f1bbd00000(0000) knlGS:0000000000000000 |
| CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 |
| CR2: ffffffffc04ef420 CR3: 000000010ee9a000 CR4: 00000000003506e0 |
| Call Trace: |
| temp_show+0x31/0x68 |
| dev_attr_show+0x1d/0x4f |
| sysfs_kf_seq_show+0x92/0x107 |
| seq_read_iter+0xf5/0x3f2 |
| vfs_read+0x205/0x379 |
| __x64_sys_read+0x7c/0xe2 |
| do_syscall_64+0x43/0x55 |
| entry_SYSCALL_64_after_hwframe+0x61/0xc6 |
| |
| if a thermal device is removed while accesses to its device attributes |
| are ongoing. |
| |
| The problem is exposed by code in iwl_op_mode_mvm_start(), which registers |
| a thermal zone device only to unregister it shortly afterwards if an |
| unrelated failure is encountered while accessing the hardware. |
| |
| Check if the thermal zone device is registered after acquiring the |
| thermal zone device mutex to ensure this does not happen. |
| |
| The code was tested by triggering the failure in iwl_op_mode_mvm_start() |
| on purpose. Without this patch, the kernel crashes reliably. The crash |
| is no longer observed after applying this and the preceding patches. |
| |
| Signed-off-by: Guenter Roeck <linux@roeck-us.net> |
| (am from https://patchwork.kernel.org/patch/13008852/) |
| (also found at https://lore.kernel.org/r/20221017130910.2307118-4-linux@roeck-us.net) |
| |
| Conflicts: |
| drivers/thermal/thermal_helpers.c |
| Context: |
| - Upsteam no longer checks if tz is valis and if tz->ops->get_temp |
| is valid |
| - Check if tz->ops->get_temp is valid under lock protection |
| after checking that the thermal device is still registered. |
| |
| UPSTREAM-TASK=b:257097168 |
| BUG=b:221250880 |
| TEST=CQ including Intel wireless tests |
| |
| Change-Id: Ied760156e0d2abcaa62f04decc88740f52eb3412 |
| Disallow-Recycled-Builds: test-failures |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/4000583 |
| Reviewed-by: Martin Faltesek <mfaltesek@google.com> |
| --- |
| drivers/thermal/thermal_helpers.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c |
| index 12fc648d92505b03d970c08aa5fce01624b64a0b..ac576f066bed7b0a2d442a222e260811d34ced3b 100644 |
| --- a/drivers/thermal/thermal_helpers.c |
| +++ b/drivers/thermal/thermal_helpers.c |
| @@ -73,7 +73,13 @@ int __thermal_zone_get_temp(struct thermal_zone_device *tz, int *temp) |
| |
| lockdep_assert_held(&tz->lock); |
| |
| - if (!tz || IS_ERR(tz) || !tz->ops->get_temp) |
| + if (!tz || IS_ERR(tz)) |
| + return -EINVAL; |
| + |
| + if (!device_is_registered(&tz->device)) |
| + return -ENODEV; |
| + |
| + if (!tz->ops->get_temp) |
| return -EINVAL; |
| |
| ret = tz->ops->get_temp(tz, temp); |
| -- |
| 2.38.1.584.g0f3c55d4c2-goog |
| |