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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.