From 42bf50a1795a1854d48717b7361dbdbce496b16b Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Wed, 16 Mar 2022 17:42:58 +0100 Subject: can: isotp: support MSG_TRUNC flag when reading from socket 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 Link: https://lore.kernel.org/all/20220316164258.54155-3-socketcan@hartkopp.net Suggested-by: Derek Will Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- net/can/isotp.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) (limited to 'net/can') diff --git a/net/can/isotp.c b/net/can/isotp.c index 6b6c82206c30..f6f8ba1f816d 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -1047,29 +1047,28 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, 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; else size = skb->len; - err = memcpy_to_msg(msg, skb->data, size); - if (err < 0) { - skb_free_datagram(sk, skb); - return err; - } + ret = memcpy_to_msg(msg, skb->data, size); + if (ret < 0) + goto out_err; sock_recv_timestamp(msg, sk, skb); @@ -1079,9 +1078,13 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, 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) -- cgit v1.2.3