]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Jul 2024 12:20:13 +0000 (14:20 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Jul 2024 12:20:13 +0000 (14:20 +0200)
added patches:
io_uring-fix-error-pbuf-checking.patch
thermal-core-allow-thermal-zones-to-tell-the-core-to-ignore-them.patch

queue-6.10/io_uring-fix-error-pbuf-checking.patch [new file with mode: 0644]
queue-6.10/series
queue-6.10/thermal-core-allow-thermal-zones-to-tell-the-core-to-ignore-them.patch [new file with mode: 0644]

diff --git a/queue-6.10/io_uring-fix-error-pbuf-checking.patch b/queue-6.10/io_uring-fix-error-pbuf-checking.patch
new file mode 100644 (file)
index 0000000..865a9c4
--- /dev/null
@@ -0,0 +1,57 @@
+From bcc87d978b834c298bbdd9c52454c5d0a946e97e Mon Sep 17 00:00:00 2001
+From: Pavel Begunkov <asml.silence@gmail.com>
+Date: Thu, 18 Jul 2024 20:00:53 +0100
+Subject: io_uring: fix error pbuf checking
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+commit bcc87d978b834c298bbdd9c52454c5d0a946e97e upstream.
+
+Syz reports a problem, which boils down to NULL vs IS_ERR inconsistent
+error handling in io_alloc_pbuf_ring().
+
+KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
+RIP: 0010:__io_remove_buffers+0xac/0x700 io_uring/kbuf.c:341
+Call Trace:
+ <TASK>
+ io_put_bl io_uring/kbuf.c:378 [inline]
+ io_destroy_buffers+0x14e/0x490 io_uring/kbuf.c:392
+ io_ring_ctx_free+0xa00/0x1070 io_uring/io_uring.c:2613
+ io_ring_exit_work+0x80f/0x8a0 io_uring/io_uring.c:2844
+ process_one_work kernel/workqueue.c:3231 [inline]
+ process_scheduled_works+0xa2c/0x1830 kernel/workqueue.c:3312
+ worker_thread+0x86d/0xd40 kernel/workqueue.c:3390
+ kthread+0x2f0/0x390 kernel/kthread.c:389
+ ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147
+ ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
+
+Cc: stable@vger.kernel.org
+Reported-by: syzbot+2074b1a3d447915c6f1c@syzkaller.appspotmail.com
+Fixes: 87585b05757dc ("io_uring/kbuf: use vm_insert_pages() for mmap'ed pbuf ring")
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Link: https://lore.kernel.org/r/c5f9df20560bd9830401e8e48abc029e7cfd9f5e.1721329239.git.asml.silence@gmail.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ io_uring/kbuf.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
+index d2945c9c812b..c95dc1736dd9 100644
+--- a/io_uring/kbuf.c
++++ b/io_uring/kbuf.c
+@@ -657,8 +657,10 @@ static int io_alloc_pbuf_ring(struct io_ring_ctx *ctx,
+       ring_size = reg->ring_entries * sizeof(struct io_uring_buf_ring);
+       bl->buf_ring = io_pages_map(&bl->buf_pages, &bl->buf_nr_pages, ring_size);
+-      if (!bl->buf_ring)
++      if (IS_ERR(bl->buf_ring)) {
++              bl->buf_ring = NULL;
+               return -ENOMEM;
++      }
+       bl->is_buf_ring = 1;
+       bl->is_mmap = 1;
+-- 
+2.45.2
+
index 0fe68a34479ca4eac0fa73ce99fc46fd3dd675ba..68e99e7c531fd22149882b8f5b53ff27e6ffa05d 100644 (file)
@@ -7,3 +7,5 @@ cifs-fix-setting-of-zero_point-after-dio-write.patch
 tpm-use-auth-only-after-null-check-in-tpm_buf_check_hmac_response.patch
 asoc-cs35l56-use-header-defines-for-speaker-volume-control-definition.patch
 asoc-cs35l56-limit-speaker-volume-to-12db-maximum.patch
+io_uring-fix-error-pbuf-checking.patch
+thermal-core-allow-thermal-zones-to-tell-the-core-to-ignore-them.patch
diff --git a/queue-6.10/thermal-core-allow-thermal-zones-to-tell-the-core-to-ignore-them.patch b/queue-6.10/thermal-core-allow-thermal-zones-to-tell-the-core-to-ignore-them.patch
new file mode 100644 (file)
index 0000000..33fe992
--- /dev/null
@@ -0,0 +1,208 @@
+From e528be3c87be953b73e7826a2d7e4b837cbad39d Mon Sep 17 00:00:00 2001
+From: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
+Date: Wed, 17 Jul 2024 21:45:02 +0200
+Subject: thermal: core: Allow thermal zones to tell the core to ignore them
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+commit e528be3c87be953b73e7826a2d7e4b837cbad39d upstream.
+
+The iwlwifi wireless driver registers a thermal zone that is only needed
+when the network interface handled by it is up and it wants that thermal
+zone to be effectively ignored by the core otherwise.
+
+Before commit a8a261774466 ("thermal: core: Call monitor_thermal_zone()
+if zone temperature is invalid") that could be achieved by returning
+an error code from the thermal zone's .get_temp() callback because the
+core did not really handle errors returned by it almost at all.
+However, commit a8a261774466 made the core attempt to recover from the
+situation in which the temperature of a thermal zone cannot be
+determined due to errors returned by its .get_temp() and is always
+invalid from the core's perspective.
+
+That was done because there are thermal zones in which .get_temp()
+returns errors to start with due to some difficulties related to the
+initialization ordering, but then it will start to produce valid
+temperature values at one point.
+
+Unfortunately, the simple approach taken by commit a8a261774466,
+which is to poll the thermal zone periodically until its .get_temp()
+callback starts to return valid temperature values, is at odds with
+the special thermal zone in iwlwifi in which .get_temp() may always
+return an error because its network interface may always be down.  If
+that happens, every attempt to invoke the thermal zone's .get_temp()
+callback resulting in an error causes the thermal core to print a
+dev_warn() message to the kernel log which is super-noisy.
+
+To address this problem, make the core handle the case in which
+.get_temp() returns 0, but the temperature value returned by it
+is not actually valid, in a special way.  Namely, make the core
+completely ignore the invalid temperature value coming from
+.get_temp() in that case, which requires folding in
+update_temperature() into its caller and a few related changes.
+
+On the iwlwifi side, modify iwl_mvm_tzone_get_temp() to return 0
+and put THERMAL_TEMP_INVALID into the temperature return memory
+location instead of returning an error when the firmware is not
+running or it is not of the right type.
+
+Also, to clearly separate the handling of invalid temperature
+values from the thermal zone initialization, introduce a special
+THERMAL_TEMP_INIT value specifically for the latter purpose.
+
+Fixes: a8a261774466 ("thermal: core: Call monitor_thermal_zone() if zone temperature is invalid")
+Closes: https://lore.kernel.org/linux-pm/20240715044527.GA1544@sol.localdomain/
+Reported-by: Eric Biggers <ebiggers@kernel.org>
+Reported-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=201761
+Tested-by: Oleksandr Natalenko <oleksandr@natalenko.name>
+Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de>
+Cc: 6.10+ <stable@vger.kernel.org> # 6.10+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Link: https://patch.msgid.link/4950004.31r3eYUQgx@rjwysocki.net
+[ rjw: Rebased on top of the current mainline ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/intel/iwlwifi/mvm/tt.c |    7 +++
+ drivers/thermal/thermal_core.c              |   51 +++++++++++++---------------
+ drivers/thermal/thermal_core.h              |    3 +
+ drivers/thermal/thermal_helpers.c           |    2 +
+ 4 files changed, 35 insertions(+), 28 deletions(-)
+
+--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
++++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+@@ -622,7 +622,12 @@ static int iwl_mvm_tzone_get_temp(struct
+       if (!iwl_mvm_firmware_running(mvm) ||
+           mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) {
+-              ret = -ENODATA;
++              /*
++               * Tell the core that there is no valid temperature value to
++               * return, but it need not worry about this.
++               */
++              *temperature = THERMAL_TEMP_INVALID;
++              ret = 0;
+               goto out;
+       }
+--- a/drivers/thermal/thermal_core.c
++++ b/drivers/thermal/thermal_core.c
+@@ -300,8 +300,6 @@ static void monitor_thermal_zone(struct
+               thermal_zone_device_set_polling(tz, tz->passive_delay_jiffies);
+       else if (tz->polling_delay_jiffies)
+               thermal_zone_device_set_polling(tz, tz->polling_delay_jiffies);
+-      else if (tz->temperature == THERMAL_TEMP_INVALID)
+-              thermal_zone_device_set_polling(tz, msecs_to_jiffies(THERMAL_RECHECK_DELAY_MS));
+ }
+ static struct thermal_governor *thermal_get_tz_governor(struct thermal_zone_device *tz)
+@@ -382,7 +380,7 @@ static void handle_thermal_trip(struct t
+       td->threshold = trip->temperature;
+       if (tz->last_temperature >= old_threshold &&
+-          tz->last_temperature != THERMAL_TEMP_INVALID) {
++          tz->last_temperature != THERMAL_TEMP_INIT) {
+               /*
+                * Mitigation is under way, so it needs to stop if the zone
+                * temperature falls below the low temperature of the trip.
+@@ -417,27 +415,6 @@ static void handle_thermal_trip(struct t
+       }
+ }
+-static void update_temperature(struct thermal_zone_device *tz)
+-{
+-      int temp, ret;
+-
+-      ret = __thermal_zone_get_temp(tz, &temp);
+-      if (ret) {
+-              if (ret != -EAGAIN)
+-                      dev_warn(&tz->device,
+-                               "failed to read out thermal zone (%d)\n",
+-                               ret);
+-              return;
+-      }
+-
+-      tz->last_temperature = tz->temperature;
+-      tz->temperature = temp;
+-
+-      trace_thermal_temperature(tz);
+-
+-      thermal_genl_sampling_temp(tz->id, temp);
+-}
+-
+ static void thermal_zone_device_check(struct work_struct *work)
+ {
+       struct thermal_zone_device *tz = container_of(work, struct
+@@ -452,7 +429,7 @@ static void thermal_zone_device_init(str
+       INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_check);
+-      tz->temperature = THERMAL_TEMP_INVALID;
++      tz->temperature = THERMAL_TEMP_INIT;
+       tz->passive = 0;
+       tz->prev_low_trip = -INT_MAX;
+       tz->prev_high_trip = INT_MAX;
+@@ -501,6 +478,7 @@ void __thermal_zone_device_update(struct
+       struct thermal_trip_desc *td;
+       LIST_HEAD(way_down_list);
+       LIST_HEAD(way_up_list);
++      int temp, ret;
+       if (tz->suspended)
+               return;
+@@ -508,10 +486,29 @@ void __thermal_zone_device_update(struct
+       if (!thermal_zone_device_is_enabled(tz))
+               return;
+-      update_temperature(tz);
++      ret = __thermal_zone_get_temp(tz, &temp);
++      if (ret) {
++              if (ret != -EAGAIN)
++                      dev_info(&tz->device, "Temperature check failed (%d)\n", ret);
+-      if (tz->temperature == THERMAL_TEMP_INVALID)
++              thermal_zone_device_set_polling(tz, msecs_to_jiffies(THERMAL_RECHECK_DELAY_MS));
++              return;
++      } else if (temp <= THERMAL_TEMP_INVALID) {
++              /*
++               * Special case: No valid temperature value is available, but
++               * the zone owner does not want the core to do anything about
++               * it.  Continue regular zone polling if needed, so that this
++               * function can be called again, but skip everything else.
++               */
+               goto monitor;
++      }
++
++      tz->last_temperature = tz->temperature;
++      tz->temperature = temp;
++
++      trace_thermal_temperature(tz);
++
++      thermal_genl_sampling_temp(tz->id, temp);
+       __thermal_zone_set_trips(tz);
+--- a/drivers/thermal/thermal_core.h
++++ b/drivers/thermal/thermal_core.h
+@@ -133,6 +133,9 @@ struct thermal_zone_device {
+       struct thermal_trip_desc trips[] __counted_by(num_trips);
+ };
++/* Initial thermal zone temperature. */
++#define THERMAL_TEMP_INIT     INT_MIN
++
+ /*
+  * Default delay after a failing thermal zone temperature check before
+  * attempting to check it again.
+--- a/drivers/thermal/thermal_helpers.c
++++ b/drivers/thermal/thermal_helpers.c
+@@ -140,6 +140,8 @@ int thermal_zone_get_temp(struct thermal
+       }
+       ret = __thermal_zone_get_temp(tz, temp);
++      if (!ret && *temp <= THERMAL_TEMP_INVALID)
++              ret = -ENODATA;
+ unlock:
+       mutex_unlock(&tz->lock);