forked from luck/tmp_suning_uos_patched
Bluetooth: Fix hci_sock_recvmsg return value
If recvmsg is called with a destination buffer that is too small to receive the contents of skb in its entirety, the return value from recvmsg was inconsistent with common SOCK_SEQPACKET or SOCK_DGRAM semantics. If destination buffer provided by userspace is too small (e.g. len < copied), then MSG_TRUNC flag is set and copied is returned. Instead, it should return the length of the message, which is consistent with how other datagram based sockets act. Quoting 'man recv': "All three calls return the length of the message on successful comple‐ tion. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depending on the type of socket the message is received from." and "MSG_TRUNC (since Linux 2.2) For raw (AF_PACKET), Internet datagram (since Linux 2.4.27/2.6.8), netlink (since Linux 2.6.22), and UNIX datagram (since Linux 3.4) sockets: return the real length of the packet or datagram, even when it was longer than the passed buffer." Signed-off-by: Denis Kenzior <denkenz@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
b5f34f9420
commit
83871f8ccd
|
@ -1048,6 +1048,7 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
struct sock *sk = sock->sk;
|
||||
struct sk_buff *skb;
|
||||
int copied, err;
|
||||
unsigned int skblen;
|
||||
|
||||
BT_DBG("sock %p, sk %p", sock, sk);
|
||||
|
||||
|
@ -1064,6 +1065,7 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
if (!skb)
|
||||
return err;
|
||||
|
||||
skblen = skb->len;
|
||||
copied = skb->len;
|
||||
if (len < copied) {
|
||||
msg->msg_flags |= MSG_TRUNC;
|
||||
|
@ -1089,6 +1091,9 @@ static int hci_sock_recvmsg(struct socket *sock, struct msghdr *msg,
|
|||
|
||||
skb_free_datagram(sk, skb);
|
||||
|
||||
if (msg->msg_flags & MSG_TRUNC)
|
||||
copied = skblen;
|
||||
|
||||
return err ? : copied;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user