From: "Wachowski, Karol" <karol.wachowski@linux.intel.com>
To: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>,
dri-devel@lists.freedesktop.org
Cc: oded.gabbay@gmail.com, jeff.hugo@oss.qualcomm.com,
lizhi.hou@amd.com, andrzej.kacprowski@linux.intel.com,
Magdalena Schulfer <magdalena.schulfer@intel.com>,
stable@vger.kernel.org
Subject: Re: [PATCH v2 2/3] accel/ivpu: Validate firmware log buffer metadata
Date: Wed, 2 Sep 2026 14:57:26 +0200 [thread overview]
Message-ID: <963bc3c2-c67d-475b-aa4d-8cc3ce76f2b7@linux.intel.com> (raw)
In-Reply-To: <20260901125749.404338-3-dawid.osuchowski@linux.intel.com>
On 01-Sep-26 14:57, Dawid Osuchowski wrote:
> From: Magdalena Schulfer <magdalena.schulfer@intel.com>
>
> The tracing log headers parsed by fw_log_print_buffer() reside in
> DMA-shared BOs that the NPU firmware can write to.
>
> fw_log_from_bo() validated log->header_size and log->size, but
> fw_log_print_buffer() re-read those same fields from shared memory
> afterwards, allowing a TOCTOU where firmware changes them between the
> check and the use, and making the host dereference out-of-bounds
> addresses while printing logs.
>
> Snapshot the validated values once with READ_ONCE() and pass them down
> explicitly in a new struct ivpu_fw_log_desc instead of re-reading them
> from the shared struct.
>
> Cc: stable@vger.kernel.org
> Fixes: d4e4257afa6e ("accel/ivpu: Add firmware tracing support")
> Signed-off-by: Magdalena Schulfer <magdalena.schulfer@intel.com>
> Signed-off-by: Dawid Osuchowski <dawid.osuchowski@linux.intel.com>
> ---
> drivers/accel/ivpu/ivpu_fw_log.c | 76 +++++++++++++++++++-------------
> 1 file changed, 45 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/accel/ivpu/ivpu_fw_log.c b/drivers/accel/ivpu/ivpu_fw_log.c
> index 716467aa3156..4f9055aa9d33 100644
> --- a/drivers/accel/ivpu/ivpu_fw_log.c
> +++ b/drivers/accel/ivpu/ivpu_fw_log.c
> @@ -26,10 +26,17 @@ MODULE_PARM_DESC(fw_log_level,
> " error=" __stringify(IVPU_FW_LOG_ERROR)
> " fatal=" __stringify(IVPU_FW_LOG_FATAL));
>
> +struct ivpu_fw_log_desc {
> + struct vpu_tracing_buffer_header *log;
> + u32 header_size;
> + u32 size;
> +};
> +
> static int fw_log_from_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *offset,
> - struct vpu_tracing_buffer_header **out_log)
> + struct ivpu_fw_log_desc *desc)
> {
> struct vpu_tracing_buffer_header *log;
> + u32 header_size, size;
>
> if ((*offset + sizeof(*log)) > ivpu_bo_size(bo))
> return -EINVAL;
> @@ -39,26 +46,32 @@ static int fw_log_from_bo(struct ivpu_device *vdev, struct ivpu_bo *bo, u32 *off
> if (log->vpu_canary_start != VPU_TRACING_BUFFER_CANARY)
> return -EINVAL;
>
> - if (log->header_size < sizeof(*log) || log->header_size > 1024) {
> - ivpu_dbg(vdev, FW_BOOT, "Invalid header size 0x%x\n", log->header_size);
> + header_size = READ_ONCE(log->header_size);
> + size = READ_ONCE(log->size);
> +
> + if (header_size < sizeof(*log) || header_size > 1024) {
> + ivpu_dbg(vdev, FW_BOOT, "Invalid header size 0x%x\n", header_size);
> return -EINVAL;
> }
> - if (log->size < log->header_size) {
> - ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size);
> + if ((char *)log + size > (char *)ivpu_bo_vaddr(bo) + ivpu_bo_size(bo)) {
> + ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", size);
> return -EINVAL;
> }
> - if ((char *)log + log->size > (char *)ivpu_bo_vaddr(bo) + ivpu_bo_size(bo)) {
> - ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x\n", log->size);
> + if (size < header_size) {
> + ivpu_dbg(vdev, FW_BOOT, "Invalid log size 0x%x < header size 0x%x\n",
> + size, header_size);
> return -EINVAL;
> }
>
> - *out_log = log;
> - *offset += log->size;
> + desc->log = log;
> + desc->header_size = header_size;
> + desc->size = size;
> + *offset += size;
>
> ivpu_dbg(vdev, FW_BOOT,
> "FW log name \"%s\", write offset 0x%x size 0x%x, wrap count %d, hdr version %d size %d format %d, alignment %d",
> - log->name, log->write_index, log->size, log->wrap_count, log->header_version,
> - log->header_size, log->format, log->alignment);
> + log->name, log->write_index, size, log->wrap_count, log->header_version,
> + header_size, log->format, log->alignment);
>
> return 0;
> }
> @@ -94,11 +107,12 @@ static void fw_log_print_lines(char *buffer, u32 size, struct drm_printer *p)
> drm_printf(p, "%s", line);
> }
>
> -static void fw_log_print_buffer(struct vpu_tracing_buffer_header *log, const char *prefix,
> +static void fw_log_print_buffer(struct ivpu_fw_log_desc *desc, const char *prefix,
> bool only_new_msgs, struct drm_printer *p)
> {
> - char *log_data = (void *)log + log->header_size;
> - u32 data_size = log->size - log->header_size;
> + struct vpu_tracing_buffer_header *log = desc->log;
> + char *log_data = (void *)log + desc->header_size;
> + u32 data_size = desc->size - desc->header_size;
> u32 log_start = only_new_msgs ? READ_ONCE(log->read_index) : 0;
> u32 log_end = READ_ONCE(log->write_index);
>
> @@ -134,11 +148,11 @@ static void
> fw_log_print_all_in_bo(struct ivpu_device *vdev, const char *name,
> struct ivpu_bo *bo, bool only_new_msgs, struct drm_printer *p)
> {
> - struct vpu_tracing_buffer_header *log;
> + struct ivpu_fw_log_desc desc;
> u32 next = 0;
>
> - while (fw_log_from_bo(vdev, bo, &next, &log) == 0)
> - fw_log_print_buffer(log, name, only_new_msgs, p);
> + while (fw_log_from_bo(vdev, bo, &next, &desc) == 0)
> + fw_log_print_buffer(&desc, name, only_new_msgs, p);
> }
>
> void ivpu_fw_log_print(struct ivpu_device *vdev, bool only_new_msgs, struct drm_printer *p)
> @@ -149,36 +163,36 @@ void ivpu_fw_log_print(struct ivpu_device *vdev, bool only_new_msgs, struct drm_
>
> void ivpu_fw_log_mark_read(struct ivpu_device *vdev)
> {
> - struct vpu_tracing_buffer_header *log;
> + struct ivpu_fw_log_desc desc;
> u32 next;
>
> next = 0;
> - while (fw_log_from_bo(vdev, vdev->fw->mem_log_crit, &next, &log) == 0) {
> - log->read_index = READ_ONCE(log->write_index);
> - log->read_wrap_count = READ_ONCE(log->wrap_count);
> + while (fw_log_from_bo(vdev, vdev->fw->mem_log_crit, &next, &desc) == 0) {
> + desc.log->read_index = READ_ONCE(desc.log->write_index);
> + desc.log->read_wrap_count = READ_ONCE(desc.log->wrap_count);
> }
>
> next = 0;
> - while (fw_log_from_bo(vdev, vdev->fw->mem_log_verb, &next, &log) == 0) {
> - log->read_index = READ_ONCE(log->write_index);
> - log->read_wrap_count = READ_ONCE(log->wrap_count);
> + while (fw_log_from_bo(vdev, vdev->fw->mem_log_verb, &next, &desc) == 0) {
> + desc.log->read_index = READ_ONCE(desc.log->write_index);
> + desc.log->read_wrap_count = READ_ONCE(desc.log->wrap_count);
> }
> }
>
> void ivpu_fw_log_reset(struct ivpu_device *vdev)
> {
> - struct vpu_tracing_buffer_header *log;
> + struct ivpu_fw_log_desc desc;
> u32 next;
>
> next = 0;
> - while (fw_log_from_bo(vdev, vdev->fw->mem_log_crit, &next, &log) == 0) {
> - log->read_index = 0;
> - log->read_wrap_count = 0;
> + while (fw_log_from_bo(vdev, vdev->fw->mem_log_crit, &next, &desc) == 0) {
> + desc.log->read_index = 0;
> + desc.log->read_wrap_count = 0;
> }
>
> next = 0;
> - while (fw_log_from_bo(vdev, vdev->fw->mem_log_verb, &next, &log) == 0) {
> - log->read_index = 0;
> - log->read_wrap_count = 0;
> + while (fw_log_from_bo(vdev, vdev->fw->mem_log_verb, &next, &desc) == 0) {
> + desc.log->read_index = 0;
> + desc.log->read_wrap_count = 0;
> }
> }
Reviewed-by: Karol Wachowski <karol.wachowski@linux.intel.com>
next prev parent reply other threads:[~2026-09-02 12:57 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-01 12:57 [PATCH v2 0/3] accel/ivpu: Harden parsing of firmware-shared buffers Dawid Osuchowski
2026-09-01 12:57 ` [PATCH v2 1/3] accel/ivpu: Validate full buffer range in ivpu_to_cpu_addr Dawid Osuchowski
2026-09-02 12:56 ` Wachowski, Karol
2026-09-01 12:57 ` [PATCH v2 2/3] accel/ivpu: Validate firmware log buffer metadata Dawid Osuchowski
2026-09-02 12:57 ` Wachowski, Karol [this message]
2026-09-01 12:57 ` [PATCH v2 3/3] accel/ivpu: Limit firmware log name prints to field size Dawid Osuchowski
2026-09-01 13:19 ` sashiko-bot
2026-09-02 12:58 ` Wachowski, Karol
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=963bc3c2-c67d-475b-aa4d-8cc3ce76f2b7@linux.intel.com \
--to=karol.wachowski@linux.intel.com \
--cc=andrzej.kacprowski@linux.intel.com \
--cc=dawid.osuchowski@linux.intel.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=jeff.hugo@oss.qualcomm.com \
--cc=lizhi.hou@amd.com \
--cc=magdalena.schulfer@intel.com \
--cc=oded.gabbay@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox