Skip to content

Commit 1a620a7

Browse files
hartkoppmarckleinebudde
authored andcommitted
can: raw: instantly reject unsupported CAN frames
For real CAN interfaces the CAN_CTRLMODE_FD and CAN_CTRLMODE_XL control modes indicate whether an interface can handle those CAN FD/XL frames. In the case a CAN XL interface is configured in CANXL-only mode with disabled error-signalling neither CAN CC nor CAN FD frames can be sent. The checks are performed on CAN_RAW sockets to give an instant feedback to the user when writing unsupported CAN frames to the interface. Signed-off-by: Oliver Hartkopp <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
1 parent 816cf43 commit 1a620a7

File tree

1 file changed

+46
-8
lines changed

1 file changed

+46
-8
lines changed

net/can/raw.c

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -892,20 +892,58 @@ static void raw_put_canxl_vcid(struct raw_sock *ro, struct sk_buff *skb)
892892
}
893893
}
894894

895-
static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb, int mtu)
895+
static inline bool raw_dev_cc_enabled(struct net_device *dev,
896+
struct can_priv *priv)
896897
{
897-
/* Classical CAN -> no checks for flags and device capabilities */
898-
if (can_is_can_skb(skb))
898+
/* The CANXL-only mode disables error-signalling on the CAN bus
899+
* which is needed to send CAN CC/FD frames
900+
*/
901+
if (priv)
902+
return !can_dev_in_xl_only_mode(priv);
903+
904+
/* virtual CAN interfaces always support CAN CC */
905+
return true;
906+
}
907+
908+
static inline bool raw_dev_fd_enabled(struct net_device *dev,
909+
struct can_priv *priv)
910+
{
911+
/* check FD ctrlmode on real CAN interfaces */
912+
if (priv)
913+
return (priv->ctrlmode & CAN_CTRLMODE_FD);
914+
915+
/* check MTU for virtual CAN FD interfaces */
916+
return (READ_ONCE(dev->mtu) >= CANFD_MTU);
917+
}
918+
919+
static inline bool raw_dev_xl_enabled(struct net_device *dev,
920+
struct can_priv *priv)
921+
{
922+
/* check XL ctrlmode on real CAN interfaces */
923+
if (priv)
924+
return (priv->ctrlmode & CAN_CTRLMODE_XL);
925+
926+
/* check MTU for virtual CAN XL interfaces */
927+
return can_is_canxl_dev_mtu(READ_ONCE(dev->mtu));
928+
}
929+
930+
static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb,
931+
struct net_device *dev)
932+
{
933+
struct can_priv *priv = safe_candev_priv(dev);
934+
935+
/* Classical CAN */
936+
if (can_is_can_skb(skb) && raw_dev_cc_enabled(dev, priv))
899937
return CAN_MTU;
900938

901-
/* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */
939+
/* CAN FD */
902940
if (ro->fd_frames && can_is_canfd_skb(skb) &&
903-
(mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu)))
941+
raw_dev_fd_enabled(dev, priv))
904942
return CANFD_MTU;
905943

906-
/* CAN XL -> needs to be enabled and a CAN XL device */
944+
/* CAN XL */
907945
if (ro->xl_frames && can_is_canxl_skb(skb) &&
908-
can_is_canxl_dev_mtu(mtu))
946+
raw_dev_xl_enabled(dev, priv))
909947
return CANXL_MTU;
910948

911949
return 0;
@@ -961,7 +999,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
961999
err = -EINVAL;
9621000

9631001
/* check for valid CAN (CC/FD/XL) frame content */
964-
txmtu = raw_check_txframe(ro, skb, READ_ONCE(dev->mtu));
1002+
txmtu = raw_check_txframe(ro, skb, dev);
9651003
if (!txmtu)
9661004
goto free_skb;
9671005

0 commit comments

Comments
 (0)