mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] rust: net: netlink: validate attribute length before casting to `c_int`
@ 2026-09-15 16:40 Sagar Taunk
  2026-09-17  9:35 ` Alice Ryhl
  2026-09-17 17:38 ` Alexandre Courbot
  0 siblings, 2 replies; 5+ messages in thread
From: Sagar Taunk @ 2026-09-15 16:40 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, Daniel Almeida, Tamir Duberstein,
	Alexandre Courbot, Onur Özkan, netdev, rust-for-linux,
	linux-kernel
  Cc: Sagar Taunk

`put()` trusted an unchecked `as` cast from `usize` to `c_int`.
When the length exceeds `i32::MAX` that cast wraps around to a
negative value.

This ultimately resulted in a kernel panic when the reinterpreted
value via `__nla_reserve()` and `skb_put()` became enormous.

Validate payload and header both fit together in a `u16`, rejecting
any payload that wouldn't leave room for `NLA_HDRLEN`.

Signed-off-by: Sagar Taunk <sagartaunk@proton.me>
---
Changes Since V1: 
Tried to make the diff smaller as pointed out by Alexandre Courbot.
Moreover, as pointed out by Sashiko,`nlattr` is stored in a 16-bit 
field which houses both the header and the payload, so make the check 
verify that there is enough space left for the header to fit with the 
payload. 

 rust/kernel/net/netlink.rs | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/rust/kernel/net/netlink.rs b/rust/kernel/net/netlink.rs
index a2f4bd171dcf..667667346f96 100644
--- a/rust/kernel/net/netlink.rs
+++ b/rust/kernel/net/netlink.rs
@@ -90,9 +90,14 @@ fn put<T>(&mut self, attrtype: c_int, value: &T) -> Result
     where
         T: ?Sized + IntoBytes + Immutable,
     {
+        let max_payload_len = u16::MAX as usize - size_of::<bindings::nlattr>();
+
         let skb = self.skb.skb.as_ptr();
         let len = size_of_val(value);
         let ptr = core::ptr::from_ref(value).cast::<c_void>();
+        if len > max_payload_len {
+            return Err(EMSGSIZE);
+        }
         // SAFETY: `skb` is valid by `NetlinkSkBuff` type invariants, and the provided value is
         // readable and initialized for its `size_of` bytes.
         to_result(unsafe { bindings::nla_put(skb, attrtype, len as c_int, ptr) })
-- 
2.55.0



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-09-17 17:39 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-15 16:40 [PATCH v2] rust: net: netlink: validate attribute length before casting to `c_int` Sagar Taunk
2026-09-17  9:35 ` Alice Ryhl
2026-09-17 13:45   ` Sagar Taunk
2026-09-17 16:23     ` Alice Ryhl
2026-09-17 17:38 ` Alexandre Courbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®