can: bcm/raw: fix msg_namelen values depending on CAN_REQUIRED_SIZE
Subsystems (2)
Oliver Hartkopp
maintainerPATCH 1/3 can: bcm/raw: fix msg_namelen values depending on CAN_REQUIRED_SIZE
Since commit f5223e9eee65 ("can: extend sockaddr_can to include j1939 members") the sockaddr_can has been extended in size and a new CAN_REQUIRED_SIZE macro has been introduced to calculate the protocol specific needed size.
The ABI for the msg_name and msg_namelen has not been adapted to the new CAN_REQUIRED_SIZE macro for the other CAN protocols which leads to a problem when an existing binary reads the (increased) struct sockaddr_can in msg_name.
--- net/can/bcm.c | 10 ++++++---- net/can/raw.c | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-)
net/can/bcm.c +6 -4
@@ -84,10 +84,12 @@MODULE_DESCRIPTION ("PF_CAN broadcast manager protocol" );MODULE_LICENSE ("Dual BSD/GPL" );MODULE_AUTHOR ("Oliver Hartkopp <[email protected]>" );MODULE_ALIAS ("can-proto-2" ); +#define BCM_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_ifindex) +/* * easy access to the first 64 bit of can(fd)_frame payload. cp->data is * 64 bit aligned so the offset has to be multiples of 8 which is ensured * by the only callers in bcm_rx_cmp_to_index() bcm_rx_handler(). */
@@ -1290,11 +1292,11 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)if (!ifindex && msg->msg_name) {/* no bound device as default => check msg_name */ DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name); -if (msg->msg_namelen <CAN_REQUIRED_SIZE (*addr, can_ifindex)) +if (msg->msg_namelen <BCM_MIN_NAMELEN )return -EINVAL ;if (addr->can_family !=AF_CAN )return -EINVAL ;
@@ -1532,11 +1534,11 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,struct sock *sk = sock->sk;struct bcm_sock *bo =bcm_sk (sk);struct net *net =sock_net (sk);int ret =0 ; -if (len <CAN_REQUIRED_SIZE (*addr, can_ifindex)) +if (len <BCM_MIN_NAMELEN )return -EINVAL ;lock_sock (sk);if (bo->bound) {
@@ -1614,12 +1616,12 @@ static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, }sock_recv_ts_and_drops (msg, sk, skb);if (msg->msg_name) { -__sockaddr_check_size (sizeof (struct sockaddr_can )); - msg->msg_namelen =sizeof (struct sockaddr_can ); +__sockaddr_check_size (BCM_MIN_NAMELEN ); + msg->msg_namelen =BCM_MIN_NAMELEN ;memcpy (msg->msg_name, skb->cb, msg->msg_namelen); }skb_free_datagram (sk, skb);
net/can/raw.c +8 -6
@@ -58,10 +58,12 @@MODULE_DESCRIPTION ("PF_CAN raw protocol" );MODULE_LICENSE ("Dual BSD/GPL" );MODULE_AUTHOR ("Urs Thuermann <[email protected]>" );MODULE_ALIAS ("can-proto-1" ); +#define RAW_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_ifindex) +#define MASK_ALL 0/* A raw socket has a list of can_filters attached to it, each receiving * the CAN frames matching that filter. If the filter list is empty, * no CAN frames will be received by the socket. The default after
@@ -392,11 +394,11 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)struct raw_sock *ro =raw_sk (sk);int ifindex;int err =0 ;int notify_enetdown =0 ; -if (len <CAN_REQUIRED_SIZE (*addr, can_ifindex)) +if (len <RAW_MIN_NAMELEN )return -EINVAL ;if (addr->can_family !=AF_CAN )return -EINVAL ;lock_sock (sk);
@@ -473,15 +475,15 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr,struct raw_sock *ro =raw_sk (sk);if (peer)return -EOPNOTSUPP ; -memset (addr,0 ,sizeof (*addr)); +memset (addr,0 ,RAW_MIN_NAMELEN ); addr->can_family =AF_CAN ; addr->can_ifindex = ro->ifindex; -return sizeof (*addr); +return RAW_MIN_NAMELEN ; }static int raw_setsockopt (struct socket *sock,int level,int optname,sockptr_t optval,unsigned int optlen) {
@@ -737,11 +739,11 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)int err;if (msg->msg_name) { DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name); -if (msg->msg_namelen <CAN_REQUIRED_SIZE (*addr, can_ifindex)) +if (msg->msg_namelen <RAW_MIN_NAMELEN )return -EINVAL ;if (addr->can_family !=AF_CAN )return -EINVAL ;
@@ -830,12 +832,12 @@ static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, }sock_recv_ts_and_drops (msg, sk, skb);if (msg->msg_name) { -__sockaddr_check_size (sizeof (struct sockaddr_can )); - msg->msg_namelen =sizeof (struct sockaddr_can ); +__sockaddr_check_size (RAW_MIN_NAMELEN ); + msg->msg_namelen =RAW_MIN_NAMELEN ;memcpy (msg->msg_name, skb->cb, msg->msg_namelen); }/* assign the flags that have been recorded in raw_rcv() */ msg->msg_flags |= *(raw_flags (skb));
Signature · 1 line
2.30.2
Oliver Hartkopp
maintainerPATCH 2/3 can: isotp: fix msg_namelen values depending on CAN_REQUIRED_SIZE
Since commit f5223e9eee65 ("can: extend sockaddr_can to include j1939 members") the sockaddr_can has been extended in size and a new CAN_REQUIRED_SIZE macro has been introduced to calculate the protocol specific needed size.
The ABI for the msg_name and msg_namelen has not been adapted to the new CAN_REQUIRED_SIZE macro for the other CAN protocols which leads to a problem when an existing binary reads the (increased) struct sockaddr_can in msg_name.
--- net/can/isotp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
net/can/isotp.c +7 -4
@@ -75,10 +75,12 @@MODULE_DESCRIPTION ("PF_CAN isotp 15765-2:2016 protocol" );MODULE_LICENSE ("Dual BSD/GPL" );MODULE_AUTHOR ("Oliver Hartkopp <[email protected]>" );MODULE_ALIAS ("can-proto-6" ); +#define ISOTP_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_addr.tp) +#define SINGLE_MASK (id) (((id) & CAN_EFF_FLAG) ? \ (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \ (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG))/* ISO 15765-2:2016 supports more than 4095 byte per ISO PDU as the FF_DL can
@@ -984,11 +986,12 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, }sock_recv_timestamp (msg, sk, skb);if (msg->msg_name) { - msg->msg_namelen =sizeof (struct sockaddr_can ); +__sockaddr_check_size (ISOTP_MIN_NAMELEN ); + msg->msg_namelen =ISOTP_MIN_NAMELEN ;memcpy (msg->msg_name, skb->cb, msg->msg_namelen); }skb_free_datagram (sk, skb);
@@ -1054,11 +1057,11 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)struct net_device *dev;int err =0 ;int notify_enetdown =0 ;int do_rx_reg =1 ; - if (len < CAN_REQUIRED_SIZE(struct sockaddr_can, can_addr.tp)) +if (len <ISOTP_MIN_NAMELEN )return -EINVAL ;/* do not register frame reception for functional addressing */ if (so->opt.flags &CAN_ISOTP_SF_BROADCAST ) do_rx_reg =0 ;
@@ -1150,17 +1153,17 @@ static int isotp_getname(struct socket *sock, struct sockaddr *uaddr, int peer)struct isotp_sock *so =isotp_sk (sk);if (peer)return -EOPNOTSUPP ; -memset (addr,0 ,sizeof (*addr)); +memset (addr,0 ,ISOTP_MIN_NAMELEN ); addr->can_family =AF_CAN ; addr->can_ifindex = so->ifindex; addr->can_addr.tp.rx_id = so->rxid; addr->can_addr.tp.tx_id = so->txid; -return sizeof (*addr); +return ISOTP_MIN_NAMELEN ; }static int isotp_setsockopt (struct socket *sock,int level,int optname,sockptr_t optval,unsigned int optlen) {
Signature · 1 line
2.30.2
Oliver Hartkopp
maintainerPATCH 3/3 can: uapi: can.h: suppress padding of union inside struct can_frame
In reply to Oliver HartkoppIn commit ea7800565a12 ("can: add optional DLC element to Classical CAN frame structure") the struct can_frame::can_dlc was put into an anonymous union with another u8 variable.
For various reasons some members in struct can_frame and canfd_frame including the first 8 byes of data are expected to have the same memory layout. This is enforced by a BUILD_BUG_ON check in af_can.c.
Since the above mentioned commit this check fails on some compilers (e.g. arm-linux-gnueabi-gcc (GCC) 9.3.0) that apply an alignment on an (anonymous) union (see Link). Rong Chen analyzed the problem and found that the union in struct can_frame takes 4 bytes instead of the expected 1:
| struct can_frame {
| canid_t can_id; /* 0 4 */
| union {
| __u8 len; /* 4 1 */
| __u8 can_dlc; /* 4 1 */
| }; /* 4 4 */
| __u8 __pad; /* 8 1 */
| __u8 __res0; /* 9 1 */
| __u8 len8_dlc; /* 10 1 */
|
| /* XXX 5 bytes hole, try to pack */
|
| __u8 data[8]
| __attribute__((__aligned__(8))); /* 16 8 */
|
| /* size: 24, cachelines: 1, members: 6 */
| /* sum members: 19, holes: 1, sum holes: 5 */
| /* forced alignments: 1, forced holes: 1, sum forced holes: 5 */
| /* last cacheline: 24 bytes */
| } __attribute__((__aligned__(8)));Marking the anonymous union as __attribute__((packed)) fixes the BUILD_BUG_ON problem on these compilers.
Author: Marc Kleine-Budde <[email protected]>
--- include/uapi/linux/can.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/uapi/linux/can.h +1 -1
@@ -111,11 +111,11 @@ struct can_frame {* was previously named can_dlc so we need to carry that * name for legacy support */ __u8 len;__u8 can_dlc;/* deprecated */ - }; + } __attribute__((packed)); /* disable padding by some compilers */__u8 __pad;/* padding */ __u8 __res0;/* reserved / padding */ __u8 len8_dlc;/* optional DLC for 8 byte payload length (9 .. 15) */ __u8 data[CAN_MAX_DLEN] __attribute__((aligned(8))); };
Signature · 1 line
2.30.2