]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.4.77/net-unix-allow-set_peek_off-to-fail.patch
Linux 4.19.31
[thirdparty/kernel/stable-queue.git] / releases / 3.4.77 / net-unix-allow-set_peek_off-to-fail.patch
CommitLineData
963efa89
GKH
1From foo@baz Mon Jan 13 09:28:30 PST 2014
2From: Sasha Levin <sasha.levin@oracle.com>
3Date: Sat, 7 Dec 2013 17:26:27 -0500
4Subject: net: unix: allow set_peek_off to fail
5
6From: Sasha Levin <sasha.levin@oracle.com>
7
8[ Upstream commit 12663bfc97c8b3fdb292428105dd92d563164050 ]
9
10unix_dgram_recvmsg() will hold the readlock of the socket until recv
11is complete.
12
13In the same time, we may try to setsockopt(SO_PEEK_OFF) which will hang until
14unix_dgram_recvmsg() will complete (which can take a while) without allowing
15us to break out of it, triggering a hung task spew.
16
17Instead, allow set_peek_off to fail, this way userspace will not hang.
18
19Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
20Acked-by: Pavel Emelyanov <xemul@parallels.com>
21Signed-off-by: David S. Miller <davem@davemloft.net>
22Signed-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