lkml.org 
[lkml]   [2018]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 51/61] libceph: validate con->state at the top of try_write()
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

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

    From: Ilya Dryomov <idryomov@gmail.com>

    commit 9c55ad1c214d9f8c4594ac2c3fa392c1c32431a7 upstream.

    ceph_con_workfn() validates con->state before calling try_read() and
    then try_write(). However, try_read() temporarily releases con->mutex,
    notably in process_message() and ceph_con_in_msg_alloc(), opening the
    window for ceph_con_close() to sneak in, close the connection and
    release con->sock. When try_write() is called on the assumption that
    con->state is still valid (i.e. not STANDBY or CLOSED), a NULL sock
    gets passed to the networking stack:

    BUG: unable to handle kernel NULL pointer dereference at 0000000000000020
    IP: selinux_socket_sendmsg+0x5/0x20

    Make sure con->state is valid at the top of try_write() and add an
    explicit BUG_ON for this, similar to try_read().

    Cc: stable@vger.kernel.org
    Link: https://tracker.ceph.com/issues/23706
    Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
    Reviewed-by: Jason Dillaman <dillaman@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    net/ceph/messenger.c | 7 +++++++
    1 file changed, 7 insertions(+)

    --- a/net/ceph/messenger.c
    +++ b/net/ceph/messenger.c
    @@ -2512,6 +2512,11 @@ static int try_write(struct ceph_connect
    int ret = 1;

    dout("try_write start %p state %lu\n", con, con->state);
    + if (con->state != CON_STATE_PREOPEN &&
    + con->state != CON_STATE_CONNECTING &&
    + con->state != CON_STATE_NEGOTIATING &&
    + con->state != CON_STATE_OPEN)
    + return 0;

    more:
    dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes);
    @@ -2537,6 +2542,8 @@ more:
    }

    more_kvec:
    + BUG_ON(!con->sock);
    +
    /* kvec data queued? */
    if (con->out_kvec_left) {
    ret = write_partial_kvec(con);

    \
     
     \ /
      Last update: 2018-04-30 22:21    [W:3.459 / U:0.264 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site