--- /dev/null
+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
+
--- /dev/null
+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);