Files
2026-08-24 10:03:24 +08:00

79 lines
3.0 KiB
Diff
Executable File

From 5040b3b8928665cf5fda0be8696a8062e2830348 Mon Sep 17 00:00:00 2001
From: Nongji Chen <[email protected]>
Date: Thu, 19 Jun 2025 11:06:04 +0100
Subject: [PATCH] CVE-2025-6349 Fix UaF in error recover path in csf_cpu_mmap_user_io
The bug has been identified in the error recovery path in function
'kbase_csf_cpu_mmap_user_io_pages()', which yields the queue-object
to go through a handling procedure that implicitly assuming a
reference-count value of 2, even though the actual value is 1 due to
the error. This undercut in the reference count value will cause a
use-after-free instance as the queue would be prematurely be freed.
This commit fixes the error recovery path to ensure the case to be
avoided.
Change-Id: Ide5f8f6f402c59f7eeae0da635edd138d8ad5656
---
diff --git a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
index f71b349..0f9ed44 100644
--- a/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
+++ b/product/kernel/drivers/gpu/arm/midgard/mali_kbase_mem_linux.c
@@ -38,6 +38,7 @@
#include <linux/math64.h>
#include <linux/migrate.h>
#include <linux/version.h>
+#include <linux/version_compat_defs.h>
#include <mali_kbase.h>
#include <mali_kbase_io.h>
#include <mali_kbase_mem_linux.h>
@@ -3501,6 +3502,29 @@
.fault = kbase_csf_user_io_pages_vm_fault
};
+static void user_io_pages_map_fail_cleanup(struct kbase_context *kctx, struct kbase_queue *queue)
+{
+ lockdep_assert_held(&kctx->csf.lock);
+
+ /* The queue should be hooked to kctx list, with its initial ref_count: 1 */
+#ifndef MALI_STRIP_KBASE_DEVELOPMENT
+ WARN(kbase_refcount_read(&queue->refcount) != 1,
+ "%s unexpected refcount != 1 (%d), hooked: %d", __func__,
+ kbase_refcount_read(&queue->refcount), !list_empty(&queue->link));
+#else
+ WARN_ON(kbase_refcount_read(&queue->refcount) != 1);
+#endif
+
+ /* Bump-up the ref-count for sharing the use of function
+ * kbase_csf_queue_unbind_stopped() to place the queue into
+ * stopped state, pending for final free from user-side, or
+ * kctx termination.
+ */
+ kbase_refcount_inc(&queue->refcount);
+
+ kbase_csf_queue_unbind_stopped(queue);
+}
+
/* Program the client process's page table entries to map the pair of
* input/output pages & Hw doorbell page. The caller should have validated that
* vma->vm_pgoff maps to the range of csf cookies.
@@ -3564,13 +3588,11 @@
return 0;
map_failed:
- /* The queue cannot have got to KBASE_CSF_QUEUE_BOUND state if we
- * reached here, so safe to use a variant of unbind that only works on
- * stopped queues
- *
- * This is so we don't enter the CSF scheduler from this path.
+ /* The queue failed to reach KBASE_CSF_QUEUE_BOUND state. It would not be
+ * runnable from here onwards. The cleanup will unbound the queue and keep
+ * it unusable, pending for user-side termination (or process exit).
*/
- kbase_csf_queue_unbind_stopped(queue);
+ user_io_pages_map_fail_cleanup(kctx, queue);
return err;
}