Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: raw: instantly reject disabled 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 now performed on CAN_RAW sockets to give an instant feedback
to the user when writing unsupported CAN frames to the interface or when
the CAN interface is in read-only mode.

Fixes: 1a620a723853 ("can: raw: instantly reject unsupported CAN frames")
Cc: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Vincent Mailhol <mailhol@kernel.org>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Link: https://patch.msgid.link/20260109144135.8495-4-socketcan@hartkopp.net
[mkl: fix dev reference leak]
Link: https://lore.kernel.org/all/0636c732-2e71-4633-8005-dfa85e1da445@hartkopp.net
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Oliver Hartkopp and committed by
Marc Kleine-Budde
faba5860 166e8732

+16 -9
+16 -9
net/can/raw.c
··· 49 49 #include <linux/if_arp.h> 50 50 #include <linux/skbuff.h> 51 51 #include <linux/can.h> 52 + #include <linux/can/can-ml.h> 52 53 #include <linux/can/core.h> 53 - #include <linux/can/dev.h> /* for can_is_canxl_dev_mtu() */ 54 54 #include <linux/can/skb.h> 55 55 #include <linux/can/raw.h> 56 56 #include <net/sock.h> ··· 892 892 } 893 893 } 894 894 895 - static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb, int mtu) 895 + static unsigned int raw_check_txframe(struct raw_sock *ro, struct sk_buff *skb, 896 + struct net_device *dev) 896 897 { 897 - /* Classical CAN -> no checks for flags and device capabilities */ 898 - if (can_is_can_skb(skb)) 898 + /* Classical CAN */ 899 + if (can_is_can_skb(skb) && can_cap_enabled(dev, CAN_CAP_CC)) 899 900 return CAN_MTU; 900 901 901 - /* CAN FD -> needs to be enabled and a CAN FD or CAN XL device */ 902 + /* CAN FD */ 902 903 if (ro->fd_frames && can_is_canfd_skb(skb) && 903 - (mtu == CANFD_MTU || can_is_canxl_dev_mtu(mtu))) 904 + can_cap_enabled(dev, CAN_CAP_FD)) 904 905 return CANFD_MTU; 905 906 906 - /* CAN XL -> needs to be enabled and a CAN XL device */ 907 + /* CAN XL */ 907 908 if (ro->xl_frames && can_is_canxl_skb(skb) && 908 - can_is_canxl_dev_mtu(mtu)) 909 + can_cap_enabled(dev, CAN_CAP_XL)) 909 910 return CANXL_MTU; 910 911 911 912 return 0; ··· 945 944 if (!dev) 946 945 return -ENXIO; 947 946 947 + /* no sending on a CAN device in read-only mode */ 948 + if (can_cap_enabled(dev, CAN_CAP_RO)) { 949 + err = -EACCES; 950 + goto put_dev; 951 + } 952 + 948 953 skb = sock_alloc_send_skb(sk, size + sizeof(struct can_skb_priv), 949 954 msg->msg_flags & MSG_DONTWAIT, &err); 950 955 if (!skb) ··· 968 961 err = -EINVAL; 969 962 970 963 /* check for valid CAN (CC/FD/XL) frame content */ 971 - txmtu = raw_check_txframe(ro, skb, READ_ONCE(dev->mtu)); 964 + txmtu = raw_check_txframe(ro, skb, dev); 972 965 if (!txmtu) 973 966 goto free_skb; 974 967