aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-09-29 13:47:08 -0700
committerDavid S. Miller <davem@davemloft.net>2015-09-29 13:47:08 -0700
commit3504bb639ec793c181de6e33a205fc8ca6cf32bf (patch)
treeba19241592c69f4336f1429cd9d2a1933722f015 /net/unix/af_unix.c
parentnet: sctp: Don't use 64 kilobyte lookup table for four elements (diff)
parentaf_unix: return data from multiple SKBs on recv() with MSG_PEEK flag (diff)
downloadwireguard-linux-3504bb639ec793c181de6e33a205fc8ca6cf32bf.tar.xz
wireguard-linux-3504bb639ec793c181de6e33a205fc8ca6cf32bf.zip
Merge branch 'af_unix_MSG_PEEK'
Aaron Conole says: ==================== af_unix: return data from multiple SKBs on recv() with MSG_PEEK flag This patch set implements a bugfix for kernel.org bugzilla #12323, allowing MSG_PEEK to return all queued data on the unix domain socket, not just the data contained in a single SKB. This is the v3 version of this patch, which includes a suggested modification by Eric Dumazet to convert the unix_sk() conversion macro to a static inline function. These patches are independent and can be applied separately. This set was tested over a 24-hour period, utilizing a loop continually executing the bugzilla issue attached python code. It was instrumented with a pr_err_once() ([ 13.798683] unix: went there at least one time). v2->v3: - Added Eric Dumazet's suggestion for #define to static inline - Fixed an issue calling unix_state_lock() with an invalid argument v3->v4: - Eliminated an XXX comment - Changed from goto unlock to explicit unix_state_unlock() and break ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 03ee4d359f6a..ef31b40ad550 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2179,8 +2179,21 @@ unlock:
if (UNIXCB(skb).fp)
scm.fp = scm_fp_dup(UNIXCB(skb).fp);
- sk_peek_offset_fwd(sk, chunk);
+ if (skip) {
+ sk_peek_offset_fwd(sk, chunk);
+ skip -= chunk;
+ }
+ if (UNIXCB(skb).fp)
+ break;
+
+ last = skb;
+ last_len = skb->len;
+ unix_state_lock(sk);
+ skb = skb_peek_next(skb, &sk->sk_receive_queue);
+ if (skb)
+ goto again;
+ unix_state_unlock(sk);
break;
}
} while (size);