From: Oliver Hartkopp <socketcan@hartkopp.net>
To: linux-can@vger.kernel.org
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Subject: [RFC PATCH v5 1/2] can: skb: enforce CANFD_FDF check in can_is_canfd_skb()
Date: Tue, 9 Sep 2025 11:24:32 +0200 [thread overview]
Message-ID: <20250909092433.30546-1-socketcan@hartkopp.net> (raw)
The check in can_is_canfd_skb() is about a length check of skb->len and
the CAN FD data length. As a skb length of CANFD_MTU can potentially be
created with a CAN XL frame with a data length of 60, the length check of
the CAN FD data length is used to detect CAN XL frames via its CANXL_XLF
flag which exceeds valid CAN FD data length values.
To make sure the CANFD_FDF flag can be safely used as a marker for CAN FD
frame skbs the bit is set in can_send() which is used by all PF_CAN
protocols. In the RX path alloc_canfd_skb() sets the CANFD_FDF flag.
The enforced CANFD_FDF check in can_is_canfd_skb() clears up the potential
uncertainty when using the skb->len check with the CANFD_MTU.
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
include/linux/can/skb.h | 19 +++++++++++++++++--
net/can/af_can.c | 2 +-
net/can/raw.c | 2 +-
3 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 1abc25a8d144..09ab4dc83199 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -107,18 +107,33 @@ static inline bool can_is_can_skb(const struct sk_buff *skb)
/* the CAN specific type of skb is identified by its data length */
return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN);
}
-static inline bool can_is_canfd_skb(const struct sk_buff *skb)
+static inline bool can_is_canfd_skb_mtu_len(const struct sk_buff *skb)
{
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
- /* the CAN specific type of skb is identified by its data length */
+ /* The CAN specific type of skb is identified by its data length.
+ * A CAN XL frame skb might have a skb->len of CANFD_MTU but the
+ * skb would have the CANXL_XLF bit set (0x80 = 128) in the
+ * cfd->len field position which would intentionally break the
+ * CAN FD length check here.
+ */
return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN);
}
+static inline bool can_is_canfd_skb(const struct sk_buff *skb)
+{
+ struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
+
+ if (!can_is_canfd_skb_mtu_len(skb))
+ return false;
+
+ return cfd->flags & CANFD_FDF;
+}
+
static inline bool can_is_canxl_skb(const struct sk_buff *skb)
{
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
if (skb->len < CANXL_HDR_SIZE + CANXL_MIN_DLEN || skb->len > CANXL_MTU)
diff --git a/net/can/af_can.c b/net/can/af_can.c
index b2387a46794a..7fd2ed510440 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -207,11 +207,11 @@ int can_send(struct sk_buff *skb, int loop)
if (can_is_canxl_skb(skb)) {
skb->protocol = htons(ETH_P_CANXL);
} else if (can_is_can_skb(skb)) {
skb->protocol = htons(ETH_P_CAN);
- } else if (can_is_canfd_skb(skb)) {
+ } else if (can_is_canfd_skb_mtu_len(skb)) {
struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
skb->protocol = htons(ETH_P_CANFD);
/* set CAN FD flag for CAN FD frames by default */
diff --git a/net/can/raw.c b/net/can/raw.c
index 76b867d21def..e5e3952b0e09 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -886,11 +886,11 @@ static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb,
/* Classical CAN -> no checks for flags and device capabilities */
if (can_is_can_skb(skb))
return CAN_MTU;
/* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */
- if (ro->fd_frames && can_is_canfd_skb(skb) &&
+ if (ro->fd_frames && can_is_canfd_skb_mtu_len(skb) &&
(mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu)))
return CANFD_MTU;
/* CAN XL -> needs to be enabled and a CAN XL device */
if (ro->xl_frames && can_is_canxl_skb(skb) &&
--
2.47.3
next reply other threads:[~2025-09-09 9:27 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-09 9:24 Oliver Hartkopp [this message]
2025-09-09 9:24 ` [RFC PATCH v5 2/2] can: reject CAN FD content when disabled on CAN XL interfaces Oliver Hartkopp
2025-09-09 16:36 ` Oliver Hartkopp
2025-09-10 5:13 ` Vincent Mailhol
2025-09-10 7:27 ` Oliver Hartkopp
2025-09-10 7:40 ` Vincent Mailhol
2025-09-10 8:48 ` Oliver Hartkopp
2025-09-10 16:19 ` Vincent Mailhol
2025-09-10 20:12 ` Oliver Hartkopp
2025-09-15 10:55 ` Vincent Mailhol
2025-09-15 13:59 ` Vincent Mailhol
2025-09-15 18:08 ` Oliver Hartkopp
2025-09-15 18:54 ` Vincent Mailhol
2025-09-16 9:14 ` Oliver Hartkopp
2025-09-16 13:17 ` Vincent Mailhol
2025-09-17 21:29 ` Oliver Hartkopp
2025-09-18 9:18 ` Vincent Mailhol
2025-09-20 17:38 ` Oliver Hartkopp
2025-09-20 17:57 ` Vincent Mailhol
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=20250909092433.30546-1-socketcan@hartkopp.net \
--to=socketcan@hartkopp.net \
--cc=linux-can@vger.kernel.org \
/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