lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <0c98b1c4-3975-4bf5-9049-9d7f10d22a6d@hartkopp.net>
Date: Sat, 29 Nov 2025 18:04:13 +0100
From: Oliver Hartkopp <socketcan@...tkopp.net>
To: Prithvi Tambewagh <activprithvi@...il.com>, mkl@...gutronix.de
Cc: linux-can@...r.kernel.org, linux-kernel@...r.kernel.org,
 syzkaller-bugs@...glegroups.com
Subject: Re: Question about to KMSAN: uninit-value in can_receive

Hello Prithvi,

thanks for picking up this topic!

I had your mail in my open tabs and I was reading some code several 
times without having a really good idea how to continue.

On 17.11.25 18:30, Prithvi Tambewagh wrote:

> The call trace suggests that the bug appears to be due to effect of change
> in headroom by pskb_header_expand(). The new headroom remains uninitialized
> and when can_receive tries accessing can_skb_prv(skb)->skbcnt, indirectly
> skb->head is accessed which causes KMSAN uninitialized value read bug.

Yes.

If you take a look at the KMSAN message:

https://lore.kernel.org/linux-can/68bae75b.050a0220.192772.0190.GAE@google.com/T/#m0372e223746b9da19cbf39348ab1cda52a5cfadc

I wonder why anybody is obviously fiddling with the with the skb->head here.

When initially creating skb for the CAN subsystem we use 
can_skb_reserve() which does a

skb_reserve(skb, sizeof(struct can_skb_priv));

so that we get some headroom for struct can_skb_priv.

Then we access this struct by referencing skb->head:

static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb)
{
	return (struct can_skb_priv *)(skb->head);
}

If anybody is now extending the headroom skb->head will likely not 
pointing to struct can_skb_priv anymore, right?

> To fix this bug, I think we can call can_dropped_invalid_skb() in can_rcv()
> just before calling can_receive(). Further, we can add a condition for these
> sk_buff with uninitialized headroom to initialize the skb, the way it had
> been done in the patch for an earlier packet injection case in a similar
> KMSAN bug:
> https://lore.kernel.org/linux-can/20191207183418.28868-1-socketcan@hartkopp.net/

No. This is definitely a wrong approach. You can not wildly poke values 
behind skb->head, when the correctly initialized struct can_skb_priv 
just sits somewhere else.

In opposite to the case in your referenced patch we do not get a skb 
from PF_PACKET but we handle a skb that has been properly created in 
isotp_sendmsg(). Including can_skb_reserve() and an initialized struct 
can_skb_priv.

> However, I am not getting on what basis can I filter the sk_buff so that
> only those with an uninitialized headroom will be initialized via this path.
> Is this the correct approach?

No.

When we are creating CAN skbs with [can_]skb_reserve(), the struct 
can_skb_priv is located directly "before" the struct can_frame which is 
at skb->data.

I'm therefore currently thinking in the direction of using skb->data 
instead of skb->head as reference to struct can_skb_priv:

diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 1abc25a8d144..8822d7d2e3df 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -60,11 +60,11 @@ struct can_skb_priv {
         struct can_frame cf[];
  };

  static inline struct can_skb_priv *can_skb_prv(struct sk_buff *skb)
  {
-       return (struct can_skb_priv *)(skb->head);
+       return (struct can_skb_priv *)(skb->data - sizeof(struct 
can_skb_priv));
  }

  static inline void can_skb_reserve(struct sk_buff *skb)
  {
         skb_reserve(skb, sizeof(struct can_skb_priv));

I have not checked what effect this might have to this patch

https://lore.kernel.org/linux-can/20191207183418.28868-1-socketcan@hartkopp.net/

when we initialize struct can_skb_priv inside skbs we did not create in 
the CAN subsystem. The difference would be that we access struct 
can_skb_priv via skb->data and not via skb->head. The effect to the 
system should be similar.

What do you think about such approach?

Best regards,
Oliver


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ