All of lore.kernel.org
 help / color / mirror / Atom feed
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

             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.