From: Dingisoul <dingiso.kernel@gmail.com>
To: Linus Walleij <linusw@kernel.org>, Jonathan Cameron <jic23@kernel.org>
Cc: "David Lechner" <dlechner@baylibre.com>,
"Nuno Sá" <nuno.sa@analog.com>,
"Andy Shevchenko" <andy@kernel.org>,
linux-iio@vger.kernel.org
Subject: [BUG] iio: gyro: mpu3050: use-after-free via trigger left on iio_trigger_list after unbind
Date: Sat, 10 Oct 2026 16:36:01 -0400 [thread overview]
Message-ID: <20261010203601.1686148-1-dingiso.kernel@gmail.com> (raw)
Hi Kernel Maintainers,
I hit the following report while testing current upstream kernel:
KASAN: slab-use-after-free in mpu3050_drdy_trigger_set_state
on commit: a90ee4305c4a (2026-10-07)
Root cause: mpu3050_trigger_probe() registers the data-ready trigger with
the non-devm iio_trigger_register(), with drvdata pointing at indio_dev:
static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
{
...
mpu3050->trig->dev.parent = dev;
mpu3050->trig->ops = &mpu3050_trigger_ops;
iio_trigger_set_drvdata(mpu3050->trig, indio_dev);
ret = iio_trigger_register(mpu3050->trig); /* device_add() pins trig; no unregister on remove */
if (ret)
goto err_iio_trigger;
indio_dev->trig = iio_trigger_get(mpu3050->trig);
return 0;
}
mpu3050_common_remove() tears down everything else, but never calls
iio_trigger_unregister() on mpu3050->trig:
void mpu3050_common_remove(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mpu3050 *mpu3050 = iio_priv(indio_dev);
iio_device_unregister(indio_dev); /* devm frees indio_dev's storage once this returns */
pm_runtime_get_sync(dev);
pm_runtime_put_noidle(dev);
pm_runtime_disable(dev);
if (mpu3050->irq)
free_irq(mpu3050->irq, mpu3050->trig);
iio_triggered_buffer_cleanup(indio_dev);
mpu3050_power_down(mpu3050);
/* trig is never unregistered: still on the global iio_trigger_list */
}
So after unbind, the trigger is still alive and discoverable by name on
the global trigger list, with drvdata still pointing at the now-freed
indio_dev. Any other IIO device with a triggered buffer can select it by
name via trigger/current_trigger and enable its buffer, which reaches
the leaked trigger's ->set_trigger_state() op:
static int mpu3050_drdy_trigger_set_state(struct iio_trigger *trig,
bool enable)
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct mpu3050 *mpu3050 = iio_priv(indio_dev); /* indio_dev is freed -- UAF read */
...
The reproducer and .config files are here.
https://gist.github.com/dingiso/985aa3eb2786b62f80e2e6780e9af090
I'm happy to test debug patches or provide additional information.
[ 24.039594][ T8117] BUG: KASAN: slab-use-after-free in mpu3050_drdy_trigger_set_state (./include/linux/iio/iio.h:980 drivers/iio/gyro/mpu3050-core.c:957)
[ 24.039630][ T8117] Read of size 8 at addr ffff888030621388 by task repro/8117
[ 24.039634][ T8117]
[ 24.039644][ T8117] Tainted: [E]=UNSIGNED_MODULE
[ 24.039645][ T8117] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 24.039648][ T8117] Call Trace:
[ 24.039650][ T8117] <TASK>
[ 24.039651][ T8117] dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
[ 24.039663][ T8117] print_report (mm/kasan/report.c:378 mm/kasan/report.c:482)
[ 24.039682][ T8117] kasan_report (mm/kasan/report.c:595)
[ 24.039690][ T8117] mpu3050_drdy_trigger_set_state (./include/linux/iio/iio.h:980 drivers/iio/gyro/mpu3050-core.c:957)
[ 24.039709][ T8117] iio_trigger_attach_poll_func (drivers/iio/industrialio-trigger.c:308)
[ 24.039715][ T8117] __iio_update_buffers (drivers/iio/industrialio-buffer.c:1207 drivers/iio/industrialio-buffer.c:1324)
[ 24.039747][ T8117] enable_store (drivers/iio/industrialio-buffer.c:1414)
[ 24.039765][ T8117] kernfs_fop_write_iter (fs/kernfs/file.c:345)
[ 24.039769][ T8117] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
[ 24.039786][ T8117] ksys_write (fs/read_write.c:739)
[ 24.039795][ T8117] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 24.039799][ T8117] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
[ 24.039803][ T8117] RIP: 0033:0x7fe293245473
[ 24.039807][ T8117] Code: 8b 15 21 2a 0e 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 64 8b 04 25 18 00 00 00 85 c0 75 14 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 55 c3 0f 1f 40 00 48 83 ec 28 48 89 54 24 18
All code
========
0: 8b 15 21 2a 0e 00 mov 0xe2a21(%rip),%edx # 0xe2a27
6: f7 d8 neg %eax
8: 64 89 02 mov %eax,%fs:(%rdx)
b: 48 c7 c0 ff ff ff ff mov $0xffffffffffffffff,%rax
12: eb b7 jmp 0xffffffffffffffcb
14: 0f 1f 00 nopl (%rax)
17: 64 8b 04 25 18 00 00 mov %fs:0x18,%eax
1e: 00
1f: 85 c0 test %eax,%eax
21: 75 14 jne 0x37
23: b8 01 00 00 00 mov $0x1,%eax
28: 0f 05 syscall
2a:* 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax <-- trapping instruction
30: 77 55 ja 0x87
32: c3 ret
33: 0f 1f 40 00 nopl 0x0(%rax)
37: 48 83 ec 28 sub $0x28,%rsp
3b: 48 89 54 24 18 mov %rdx,0x18(%rsp)
Code starting with the faulting instruction
===========================================
0: 48 3d 00 f0 ff ff cmp $0xfffffffffffff000,%rax
6: 77 55 ja 0x5d
8: c3 ret
9: 0f 1f 40 00 nopl 0x0(%rax)
d: 48 83 ec 28 sub $0x28,%rsp
11: 48 89 54 24 18 mov %rdx,0x18(%rsp)
[ 24.039810][ T8117] RSP: 002b:00007fff7856e628 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[ 24.039815][ T8117] RAX: ffffffffffffffda RBX: 00007fff7856e6e0 RCX: 00007fe293245473
[ 24.039818][ T8117] RDX: 0000000000000001 RSI: 000056386e819159 RDI: 0000000000000003
[ 24.039820][ T8117] RBP: 0000000000000003 R08: 0000000000004000 R09: 00007fe2932e90c0
[ 24.039822][ T8117] R10: 0000000000000000 R11: 0000000000000246 R12: 000056386e819159
[ 24.039824][ T8117] R13: 00007fff7856ea60 R14: 00007fff7856ea60 R15: 0000563885c1635b
[ 24.039827][ T8117] </TASK>
[ 24.039829][ T8117]
[ 24.039830][ T8117] Freed by task 8117:
[ 24.039832][ T8117] kasan_save_stack (mm/kasan/common.c:57)
[ 24.039835][ T8117] kasan_save_track (mm/kasan/common.c:78)
[ 24.039838][ T8117] kasan_save_free_info (mm/kasan/generic.c:584)
[ 24.039841][ T8117] __kasan_slab_free (mm/kasan/common.c:264 mm/kasan/common.c:296)
[ 24.039844][ T8117] kfree (./include/linux/kasan.h:235 mm/slub.c:2748 mm/slub.c:6509 mm/slub.c:6802)
[ 24.039849][ T8117] device_release (drivers/base/core.c:2645)
[ 24.039854][ T8117] kobject_put (lib/kobject.c:689 lib/kobject.c:720 ./include/linux/kref.h:65 lib/kobject.c:737)
[ 24.039859][ T8117] release_nodes (drivers/base/devres.c:546)
[ 24.039862][ T8117] devres_release_group (drivers/base/devres.c:739)
[ 24.039865][ T8117] i2c_device_remove (drivers/i2c/i2c-core-base.c:637)
[ 24.039871][ T8117] device_release_driver_internal (drivers/base/dd.c:1349 drivers/base/dd.c:1372)
[ 24.039874][ T8117] bus_remove_device (drivers/base/bus.c:664)
[ 24.039878][ T8117] device_del (drivers/base/core.c:3965)
[ 24.039882][ T8117] device_unregister (drivers/base/core.c:4006)
[ 24.039885][ T8117] delete_device_store (drivers/i2c/i2c-core-base.c:1369)
[ 24.039889][ T8117] kernfs_fop_write_iter (fs/kernfs/file.c:345)
[ 24.039892][ T8117] vfs_write (fs/read_write.c:595 fs/read_write.c:687)
[ 24.039895][ T8117] ksys_write (fs/read_write.c:739)
[ 24.039899][ T8117] do_syscall_64 (arch/x86/entry/syscall_64.c:61 arch/x86/entry/syscall_64.c:84)
[ 24.039901][ T8117] entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
(Full KASAN report, including the trailing slab/page-owner and memory-state info after this point, is in the gist as kasan_report_full.txt. Lines starting with "?" above are stack-scanned frames, not reliable return addresses, and have been omitted here.)
Best,
Dingisoul
next reply other threads:[~2026-10-10 20:36 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-10 20:36 Dingisoul [this message]
2026-10-11 17:05 ` [BUG] iio: gyro: mpu3050: use-after-free via trigger left on iio_trigger_list after unbind Joshua Crofts
2026-10-12 20:09 ` Dingisoul
2026-10-13 11:30 ` Joshua Crofts
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=20261010203601.1686148-1-dingiso.kernel@gmail.com \
--to=dingiso.kernel@gmail.com \
--cc=andy@kernel.org \
--cc=dlechner@baylibre.com \
--cc=jic23@kernel.org \
--cc=linusw@kernel.org \
--cc=linux-iio@vger.kernel.org \
--cc=nuno.sa@analog.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.