lkml.org 
[lkml]   [2014]   [Jan]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.10 16/62] net: unix: allow set_peek_off to fail
    Date
    3.10-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Sasha Levin <sasha.levin@oracle.com>

    [ 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@oracle.com>
    Acked-by: Pavel Emelyanov <xemul@parallels.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    include/linux/net.h | 2 +-
    net/core/sock.c | 2 +-
    net/unix/af_unix.c | 8 ++++++--
    3 files changed, 8 insertions(+), 4 deletions(-)

    --- 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) \
    --- a/net/core/sock.c
    +++ b/net/core/sock.c
    @@ -885,7 +885,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;
    --- a/net/unix/af_unix.c
    +++ b/net/unix/af_unix.c
    @@ -529,13 +529,17 @@ static int unix_seqpacket_sendmsg(struct
    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;
    }





    \
     
     \ /
      Last update: 2014-01-14 07:21    [W:4.597 / U:0.152 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site