public inbox for drm-ai-reviews@public-inbox.freedesktop.org
 help / color / mirror / Atom feed
From: Claude Code Review Bot <claude-review@example.com>
To: dri-devel-reviews@example.com
Subject: Claude review: misc: fastrpc: fix use-after-free of fastrpc_user in workqueue context
Date: Thu, 30 Apr 2026 10:52:17 +1000	[thread overview]
Message-ID: <review-patch1-20260427074021.3774769-1-anandu.e@oss.qualcomm.com> (raw)
In-Reply-To: <20260427074021.3774769-1-anandu.e@oss.qualcomm.com>

Patch Review

**Commit message**: Well-written. Clearly establishes the race, identifies all three UAF dereference sites, explains the fix approach, and includes the crash trace. Good use of Fixes/Cc: stable tags.

**kref_init ordering (bug)**

In `fastrpc_device_open()`, the kref is initialized **after** the user is added to the channel's user list:

```c
	spin_lock_irqsave(&cctx->lock, flags);
	list_add_tail(&fl->user, &cctx->users);
	spin_unlock_irqrestore(&cctx->lock, flags);
+	kref_init(&fl->refcount);
```

The refcount must be initialized **before** the structure becomes visible to other code paths. `fastrpc_rpmsg_remove()` traverses `cctx->users` under the same lock, and could race with open. Move `kref_init(&fl->refcount)` before the `list_add_tail`, ideally next to `spin_lock_init`/`mutex_init` where other initialization happens.

**Use-after-free on fl->pending in fastrpc_user_free() (bug)**

This is the most significant issue. The patch moves the pending context cleanup from `fastrpc_device_release()` into the kref release callback `fastrpc_user_free()`:

```c
+static void fastrpc_user_free(struct kref *ref)
+{
+	...
+	list_for_each_entry_safe(ctx, n, &fl->pending, node) {
+		list_del(&ctx->node);
+		fastrpc_context_put(ctx);
+	}
```

But `fastrpc_context_free()` (the context kref release) does `kfree(ctx)` **without** removing `ctx->node` from `fl->pending`, then calls `fastrpc_user_put()`:

```c
 static void fastrpc_context_free(struct kref *ref)
 {
 	...
 	kfree(ctx);
 
 	fastrpc_channel_ctx_put(cctx);
+	/* Release the reference taken in fastrpc_context_alloc() */
+	fastrpc_user_put(fl);
 }
```

Consider the "abandoned invoke" scenario (invoker interrupted with `-ERESTARTSYS` or timed out with `-ETIMEDOUT`):

1. Invoker sets `is_work_done = true` (or equivalent), does **not** call `list_del(&ctx->node)` or `fastrpc_context_put(ctx)`. Context remains on `fl->pending` with refcount 1; user refcount is 2 (initial + context).
2. `fastrpc_device_release()` calls `fastrpc_user_put()` → user refcount drops to 1.
3. DSP eventually responds; callback schedules `ctx->put_work`.
4. Workqueue runs `fastrpc_context_put_wq()` → `fastrpc_context_free()`:
   - `kfree(ctx)` — context memory freed, but `ctx->node` is **still linked** into `fl->pending`.
   - `fastrpc_user_put(fl)` → user refcount drops to 0 → `fastrpc_user_free()` runs.
5. `fastrpc_user_free()` does `list_for_each_entry_safe` over `fl->pending` — dereferences the just-freed `ctx`. **Use-after-free.**

With the patch's refcounting model, every context on `fl->pending` holds a user reference. For `fastrpc_user_free()` to execute, **all** those contexts must have already been freed (their `fastrpc_context_free()` called `fastrpc_user_put()`). So the pending list iteration in `fastrpc_user_free()` can never find a live context — it either finds an empty list or freed entries.

To fix this, `fastrpc_context_free()` must remove `ctx->node` from `fl->pending` before `kfree(ctx)`. Since the normal invoke path (`fastrpc_internal_invoke` bail label) already does `list_del(&ctx->node)`, you'd need to avoid double-delete. A clean approach:

- Change `fastrpc_internal_invoke`'s `list_del(&ctx->node)` to `list_del_init(&ctx->node)`.
- In `fastrpc_context_free()`, before `kfree(ctx)`, add:
  ```c
  spin_lock(&fl->lock);
  if (!list_empty(&ctx->node))
      list_del(&ctx->node);
  spin_unlock(&fl->lock);
  ```
- Then the `fl->pending` iteration in `fastrpc_user_free()` becomes a safety net for any contexts that somehow weren't cleaned up, rather than a guaranteed UAF.

**fastrpc_session_free ordering (minor observation)**

`fastrpc_session_free(cctx, fl->sctx)` remains in `fastrpc_device_release()` rather than moving to `fastrpc_user_free()`. This means if the user structure outlives `device_release` (because a context still holds a reference), the session is already freed when the deferred cleanup runs. This appears safe since `fastrpc_buf_free()` and `fastrpc_free_map()` dereference `fl->cctx`, not `fl->sctx`, but it deserves an explicit comment noting the intentional ordering.

**Trivial comment nit**

```c
+	/* Reference count */
+	struct kref refcount;
```

This comment adds no information beyond what `struct kref refcount` already conveys. Either drop it or say something about the lifetime contract (e.g., `/* one ref per open + one per in-flight ctx */`).

**Forward declaration**

```c
+static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx);
```

Needed because `fastrpc_user_free()` is defined before `fastrpc_context_put()`. This is acceptable but worth noting: if the pending list iteration is removed from `fastrpc_user_free()` (because it's unreachable with valid data), this forward declaration can also be removed.

---
Generated by Claude Code Patch Reviewer

  reply	other threads:[~2026-04-30  0:52 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-27  7:40 [PATCH v2] misc: fastrpc: fix use-after-free of fastrpc_user in workqueue context Anandu Krishnan E
2026-04-30  0:52 ` Claude Code Review Bot [this message]
2026-04-30  0:52 ` Claude review: " Claude Code Review Bot

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=review-patch1-20260427074021.3774769-1-anandu.e@oss.qualcomm.com \
    --to=claude-review@example.com \
    --cc=dri-devel-reviews@example.com \
    /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