aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 3d9481de031..0be4d24f6ae 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -559,6 +559,7 @@ static const struct proto_ops unix_stream_ops = {
559 .recvmsg = unix_stream_recvmsg, 559 .recvmsg = unix_stream_recvmsg,
560 .mmap = sock_no_mmap, 560 .mmap = sock_no_mmap,
561 .sendpage = sock_no_sendpage, 561 .sendpage = sock_no_sendpage,
562 .set_peek_off = unix_set_peek_off,
562}; 563};
563 564
564static const struct proto_ops unix_dgram_ops = { 565static const struct proto_ops unix_dgram_ops = {
@@ -1904,6 +1905,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1904 int target; 1905 int target;
1905 int err = 0; 1906 int err = 0;
1906 long timeo; 1907 long timeo;
1908 int skip;
1907 1909
1908 err = -EINVAL; 1910 err = -EINVAL;
1909 if (sk->sk_state != TCP_ESTABLISHED) 1911 if (sk->sk_state != TCP_ESTABLISHED)
@@ -1933,12 +1935,15 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1933 goto out; 1935 goto out;
1934 } 1936 }
1935 1937
1938 skip = sk_peek_offset(sk, flags);
1939
1936 do { 1940 do {
1937 int chunk; 1941 int chunk;
1938 struct sk_buff *skb; 1942 struct sk_buff *skb;
1939 1943
1940 unix_state_lock(sk); 1944 unix_state_lock(sk);
1941 skb = skb_peek(&sk->sk_receive_queue); 1945 skb = skb_peek(&sk->sk_receive_queue);
1946again:
1942 if (skb == NULL) { 1947 if (skb == NULL) {
1943 unix_sk(sk)->recursion_level = 0; 1948 unix_sk(sk)->recursion_level = 0;
1944 if (copied >= target) 1949 if (copied >= target)
@@ -1973,6 +1978,13 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1973 unix_state_unlock(sk); 1978 unix_state_unlock(sk);
1974 break; 1979 break;
1975 } 1980 }
1981
1982 if (skip >= skb->len) {
1983 skip -= skb->len;
1984 skb = skb_peek_next(skb, &sk->sk_receive_queue);
1985 goto again;
1986 }
1987
1976 unix_state_unlock(sk); 1988 unix_state_unlock(sk);
1977 1989
1978 if (check_creds) { 1990 if (check_creds) {
@@ -1992,8 +2004,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
1992 sunaddr = NULL; 2004 sunaddr = NULL;
1993 } 2005 }
1994 2006
1995 chunk = min_t(unsigned int, skb->len, size); 2007 chunk = min_t(unsigned int, skb->len - skip, size);
1996 if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { 2008 if (memcpy_toiovec(msg->msg_iov, skb->data + skip, chunk)) {
1997 if (copied == 0) 2009 if (copied == 0)
1998 copied = -EFAULT; 2010 copied = -EFAULT;
1999 break; 2011 break;
@@ -2005,6 +2017,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
2005 if (!(flags & MSG_PEEK)) { 2017 if (!(flags & MSG_PEEK)) {
2006 skb_pull(skb, chunk); 2018 skb_pull(skb, chunk);
2007 2019
2020 sk_peek_offset_bwd(sk, chunk);
2021
2008 if (UNIXCB(skb).fp) 2022 if (UNIXCB(skb).fp)
2009 unix_detach_fds(siocb->scm, skb); 2023 unix_detach_fds(siocb->scm, skb);
2010 2024
@@ -2022,6 +2036,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
2022 if (UNIXCB(skb).fp) 2036 if (UNIXCB(skb).fp)
2023 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); 2037 siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
2024 2038
2039 sk_peek_offset_fwd(sk, chunk);
2040
2025 break; 2041 break;
2026 } 2042 }
2027 } while (size); 2043 } while (size);