]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.4.77/net-unix-allow-set_peek_off-to-fail.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.4.77 / net-unix-allow-set_peek_off-to-fail.patch
1 From foo@baz Mon Jan 13 09:28:30 PST 2014
2 From: Sasha Levin <sasha.levin@oracle.com>
3 Date: Sat, 7 Dec 2013 17:26:27 -0500
4 Subject: net: unix: allow set_peek_off to fail
5
6 From: Sasha Levin <sasha.levin@oracle.com>
7
8 [ Upstream commit 12663bfc97c8b3fdb292428105dd92d563164050 ]
9
10 unix_dgram_recvmsg() will hold the readlock of the socket until recv
11 is complete.
12
13 In the same time, we may try to setsockopt(SO_PEEK_OFF) which will hang until
14 unix_dgram_recvmsg() will complete (which can take a while) without allowing
15 us to break out of it, triggering a hung task spew.
16
17 Instead, allow set_peek_off to fail, this way userspace will not hang.
18
19 Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
20 Acked-by: Pavel Emelyanov <xemul@parallels.com>
21 Signed-off-by: David S. Miller <davem@davemloft.net>
22 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
23 ---
24 include/linux/net.h | 2 +-
25 net/core/sock.c | 2 +-
26 net/unix/af_unix.c | 8 ++++++--
27 3 files changed, 8 insertions(+), 4 deletions(-)
28
29 --- a/include/linux/net.h
30 +++ b/include/linux/net.h
31 @@ -215,7 +215,7 @@ struct proto_ops {
32 int offset, size_t size, int flags);
33 ssize_t (*splice_read)(struct socket *sock, loff_t *ppos,
34 struct pipe_inode_info *pipe, size_t len, unsigned int flags);
35 - void (*set_peek_off)(struct sock *sk, int val);
36 + int (*set_peek_off)(struct sock *sk, int val);
37 };
38
39 #define DECLARE_SOCKADDR(type, dst, src) \
40 --- a/net/core/sock.c
41 +++ b/net/core/sock.c
42 @@ -795,7 +795,7 @@ set_rcvbuf:
43
44 case SO_PEEK_OFF:
45 if (sock->ops->set_peek_off)
46 - sock->ops->set_peek_off(sk, val);
47 + ret = sock->ops->set_peek_off(sk, val);
48 else
49 ret = -EOPNOTSUPP;
50 break;
51 --- a/net/unix/af_unix.c
52 +++ b/net/unix/af_unix.c
53 @@ -524,13 +524,17 @@ static int unix_seqpacket_sendmsg(struct
54 static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
55 struct msghdr *, size_t, int);
56
57 -static void unix_set_peek_off(struct sock *sk, int val)
58 +static int unix_set_peek_off(struct sock *sk, int val)
59 {
60 struct unix_sock *u = unix_sk(sk);
61
62 - mutex_lock(&u->readlock);
63 + if (mutex_lock_interruptible(&u->readlock))
64 + return -EINTR;
65 +
66 sk->sk_peek_off = val;
67 mutex_unlock(&u->readlock);
68 +
69 + return 0;
70 }
71
72