lkml.org 
[lkml]   [2018]   [Oct]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 41/71] tcp/dccp: fix lockdep issue when SYN is backlogged
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

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

    From: Eric Dumazet <edumazet@google.com>

    [ Upstream commit 1ad98e9d1bdf4724c0a8532fabd84bf3c457c2bc ]

    In normal SYN processing, packets are handled without listener
    lock and in RCU protected ingress path.

    But syzkaller is known to be able to trick us and SYN
    packets might be processed in process context, after being
    queued into socket backlog.

    In commit 06f877d613be ("tcp/dccp: fix other lockdep splats
    accessing ireq_opt") I made a very stupid fix, that happened
    to work mostly because of the regular path being RCU protected.

    Really the thing protecting ireq->ireq_opt is RCU read lock,
    and the pseudo request refcnt is not relevant.

    This patch extends what I did in commit 449809a66c1d ("tcp/dccp:
    block BH for SYN processing") by adding an extra rcu_read_{lock|unlock}
    pair in the paths that might be taken when processing SYN from
    socket backlog (thus possibly in process context)

    Fixes: 06f877d613be ("tcp/dccp: fix other lockdep splats accessing ireq_opt")
    Signed-off-by: Eric Dumazet <edumazet@google.com>
    Reported-by: syzbot <syzkaller@googlegroups.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    include/net/inet_sock.h | 3 +--
    net/dccp/input.c | 4 +++-
    net/ipv4/tcp_input.c | 4 +++-
    3 files changed, 7 insertions(+), 4 deletions(-)

    --- a/include/net/inet_sock.h
    +++ b/include/net/inet_sock.h
    @@ -134,8 +134,7 @@ static inline int inet_request_bound_dev

    static inline struct ip_options_rcu *ireq_opt_deref(const struct inet_request_sock *ireq)
    {
    - return rcu_dereference_check(ireq->ireq_opt,
    - atomic_read(&ireq->req.rsk_refcnt) > 0);
    + return rcu_dereference(ireq->ireq_opt);
    }

    struct inet_cork {
    --- a/net/dccp/input.c
    +++ b/net/dccp/input.c
    @@ -605,11 +605,13 @@ int dccp_rcv_state_process(struct sock *
    if (sk->sk_state == DCCP_LISTEN) {
    if (dh->dccph_type == DCCP_PKT_REQUEST) {
    /* It is possible that we process SYN packets from backlog,
    - * so we need to make sure to disable BH right there.
    + * so we need to make sure to disable BH and RCU right there.
    */
    + rcu_read_lock();
    local_bh_disable();
    acceptable = inet_csk(sk)->icsk_af_ops->conn_request(sk, skb) >= 0;
    local_bh_enable();
    + rcu_read_unlock();
    if (!acceptable)
    return 1;
    consume_skb(skb);
    --- a/net/ipv4/tcp_input.c
    +++ b/net/ipv4/tcp_input.c
    @@ -5978,11 +5978,13 @@ int tcp_rcv_state_process(struct sock *s
    if (th->fin)
    goto discard;
    /* It is possible that we process SYN packets from backlog,
    - * so we need to make sure to disable BH right there.
    + * so we need to make sure to disable BH and RCU right there.
    */
    + rcu_read_lock();
    local_bh_disable();
    acceptable = icsk->icsk_af_ops->conn_request(sk, skb) >= 0;
    local_bh_enable();
    + rcu_read_unlock();

    if (!acceptable)
    return 1;

    \
     
     \ /
      Last update: 2018-10-16 19:30    [W:4.123 / U:0.120 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site