lkml.org 
[lkml]   [2022]   [Apr]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 0823/1126] net/x25: Fix null-ptr-deref caused by x25_disconnect
    Date
    From: Duoming Zhou <duoming@zju.edu.cn>

    [ Upstream commit 7781607938c8371d4c2b243527430241c62e39c2 ]

    When the link layer is terminating, x25->neighbour will be set to NULL
    in x25_disconnect(). As a result, it could cause null-ptr-deref bugs in
    x25_sendmsg(),x25_recvmsg() and x25_connect(). One of the bugs is
    shown below.

    (Thread 1) | (Thread 2)
    x25_link_terminated() | x25_recvmsg()
    x25_kill_by_neigh() | ...
    x25_disconnect() | lock_sock(sk)
    ... | ...
    x25->neighbour = NULL //(1) |
    ... | x25->neighbour->extended //(2)

    The code sets NULL to x25->neighbour in position (1) and dereferences
    x25->neighbour in position (2), which could cause null-ptr-deref bug.

    This patch adds lock_sock() in x25_kill_by_neigh() in order to synchronize
    with x25_sendmsg(), x25_recvmsg() and x25_connect(). What`s more, the
    sock held by lock_sock() is not NULL, because it is extracted from x25_list
    and uses x25_list_lock to synchronize.

    Fixes: 4becb7ee5b3d ("net/x25: Fix x25_neigh refcnt leak when x25 disconnect")
    Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
    Reviewed-by: Lin Ma <linma@zju.edu.cn>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/x25/af_x25.c | 11 ++++++++---
    1 file changed, 8 insertions(+), 3 deletions(-)

    diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
    index 3583354a7d7f..3a171828638b 100644
    --- a/net/x25/af_x25.c
    +++ b/net/x25/af_x25.c
    @@ -1765,10 +1765,15 @@ void x25_kill_by_neigh(struct x25_neigh *nb)

    write_lock_bh(&x25_list_lock);

    - sk_for_each(s, &x25_list)
    - if (x25_sk(s)->neighbour == nb)
    + sk_for_each(s, &x25_list) {
    + if (x25_sk(s)->neighbour == nb) {
    + write_unlock_bh(&x25_list_lock);
    + lock_sock(s);
    x25_disconnect(s, ENETUNREACH, 0, 0);
    -
    + release_sock(s);
    + write_lock_bh(&x25_list_lock);
    + }
    + }
    write_unlock_bh(&x25_list_lock);

    /* Remove any related forwards */
    --
    2.34.1


    \
     
     \ /
      Last update: 2022-09-17 16:20    [W:4.664 / U:0.056 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site