Skip to content

Commit b338869

Browse files
shayshyiSaeed Mahameed
authored and
Saeed Mahameed
committed
net/mlx5: Initialize flow steering during driver probe
Currently, software objects of flow steering are created and destroyed during reload flow. In case a device is unloaded, the following error is printed during grace period: mlx5_core 0000:00:0b.0: mlx5_fw_fatal_reporter_err_work:690:(pid 95): Driver is in error state. Unloading As a solution to fix use-after-free bugs, where we try to access these objects, when reading the value of flow_steering_mode devlink param[1], let's split flow steering creation and destruction into two routines: * init and cleanup: memory, cache, and pools allocation/free. * create and destroy: namespaces initialization and cleanup. While at it, re-order the cleanup function to mirror the init function. [1] Kasan trace: [ 385.119849 ] BUG: KASAN: use-after-free in mlx5_devlink_fs_mode_get+0x3b/0xa0 [ 385.119849 ] Read of size 4 at addr ffff888104b79308 by task bash/291 [ 385.119849 ] [ 385.119849 ] CPU: 1 PID: 291 Comm: bash Not tainted 5.17.0-rc1+ rib#2 [ 385.119849 ] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-2.fc32 04/01/2014 [ 385.119849 ] Call Trace: [ 385.119849 ] <TASK> [ 385.119849 ] dump_stack_lvl+0x6e/0x91 [ 385.119849 ] print_address_description.constprop.0+0x1f/0x160 [ 385.119849 ] ? mlx5_devlink_fs_mode_get+0x3b/0xa0 [ 385.119849 ] ? mlx5_devlink_fs_mode_get+0x3b/0xa0 [ 385.119849 ] kasan_report.cold+0x83/0xdf [ 385.119849 ] ? devlink_param_notify+0x20/0x190 [ 385.119849 ] ? mlx5_devlink_fs_mode_get+0x3b/0xa0 [ 385.119849 ] mlx5_devlink_fs_mode_get+0x3b/0xa0 [ 385.119849 ] devlink_nl_param_fill+0x18a/0xa50 [ 385.119849 ] ? _raw_spin_lock_irqsave+0x8d/0xe0 [ 385.119849 ] ? devlink_flash_update_timeout_notify+0xf0/0xf0 [ 385.119849 ] ? __wake_up_common+0x4b/0x1e0 [ 385.119849 ] ? preempt_count_sub+0x14/0xc0 [ 385.119849 ] ? _raw_spin_unlock_irqrestore+0x28/0x40 [ 385.119849 ] ? __wake_up_common_lock+0xe3/0x140 [ 385.119849 ] ? __wake_up_common+0x1e0/0x1e0 [ 385.119849 ] ? __sanitizer_cov_trace_const_cmp8+0x27/0x80 [ 385.119849 ] ? __rcu_read_unlock+0x48/0x70 [ 385.119849 ] ? kasan_unpoison+0x23/0x50 [ 385.119849 ] ? __kasan_slab_alloc+0x2c/0x80 [ 385.119849 ] ? memset+0x20/0x40 [ 385.119849 ] ? __sanitizer_cov_trace_const_cmp4+0x25/0x80 [ 385.119849 ] devlink_param_notify+0xce/0x190 [ 385.119849 ] devlink_unregister+0x92/0x2b0 [ 385.119849 ] remove_one+0x41/0x140 [ 385.119849 ] pci_device_remove+0x68/0x140 [ 385.119849 ] ? pcibios_free_irq+0x10/0x10 [ 385.119849 ] __device_release_driver+0x294/0x3f0 [ 385.119849 ] device_driver_detach+0x82/0x130 [ 385.119849 ] unbind_store+0x193/0x1b0 [ 385.119849 ] ? subsys_interface_unregister+0x270/0x270 [ 385.119849 ] drv_attr_store+0x4e/0x70 [ 385.119849 ] ? drv_attr_show+0x60/0x60 [ 385.119849 ] sysfs_kf_write+0xa7/0xc0 [ 385.119849 ] kernfs_fop_write_iter+0x23a/0x2f0 [ 385.119849 ] ? sysfs_kf_bin_read+0x160/0x160 [ 385.119849 ] new_sync_write+0x311/0x430 [ 385.119849 ] ? new_sync_read+0x480/0x480 [ 385.119849 ] ? _raw_spin_lock+0x87/0xe0 [ 385.119849 ] ? __sanitizer_cov_trace_cmp4+0x25/0x80 [ 385.119849 ] ? security_file_permission+0x94/0xa0 [ 385.119849 ] vfs_write+0x4c7/0x590 [ 385.119849 ] ksys_write+0xf6/0x1e0 [ 385.119849 ] ? __x64_sys_read+0x50/0x50 [ 385.119849 ] ? fpregs_assert_state_consistent+0x99/0xa0 [ 385.119849 ] do_syscall_64+0x3d/0x90 [ 385.119849 ] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 385.119849 ] RIP: 0033:0x7fc36ef38504 [ 385.119849 ] Code: 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b3 0f 1f 80 00 00 00 00 48 8d 05 f9 61 0d 00 8b 00 85 c0 75 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 41 54 49 89 d4 55 48 89 f5 53 [ 385.119849 ] RSP: 002b:00007ffde0ff3d08 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 [ 385.119849 ] RAX: ffffffffffffffda RBX: 000000000000000c RCX: 00007fc36ef38504 [ 385.119849 ] RDX: 000000000000000c RSI: 00007fc370521040 RDI: 0000000000000001 [ 385.119849 ] RBP: 00007fc370521040 R08: 00007fc36f00b8c0 R09: 00007fc36ee4b740 [ 385.119849 ] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fc36f00a760 [ 385.119849 ] R13: 000000000000000c R14: 00007fc36f005760 R15: 000000000000000c [ 385.119849 ] </TASK> [ 385.119849 ] [ 385.119849 ] Allocated by task 65: [ 385.119849 ] kasan_save_stack+0x1e/0x40 [ 385.119849 ] __kasan_kmalloc+0x81/0xa0 [ 385.119849 ] mlx5_init_fs+0x11b/0x1160 [ 385.119849 ] mlx5_load+0x13c/0x220 [ 385.119849 ] mlx5_load_one+0xda/0x160 [ 385.119849 ] mlx5_recover_device+0xb8/0x100 [ 385.119849 ] mlx5_health_try_recover+0x2f9/0x3a1 [ 385.119849 ] devlink_health_reporter_recover+0x75/0x100 [ 385.119849 ] devlink_health_report+0x26c/0x4b0 [ 385.275909 ] mlx5_fw_fatal_reporter_err_work+0x11e/0x1b0 [ 385.275909 ] process_one_work+0x520/0x970 [ 385.275909 ] worker_thread+0x378/0x950 [ 385.275909 ] kthread+0x1bb/0x200 [ 385.275909 ] ret_from_fork+0x1f/0x30 [ 385.275909 ] [ 385.275909 ] Freed by task 65: [ 385.275909 ] kasan_save_stack+0x1e/0x40 [ 385.275909 ] kasan_set_track+0x21/0x30 [ 385.275909 ] kasan_set_free_info+0x20/0x30 [ 385.275909 ] __kasan_slab_free+0xfc/0x140 [ 385.275909 ] kfree+0xa5/0x3b0 [ 385.275909 ] mlx5_unload+0x2e/0xb0 [ 385.275909 ] mlx5_unload_one+0x86/0xb0 [ 385.275909 ] mlx5_fw_fatal_reporter_err_work.cold+0xca/0xcf [ 385.275909 ] process_one_work+0x520/0x970 [ 385.275909 ] worker_thread+0x378/0x950 [ 385.275909 ] kthread+0x1bb/0x200 [ 385.275909 ] ret_from_fork+0x1f/0x30 [ 385.275909 ] [ 385.275909 ] The buggy address belongs to the object at ffff888104b79300 [ 385.275909 ] which belongs to the cache kmalloc-128 of size 128 [ 385.275909 ] The buggy address is located 8 bytes inside of [ 385.275909 ] 128-byte region [ffff888104b79300, ffff888104b79380) [ 385.275909 ] The buggy address belongs to the page: [ 385.275909 ] page:00000000de44dd39 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x104b78 [ 385.275909 ] head:00000000de44dd39 order:1 compound_mapcount:0 [ 385.275909 ] flags: 0x8000000000010200(slab|head|zone=2) [ 385.275909 ] raw: 8000000000010200 0000000000000000 dead000000000122 ffff8881000428c0 [ 385.275909 ] raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000 [ 385.275909 ] page dumped because: kasan: bad access detected [ 385.275909 ] [ 385.275909 ] Memory state around the buggy address: [ 385.275909 ] ffff888104b79200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fc fc [ 385.275909 ] ffff888104b79280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 385.275909 ] >ffff888104b79300: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 385.275909 ] ^ [ 385.275909 ] ffff888104b79380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc [ 385.275909 ] ffff888104b79400: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 385.275909 ]] Fixes: e890acd ("net/mlx5: Add devlink flow_steering_mode parameter") Signed-off-by: Shay Drory <[email protected]> Reviewed-by: Mark Bloch <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent 2c5fc6c commit b338869

File tree

3 files changed

+91
-61
lines changed

3 files changed

+91
-61
lines changed

drivers/net/ethernet/mellanox/mlx5/core/fs_core.c

+75-56
Original file line numberDiff line numberDiff line change
@@ -2663,28 +2663,6 @@ static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns)
26632663
clean_tree(&root_ns->ns.node);
26642664
}
26652665

2666-
void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
2667-
{
2668-
struct mlx5_flow_steering *steering = dev->priv.steering;
2669-
2670-
cleanup_root_ns(steering->root_ns);
2671-
cleanup_root_ns(steering->fdb_root_ns);
2672-
steering->fdb_root_ns = NULL;
2673-
kfree(steering->fdb_sub_ns);
2674-
steering->fdb_sub_ns = NULL;
2675-
cleanup_root_ns(steering->port_sel_root_ns);
2676-
cleanup_root_ns(steering->sniffer_rx_root_ns);
2677-
cleanup_root_ns(steering->sniffer_tx_root_ns);
2678-
cleanup_root_ns(steering->rdma_rx_root_ns);
2679-
cleanup_root_ns(steering->rdma_tx_root_ns);
2680-
cleanup_root_ns(steering->egress_root_ns);
2681-
mlx5_cleanup_fc_stats(dev);
2682-
kmem_cache_destroy(steering->ftes_cache);
2683-
kmem_cache_destroy(steering->fgs_cache);
2684-
mlx5_ft_pool_destroy(dev);
2685-
kfree(steering);
2686-
}
2687-
26882666
static int init_sniffer_tx_root_ns(struct mlx5_flow_steering *steering)
26892667
{
26902668
struct fs_prio *prio;
@@ -3086,42 +3064,27 @@ static int init_egress_root_ns(struct mlx5_flow_steering *steering)
30863064
return err;
30873065
}
30883066

3089-
int mlx5_init_fs(struct mlx5_core_dev *dev)
3067+
void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev)
30903068
{
3091-
struct mlx5_flow_steering *steering;
3092-
int err = 0;
3093-
3094-
err = mlx5_init_fc_stats(dev);
3095-
if (err)
3096-
return err;
3097-
3098-
err = mlx5_ft_pool_init(dev);
3099-
if (err)
3100-
return err;
3101-
3102-
steering = kzalloc(sizeof(*steering), GFP_KERNEL);
3103-
if (!steering) {
3104-
err = -ENOMEM;
3105-
goto err;
3106-
}
3107-
3108-
steering->dev = dev;
3109-
dev->priv.steering = steering;
3069+
struct mlx5_flow_steering *steering = dev->priv.steering;
31103070

3111-
if (mlx5_fs_dr_is_supported(dev))
3112-
steering->mode = MLX5_FLOW_STEERING_MODE_SMFS;
3113-
else
3114-
steering->mode = MLX5_FLOW_STEERING_MODE_DMFS;
3071+
cleanup_root_ns(steering->root_ns);
3072+
cleanup_root_ns(steering->fdb_root_ns);
3073+
steering->fdb_root_ns = NULL;
3074+
kfree(steering->fdb_sub_ns);
3075+
steering->fdb_sub_ns = NULL;
3076+
cleanup_root_ns(steering->port_sel_root_ns);
3077+
cleanup_root_ns(steering->sniffer_rx_root_ns);
3078+
cleanup_root_ns(steering->sniffer_tx_root_ns);
3079+
cleanup_root_ns(steering->rdma_rx_root_ns);
3080+
cleanup_root_ns(steering->rdma_tx_root_ns);
3081+
cleanup_root_ns(steering->egress_root_ns);
3082+
}
31153083

3116-
steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
3117-
sizeof(struct mlx5_flow_group), 0,
3118-
0, NULL);
3119-
steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
3120-
0, NULL);
3121-
if (!steering->ftes_cache || !steering->fgs_cache) {
3122-
err = -ENOMEM;
3123-
goto err;
3124-
}
3084+
int mlx5_fs_core_init(struct mlx5_core_dev *dev)
3085+
{
3086+
struct mlx5_flow_steering *steering = dev->priv.steering;
3087+
int err = 0;
31253088

31263089
if ((((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
31273090
(MLX5_CAP_GEN(dev, nic_flow_table))) ||
@@ -3180,8 +3143,64 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
31803143
}
31813144

31823145
return 0;
3146+
3147+
err:
3148+
mlx5_fs_core_cleanup(dev);
3149+
return err;
3150+
}
3151+
3152+
void mlx5_fs_core_free(struct mlx5_core_dev *dev)
3153+
{
3154+
struct mlx5_flow_steering *steering = dev->priv.steering;
3155+
3156+
kmem_cache_destroy(steering->ftes_cache);
3157+
kmem_cache_destroy(steering->fgs_cache);
3158+
kfree(steering);
3159+
mlx5_ft_pool_destroy(dev);
3160+
mlx5_cleanup_fc_stats(dev);
3161+
}
3162+
3163+
int mlx5_fs_core_alloc(struct mlx5_core_dev *dev)
3164+
{
3165+
struct mlx5_flow_steering *steering;
3166+
int err = 0;
3167+
3168+
err = mlx5_init_fc_stats(dev);
3169+
if (err)
3170+
return err;
3171+
3172+
err = mlx5_ft_pool_init(dev);
3173+
if (err)
3174+
goto err;
3175+
3176+
steering = kzalloc(sizeof(*steering), GFP_KERNEL);
3177+
if (!steering) {
3178+
err = -ENOMEM;
3179+
goto err;
3180+
}
3181+
3182+
steering->dev = dev;
3183+
dev->priv.steering = steering;
3184+
3185+
if (mlx5_fs_dr_is_supported(dev))
3186+
steering->mode = MLX5_FLOW_STEERING_MODE_SMFS;
3187+
else
3188+
steering->mode = MLX5_FLOW_STEERING_MODE_DMFS;
3189+
3190+
steering->fgs_cache = kmem_cache_create("mlx5_fs_fgs",
3191+
sizeof(struct mlx5_flow_group), 0,
3192+
0, NULL);
3193+
steering->ftes_cache = kmem_cache_create("mlx5_fs_ftes", sizeof(struct fs_fte), 0,
3194+
0, NULL);
3195+
if (!steering->ftes_cache || !steering->fgs_cache) {
3196+
err = -ENOMEM;
3197+
goto err;
3198+
}
3199+
3200+
return 0;
3201+
31833202
err:
3184-
mlx5_cleanup_fs(dev);
3203+
mlx5_fs_core_free(dev);
31853204
return err;
31863205
}
31873206

drivers/net/ethernet/mellanox/mlx5/core/fs_core.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,10 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
298298
int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
299299
enum mlx5_flow_steering_mode mode);
300300

301-
int mlx5_init_fs(struct mlx5_core_dev *dev);
302-
void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
301+
int mlx5_fs_core_alloc(struct mlx5_core_dev *dev);
302+
void mlx5_fs_core_free(struct mlx5_core_dev *dev);
303+
int mlx5_fs_core_init(struct mlx5_core_dev *dev);
304+
void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev);
303305

304306
int mlx5_fs_egress_acls_init(struct mlx5_core_dev *dev, int total_vports);
305307
void mlx5_fs_egress_acls_cleanup(struct mlx5_core_dev *dev);

drivers/net/ethernet/mellanox/mlx5/core/main.c

+12-3
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,12 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
938938
goto err_sf_table_cleanup;
939939
}
940940

941+
err = mlx5_fs_core_alloc(dev);
942+
if (err) {
943+
mlx5_core_err(dev, "Failed to alloc flow steering\n");
944+
goto err_fs;
945+
}
946+
941947
dev->dm = mlx5_dm_create(dev);
942948
if (IS_ERR(dev->dm))
943949
mlx5_core_warn(dev, "Failed to init device memory%d\n", err);
@@ -948,6 +954,8 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
948954

949955
return 0;
950956

957+
err_fs:
958+
mlx5_sf_table_cleanup(dev);
951959
err_sf_table_cleanup:
952960
mlx5_sf_hw_table_cleanup(dev);
953961
err_sf_hw_table_cleanup:
@@ -985,6 +993,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
985993
mlx5_hv_vhca_destroy(dev->hv_vhca);
986994
mlx5_fw_tracer_destroy(dev->tracer);
987995
mlx5_dm_cleanup(dev);
996+
mlx5_fs_core_free(dev);
988997
mlx5_sf_table_cleanup(dev);
989998
mlx5_sf_hw_table_cleanup(dev);
990999
mlx5_vhca_event_cleanup(dev);
@@ -1191,7 +1200,7 @@ static int mlx5_load(struct mlx5_core_dev *dev)
11911200
goto err_tls_start;
11921201
}
11931202

1194-
err = mlx5_init_fs(dev);
1203+
err = mlx5_fs_core_init(dev);
11951204
if (err) {
11961205
mlx5_core_err(dev, "Failed to init flow steering\n");
11971206
goto err_fs;
@@ -1236,7 +1245,7 @@ static int mlx5_load(struct mlx5_core_dev *dev)
12361245
err_vhca:
12371246
mlx5_vhca_event_stop(dev);
12381247
err_set_hca:
1239-
mlx5_cleanup_fs(dev);
1248+
mlx5_fs_core_cleanup(dev);
12401249
err_fs:
12411250
mlx5_accel_tls_cleanup(dev);
12421251
err_tls_start:
@@ -1265,7 +1274,7 @@ static void mlx5_unload(struct mlx5_core_dev *dev)
12651274
mlx5_ec_cleanup(dev);
12661275
mlx5_sf_hw_table_destroy(dev);
12671276
mlx5_vhca_event_stop(dev);
1268-
mlx5_cleanup_fs(dev);
1277+
mlx5_fs_core_cleanup(dev);
12691278
mlx5_accel_ipsec_cleanup(dev);
12701279
mlx5_accel_tls_cleanup(dev);
12711280
mlx5_fpga_device_stop(dev);

0 commit comments

Comments
 (0)