diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 30 |
1 files changed, 25 insertions, 5 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 85d3bb7490aa..3d9481de031f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -530,6 +530,16 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, | |||
530 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, | 530 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, |
531 | struct msghdr *, size_t, int); | 531 | struct msghdr *, size_t, int); |
532 | 532 | ||
533 | static void unix_set_peek_off(struct sock *sk, int val) | ||
534 | { | ||
535 | struct unix_sock *u = unix_sk(sk); | ||
536 | |||
537 | mutex_lock(&u->readlock); | ||
538 | sk->sk_peek_off = val; | ||
539 | mutex_unlock(&u->readlock); | ||
540 | } | ||
541 | |||
542 | |||
533 | static const struct proto_ops unix_stream_ops = { | 543 | static const struct proto_ops unix_stream_ops = { |
534 | .family = PF_UNIX, | 544 | .family = PF_UNIX, |
535 | .owner = THIS_MODULE, | 545 | .owner = THIS_MODULE, |
@@ -570,6 +580,7 @@ static const struct proto_ops unix_dgram_ops = { | |||
570 | .recvmsg = unix_dgram_recvmsg, | 580 | .recvmsg = unix_dgram_recvmsg, |
571 | .mmap = sock_no_mmap, | 581 | .mmap = sock_no_mmap, |
572 | .sendpage = sock_no_sendpage, | 582 | .sendpage = sock_no_sendpage, |
583 | .set_peek_off = unix_set_peek_off, | ||
573 | }; | 584 | }; |
574 | 585 | ||
575 | static const struct proto_ops unix_seqpacket_ops = { | 586 | static const struct proto_ops unix_seqpacket_ops = { |
@@ -591,6 +602,7 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
591 | .recvmsg = unix_seqpacket_recvmsg, | 602 | .recvmsg = unix_seqpacket_recvmsg, |
592 | .mmap = sock_no_mmap, | 603 | .mmap = sock_no_mmap, |
593 | .sendpage = sock_no_sendpage, | 604 | .sendpage = sock_no_sendpage, |
605 | .set_peek_off = unix_set_peek_off, | ||
594 | }; | 606 | }; |
595 | 607 | ||
596 | static struct proto unix_proto = { | 608 | static struct proto unix_proto = { |
@@ -1756,6 +1768,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1756 | int noblock = flags & MSG_DONTWAIT; | 1768 | int noblock = flags & MSG_DONTWAIT; |
1757 | struct sk_buff *skb; | 1769 | struct sk_buff *skb; |
1758 | int err; | 1770 | int err; |
1771 | int peeked, skip; | ||
1759 | 1772 | ||
1760 | err = -EOPNOTSUPP; | 1773 | err = -EOPNOTSUPP; |
1761 | if (flags&MSG_OOB) | 1774 | if (flags&MSG_OOB) |
@@ -1769,7 +1782,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1769 | goto out; | 1782 | goto out; |
1770 | } | 1783 | } |
1771 | 1784 | ||
1772 | skb = skb_recv_datagram(sk, flags, noblock, &err); | 1785 | skip = sk_peek_offset(sk, flags); |
1786 | |||
1787 | skb = __skb_recv_datagram(sk, flags, &peeked, &skip, &err); | ||
1773 | if (!skb) { | 1788 | if (!skb) { |
1774 | unix_state_lock(sk); | 1789 | unix_state_lock(sk); |
1775 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ | 1790 | /* Signal EOF on disconnected non-blocking SEQPACKET socket. */ |
@@ -1786,12 +1801,12 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1786 | if (msg->msg_name) | 1801 | if (msg->msg_name) |
1787 | unix_copy_addr(msg, skb->sk); | 1802 | unix_copy_addr(msg, skb->sk); |
1788 | 1803 | ||
1789 | if (size > skb->len) | 1804 | if (size > skb->len - skip) |
1790 | size = skb->len; | 1805 | size = skb->len - skip; |
1791 | else if (size < skb->len) | 1806 | else if (size < skb->len - skip) |
1792 | msg->msg_flags |= MSG_TRUNC; | 1807 | msg->msg_flags |= MSG_TRUNC; |
1793 | 1808 | ||
1794 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, size); | 1809 | err = skb_copy_datagram_iovec(skb, skip, msg->msg_iov, size); |
1795 | if (err) | 1810 | if (err) |
1796 | goto out_free; | 1811 | goto out_free; |
1797 | 1812 | ||
@@ -1808,6 +1823,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1808 | if (!(flags & MSG_PEEK)) { | 1823 | if (!(flags & MSG_PEEK)) { |
1809 | if (UNIXCB(skb).fp) | 1824 | if (UNIXCB(skb).fp) |
1810 | unix_detach_fds(siocb->scm, skb); | 1825 | unix_detach_fds(siocb->scm, skb); |
1826 | |||
1827 | sk_peek_offset_bwd(sk, skb->len); | ||
1811 | } else { | 1828 | } else { |
1812 | /* It is questionable: on PEEK we could: | 1829 | /* It is questionable: on PEEK we could: |
1813 | - do not return fds - good, but too simple 8) | 1830 | - do not return fds - good, but too simple 8) |
@@ -1821,6 +1838,9 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1821 | clearly however! | 1838 | clearly however! |
1822 | 1839 | ||
1823 | */ | 1840 | */ |
1841 | |||
1842 | sk_peek_offset_fwd(sk, size); | ||
1843 | |||
1824 | if (UNIXCB(skb).fp) | 1844 | if (UNIXCB(skb).fp) |
1825 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); | 1845 | siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); |
1826 | } | 1846 | } |