Rust for Linux List
 help / color / mirror / Atom feed
From: Priya Bala Govindasamy <pgovind2@uci.edu>
To: m.wilczynski@samsung.com, ojeda@kernel.org, ukleinek@kernel.org,
	boqun@kernel.org, gary@garyguo.net, bjorn3_gh@protonmail.com,
	lossin@kernel.org, a.hindborg@kernel.org, aliceryhl@google.com,
	tmgross@umich.edu, dakr@kernel.org, daniel.almeida@collabora.com,
	tamird@kernel.org, acourbot@nvidia.com, work@onurozkan.dev,
	elle@weathered-steel.dev, linux-pwm@vger.kernel.org,
	rust-for-linux@vger.kernel.org, ardalan@uci.edu,
	zhiyunq@cs.ucr.edu, dzueck@uci.edu, pgovind2@uci.edu
Subject: [PATCH 0/1] rust: pwm: reject over-aligned driver data in `Chip::new()`
Date: Fri, 13 Nov 2026 20:25:33 +0000	[thread overview]
Message-ID: <cover.1794600927.git.pgovind2@uci.edu> (raw)

Dear Linux kernel maintainers,

We are developing a tool called FerroLens to detect potential
unsound behavior in Rust code in the Linux kernel. The tool
internally uses an LLM to detect bugs.
We then perform manual analysis to verify these reports.
FerroLens reported the following bug in rust/kernel/pwm.rs:

`Chip::new()` does not check the alignment of the driver data type `T`.
This allows a Rust kernel module to choose an arbitrary alignment for `T`.

`pwmchip_alloc()` reserves `size_of::<T>()` bytes for the driver's
private data. `pwmchip_priv()` aligns this storage to `PWMCHIP_ALIGN`,
which is defined as `ARCH_DMA_MINALIGN`. But, `PwmOps` does not restrict
the alignment of `T`, so a caller may provide a `T` whose required
alignment is greater than `ARCH_DMA_MINALIGN`.

This can result in `drvdata_ptr` pointing to misaligned storage for `T`
in the underlying C allocation.
If `drvdata_ptr` is misaligned for `T`, that breaks the safety
requirements of `pin_init::raw_try_init()` which requires a valid,
aligned pointer as an argument. This is undefined behavior.

Additionally, `Chip::drvdata()` can be called using the `Chip` produced by
`Chip::new()`. It creates a reference to `T` from the misaligned storage
which is also undefined behavior.

Here is a PoC kernel module that demonstrates this issue:

    // SPDX-License-Identifier: GPL-2.0

    use kernel::{prelude::*, pwm, faux};
    use core::ptr;

    module! {
        type: PwmAlignPoc,
        name: "pwm_align_poc",
        authors: ["Priya Govindasamy"],
        description: "PoC that calls pwm::Chip::new with a PwmOps implementation that has unexpected alignment",
        license: "GPL",
        imports_ns: ["PWM"],
    }

    #[repr(align(8192))]
    #[pin_data]
    struct DemoPwmOps {
        #[pin]
        value: u64,
    }

    impl pwm::PwmOps for DemoPwmOps {
        type WfHw = [u8; 16];
    }

    struct PwmAlignPoc{
        _fdev: faux::Registration,
    }

    const DEVICE_NAME: &CStr = c"pwmchip_add_poc";

    impl kernel::Module for PwmAlignPoc {
        fn init(_module: &'static ThisModule) -> Result<Self> {
            pr_info!("pwm-align-poc: init\n");

            let fdev = faux::Registration::new(DEVICE_NAME, None)?;
            let dev = fdev.as_ref().as_ref();

            let chip = pwm::Chip::new(
                dev,
                1,
                try_pin_init!(DemoPwmOps {
                    value: 0x1122_3344_5566_7788,
                }),
            )?;

            pr_info!("pwm-align-poc: pwm::Chip::new returned successfully\n");

            let chip_ref: &pwm::Chip<DemoPwmOps> = &*chip;
            let drvdata = chip_ref.drvdata();

            let drvdata_addr = ptr::from_ref(drvdata) as usize;

            let align = core::mem::align_of::<DemoPwmOps>();
            let size = core::mem::size_of::<DemoPwmOps>();
            let misalignment = (drvdata_addr as usize) & (align - 1);

            pr_info!(
                "pwm-align-poc: T size={} align={} drvdata={:#x} drvdata%align={:#x}\n",
                size,
                align,
                drvdata_addr as usize,
                misalignment,
            );

            if misalignment != 0 {
                pr_info!("pwm-align-poc: BUG: drvdata is not aligned for DemoPwmOps\n");
            } else {
                pr_info!("pwm-align-poc: drvdata happened to be aligned; try reloading or increasing repr(align)\n");
            }

            drop(chip);

            Ok(Self { _fdev: fdev })
        }
    }

    impl Drop for PwmAlignPoc {
        fn drop(&mut self) {
            pr_info!("pwm-align-poc: exit\n");
        }
    }



Output:

[935472.295875] pwm_align_poc: pwm-align-poc: init
[935472.300101] pwm_align_poc: pwm-align-poc: pwm::Chip::new returned successfully
[935472.300125] rust_kernel: panicked at rust/kernel/pwm.rs:561:18:
                misaligned pointer dereference: address must be a multiple of 0x2000 but is 0xffff88811a9bc8a8
[935472.300296] ------------[ cut here ]------------
[935472.300302] kernel BUG at rust/helpers/bug.c:7!
[935472.300357] Oops: invalid opcode: 0000 [#1] SMP KASAN PTI
[935472.321291] CPU: 11 UID: 0 PID: 168877 Comm: insmod Tainted: G           OE    N   7.3.0+ #71 PREEMPT(lazy) 
[935472.326767] Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE, [N]=TEST
[935472.330167] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1ubuntu2 04/01/2014
[935472.335684] RIP: 0010:rust_helper_BUG+0x8/0x10
[935472.338311] Code: ff 5d c3 cc cc cc cc cc 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 55 48 89 e5 <0f> 0b 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90
[935472.348377] RSP: 0018:ffff888163fe7610 EFLAGS: 00010282
[935472.351153] RAX: 0000000000000092 RBX: ffff888163fe7638 RCX: 79d6f1f055ce0500
[935472.355104] RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffffffff85cb7348
[935472.359054] RBP: ffff888163fe7610 R08: ffffffff85cb734b R09: 1ffffffff0b96e69
[935472.365925] R10: dffffc0000000000 R11: fffffbfff0b96e6a R12: ffff88811a9bc8a8
[935472.369831] R13: ffff88811a9bc8a8 R14: dffffc0000000000 R15: ffff88811a9bc000
[935472.373766] FS:  00007fb90f158c40(0000) GS:ffff88842697a000(0000) knlGS:0000000000000000
[935472.377958] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[935472.380839] CR2: 00007f2817fd91ac CR3: 000000010c31e004 CR4: 0000000000372ef0
[935472.384553] Call Trace:
[935472.385839]  <TASK>
[935472.386965]  _RNvCsGIExRX8pES_7___rustc17rust_begin_unwind+0x8c/0x90
[935472.390092]  ? __pfx__RNvXs6_NtCsbuTvttuFvbr_6kernel3fmtINtB5_7AdapterRRNtNtNtCsjYlAz7NZ3Sw_4core5panic10panic_info9PanicInfoENtNtBS_3fmt7Display3fmtB7_+0x10/0x10
[935472.396837]  _RNvNtCsjYlAz7NZ3Sw_4core9panicking18panic_nounwind_fmt+0x5e/0x5e
[935472.400208]  _RNvNtCsjYlAz7NZ3Sw_4core9panicking36panic_misaligned_pointer_dereference+0x90/0x91
[935472.404082]  ? __pfx__RNvXsC_NtNtCsjYlAz7NZ3Sw_4core3fmt3numyNtB7_8LowerHex3fmt+0x10/0x10
[935472.407670]  ? __pfx__RNvXsC_NtNtCsjYlAz7NZ3Sw_4core3fmt3numyNtB7_8LowerHex3fmt+0x10/0x10
[935472.411102]  _RNvXs_CsiYPS3iQo6vD_13pwm_align_pocNtB4_11PwmAlignPocNtNtCsbuTvttuFvbr_6kernel6module6Module4init+0x599/0x5d0 [pwm_align_poc]
[935472.416147]  ? debug_smp_processor_id+0x1b/0x30
[935472.418137]  init_module+0x15/0xff0 [pwm_align_poc]
[935472.420132]  do_one_initcall+0x119/0x4f0
[935472.421738]  ? __pfx_init_module+0x10/0x10 [pwm_align_poc]
[935472.423926]  ? __schedule+0x171a/0x5910
[935472.425480]  ? __x64_sys_finit_module+0x7f/0x90
[935472.427411]  ? __lock_acquire+0xeeb/0x1040
[935472.429044]  ? debug_smp_processor_id+0x1b/0x30
[935472.430831]  ? irqentry_exit+0x1e1/0x870
[935472.432174]  ? __this_cpu_preempt_check+0x17/0x20
[935472.434047]  ? lockdep_hardirqs_on+0xdc/0x160
[935472.435746]  ? trace_hardirqs_on+0x3d/0x50
[935472.437405]  ? irqentry_exit+0x1e1/0x870
[935472.438833]  ? trace_irq_disable+0x3c/0x130
[935472.440421]  ? sysvec_apic_timer_interrupt+0x68/0xd0
[935472.442163]  ? asm_sysvec_apic_timer_interrupt+0x1f/0x30
[935472.444092]  ? _RNvNvNtCsjYlAz7NZ3Sw_4core4hint21unreachable_unchecked18precondition_check+0x30/0x30 [pwm_align_poc]
[935472.447576]  ? __pfx_init_module+0x10/0x10 [pwm_align_poc]
[935472.449472]  do_init_module+0x23f/0x740
[935472.450781]  load_module+0x32d1/0x3f20
[935472.452116]  __se_sys_finit_module+0x39d/0x5f0
[935472.453645]  __x64_sys_finit_module+0x7f/0x90
[935472.455093]  x64_sys_call+0xa66/0x2600
[935472.456370]  do_syscall_64+0x11c/0x3f0
[935472.457696]  ? do_syscall_64+0x217/0x3f0
[935472.459046]  ? debug_smp_processor_id+0x1b/0x30
[935472.460488]  ? rcu_is_watching+0x1a/0xc0
[935472.461701]  ? trace_irq_disable+0x3c/0x130
[935472.463044]  ? do_syscall_64+0x6d/0x3f0
[935472.464254]  ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
[935472.465663]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[935472.467238] RIP: 0033:0x7fb90e91e9dd
[935472.468444] Code: 5b 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 23 b4 0f 00 f7 d8 64 89 01 48
[935472.473776] RSP: 002b:00007ffd3d6cabb8 EFLAGS: 00000246 ORIG_RAX: 0000000000000139
[935472.476032] RAX: ffffffffffffffda RBX: 0000559f8e9df7d0 RCX: 00007fb90e91e9dd
[935472.478187] RDX: 0000000000000000 RSI: 0000559f772fecd2 RDI: 0000000000000003
[935472.480301] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
[935472.482103] R10: 0000000000000003 R11: 0000000000000246 R12: 0000559f772fecd2
[935472.484269] R13: 0000559f8e9df790 R14: 0000559f772fd888 R15: 0000559f8e9df8e0
[935472.486330]  </TASK>
[935472.487082] Modules linked in: pwm_align_poc(OE+) registration_poc(OE) binfmt_misc intel_rapl_msr intel_rapl_common kvm_intel kvm e1000 i2c_piix4 joydev i2c_smbus floppy rapl qemu_fw_cfg sch_fq_codel dm_multipath scsi_dh_rdac scsi_dh_emc scsi_dh_alua msr efi_pstore autofs4 raid10 raid456 async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq raid1 raid0 aesni_intel gf128mul input_leds psmouse mac_hid serio_raw pata_acpi
[935472.498241] ---[ end trace 0000000000000000 ]---
[935472.499836] RIP: 0010:rust_helper_BUG+0x8/0x10
[935472.499845] Code: ff 5d c3 cc cc cc cc cc 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa 55 48 89 e5 <0f> 0b 66 0f 1f 44 00 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90
[935472.499849] RSP: 0018:ffff888163fe7610 EFLAGS: 00010282
[935472.499865] RAX: 0000000000000092 RBX: ffff888163fe7638 RCX: 79d6f1f055ce0500
[935472.499868] RDX: 0000000000000001 RSI: 0000000000000004 RDI: ffffffff85cb7348
[935472.499871] RBP: ffff888163fe7610 R08: ffffffff85cb734b R09: 1ffffffff0b96e69
[935472.499874] R10: dffffc0000000000 R11: fffffbfff0b96e6a R12: ffff88811a9bc8a8
[935472.499876] R13: ffff88811a9bc8a8 R14: dffffc0000000000 R15: ffff88811a9bc000
[935472.499879] FS:  00007fb90f158c40(0000) GS:ffff88842697a000(0000) knlGS:0000000000000000
[935472.499882] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[935472.499885] CR2: 00007f2817fd91ac CR3: 000000010c31e004 CR4: 0000000000372ef0

Priya Bala Govindasamy (1):
  rust: pwm: reject over-aligned driver data in `Chip::new()`

 rust/bindgen_parameters         | 1 +
 rust/bindings/bindings_helper.h | 1 +
 rust/kernel/pwm.rs              | 5 +++++
 3 files changed, 7 insertions(+)

-- 
2.34.1


             reply	other threads:[~2026-11-13 20:25 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13 20:25 Priya Bala Govindasamy [this message]
2026-11-13 20:25 ` [PATCH 1/1] rust: pwm: reject over-aligned driver data in `Chip::new()` Priya Bala Govindasamy

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=cover.1794600927.git.pgovind2@uci.edu \
    --to=pgovind2@uci.edu \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=aliceryhl@google.com \
    --cc=ardalan@uci.edu \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dzueck@uci.edu \
    --cc=elle@weathered-steel.dev \
    --cc=gary@garyguo.net \
    --cc=linux-pwm@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=m.wilczynski@samsung.com \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tamird@kernel.org \
    --cc=tmgross@umich.edu \
    --cc=ukleinek@kernel.org \
    --cc=work@onurozkan.dev \
    --cc=zhiyunq@cs.ucr.edu \
    /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