Skip to contentSkip to conversation

FAILED: patch "[PATCH] rust: irq: declare cfi_encoding for irqreturn" failed to apply to 6.18-stable tree

PATCH In review [email protected] 4 participants 6 messages Nov 4 – Nov 6

Subsystems (3)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 01f3e6b4b1c8c1748e59ba53631ab1f5d9ad0ea4
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026110407-hydrated-decipher-a8a9@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'

Possible dependencies:

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 01f3e6b4b1c8c1748e59ba53631ab1f5d9ad0ea4 Mon Sep 17 00:00:00 2001
From: Sami Tolvanen <[email protected]>
Date: Mon, 19 Oct 2026 23:34:37 +0000
Subject: [PATCH] rust: irq: declare cfi_encoding for irqreturn

The IRQ callbacks return c_uint. C calls them through irq_handler_t, which returns enum irqreturn. kCFI encodes enum types by name even with integer normalization, so the type ids never match and every call fails the CFI check.

Generate irqreturn as a newtype with a cfi_encoding, as is done for lru_status, and return bindings::irqreturn_t from the callbacks.

Fixes 0851d34a8cc3 ("rust: irq: add support for non-threaded IRQs and handlers")
Fixes 135d40523244 ("rust: irq: add support for threaded IRQs and handlers")
rust/bindgen_parameters +2 -0
index 8402b0c93545..5059cc74cb3c 100644
@@ -27,6 +27,8 @@
 --opaque-type spinlock
 
 # enums that appear in indirect function calls should specify a cfi type
+--newtype-enum irqreturn
+--with-attribute-custom-enum=irqreturn='#[cfi_encoding="9irqreturn"]'
 --newtype-enum lru_status
 --with-attribute-custom-enum=lru_status='#[cfi_encoding="10lru_status"]'
 
rust/kernel/irq/request.rs +17 -11
index c1c6525a676a..1afa9fcaad1f 100644
@@ -25,10 +25,10 @@
 #[repr(u32)]
 pub enum IrqReturn {
     /// The interrupt was not from this device or was not handled.
-    None = bindings::irqreturn_IRQ_NONE,
+    None = bindings::irqreturn::IRQ_NONE.0,
 
     /// The interrupt was handled by this device.
-    Handled = bindings::irqreturn_IRQ_HANDLED,
+    Handled = bindings::irqreturn::IRQ_HANDLED.0,
 }
 
 /// Callbacks for an IRQ handler.
@@ -240,25 +240,28 @@ fn drop(self: Pin<&mut Self>) {
 /// # Safety
 ///
 /// This function should be only used as the callback in `request_irq`.
-unsafe extern "C" fn handle_irq_callback<T: Handler>(_irq: i32, ptr: *mut c_void) -> c_uint {
+unsafe extern "C" fn handle_irq_callback<T: Handler>(
+    _irq: i32,
+    ptr: *mut c_void,
+) -> bindings::irqreturn_t {
     let ptr = ptr.cast_const().cast::<Registration<'_, T>>();
     // SAFETY: `ptr` is a pointer to `Registration<'_, T>` set in `Registration::new()`.
     let registration = unsafe { &*ptr };
 
-    T::handle(&registration.handler) as c_uint
+    bindings::irqreturn_t(T::handle(&registration.handler) as c_uint)
 }
 
 /// The value that can be returned from [`ThreadedHandler::handle`].
 #[repr(u32)]
 pub enum ThreadedIrqReturn {
     /// The interrupt was not from this device or was not handled.
-    None = bindings::irqreturn_IRQ_NONE,
+    None = bindings::irqreturn::IRQ_NONE.0,
 
     /// The interrupt was handled by this device.
-    Handled = bindings::irqreturn_IRQ_HANDLED,
+    Handled = bindings::irqreturn::IRQ_HANDLED.0,
 
     /// The handler wants the handler thread to wake up.
-    WakeThread = bindings::irqreturn_IRQ_WAKE_THREAD,
+    WakeThread = bindings::irqreturn::IRQ_WAKE_THREAD.0,
 }
 
 /// Callbacks for a threaded IRQ handler.
@@ -461,23 +464,26 @@ fn drop(self: Pin<&mut Self>) {
 unsafe extern "C" fn handle_threaded_irq_callback<T: ThreadedHandler>(
     _irq: i32,
     ptr: *mut c_void,
-) -> c_uint {
+) -> bindings::irqreturn_t {
     let ptr = ptr.cast_const().cast::<ThreadedRegistration<'_, T>>();
     // SAFETY: `ptr` is a pointer to `ThreadedRegistration<'_, T>` set in
     // `ThreadedRegistration::new()`.
     let registration = unsafe { &*ptr };
 
-    T::handle(&registration.handler) as c_uint
+    bindings::irqreturn_t(T::handle(&registration.handler) as c_uint)
 }
 
 /// # Safety
 ///
 /// This function should be only used as the callback in `request_threaded_irq`.
-unsafe extern "C" fn thread_fn_callback<T: ThreadedHandler>(_irq: i32, ptr: *mut c_void) -> c_uint {
+unsafe extern "C" fn thread_fn_callback<T: ThreadedHandler>(
+    _irq: i32,
+    ptr: *mut c_void,
+) -> bindings::irqreturn_t {
     let ptr = ptr.cast_const().cast::<ThreadedRegistration<'_, T>>();
     // SAFETY: `ptr` is a pointer to `ThreadedRegistration<'_, T>` set in
     // `ThreadedRegistration::new()`.
     let registration = unsafe { &*ptr };
 
-    T::handle_threaded(&registration.handler) as c_uint
+    bindings::irqreturn_t(T::handle_threaded(&registration.handler) as c_uint)
 }
maintainer
#1 lore raw

PATCH 1/1 rust: irq: declare cfi_encoding for irqreturn

From: Sami Tolvanen <[email protected]>

[ Upstream commit 01f3e6b4b1c8c1748e59ba53631ab1f5d9ad0ea4 ]

The IRQ callbacks return c_uint. C calls them through irq_handler_t, which returns enum irqreturn. kCFI encodes enum types by name even with integer normalization, so the type ids never match and every call fails the CFI check.

Generate irqreturn as a newtype with a cfi_encoding, as is done for lru_status, and return bindings::irqreturn_t from the callbacks.

Fixes 0851d34a8cc3 ("rust: irq: add support for non-threaded IRQs and handlers")
Fixes 135d40523244 ("rust: irq: add support for threaded IRQs and handlers")
[ sashal: replaced bindgen's custom enum attribute option with sed post-processing to support older bindgen ]
---
 rust/Makefile              |  3 ++-
 rust/bindgen_parameters    |  3 +++
 rust/bindings/lib.rs       |  1 +
 rust/kernel/irq/request.rs | 22 +++++++++++-----------
 4 files changed, 17 insertions(+), 12 deletions(-)
rust/Makefile +2 -1
index d4618f646b05b..3867ff14fbdec 100644
@@ -367,7 +367,8 @@ quiet_cmd_bindgen = BINDGEN $@
 $(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \
     $(shell grep -Ev '^#|^$$' $(src)/bindgen_parameters)
 $(obj)/bindings/bindings_generated.rs: private bindgen_target_extra = ; \
-    sed -Ei 's/pub const RUST_CONST_HELPER_([a-zA-Z0-9_]*)/pub const \1/g' $@
+    sed -Ei 's/pub const RUST_CONST_HELPER_([a-zA-Z0-9_]*)/pub const \1/g' $@; \
+    sed -Ei 's/^pub struct irqreturn\(/#[cfi_encoding="9irqreturn"]\n&/' $@
 $(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
     $(src)/bindgen_parameters FORCE
 	$(call if_changed_dep,bindgen)
rust/bindgen_parameters +3 -0
index e13c6f9dd17b2..9e02500dc9792 100644
@@ -23,6 +23,9 @@
 # warning. We don't need to peek into it anyway.
 --opaque-type spinlock
 
+# enums that appear in indirect function calls should specify a cfi type
+--newtype-enum irqreturn
+
 # `seccomp`'s comment gets understood as a doctest
 --no-doc-comments
 
rust/bindings/lib.rs +1 -0
index 8305adbdf8cbf..37f584727eba1 100644
@@ -23,6 +23,7 @@
     unreachable_pub,
     unsafe_op_in_unsafe_fn
 )]
+#![feature(cfi_encoding)]
 
 #[allow(dead_code)]
 #[allow(clippy::as_underscore)]
rust/kernel/irq/request.rs +11 -11
index 70700f43ddd37..4f2b315856b9b 100644
@@ -20,10 +20,10 @@
 #[repr(u32)]
 pub enum IrqReturn {
     /// The interrupt was not from this device or was not handled.
-    None = bindings::irqreturn_IRQ_NONE,
+    None = bindings::irqreturn::IRQ_NONE.0,
 
     /// The interrupt was handled by this device.
-    Handled = bindings::irqreturn_IRQ_HANDLED,
+    Handled = bindings::irqreturn::IRQ_HANDLED.0,
 }
 
 /// Callbacks for an IRQ handler.
@@ -275,7 +275,7 @@ pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
 unsafe extern "C" fn handle_irq_callback<T: Handler + 'static>(
     _irq: i32,
     ptr: *mut c_void,
-) -> c_uint {
+) -> bindings::irqreturn_t {
     // SAFETY: `ptr` is a pointer to `RegistrationInner` set in `Registration::new`
     let inner = unsafe { &*(ptr as *const RegistrationInner) };
     // SAFETY: `inner.handler` is a pointer to `T` set in `Registration::new`
@@ -284,20 +284,20 @@ pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
     // callback is running implies that the device has not yet been unbound.
     let device = unsafe { inner.dev.as_bound() };
 
-    T::handle(handler, device) as c_uint
+    bindings::irqreturn_t(T::handle(handler, device) as c_uint)
 }
 
 /// The value that can be returned from [`ThreadedHandler::handle`].
 #[repr(u32)]
 pub enum ThreadedIrqReturn {
     /// The interrupt was not from this device or was not handled.
-    None = bindings::irqreturn_IRQ_NONE,
+    None = bindings::irqreturn::IRQ_NONE.0,
 
     /// The interrupt was handled by this device.
-    Handled = bindings::irqreturn_IRQ_HANDLED,
+    Handled = bindings::irqreturn::IRQ_HANDLED.0,
 
     /// The handler wants the handler thread to wake up.
-    WakeThread = bindings::irqreturn_IRQ_WAKE_THREAD,
+    WakeThread = bindings::irqreturn::IRQ_WAKE_THREAD.0,
 }
 
 /// Callbacks for a threaded IRQ handler.
@@ -501,7 +501,7 @@ pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
 unsafe extern "C" fn handle_threaded_irq_callback<T: ThreadedHandler + 'static>(
     _irq: i32,
     ptr: *mut c_void,
-) -> c_uint {
+) -> bindings::irqreturn_t {
     // SAFETY: `ptr` is a pointer to `RegistrationInner` set in `ThreadedRegistration::new`
     let inner = unsafe { &*(ptr as *const RegistrationInner) };
     // SAFETY: `inner.handler` is a pointer to `T` set in `ThreadedRegistration::new`
@@ -510,7 +510,7 @@ pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
     // callback is running implies that the device has not yet been unbound.
     let device = unsafe { inner.dev.as_bound() };
 
-    T::handle(handler, device) as c_uint
+    bindings::irqreturn_t(T::handle(handler, device) as c_uint)
 }
 
 /// # Safety
@@ -519,7 +519,7 @@ pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
 unsafe extern "C" fn thread_fn_callback<T: ThreadedHandler + 'static>(
     _irq: i32,
     ptr: *mut c_void,
-) -> c_uint {
+) -> bindings::irqreturn_t {
     // SAFETY: `ptr` is a pointer to `RegistrationInner` set in `ThreadedRegistration::new`
     let inner = unsafe { &*(ptr as *const RegistrationInner) };
     // SAFETY: `inner.handler` is a pointer to `T` set in `ThreadedRegistration::new`
@@ -528,5 +528,5 @@ pub fn synchronize(&self, dev: &Device<Bound>) -> Result {
     // callback is running implies that the device has not yet been unbound.
     let device = unsafe { inner.dev.as_bound() };
 
-    T::handle_threaded(handler, device) as c_uint
+    bindings::irqreturn_t(T::handle_threaded(handler, device) as c_uint)
 }
Signature · 1 line
2.53.0
#2 lore raw

Re: [PATCH 6.18.y] rust: irq: declare cfi_encoding for irqreturn

Quoted 4 lines · Sasha Levin

[ sashal: replaced bindgen's custom enum attribute option with sed post-processing to support older bindgen ]

+ sed -Ei 's/^pub struct irqreturn\(/#[cfi_encoding="9irqreturn"]\n&/' $@

Meh, not great, but it is what it is I guess :(

Should we send the other two, i.e. for dma and hrtimer? i.e. we had these:

FAILED: patch "[PATCH] rust: hrtimer: declare cfi_encoding for
hrtimer_restart" failed to apply to 6.18-stable tree
FAILED: patch "[PATCH] rust: dma: declare cfi_encoding for
dma_data_direction" failed to apply to 6.18-stable tree
FAILED: patch "[PATCH] rust: irq: declare cfi_encoding for
irqreturn" failed to apply to 6.18-stable tree

but I only see this one for irq (I imagine perhaps you sent this one to see whether the approach is OK first?). Do you want the other two to be sent on top of this one if so? I have them, and checked that the hashes match C's.

Then there were the 7.3 ones -- I will send those.

Thanks!

Cheers,
Miguel

maintainer
#3 lore raw

PATCH 1/2 rust: hrtimer: declare cfi_encoding for hrtimer_restart

In reply to Sasha Levin

From: Sami Tolvanen <[email protected]>

commit 39fe6892fd52faed6325ff7f13a92da01ab35727 upstream.

The hrtimer callbacks return bindings::hrtimer_restart, which bindgen generates as c_uint. C calls them through hrtimer->function, which returns enum hrtimer_restart. kCFI encodes enum types by name even with integer normalization, so the type ids never match and every call fails the CFI check.

Generate hrtimer_restart as a newtype with a cfi_encoding, as is done for lru_status, and adapt HrTimerRestart to the newtype.

[ Replaced bindgen's custom enum attribute option with sed
post-processing to support older bindgen. - Miguel ]

---
 rust/Makefile               | 1 +
 rust/bindgen_parameters     | 1 +
 rust/kernel/time/hrtimer.rs | 6 +++---
 3 files changed, 5 insertions(+), 3 deletions(-)
rust/Makefile +1 -0
index 3867ff14fbde..3f1abad648e6 100644
@@ -368,6 +368,7 @@ $(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \
     $(shell grep -Ev '^#|^$$' $(src)/bindgen_parameters)
 $(obj)/bindings/bindings_generated.rs: private bindgen_target_extra = ; \
     sed -Ei 's/pub const RUST_CONST_HELPER_([a-zA-Z0-9_]*)/pub const \1/g' $@; \
+    sed -Ei 's/^pub struct hrtimer_restart\(/#[cfi_encoding="15hrtimer_restart"]\n&/' $@; \
     sed -Ei 's/^pub struct irqreturn\(/#[cfi_encoding="9irqreturn"]\n&/' $@
 $(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
     $(src)/bindgen_parameters FORCE
rust/bindgen_parameters +1 -0
index 9e02500dc979..6f76fdcffd58 100644
@@ -24,6 +24,7 @@
 --opaque-type spinlock
 
 # enums that appear in indirect function calls should specify a cfi type
+--newtype-enum hrtimer_restart
 --newtype-enum irqreturn
 
 # `seccomp`'s comment gets understood as a doctest
rust/kernel/time/hrtimer.rs +3 -3
index 856d2d929a00..35ff2ef7d944 100644
@@ -498,14 +498,14 @@ unsafe fn start(this: *const Self, expires: <Self::TimerMode as HrTimerMode>::Ex
 #[repr(u32)]
 pub enum HrTimerRestart {
     /// Timer should not be restarted.
-    NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART,
+    NoRestart = bindings::hrtimer_restart::HRTIMER_NORESTART.0,
     /// Timer should be restarted.
-    Restart = bindings::hrtimer_restart_HRTIMER_RESTART,
+    Restart = bindings::hrtimer_restart::HRTIMER_RESTART.0,
 }
 
 impl HrTimerRestart {
     fn into_c(self) -> bindings::hrtimer_restart {
-        self as bindings::hrtimer_restart
+        bindings::hrtimer_restart(self as c_uint)
     }
 }
 
Signature · 1 line
2.56.0
maintainer
#4 lore raw

PATCH 2/2 rust: dma: declare cfi_encoding for dma_data_direction

From: Sami Tolvanen <[email protected]>

commit 7d109178cd644268326cd31702ed46c7ac8bb300 upstream.

bindgen generates bindings::dma_data_direction as an integer by default, while C callback tables such as dma_buf_ops declare the parameter as enum dma_data_direction. kCFI encodes enum types by name even with integer normalization, so the type ids would not match when C calls into a Rust callback taking bindings::dma_data_direction.

Generate dma_data_direction as a newtype with a cfi_encoding, as is done for lru_status, and convert DataDirection through the newtype's constants.

[ Replaced bindgen's custom enum attribute option with sed
post-processing to support older bindgen. - Miguel ]

---
 rust/Makefile           |  1 +
 rust/bindgen_parameters |  1 +
 rust/kernel/dma.rs      | 21 +++++++++++----------
 3 files changed, 13 insertions(+), 10 deletions(-)
rust/Makefile +1 -0
index 3f1abad648e6..d6429e68949f 100644
@@ -368,6 +368,7 @@ $(obj)/bindings/bindings_generated.rs: private bindgen_target_flags = \
     $(shell grep -Ev '^#|^$$' $(src)/bindgen_parameters)
 $(obj)/bindings/bindings_generated.rs: private bindgen_target_extra = ; \
     sed -Ei 's/pub const RUST_CONST_HELPER_([a-zA-Z0-9_]*)/pub const \1/g' $@; \
+    sed -Ei 's/^pub struct dma_data_direction\(/#[cfi_encoding="18dma_data_direction"]\n&/' $@; \
     sed -Ei 's/^pub struct hrtimer_restart\(/#[cfi_encoding="15hrtimer_restart"]\n&/' $@; \
     sed -Ei 's/^pub struct irqreturn\(/#[cfi_encoding="9irqreturn"]\n&/' $@
 $(obj)/bindings/bindings_generated.rs: $(src)/bindings/bindings_helper.h \
rust/bindgen_parameters +1 -0
index 6f76fdcffd58..a5d547dc8e8e 100644
@@ -24,6 +24,7 @@
 --opaque-type spinlock
 
 # enums that appear in indirect function calls should specify a cfi type
+--newtype-enum dma_data_direction
 --newtype-enum hrtimer_restart
 --newtype-enum irqreturn
 
rust/kernel/dma.rs +11 -10
index 4ce9e5d7f3dd..b6c73db358ce 100644
@@ -267,25 +267,25 @@ pub enum DataDirection {
     ///
     /// This is used when the buffer can be both read from and written to by the device.
     /// The cache for the corresponding memory region is both flushed and invalidated.
-    Bidirectional = Self::const_cast(bindings::dma_data_direction_DMA_BIDIRECTIONAL),
+    Bidirectional = Self::const_cast(bindings::dma_data_direction::DMA_BIDIRECTIONAL),
 
     /// The DMA mapping is for data transfer from memory to the device (write).
     ///
     /// The CPU has prepared data in the buffer, and the device will read it.
     /// The cache for the corresponding memory region is flushed before device access.
-    ToDevice = Self::const_cast(bindings::dma_data_direction_DMA_TO_DEVICE),
+    ToDevice = Self::const_cast(bindings::dma_data_direction::DMA_TO_DEVICE),
 
     /// The DMA mapping is for data transfer from the device to memory (read).
     ///
     /// The device will write data into the buffer for the CPU to read.
     /// The cache for the corresponding memory region is invalidated before CPU access.
-    FromDevice = Self::const_cast(bindings::dma_data_direction_DMA_FROM_DEVICE),
+    FromDevice = Self::const_cast(bindings::dma_data_direction::DMA_FROM_DEVICE),
 
     /// The DMA mapping is not for data transfer.
     ///
     /// This is primarily for debugging purposes. With this direction, the DMA mapping API
     /// will not perform any cache coherency operations.
-    None = Self::const_cast(bindings::dma_data_direction_DMA_NONE),
+    None = Self::const_cast(bindings::dma_data_direction::DMA_NONE),
 }
 
 impl DataDirection {
@@ -297,7 +297,7 @@ const fn const_cast(val: bindings::dma_data_direction) -> u32 {
         // CAST: The C standard allows compilers to choose different integer types for enums.
         // To safely check the value, we cast it to a wide signed integer type (`i128`)
         // which can hold any standard C integer enum type without truncation.
-        let wide_val = val as i128;
+        let wide_val = val.0 as i128;
 
         // Check if the value is outside the valid range for the target type `u32`.
         // CAST: `u32::MAX` is cast to `i128` to match the type of `wide_val` for the comparison.
@@ -315,11 +315,12 @@ const fn const_cast(val: bindings::dma_data_direction) -> u32 {
 impl From<DataDirection> for bindings::dma_data_direction {
     /// Returns the raw representation of [`enum dma_data_direction`].
     fn from(direction: DataDirection) -> Self {
-        // CAST: `direction as u32` gets the underlying representation of our `#[repr(u32)]` enum.
-        // The subsequent cast to `Self` (the bindgen type) assumes the C enum is compatible
-        // with the enum variants of `DataDirection`, which is a valid assumption given our
-        // compile-time checks.
-        direction as u32 as Self
+        match direction {
+            DataDirection::Bidirectional => Self::DMA_BIDIRECTIONAL,
+            DataDirection::ToDevice => Self::DMA_TO_DEVICE,
+            DataDirection::FromDevice => Self::DMA_FROM_DEVICE,
+            DataDirection::None => Self::DMA_NONE,
+        }
     }
 }
 
Signature · 1 line
2.56.0
maintainer Applied
#5 lore raw

Re: [PATCH 6.18.y 1/2] rust: hrtimer: declare cfi_encoding for hrtimer_restart

In reply to Miguel Ojeda
Quoted 1 line

[PATCH 6.18.y 1/2] rust: hrtimer: declare cfi_encoding for hrtimer_restart

Queued the series for 6.18, thanks.

Signature · 2 lines
Thanks,
Sasha