79 lines
3.0 KiB
Diff
Executable File
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;
|
|
}
|