[3.8.y.z extended stable] Patch "net: unix: allow set_peek_off to fail" has been added to staging queue
Kamal Mostafa
kamal at canonical.com
Wed Jan 15 21:49:42 UTC 2014
This is a note to let you know that I have just added a patch titled
net: unix: allow set_peek_off to fail
to the linux-3.8.y-queue branch of the 3.8.y.z extended stable tree
which can be found at:
http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.8.y-queue
This patch is scheduled to be released in version 3.8.13.16.
If you, or anyone else, feels it should not be added to this tree, please
reply to this email.
For more information about the 3.8.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
Thanks.
-Kamal
------
>From 7386262e8a5947cd3e93150da78facae46767b19 Mon Sep 17 00:00:00 2001
From: Sasha Levin <sasha.levin at oracle.com>
Date: Sat, 7 Dec 2013 17:26:27 -0500
Subject: net: unix: allow set_peek_off to fail
[ Upstream commit 12663bfc97c8b3fdb292428105dd92d563164050 ]
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 at oracle.com>
Acked-by: Pavel Emelyanov <xemul at parallels.com>
Signed-off-by: David S. Miller <davem at davemloft.net>
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
include/linux/net.h | 2 +-
net/core/sock.c | 2 +-
net/unix/af_unix.c | 8 ++++++--
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/include/linux/net.h b/include/linux/net.h
index 5ea38d9..f6dc1f5 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -180,7 +180,7 @@ struct proto_ops {
int offset, size_t size, int flags);
ssize_t (*splice_read)(struct socket *sock, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len, unsigned int flags);
- void (*set_peek_off)(struct sock *sk, int val);
+ int (*set_peek_off)(struct sock *sk, int val);
};
#define DECLARE_SOCKADDR(type, dst, src) \
diff --git a/net/core/sock.c b/net/core/sock.c
index fc0d751..7367c05 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -886,7 +886,7 @@ set_rcvbuf:
case SO_PEEK_OFF:
if (sock->ops->set_peek_off)
- sock->ops->set_peek_off(sk, val);
+ ret = sock->ops->set_peek_off(sk, val);
else
ret = -EOPNOTSUPP;
break;
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 6cc5803..499efb7 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -531,13 +531,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
struct msghdr *, size_t, int);
-static void unix_set_peek_off(struct sock *sk, int val)
+static int unix_set_peek_off(struct sock *sk, int val)
{
struct unix_sock *u = unix_sk(sk);
- mutex_lock(&u->readlock);
+ if (mutex_lock_interruptible(&u->readlock))
+ return -EINTR;
+
sk->sk_peek_off = val;
mutex_unlock(&u->readlock);
+
+ return 0;
}
--
1.8.3.2
More information about the kernel-team
mailing list