lkml.org 
[lkml]   [2022]   [May]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 072/140] net/mlx5e: Lag, Fix use-after-free in fib event handler
    Date
    From: Vlad Buslov <vladbu@nvidia.com>

    commit 27b0420fd959e38e3500e60b637d39dfab065645 upstream.

    Recent commit that modified fib route event handler to handle events
    according to their priority introduced use-after-free[0] in mp->mfi pointer
    usage. The pointer now is not just cached in order to be compared to
    following fib_info instances, but is also dereferenced to obtain
    fib_priority. However, since mlx5 lag code doesn't hold the reference to
    fin_info during whole mp->mfi lifetime, it could be used after fib_info
    instance has already been freed be kernel infrastructure code.

    Don't ever dereference mp->mfi pointer. Refactor it to be 'const void*'
    type and cache fib_info priority in dedicated integer. Group
    fib_info-related data into dedicated 'fib' structure that will be further
    extended by following patches in the series.

    [0]:

    [ 203.588029] ==================================================================
    [ 203.590161] BUG: KASAN: use-after-free in mlx5_lag_fib_update+0xabd/0xd60 [mlx5_core]
    [ 203.592386] Read of size 4 at addr ffff888144df2050 by task kworker/u20:4/138

    [ 203.594766] CPU: 3 PID: 138 Comm: kworker/u20:4 Tainted: G B 5.17.0-rc7+ #6
    [ 203.596751] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
    [ 203.598813] Workqueue: mlx5_lag_mp mlx5_lag_fib_update [mlx5_core]
    [ 203.600053] Call Trace:
    [ 203.600608] <TASK>
    [ 203.601110] dump_stack_lvl+0x48/0x5e
    [ 203.601860] print_address_description.constprop.0+0x1f/0x160
    [ 203.602950] ? mlx5_lag_fib_update+0xabd/0xd60 [mlx5_core]
    [ 203.604073] ? mlx5_lag_fib_update+0xabd/0xd60 [mlx5_core]
    [ 203.605177] kasan_report.cold+0x83/0xdf
    [ 203.605969] ? mlx5_lag_fib_update+0xabd/0xd60 [mlx5_core]
    [ 203.607102] mlx5_lag_fib_update+0xabd/0xd60 [mlx5_core]
    [ 203.608199] ? mlx5_lag_init_fib_work+0x1c0/0x1c0 [mlx5_core]
    [ 203.609382] ? read_word_at_a_time+0xe/0x20
    [ 203.610463] ? strscpy+0xa0/0x2a0
    [ 203.611463] process_one_work+0x722/0x1270
    [ 203.612344] worker_thread+0x540/0x11e0
    [ 203.613136] ? rescuer_thread+0xd50/0xd50
    [ 203.613949] kthread+0x26e/0x300
    [ 203.614627] ? kthread_complete_and_exit+0x20/0x20
    [ 203.615542] ret_from_fork+0x1f/0x30
    [ 203.616273] </TASK>

    [ 203.617174] Allocated by task 3746:
    [ 203.617874] kasan_save_stack+0x1e/0x40
    [ 203.618644] __kasan_kmalloc+0x81/0xa0
    [ 203.619394] fib_create_info+0xb41/0x3c50
    [ 203.620213] fib_table_insert+0x190/0x1ff0
    [ 203.621020] fib_magic.isra.0+0x246/0x2e0
    [ 203.621803] fib_add_ifaddr+0x19f/0x670
    [ 203.622563] fib_inetaddr_event+0x13f/0x270
    [ 203.623377] blocking_notifier_call_chain+0xd4/0x130
    [ 203.624355] __inet_insert_ifa+0x641/0xb20
    [ 203.625185] inet_rtm_newaddr+0xc3d/0x16a0
    [ 203.626009] rtnetlink_rcv_msg+0x309/0x880
    [ 203.626826] netlink_rcv_skb+0x11d/0x340
    [ 203.627626] netlink_unicast+0x4cc/0x790
    [ 203.628430] netlink_sendmsg+0x762/0xc00
    [ 203.629230] sock_sendmsg+0xb2/0xe0
    [ 203.629955] ____sys_sendmsg+0x58a/0x770
    [ 203.630756] ___sys_sendmsg+0xd8/0x160
    [ 203.631523] __sys_sendmsg+0xb7/0x140
    [ 203.632294] do_syscall_64+0x35/0x80
    [ 203.633045] entry_SYSCALL_64_after_hwframe+0x44/0xae

    [ 203.634427] Freed by task 0:
    [ 203.635063] kasan_save_stack+0x1e/0x40
    [ 203.635844] kasan_set_track+0x21/0x30
    [ 203.636618] kasan_set_free_info+0x20/0x30
    [ 203.637450] __kasan_slab_free+0xfc/0x140
    [ 203.638271] kfree+0x94/0x3b0
    [ 203.638903] rcu_core+0x5e4/0x1990
    [ 203.639640] __do_softirq+0x1ba/0x5d3

    [ 203.640828] Last potentially related work creation:
    [ 203.641785] kasan_save_stack+0x1e/0x40
    [ 203.642571] __kasan_record_aux_stack+0x9f/0xb0
    [ 203.643478] call_rcu+0x88/0x9c0
    [ 203.644178] fib_release_info+0x539/0x750
    [ 203.644997] fib_table_delete+0x659/0xb80
    [ 203.645809] fib_magic.isra.0+0x1a3/0x2e0
    [ 203.646617] fib_del_ifaddr+0x93f/0x1300
    [ 203.647415] fib_inetaddr_event+0x9f/0x270
    [ 203.648251] blocking_notifier_call_chain+0xd4/0x130
    [ 203.649225] __inet_del_ifa+0x474/0xc10
    [ 203.650016] devinet_ioctl+0x781/0x17f0
    [ 203.650788] inet_ioctl+0x1ad/0x290
    [ 203.651533] sock_do_ioctl+0xce/0x1c0
    [ 203.652315] sock_ioctl+0x27b/0x4f0
    [ 203.653058] __x64_sys_ioctl+0x124/0x190
    [ 203.653850] do_syscall_64+0x35/0x80
    [ 203.654608] entry_SYSCALL_64_after_hwframe+0x44/0xae

    [ 203.666952] The buggy address belongs to the object at ffff888144df2000
    which belongs to the cache kmalloc-256 of size 256
    [ 203.669250] The buggy address is located 80 bytes inside of
    256-byte region [ffff888144df2000, ffff888144df2100)
    [ 203.671332] The buggy address belongs to the page:
    [ 203.672273] page:00000000bf6c9314 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x144df0
    [ 203.674009] head:00000000bf6c9314 order:2 compound_mapcount:0 compound_pincount:0
    [ 203.675422] flags: 0x2ffff800010200(slab|head|node=0|zone=2|lastcpupid=0x1ffff)
    [ 203.676819] raw: 002ffff800010200 0000000000000000 dead000000000122 ffff888100042b40
    [ 203.678384] raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000
    [ 203.679928] page dumped because: kasan: bad access detected

    [ 203.681455] Memory state around the buggy address:
    [ 203.682421] ffff888144df1f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    [ 203.683863] ffff888144df1f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    [ 203.685310] >ffff888144df2000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    [ 203.686701] ^
    [ 203.687820] ffff888144df2080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    [ 203.689226] ffff888144df2100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    [ 203.690620] ==================================================================

    Fixes: ad11c4f1d8fd ("net/mlx5e: Lag, Only handle events from highest priority multipath entry")
    Signed-off-by: Vlad Buslov <vladbu@nvidia.com>
    Reviewed-by: Maor Dickman <maord@nvidia.com>
    Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
    Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c | 26 ++++++++++++++---------
    drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h | 5 +++-
    2 files changed, 20 insertions(+), 11 deletions(-)

    --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
    +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
    @@ -100,6 +100,12 @@ static void mlx5_lag_fib_event_flush(str
    flush_workqueue(mp->wq);
    }

    +static void mlx5_lag_fib_set(struct lag_mp *mp, struct fib_info *fi)
    +{
    + mp->fib.mfi = fi;
    + mp->fib.priority = fi->fib_priority;
    +}
    +
    struct mlx5_fib_event_work {
    struct work_struct work;
    struct mlx5_lag *ldev;
    @@ -121,13 +127,13 @@ static void mlx5_lag_fib_route_event(str
    /* Handle delete event */
    if (event == FIB_EVENT_ENTRY_DEL) {
    /* stop track */
    - if (mp->mfi == fi)
    - mp->mfi = NULL;
    + if (mp->fib.mfi == fi)
    + mp->fib.mfi = NULL;
    return;
    }

    /* Handle multipath entry with lower priority value */
    - if (mp->mfi && mp->mfi != fi && fi->fib_priority >= mp->mfi->fib_priority)
    + if (mp->fib.mfi && mp->fib.mfi != fi && fi->fib_priority >= mp->fib.priority)
    return;

    /* Handle add/replace event */
    @@ -145,7 +151,7 @@ static void mlx5_lag_fib_route_event(str
    mlx5_lag_set_port_affinity(ldev, i);
    }

    - mp->mfi = fi;
    + mlx5_lag_fib_set(mp, fi);
    return;
    }

    @@ -165,7 +171,7 @@ static void mlx5_lag_fib_route_event(str
    }

    /* First time we see multipath route */
    - if (!mp->mfi && !__mlx5_lag_is_active(ldev)) {
    + if (!mp->fib.mfi && !__mlx5_lag_is_active(ldev)) {
    struct lag_tracker tracker;

    tracker = ldev->tracker;
    @@ -173,7 +179,7 @@ static void mlx5_lag_fib_route_event(str
    }

    mlx5_lag_set_port_affinity(ldev, MLX5_LAG_NORMAL_AFFINITY);
    - mp->mfi = fi;
    + mlx5_lag_fib_set(mp, fi);
    }

    static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
    @@ -184,7 +190,7 @@ static void mlx5_lag_fib_nexthop_event(s
    struct lag_mp *mp = &ldev->lag_mp;

    /* Check the nh event is related to the route */
    - if (!mp->mfi || mp->mfi != fi)
    + if (!mp->fib.mfi || mp->fib.mfi != fi)
    return;

    /* nh added/removed */
    @@ -313,7 +319,7 @@ void mlx5_lag_mp_reset(struct mlx5_lag *
    /* Clear mfi, as it might become stale when a route delete event
    * has been missed, see mlx5_lag_fib_route_event().
    */
    - ldev->lag_mp.mfi = NULL;
    + ldev->lag_mp.fib.mfi = NULL;
    }

    int mlx5_lag_mp_init(struct mlx5_lag *ldev)
    @@ -324,7 +330,7 @@ int mlx5_lag_mp_init(struct mlx5_lag *ld
    /* always clear mfi, as it might become stale when a route delete event
    * has been missed
    */
    - mp->mfi = NULL;
    + mp->fib.mfi = NULL;

    if (mp->fib_nb.notifier_call)
    return 0;
    @@ -354,5 +360,5 @@ void mlx5_lag_mp_cleanup(struct mlx5_lag
    unregister_fib_notifier(&init_net, &mp->fib_nb);
    destroy_workqueue(mp->wq);
    mp->fib_nb.notifier_call = NULL;
    - mp->mfi = NULL;
    + mp->fib.mfi = NULL;
    }
    --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h
    +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.h
    @@ -15,7 +15,10 @@ enum mlx5_lag_port_affinity {

    struct lag_mp {
    struct notifier_block fib_nb;
    - struct fib_info *mfi; /* used in tracking fib events */
    + struct {
    + const void *mfi; /* used in tracking fib events */
    + u32 priority;
    + } fib;
    struct workqueue_struct *wq;
    };


    \
     
     \ /
      Last update: 2022-05-10 16:25    [W:4.194 / U:1.284 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site