From: Oliver Hartkopp <socketcan@hartkopp.net>
To: linux-can@vger.kernel.org
Cc: Oliver Hartkopp <socketcan@hartkopp.net>
Subject: [RFC PATCH v3 1/2] can: skb: enforce CANFD_FDF check in can_is_canfd_skb()
Date: Mon, 8 Sep 2025 20:45:11 +0200 [thread overview]
Message-ID: <20250908184512.78449-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 was set in can_send() and is now also set in
raw_check_txframe() to re-use the indroduced can_is_canfd_skb_set_fdf()
function. 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 | 25 +++++++++++++++++++++++--
net/can/af_can.c | 7 +------
net/can/raw.c | 2 +-
3 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 1abc25a8d144..38d036b43280 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -111,12 +111,33 @@ static inline bool can_is_can_skb(const struct sk_buff *skb)
static inline bool can_is_canfd_skb(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 */
- return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN);
+ if (skb->len != CANFD_MTU || cfd->len > CANFD_MAX_DLEN)
+ return false;
+
+ return cfd->flags & CANFD_FDF;
+}
+
+static inline bool can_is_canfd_skb_set_fdf(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.
+ * 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. So we can surely tag it as CAN FD.
+ */
+ if (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN) {
+ /* set CAN FD flag for CAN FD frames by default */
+ cfd->flags |= CANFD_FDF;
+ return true;
+ }
+
+ return false;
}
static inline bool can_is_canxl_skb(const struct sk_buff *skb)
{
const struct canxl_frame *cxl = (struct canxl_frame *)skb->data;
diff --git a/net/can/af_can.c b/net/can/af_can.c
index b2387a46794a..0caf75a9e27f 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -207,17 +207,12 @@ 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)) {
- struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
-
+ } else if (can_is_canfd_skb_set_fdf(skb)) {
skb->protocol = htons(ETH_P_CANFD);
-
- /* set CAN FD flag for CAN FD frames by default */
- cfd->flags |= CANFD_FDF;
} else {
goto inval_skb;
}
/* Make sure the CAN frame can pass the selected CAN netdevice. */
diff --git a/net/can/raw.c b/net/can/raw.c
index 76b867d21def..f48b1f3fd6e8 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_set_fdf(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-08 18:45 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-08 18:45 Oliver Hartkopp [this message]
2025-09-08 18:45 ` [RFC PATCH v3 2/2] can: support XL only content on real CAN XL interfaces Oliver Hartkopp
2025-09-09 6:31 ` Vincent Mailhol
2025-09-09 8:40 ` Oliver Hartkopp
2025-09-09 6:25 ` [RFC PATCH v3 1/2] can: skb: enforce CANFD_FDF check in can_is_canfd_skb() Vincent Mailhol
2025-09-09 8:35 ` Oliver Hartkopp
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=20250908184512.78449-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.