From f51b3b3bb1df6e96357d9631a2fcb94657d409f4 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 17 Mar 2022 14:32:04 +0100 Subject: [PATCH] can: isotp: support MSG_TRUNC flag when reading from socket Upstream commit https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=42bf50a1795a When providing the MSG_TRUNC flag via recvmsg() syscall the return value provides the real length of the packet or datagram, even when it was longer than the passed buffer. Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol") Link: https://github.com/linux-can/can-utils/issues/347#issuecomment-1065932671 Suggested-by: Derek Will Signed-off-by: Oliver Hartkopp --- net/can/isotp.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/net/can/isotp.c b/net/can/isotp.c index ed8fc0a..d125413 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -1042,18 +1042,19 @@ static int isotp_recvmsg(struct kiocb *iocb, struct socket *sock, struct sock *sk = sock->sk; struct sk_buff *skb; struct isotp_sock *so = isotp_sk(sk); - int err = 0; - int noblock; + int noblock = flags & MSG_DONTWAIT; + int ret = 0; - noblock = flags & MSG_DONTWAIT; - flags &= ~MSG_DONTWAIT; + if (flags & ~(MSG_DONTWAIT | MSG_TRUNC)) + return -EINVAL; if (!so->bound) return -EADDRNOTAVAIL; - skb = skb_recv_datagram(sk, flags, noblock, &err); + flags &= ~MSG_DONTWAIT; + skb = skb_recv_datagram(sk, flags, noblock, &ret); if (!skb) - return err; + return ret; if (size < skb->len) msg->msg_flags |= MSG_TRUNC; @@ -1061,14 +1062,12 @@ static int isotp_recvmsg(struct kiocb *iocb, struct socket *sock, size = skb->len; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) - err = memcpy_to_msg(msg, skb->data, size); + ret = memcpy_to_msg(msg, skb->data, size); #else - err = memcpy_toiovec(msg->msg_iov, skb->data, size); + ret = memcpy_toiovec(msg->msg_iov, skb->data, size); #endif - if (err < 0) { - skb_free_datagram(sk, skb); - return err; - } + if (ret < 0) + goto out_err; sock_recv_timestamp(msg, sk, skb); @@ -1077,9 +1076,13 @@ static int isotp_recvmsg(struct kiocb *iocb, struct socket *sock, memcpy(msg->msg_name, skb->cb, msg->msg_namelen); } + /* set length of return value */ + ret = (flags & MSG_TRUNC) ? skb->len : size; + +out_err: skb_free_datagram(sk, skb); - return size; + return ret; } static int isotp_release(struct socket *sock)