Linux USB
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Sasha Levin" <sashal@kernel.org>
Cc: linux-usb@vger.kernel.org
Subject: Re: [PATCH AUTOSEL 6.18-5.10] USB: gadget: inode: fix mm lifetime handling
Date: Mon, 19 Oct 2026 15:11:49 +0000	[thread overview]
Message-ID: <sashiko-outbox-177640@kernel.org> (raw)
In-Reply-To: <20261019135441.1420968-360-sashal@kernel.org>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] usb: gadget: inode: mmdrop() called in atomic context in ep_aio_complete()
--

commit 1034aa9a2c06c8a1a74aa881eb54ff67ca5c0fee
Author: Gabriel Prostitis <prostitisgabriel@gmail.com>

USB: gadget: inode: fix mm lifetime handling

This commit fixes a use-after-free in gadgetfs async I/O handling by pinning
the submitting task's mm_struct with mmgrab() in ep_aio() and releasing it
with mmdrop() upon request completion. It also uses mmget_not_zero() in
ep_user_copy_worker() before switching to the address space.

Link: https://patch.msgid.link/20260601-mm-uaf-fix-v2-2-3c942a707bce@gmail.com

> diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
> index 13c3da49348c5..7d201c065ae3b 100644
> --- a/drivers/usb/gadget/legacy/inode.c
> +++ b/drivers/usb/gadget/legacy/inode.c

[ ... ]

> @@ -503,6 +509,7 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
>  	 * complete the aio request immediately.
>  	 */
>  	if (priv->to_free == NULL || unlikely(req->actual == 0)) {
> +		mmdrop(priv->mm);

[Severity: High]
Is it safe to call mmdrop(priv->mm) directly in ep_aio_complete()?

ep_aio() pins current->mm with mmgrab(priv->mm) for all async requests. If
the submitting task exits before the USB request completes (for example,
with io_uring or a forked process where do_exit() -> exit_mm() -> mmput()
runs before completion), priv->mm can hold the final reference on
mm->mm_count.

When the request completes and takes the immediate completion branch
(priv->to_free == NULL || unlikely(req->actual == 0)) — which occurs for
async writes, single-buffer ITER_UBUF reads where dup_iter() returns NULL,
zero-length reads, errors, disconnects, or cancellations via
ep_aio_cancel() -> usb_ep_dequeue() — ep_aio_complete() runs as the
usb_request->complete callback with interrupts disabled and while holding
spin_lock(&epdata->dev->lock):

drivers/usb/gadget/legacy/inode.c:ep_aio_complete() {
	spin_lock(&epdata->dev->lock);
	priv->req = NULL;
	priv->epdata = NULL;

	if (priv->to_free == NULL || unlikely(req->actual == 0)) {
		mmdrop(priv->mm);
}

If mmdrop(priv->mm) drops the last reference, it invokes __mmdrop() from
atomic, interrupts-disabled context:

kernel/fork.c:__mmdrop() {
	...
	cleanup_lazy_tlbs(mm);

	WARN_ON_ONCE(mm == current->active_mm);
	mm_free_pgd(mm);
	...
}

This appears to cause a few issues:

1. On architectures with CONFIG_MMU_LAZY_TLB_SHOOTDOWN=y,
__mmdrop() -> cleanup_lazy_tlbs() -> on_each_cpu_mask() ->
smp_call_function_many_cond() waits synchronously for cross-CPU IPIs,
triggering lockdep_assert_irqs_enabled() and WARN_ON_ONCE(!in_task()) in
kernel/smp.c and potentially deadlocking with interrupts disabled.

2. On x86, __mmdrop() -> mm_free_pgd() -> pgd_free() -> pgd_dtor() acquires
spin_lock(&pgd_lock) without disabling interrupts:

arch/x86/mm/pgtable.c:pgd_dtor() {
	spin_lock(&pgd_lock);
	pgd_list_del(pgd);
	spin_unlock(&pgd_lock);
}

As noted in free_signal_struct() in kernel/fork.c, __mmdrop() is not safe to
call from interrupt or softirq context on x86 because taking pgd_lock can
deadlock if the interrupted context already holds pgd_lock.

3. On CONFIG_PREEMPT_RT=y, __mmdrop() acquires sleeping spinlock_t locks
while interrupts are disabled and a spinlock is held.

Should ep_aio_complete() use mmdrop_async(priv->mm) here (or avoid grabbing
priv->mm when priv->to_free == NULL, since the worker is only scheduled when
priv->to_free != NULL)?

>  		kfree(req->buf);
>  		kfree(priv->to_free);
>  		kfree(priv);

[ ... ]

> @@ -543,6 +550,7 @@ static ssize_t ep_aio(struct kiocb *iocb,
>  	priv->epdata = epdata;
>  	priv->actual = 0;
>  	priv->mm = current->mm; /* mm teardown waits for iocbs in exit_aio() */
> +	mmgrab(priv->mm);

[ ... ]

> @@ -572,6 +580,7 @@ static ssize_t ep_aio(struct kiocb *iocb,
>  
>  fail:
>  	spin_unlock_irq(&epdata->dev->lock);
> +	mmdrop(priv->mm);
>  	kfree(priv->to_free);
>  	kfree(priv);
>  	put_ep(epdata);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261019135441.1420968-360-sashal@kernel.org?part=1

  reply	other threads:[~2026-10-19 15:11 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20261019135441.1420968-1-sashal@kernel.org>
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18-5.10] usb_string_copy: Use kzalloc() to avoid leaking old data Sasha Levin
2026-10-19 14:02   ` sashiko-bot
2026-10-19 13:45 ` [PATCH AUTOSEL 6.18] usb: typec: mux: tusb1046: add missing MODULE_DEVICE_TABLE() Sasha Levin
2026-10-19 14:03   ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-6.1] thunderbolt: xdomain: Notify peers after enumeration Sasha Levin
2026-10-19 14:17   ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] usb: fsl_qe_udc: check qe_alloc_request() failure in ch9getstatus() Sasha Levin
2026-10-19 14:20   ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: qmi_wwan: add Rolling Wireless RN947R Sasha Levin
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] usb: mtu3: Fix double dereference in TP_printk Sasha Levin
2026-10-19 14:18   ` sashiko-bot
2026-10-19 13:46 ` [PATCH AUTOSEL 6.18-5.10] net: usb: rtl8150: handle link status read failures Sasha Levin
2026-10-19 14:20   ` sashiko-bot
2026-10-19 13:47 ` [PATCH AUTOSEL 6.18-5.10] usb: musb: host: clear stale RX interrupt on three-strikes error Sasha Levin
2026-10-19 14:28   ` sashiko-bot
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.10] USB: misc: uss720: Fix leak in get_1284_register Sasha Levin
2026-10-19 14:34   ` sashiko-bot
2026-10-19 13:48 ` [PATCH AUTOSEL 6.18-5.15] net: usb: cdc_ether: add quirk for AMI BMC stale link events Sasha Levin
2026-10-19 14:44   ` sashiko-bot
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] usb: misc: cypress_cy7c63: check result of IO Sasha Levin
2026-10-19 14:59   ` sashiko-bot
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18-5.10] USB: gadget: inode: fix mm lifetime handling Sasha Levin
2026-10-19 15:11   ` sashiko-bot [this message]
2026-10-19 13:50 ` [PATCH AUTOSEL 6.18] xhci: include all root port children in recovery prevention on link error Sasha Levin
2026-10-19 15:25   ` sashiko-bot
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.1] usb: gadget: u_audio: clean up capture endpoint on feedback failure Sasha Levin
2026-10-19 15:18   ` sashiko-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=sashiko-outbox-177640@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=sashal@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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