aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSasha Levin <sasha.levin@oracle.com>2013-12-07 17:26:27 -0500
committerDavid S. Miller <davem@davemloft.net>2013-12-10 21:45:15 -0500
commit12663bfc97c8b3fdb292428105dd92d563164050 (patch)
tree3cfc0b33e9c96636e397c9c19806208735556b14 /net
parent88b07b3660362049769f36c94f2c5a623424c992 (diff)
net: unix: allow set_peek_off to fail
unix_dgram_recvmsg() will hold the readlock of the socket until recv is complete. In the same time, we may try to setsockopt(SO_PEEK_OFF) which will hang until unix_dgram_recvmsg() will complete (which can take a while) without allowing us to break out of it, triggering a hung task spew. Instead, allow set_peek_off to fail, this way userspace will not hang. Signed-off-by: Sasha Levin <sasha.levin@oracle.com> Acked-by: Pavel Emelyanov <xemul@parallels.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/sock.c2
-rw-r--r--net/unix/af_unix.c8
2 files changed, 7 insertions, 3 deletions
diff --git a/net/core/sock.c b/net/core/sock.c
index ab20ed9b0f31..5393b4b719d7 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -882,7 +882,7 @@ set_rcvbuf:
882 882
883 case SO_PEEK_OFF: 883 case SO_PEEK_OFF:
884 if (sock->ops->set_peek_off) 884 if (sock->ops->set_peek_off)
885 sock->ops->set_peek_off(sk, val); 885 ret = sock->ops->set_peek_off(sk, val);
886 else 886 else
887 ret = -EOPNOTSUPP; 887 ret = -EOPNOTSUPP;
888 break; 888 break;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 01625ccc3ae6..a0ca162e5bd5 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -530,13 +530,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
530static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, 530static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
531 struct msghdr *, size_t, int); 531 struct msghdr *, size_t, int);
532 532
533static void unix_set_peek_off(struct sock *sk, int val) 533static int unix_set_peek_off(struct sock *sk, int val)
534{ 534{
535 struct unix_sock *u = unix_sk(sk); 535 struct unix_sock *u = unix_sk(sk);
536 536
537 mutex_lock(&u->readlock); 537 if (mutex_lock_interruptible(&u->readlock))
538 return -EINTR;
539
538 sk->sk_peek_off = val; 540 sk->sk_peek_off = val;
539 mutex_unlock(&u->readlock); 541 mutex_unlock(&u->readlock);
542
543 return 0;
540} 544}
541 545
542 546