Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dcda138d authored by Sjur Braendeland's avatar Sjur Braendeland Committed by David S. Miller
Browse files

caif: Bugfix - use MSG_TRUNC in receive



Fixed handling when skb don't fit in user buffer,
instead of returning -EMSGSIZE, the buffer is truncated (just
as unix seqpakcet does).

Signed-off-by: default avatarSjur Braendeland <sjur.brandeland@stericsson.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a9a8f107
Loading
Loading
Loading
Loading
+18 −29
Original line number Diff line number Diff line
@@ -292,53 +292,42 @@ static void caif_check_flow_release(struct sock *sk)
			caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_ON_REQ);
	}
}

/*
 * Copied from sock.c:sock_queue_rcv_skb(), and added check that user buffer
 * has sufficient size.
 * Copied from unix_dgram_recvmsg, but removed credit checks,
 * changed locking, address handling and added MSG_TRUNC.
 */

static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock,
				struct msghdr *m, size_t buf_len, int flags)
				struct msghdr *m, size_t len, int flags)

{
	struct sock *sk = sock->sk;
	struct sk_buff *skb;
	int ret = 0;
	int len;
	int ret;
	int copylen;

	if (unlikely(!buf_len))
		return -EINVAL;
	ret = -EOPNOTSUPP;
	if (m->msg_flags&MSG_OOB)
		goto read_error;

	skb = skb_recv_datagram(sk, flags, 0 , &ret);
	if (!skb)
		goto read_error;

	len = skb->len;

	if (skb && skb->len > buf_len && !(flags & MSG_PEEK)) {
		len = buf_len;
		/*
		 * Push skb back on receive queue if buffer too small.
		 * This has a built-in race where multi-threaded receive
		 * may get packet in wrong order, but multiple read does
		 * not really guarantee ordered delivery anyway.
		 * Let's optimize for speed without taking locks.
		 */

		skb_queue_head(&sk->sk_receive_queue, skb);
		ret = -EMSGSIZE;
		goto read_error;
	copylen = skb->len;
	if (len < copylen) {
		m->msg_flags |= MSG_TRUNC;
		copylen = len;
	}

	ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, len);
	ret = skb_copy_datagram_iovec(skb, 0, m->msg_iov, copylen);
	if (ret)
		goto read_error;
		goto out_free;

	ret = (flags & MSG_TRUNC) ? skb->len : copylen;
out_free:
	skb_free_datagram(sk, skb);

	caif_check_flow_release(sk);

	return len;
	return ret;

read_error:
	return ret;