lkml.org 
[lkml]   [2021]   [Jul]   [26]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.13 097/223] netrom: Decrease sock refcount when sock timers expire
    Date
    From: Nguyen Dinh Phi <phind.uet@gmail.com>

    [ Upstream commit 517a16b1a88bdb6b530f48d5d153478b2552d9a8 ]

    Commit 63346650c1a9 ("netrom: switch to sock timer API") switched to use
    sock timer API. It replaces mod_timer() by sk_reset_timer(), and
    del_timer() by sk_stop_timer().

    Function sk_reset_timer() will increase the refcount of sock if it is
    called on an inactive timer, hence, in case the timer expires, we need to
    decrease the refcount ourselves in the handler, otherwise, the sock
    refcount will be unbalanced and the sock will never be freed.

    Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
    Reported-by: syzbot+10f1194569953b72f1ae@syzkaller.appspotmail.com
    Fixes: 63346650c1a9 ("netrom: switch to sock timer API")
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/netrom/nr_timer.c | 20 +++++++++++---------
    1 file changed, 11 insertions(+), 9 deletions(-)

    diff --git a/net/netrom/nr_timer.c b/net/netrom/nr_timer.c
    index 9115f8a7dd45..a8da88db7893 100644
    --- a/net/netrom/nr_timer.c
    +++ b/net/netrom/nr_timer.c
    @@ -121,11 +121,9 @@ static void nr_heartbeat_expiry(struct timer_list *t)
    is accepted() it isn't 'dead' so doesn't get removed. */
    if (sock_flag(sk, SOCK_DESTROY) ||
    (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) {
    - sock_hold(sk);
    bh_unlock_sock(sk);
    nr_destroy_socket(sk);
    - sock_put(sk);
    - return;
    + goto out;
    }
    break;

    @@ -146,6 +144,8 @@ static void nr_heartbeat_expiry(struct timer_list *t)

    nr_start_heartbeat(sk);
    bh_unlock_sock(sk);
    +out:
    + sock_put(sk);
    }

    static void nr_t2timer_expiry(struct timer_list *t)
    @@ -159,6 +159,7 @@ static void nr_t2timer_expiry(struct timer_list *t)
    nr_enquiry_response(sk);
    }
    bh_unlock_sock(sk);
    + sock_put(sk);
    }

    static void nr_t4timer_expiry(struct timer_list *t)
    @@ -169,6 +170,7 @@ static void nr_t4timer_expiry(struct timer_list *t)
    bh_lock_sock(sk);
    nr_sk(sk)->condition &= ~NR_COND_PEER_RX_BUSY;
    bh_unlock_sock(sk);
    + sock_put(sk);
    }

    static void nr_idletimer_expiry(struct timer_list *t)
    @@ -197,6 +199,7 @@ static void nr_idletimer_expiry(struct timer_list *t)
    sock_set_flag(sk, SOCK_DEAD);
    }
    bh_unlock_sock(sk);
    + sock_put(sk);
    }

    static void nr_t1timer_expiry(struct timer_list *t)
    @@ -209,8 +212,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
    case NR_STATE_1:
    if (nr->n2count == nr->n2) {
    nr_disconnect(sk, ETIMEDOUT);
    - bh_unlock_sock(sk);
    - return;
    + goto out;
    } else {
    nr->n2count++;
    nr_write_internal(sk, NR_CONNREQ);
    @@ -220,8 +222,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
    case NR_STATE_2:
    if (nr->n2count == nr->n2) {
    nr_disconnect(sk, ETIMEDOUT);
    - bh_unlock_sock(sk);
    - return;
    + goto out;
    } else {
    nr->n2count++;
    nr_write_internal(sk, NR_DISCREQ);
    @@ -231,8 +232,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
    case NR_STATE_3:
    if (nr->n2count == nr->n2) {
    nr_disconnect(sk, ETIMEDOUT);
    - bh_unlock_sock(sk);
    - return;
    + goto out;
    } else {
    nr->n2count++;
    nr_requeue_frames(sk);
    @@ -241,5 +241,7 @@ static void nr_t1timer_expiry(struct timer_list *t)
    }

    nr_start_t1timer(sk);
    +out:
    bh_unlock_sock(sk);
    + sock_put(sk);
    }
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-26 18:31    [W:4.384 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site