CVE-2025-38106 in Linuxinformazioni

Riassunto

di VulDB • 18/06/2026

Based on the KASAN report and the description provided, here is the analysis and the fix for the use-after-free bug in `io_uring`.

### Analysis

1. **The Bug**: A `task_struct` (specifically `sq->thread` in the `io_uring` context) is being accessed after it has been freed. 2. **The Cause**: The code in `__io_uring_show_fdinfo()` accesses `sq->thread` while holding `ctx->uring_lock`. However, `uring_lock` does not prevent the `sq->thread` task from exiting or being released. The task can be freed by the kernel's exit path (as seen in the "Freed by task 22" stack trace involving `rcu_core` and `do_exit`) while `__io_uring_show_fdinfo()` is still trying to read it. 3. **The Solution**: Use RCU (Read-Copy-Update) to safely access the `task_struct`. * Assign `sq->thread` using `rcu_assign_pointer()`. * Look up `sq->thread` using `rcu_dereference()`. * Grab a reference to the task using `get_task_struct()` to prevent it from being freed while in use. * Release the reference using `put_task_struct()` when done.

### The Fix

The fix needs to be applied in the `__io_uring_show_fdinfo()` function (and potentially where `sq->thread` is assigned, though the prompt implies the access is the main issue).

Here is the patch for `fs/io_uring.c`:

```c diff --git a/fs/io_uring.c b/fs/io_uring.c index 1234567890..abcdef1234 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -... +... @@ static int __io_uring_show_fdinfo(struct seq_file *m, struct io_ring_ctx *ctx) {
struct io_sq_data *sq = ctx->sq_data; + struct task_struct *task; if (!sq) return 0; + task = rcu_dereference(sq->thread); + if (task) {
+ get_task_struct(task); + seq_printf(m, "sq_thread: %s\n", task->comm); + put_task_struct(task); + } + return 0; } ```

Additionally, ensure that `sq->thread` is assigned using `rcu_assign_pointer()` when the thread is created or assigned, and that any previous assignments are updated to use RCU semantics if they weren't already. For example, in `io_sq_offload_create()`:

```c diff --git a/fs/io_uring.c b/fs/io_uring.c index 1234567890..abcdef1234 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -... +... @@ static int io_sq_offload_create(struct io_ring_ctx *ctx, unsigned int issue_flags) {
// ... existing code ... + rcu_assign_pointer(sq->thread, thread); + // ... existing code ... } ```

And in `io_sq_offload_stop()` or similar cleanup functions, ensure the pointer is cleared with `synchronize_rcu()` or `call_rcu()` to ensure all RCU readers have finished before freeing the `sq_data` structure if it contains the pointer. However, since `sq_data` is typically freed after the context is destroyed, and `__io_uring_show_fdinfo` is called while the context is alive, the primary fix is in the reader side (`__io_uring_show_fdinfo`).

### Explanation of the Fix

1. **`rcu_dereference(sq->thread)`**: This safely reads the pointer to the `task_struct`. It ensures that the compiler and CPU do not reorder the read in a way that could see a partially initialized or freed pointer. 2. **`get_task_struct(task)`**: This increments the reference count of the `task_struct`. This prevents the task from being freed by the kernel's exit path while we are using it. 3. **`put_task_struct(task)`**: This decrements the reference count. If the count reaches zero, the task will be freed. This must be called after we are done using the task. 4. **`rcu_assign_pointer(sq->thread, thread)`**: This ensures that the write to `sq->thread` is visible to all RCU readers before the pointer is considered valid.

This

If you want to get best quality of vulnerability data, you may have to visit VulDB.

Responsabile

Linux

Prenotare

16/04/2025

Divulgazione

03/07/2025

Moderazione

accettato

CPE

pronto

EPSS

0.00159

KEV

no

Attività

molto basso

Fonti

Want to know what is going to be exploited?

We predict KEV entries!