lkml.org 
[lkml]   [2018]   [Sep]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 004/173] rds: fix two RCU related problems
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

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

    From: Cong Wang <xiyou.wangcong@gmail.com>

    [ Upstream commit cc4dfb7f70a344f24c1c71e298deea0771dadcb2 ]

    When a rds sock is bound, it is inserted into the bind_hash_table
    which is protected by RCU. But when releasing rds sock, after it
    is removed from this hash table, it is freed immediately without
    respecting RCU grace period. This could cause some use-after-free
    as reported by syzbot.

    Mark the rds sock with SOCK_RCU_FREE before inserting it into the
    bind_hash_table, so that it would be always freed after a RCU grace
    period.

    The other problem is in rds_find_bound(), the rds sock could be
    freed in between rhashtable_lookup_fast() and rds_sock_addref(),
    so we need to extend RCU read lock protection in rds_find_bound()
    to close this race condition.

    Reported-and-tested-by: syzbot+8967084bcac563795dc6@syzkaller.appspotmail.com
    Reported-by: syzbot+93a5839deb355537440f@syzkaller.appspotmail.com
    Cc: Sowmini Varadhan <sowmini.varadhan@oracle.com>
    Cc: Santosh Shilimkar <santosh.shilimkar@oracle.com>
    Cc: rds-devel@oss.oracle.com
    Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
    Acked-by: Santosh Shilimkar <santosh.shilimkar@oarcle.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/rds/bind.c | 5 ++++-
    1 file changed, 4 insertions(+), 1 deletion(-)

    --- a/net/rds/bind.c
    +++ b/net/rds/bind.c
    @@ -60,11 +60,13 @@ struct rds_sock *rds_find_bound(__be32 a
    u64 key = ((u64)addr << 32) | port;
    struct rds_sock *rs;

    - rs = rhashtable_lookup_fast(&bind_hash_table, &key, ht_parms);
    + rcu_read_lock();
    + rs = rhashtable_lookup(&bind_hash_table, &key, ht_parms);
    if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
    rds_sock_addref(rs);
    else
    rs = NULL;
    + rcu_read_unlock();

    rdsdebug("returning rs %p for %pI4:%u\n", rs, &addr,
    ntohs(port));
    @@ -157,6 +159,7 @@ int rds_bind(struct socket *sock, struct
    goto out;
    }

    + sock_set_flag(sk, SOCK_RCU_FREE);
    ret = rds_add_bound(rs, sin->sin_addr.s_addr, &sin->sin_port);
    if (ret)
    goto out;

    \
     
     \ /
      Last update: 2018-09-24 14:57    [W:4.274 / U:0.172 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site