Linux GPIO subsystem development
 help / color / mirror / Atom feed
From: Jia Jia <physicalmtea@gmail.com>
To: linux-gpio@vger.kernel.org
Cc: brgl@kernel.org, warthog618@gmail.com, linusw@kernel.org,
	info@metux.net, vireshk@kernel.org,
	virtualization@lists.linux.dev
Subject: [BUG] gpio: cdev: irq_desc UAF on close after chip removal
Date: Mon, 17 Aug 2026 15:04:29 +0800	[thread overview]
Message-ID: <20260817070429.157993-1-physicalmtea@gmail.com> (raw)

Hi,

I hit a KASAN slab-use-after-free in the gpio cdev close path while
playing with virtio-gpio unbind on x86-64/KVM (linux-next, KASAN guest).
The tree already has ec8b6f55b981 ("gpio: free irqs that are still
requested when the chip is being removed").

Repro is straightforward: request a v2 line with edge detection, unbind
the chip while the line fd is still open, and then close the fd.

==================================================================
BUG: KASAN: slab-use-after-free in _raw_spin_unlock_irqrestore+0x16/0x40
Write of size 1 at addr ffff88800bc9a914 by task gpio_uaf_repro/135

CPU: 1 UID: 0 PID: 135 Comm: gpio_uaf_repro Tainted: G        W
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009)
Call Trace:
 <TASK>
 dump_stack_lvl+0x55/0x70
 print_report+0xcb/0x5e0
 kasan_report+0xb8/0xf0
 _raw_spin_unlock_irqrestore+0x16/0x40
 free_irq+0x16a/0x490
 edge_detector_stop+0x90/0xc0
 linereq_free+0x8c/0xf0
 linereq_release+0x1f/0x30
 __fput+0x1c5/0x490
 fput_close_sync+0xc9/0x160
 __x64_sys_close+0x55/0x90
 do_syscall_64+0x5a/0x4d0
 entry_SYSCALL_64_after_hwframe+0x76/0x7e
 </TASK>

Allocated by task 135:
 kasan_save_stack+0x24/0x50
 kasan_save_track+0x14/0x30
 __kasan_kmalloc+0x7f/0x90
 __irq_alloc_descs+0x1f7/0x460
 irq_domain_alloc_descs.part.0+0x4b/0x90
 irq_create_mapping_affinity_locked+0x67/0x160
 irq_create_mapping_affinity+0x10f/0x180
 gpiochip_to_irq+0x180/0x1a0
 gpiod_to_irq+0xa7/0x140
 edge_detector_setup+0x2d4/0x4f0
 linereq_create+0x711/0x830
 gpio_ioctl+0x115/0x830
 __x64_sys_ioctl+0x56a/0xbf0
 do_syscall_64+0x5a/0x4d0
 entry_SYSCALL_64_after_hwframe+0x76/0x7e

Freed by task 31:
 kasan_save_stack+0x24/0x50
 kasan_save_track+0x14/0x30
 kasan_save_free_info+0x3b/0x60
 __kasan_slab_free+0x43/0x70
 kfree+0x177/0x450
 kobject_put+0xe1/0x2c0
 rcu_core+0x3de/0xeb0
 handle_softirqs+0xf9/0x3c0
 run_ksoftirqd+0x27/0x30
 smpboot_thread_fn+0x19c/0x370
 kthread+0x1cb/0x220
 ret_from_fork+0x2d6/0x3f0
 ret_from_fork_asm+0x1a/0x30

Last potentially related work creation:
 kasan_save_stack+0x24/0x50
 kasan_record_aux_stack+0x8c/0xa0
 __call_rcu_common.constprop.0+0x4f/0x550
 free_desc+0xef/0x150
 irq_free_descs+0x47/0x70
 gpiochip_irqchip_remove+0x1ca/0x400
 gpiochip_remove+0x23b/0x2d0
 virtio_gpio_remove+0x2a/0x60
 virtio_dev_remove+0x68/0x100
 device_release_driver_internal+0x24f/0x2f0
 unbind_store+0xb1/0xc0
 kernfs_fop_write_iter+0x1c9/0x270
 vfs_write+0x5f1/0x760
 ksys_write+0xc3/0x160
 do_syscall_64+0x5a/0x4d0
 entry_SYSCALL_64_after_hwframe+0x76/0x7e

The buggy address belongs to the object at ffff88800bc9a800
 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 276 bytes inside of
 freed 1024-byte region [ffff88800bc9a800, ffff88800bc9ac00)
==================================================================

So the irq_desc is freed from gpiochip_irqchip_remove() ->
irq_free_descs(), then close() still calls free_irq() because cdev
cached the irq number in the line request.

virtio-gpio is only how I triggered it. The close path is generic
gpiolib-cdev.

ec8b6f55b981 already drops leftover irq actions on chip removal, so the
original procfs leak is gone. It does not clear the irq stored in the cdev line
request, which is how this UAF still happens.

Related earlier discussion:

  https://lore.kernel.org/r/20240919135104.3583-1-brgl@bgdev.pl
  https://patchew.org/linux/20240227113426.253232-1-herve.codina@bootlin.com/

I tried to write a patch, but a complete fix seems to touch more than I
am comfortable changing as a minimal fix: notify vs close, line
reconfigure, and the remaining-irq teardown all need to stay in sync.
My reading of gpiolib is also pretty limited, so I am just reporting
the bug for now.

Thanks,
Jia


                 reply	other threads:[~2026-08-17  7:04 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260817070429.157993-1-physicalmtea@gmail.com \
    --to=physicalmtea@gmail.com \
    --cc=brgl@kernel.org \
    --cc=info@metux.net \
    --cc=linusw@kernel.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=vireshk@kernel.org \
    --cc=virtualization@lists.linux.dev \
    --cc=warthog618@gmail.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