2017-12-02 07:08:58 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2017 Netronome Systems, Inc.
|
|
|
|
*
|
|
|
|
* This software is licensed under the GNU General License Version 2,
|
|
|
|
* June 1991 as shown in the file COPYING in the top-level directory of this
|
|
|
|
* source tree.
|
|
|
|
*
|
|
|
|
* THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS"
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
|
|
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
|
|
|
|
* OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
|
|
|
|
* THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
|
|
|
*/
|
|
|
|
|
2020-07-10 08:42:48 +08:00
|
|
|
#include <linux/debugfs.h>
|
2017-12-02 07:09:01 +08:00
|
|
|
#include <linux/device.h>
|
2020-11-19 04:45:19 +08:00
|
|
|
#include <linux/ethtool.h>
|
2017-12-02 07:08:58 +08:00
|
|
|
#include <linux/kernel.h>
|
2017-12-02 07:08:59 +08:00
|
|
|
#include <linux/list.h>
|
2017-12-02 07:08:58 +08:00
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#include <linux/u64_stats_sync.h>
|
2019-04-25 21:59:53 +08:00
|
|
|
#include <net/devlink.h>
|
2020-09-26 08:56:42 +08:00
|
|
|
#include <net/udp_tunnel.h>
|
2018-07-12 11:36:40 +08:00
|
|
|
#include <net/xdp.h>
|
2017-12-02 07:08:58 +08:00
|
|
|
|
|
|
|
#define DRV_NAME "netdevsim"
|
|
|
|
|
2017-12-02 07:08:59 +08:00
|
|
|
#define NSIM_XDP_MAX_MTU 4000
|
|
|
|
|
|
|
|
#define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg)
|
|
|
|
|
2018-06-27 01:07:54 +08:00
|
|
|
#define NSIM_IPSEC_MAX_SA_COUNT 33
|
|
|
|
#define NSIM_IPSEC_VALID BIT(31)
|
2020-07-10 08:42:48 +08:00
|
|
|
#define NSIM_UDP_TUNNEL_N_PORTS 4
|
2018-06-27 01:07:54 +08:00
|
|
|
|
|
|
|
struct nsim_sa {
|
|
|
|
struct xfrm_state *xs;
|
|
|
|
__be32 ipaddr[4];
|
|
|
|
u32 key[4];
|
|
|
|
u32 salt;
|
|
|
|
bool used;
|
|
|
|
bool crypt;
|
|
|
|
bool rx;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct nsim_ipsec {
|
|
|
|
struct nsim_sa sa[NSIM_IPSEC_MAX_SA_COUNT];
|
|
|
|
struct dentry *pfile;
|
|
|
|
u32 count;
|
|
|
|
u32 tx;
|
|
|
|
u32 ok;
|
|
|
|
};
|
|
|
|
|
2020-11-19 04:45:18 +08:00
|
|
|
struct nsim_ethtool_pauseparam {
|
2020-09-15 08:11:54 +08:00
|
|
|
bool rx;
|
|
|
|
bool tx;
|
|
|
|
bool report_stats_rx;
|
|
|
|
bool report_stats_tx;
|
|
|
|
};
|
|
|
|
|
2020-11-19 04:45:18 +08:00
|
|
|
struct nsim_ethtool {
|
2021-03-30 11:59:53 +08:00
|
|
|
u32 get_err;
|
|
|
|
u32 set_err;
|
2020-11-19 04:45:18 +08:00
|
|
|
struct nsim_ethtool_pauseparam pauseparam;
|
2020-11-19 04:45:19 +08:00
|
|
|
struct ethtool_coalesce coalesce;
|
|
|
|
struct ethtool_ringparam ring;
|
2021-03-30 11:59:53 +08:00
|
|
|
struct ethtool_fecparam fec;
|
2020-11-19 04:45:18 +08:00
|
|
|
};
|
|
|
|
|
2017-12-02 07:08:58 +08:00
|
|
|
struct netdevsim {
|
2017-12-02 07:08:59 +08:00
|
|
|
struct net_device *netdev;
|
2019-04-25 21:59:49 +08:00
|
|
|
struct nsim_dev *nsim_dev;
|
2019-04-25 21:59:55 +08:00
|
|
|
struct nsim_dev_port *nsim_dev_port;
|
2017-12-02 07:08:59 +08:00
|
|
|
|
2017-12-02 07:08:58 +08:00
|
|
|
u64 tx_packets;
|
|
|
|
u64 tx_bytes;
|
|
|
|
struct u64_stats_sync syncp;
|
2017-12-02 07:08:59 +08:00
|
|
|
|
2019-04-25 21:59:45 +08:00
|
|
|
struct nsim_bus_dev *nsim_bus_dev;
|
2017-12-02 07:09:01 +08:00
|
|
|
|
2017-12-02 07:08:59 +08:00
|
|
|
struct bpf_prog *bpf_offloaded;
|
|
|
|
u32 bpf_offloaded_id;
|
|
|
|
|
2018-07-12 11:36:40 +08:00
|
|
|
struct xdp_attachment_info xdp;
|
2018-07-12 11:36:42 +08:00
|
|
|
struct xdp_attachment_info xdp_hw;
|
2017-12-02 07:08:59 +08:00
|
|
|
|
|
|
|
bool bpf_tc_accept;
|
|
|
|
bool bpf_tc_non_bound_accept;
|
|
|
|
bool bpf_xdpdrv_accept;
|
|
|
|
bool bpf_xdpoffload_accept;
|
2018-01-18 11:13:30 +08:00
|
|
|
|
|
|
|
bool bpf_map_accept;
|
2018-06-27 01:07:54 +08:00
|
|
|
struct nsim_ipsec ipsec;
|
2020-07-10 08:42:48 +08:00
|
|
|
struct {
|
|
|
|
u32 inject_error;
|
|
|
|
u32 sleep;
|
2020-09-26 08:56:42 +08:00
|
|
|
u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS];
|
|
|
|
u32 (*ports)[NSIM_UDP_TUNNEL_N_PORTS];
|
2020-07-10 08:42:48 +08:00
|
|
|
struct debugfs_u32_array dfs_ports[2];
|
|
|
|
} udp_ports;
|
2020-09-15 08:11:54 +08:00
|
|
|
|
|
|
|
struct nsim_ethtool ethtool;
|
2017-12-02 07:08:58 +08:00
|
|
|
};
|
2017-12-02 07:08:59 +08:00
|
|
|
|
2019-04-25 21:59:55 +08:00
|
|
|
struct netdevsim *
|
|
|
|
nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port);
|
|
|
|
void nsim_destroy(struct netdevsim *ns);
|
|
|
|
|
2020-09-15 08:11:54 +08:00
|
|
|
void nsim_ethtool_init(struct netdevsim *ns);
|
|
|
|
|
2020-07-10 08:42:48 +08:00
|
|
|
void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev);
|
|
|
|
int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev,
|
|
|
|
struct net_device *dev);
|
|
|
|
void nsim_udp_tunnels_info_destroy(struct net_device *dev);
|
|
|
|
|
2018-01-24 03:22:54 +08:00
|
|
|
#ifdef CONFIG_BPF_SYSCALL
|
2019-04-25 21:59:50 +08:00
|
|
|
int nsim_bpf_dev_init(struct nsim_dev *nsim_dev);
|
|
|
|
void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev);
|
2017-12-02 07:08:59 +08:00
|
|
|
int nsim_bpf_init(struct netdevsim *ns);
|
|
|
|
void nsim_bpf_uninit(struct netdevsim *ns);
|
|
|
|
int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf);
|
|
|
|
int nsim_bpf_disable_tc(struct netdevsim *ns);
|
|
|
|
int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type,
|
|
|
|
void *type_data, void *cb_priv);
|
2018-01-24 03:22:54 +08:00
|
|
|
#else
|
2019-04-25 21:59:50 +08:00
|
|
|
|
|
|
|
static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev)
|
|
|
|
{
|
|
|
|
}
|
2018-01-24 03:22:54 +08:00
|
|
|
static inline int nsim_bpf_init(struct netdevsim *ns)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void nsim_bpf_uninit(struct netdevsim *ns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf)
|
|
|
|
{
|
2020-07-22 14:46:02 +08:00
|
|
|
return -EOPNOTSUPP;
|
2018-01-24 03:22:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline int nsim_bpf_disable_tc(struct netdevsim *ns)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int
|
|
|
|
nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, void *type_data,
|
|
|
|
void *cb_priv)
|
|
|
|
{
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
#endif
|
2017-12-02 07:09:01 +08:00
|
|
|
|
2018-03-28 09:22:00 +08:00
|
|
|
enum nsim_resource_id {
|
|
|
|
NSIM_RESOURCE_NONE, /* DEVLINK_RESOURCE_ID_PARENT_TOP */
|
|
|
|
NSIM_RESOURCE_IPV4,
|
|
|
|
NSIM_RESOURCE_IPV4_FIB,
|
|
|
|
NSIM_RESOURCE_IPV4_FIB_RULES,
|
|
|
|
NSIM_RESOURCE_IPV6,
|
|
|
|
NSIM_RESOURCE_IPV6_FIB,
|
|
|
|
NSIM_RESOURCE_IPV6_FIB_RULES,
|
2020-11-04 21:30:37 +08:00
|
|
|
NSIM_RESOURCE_NEXTHOPS,
|
2018-03-28 09:22:00 +08:00
|
|
|
};
|
|
|
|
|
2019-10-10 21:18:50 +08:00
|
|
|
struct nsim_dev_health {
|
|
|
|
struct devlink_health_reporter *empty_reporter;
|
|
|
|
struct devlink_health_reporter *dummy_reporter;
|
|
|
|
struct dentry *ddir;
|
|
|
|
char *recovered_break_msg;
|
|
|
|
u32 binary_len;
|
|
|
|
bool fail_recover;
|
|
|
|
};
|
|
|
|
|
|
|
|
int nsim_dev_health_init(struct nsim_dev *nsim_dev, struct devlink *devlink);
|
|
|
|
void nsim_dev_health_exit(struct nsim_dev *nsim_dev);
|
|
|
|
|
2021-03-14 20:19:32 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PSAMPLE)
|
|
|
|
int nsim_dev_psample_init(struct nsim_dev *nsim_dev);
|
|
|
|
void nsim_dev_psample_exit(struct nsim_dev *nsim_dev);
|
|
|
|
#else
|
|
|
|
static inline int nsim_dev_psample_init(struct nsim_dev *nsim_dev)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void nsim_dev_psample_exit(struct nsim_dev *nsim_dev)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2021-06-02 20:17:16 +08:00
|
|
|
enum nsim_dev_port_type {
|
|
|
|
NSIM_DEV_PORT_TYPE_PF,
|
|
|
|
NSIM_DEV_PORT_TYPE_VF,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define NSIM_DEV_VF_PORT_INDEX_BASE 128
|
|
|
|
#define NSIM_DEV_VF_PORT_INDEX_MAX UINT_MAX
|
|
|
|
|
2019-04-25 21:59:53 +08:00
|
|
|
struct nsim_dev_port {
|
|
|
|
struct list_head list;
|
|
|
|
struct devlink_port devlink_port;
|
|
|
|
unsigned int port_index;
|
2021-06-02 20:17:16 +08:00
|
|
|
enum nsim_dev_port_type port_type;
|
2019-04-25 21:59:53 +08:00
|
|
|
struct dentry *ddir;
|
2021-06-02 20:17:29 +08:00
|
|
|
struct dentry *rate_parent;
|
|
|
|
char *parent_name;
|
2019-04-25 21:59:55 +08:00
|
|
|
struct netdevsim *ns;
|
2019-04-25 21:59:53 +08:00
|
|
|
};
|
|
|
|
|
2019-04-25 21:59:49 +08:00
|
|
|
struct nsim_dev {
|
2019-04-25 21:59:50 +08:00
|
|
|
struct nsim_bus_dev *nsim_bus_dev;
|
2019-04-25 21:59:49 +08:00
|
|
|
struct nsim_fib_data *fib_data;
|
2019-08-17 21:28:20 +08:00
|
|
|
struct nsim_trap_data *trap_data;
|
2019-04-25 21:59:50 +08:00
|
|
|
struct dentry *ddir;
|
2019-04-25 21:59:52 +08:00
|
|
|
struct dentry *ports_ddir;
|
netdevsim: fix panic in nsim_dev_take_snapshot_write()
nsim_dev_take_snapshot_write() uses nsim_dev and nsim_dev->dummy_region.
So, during this function, these data shouldn't be removed.
But there is no protecting stuff in this function.
There are two similar cases.
1. reload case
reload could be called during nsim_dev_take_snapshot_write().
When reload is being executed, nsim_dev_reload_down() is called and it
calls nsim_dev_reload_destroy(). nsim_dev_reload_destroy() calls
devlink_region_destroy() to destroy nsim_dev->dummy_region.
So, during nsim_dev_take_snapshot_write(), nsim_dev->dummy_region()
would be removed.
At this point, snapshot_write() would access freed pointer.
In order to fix this case, take_snapshot file will be removed before
devlink_region_destroy().
The take_snapshot file will be re-created by ->reload_up().
2. del_device_store case
del_device_store() also could call nsim_dev_reload_destroy()
during nsim_dev_take_snapshot_write(). If so, panic would occur.
This problem is actually the same problem with the first case.
So, this problem will be fixed by the first case's solution.
Test commands:
modprobe netdevsim
while :
do
echo 1 > /sys/bus/netdevsim/new_device &
echo 1 > /sys/bus/netdevsim/del_device &
devlink dev reload netdevsim/netdevsim1 &
echo 1 > /sys/kernel/debug/netdevsim/netdevsim1/take_snapshot &
done
Splat looks like:
[ 45.564513][ T975] general protection fault, probably for non-canonical address 0xdffffc000000003a: 0000 [#1] SMP DEI
[ 45.566131][ T975] KASAN: null-ptr-deref in range [0x00000000000001d0-0x00000000000001d7]
[ 45.566135][ T975] CPU: 1 PID: 975 Comm: bash Not tainted 5.5.0+ #322
[ 45.569020][ T975] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 45.569026][ T975] RIP: 0010:__mutex_lock+0x10a/0x14b0
[ 45.570518][ T975] Code: 08 84 d2 0f 85 7f 12 00 00 44 8b 0d 10 23 65 02 45 85 c9 75 29 49 8d 7f 68 48 b8 00 00 00 0f
[ 45.570522][ T975] RSP: 0018:ffff888046ccfbf0 EFLAGS: 00010206
[ 45.572305][ T975] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 45.572308][ T975] RDX: 000000000000003a RSI: ffffffffac926440 RDI: 00000000000001d0
[ 45.576843][ T975] RBP: ffff888046ccfd70 R08: ffffffffab610645 R09: 0000000000000000
[ 45.576847][ T975] R10: ffff888046ccfd90 R11: ffffed100d6360ad R12: 0000000000000000
[ 45.578471][ T975] R13: dffffc0000000000 R14: ffffffffae1976c0 R15: 0000000000000168
[ 45.578475][ T975] FS: 00007f614d6e7740(0000) GS:ffff88806c400000(0000) knlGS:0000000000000000
[ 45.581492][ T975] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 45.582942][ T975] CR2: 00005618677d1cf0 CR3: 000000005fb9c002 CR4: 00000000000606e0
[ 45.584543][ T975] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 45.586633][ T975] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 45.589889][ T975] Call Trace:
[ 45.591445][ T975] ? devlink_region_snapshot_create+0x55/0x4a0
[ 45.601250][ T975] ? mutex_lock_io_nested+0x1380/0x1380
[ 45.602817][ T975] ? mutex_lock_io_nested+0x1380/0x1380
[ 45.603875][ T975] ? mark_held_locks+0xa5/0xe0
[ 45.604769][ T975] ? _raw_spin_unlock_irqrestore+0x2d/0x50
[ 45.606147][ T975] ? __mutex_unlock_slowpath+0xd0/0x670
[ 45.607723][ T975] ? crng_backtrack_protect+0x80/0x80
[ 45.613530][ T975] ? wait_for_completion+0x390/0x390
[ 45.615152][ T975] ? devlink_region_snapshot_create+0x55/0x4a0
[ 45.616834][ T975] devlink_region_snapshot_create+0x55/0x4a0
[ ... ]
Fixes: 4418f862d675 ("netdevsim: implement support for devlink region and snapshots")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-02-02 00:43:13 +08:00
|
|
|
struct dentry *take_snapshot;
|
2021-06-02 20:17:14 +08:00
|
|
|
struct dentry *max_vfs;
|
2021-06-02 20:17:26 +08:00
|
|
|
struct dentry *nodes_ddir;
|
2019-04-25 21:59:50 +08:00
|
|
|
struct bpf_offload_dev *bpf_dev;
|
|
|
|
bool bpf_bind_accept;
|
2020-12-09 21:57:39 +08:00
|
|
|
bool bpf_bind_verifier_accept;
|
2019-04-25 21:59:50 +08:00
|
|
|
u32 bpf_bind_verifier_delay;
|
|
|
|
struct dentry *ddir_bpf_bound_progs;
|
|
|
|
u32 prog_id_gen;
|
|
|
|
struct list_head bpf_bound_progs;
|
|
|
|
struct list_head bpf_bound_maps;
|
2019-04-25 21:59:51 +08:00
|
|
|
struct netdev_phys_item_id switch_id;
|
2019-04-25 21:59:53 +08:00
|
|
|
struct list_head port_list;
|
2019-04-25 21:59:54 +08:00
|
|
|
struct mutex port_list_lock; /* protects port list */
|
2019-06-04 21:40:43 +08:00
|
|
|
bool fw_update_status;
|
2020-09-26 04:46:08 +08:00
|
|
|
u32 fw_update_overwrite_mask;
|
2019-08-09 19:05:12 +08:00
|
|
|
u32 max_macs;
|
|
|
|
bool test1;
|
2019-10-06 14:30:01 +08:00
|
|
|
bool dont_allow_reload;
|
|
|
|
bool fail_reload;
|
2019-08-15 21:46:33 +08:00
|
|
|
struct devlink_region *dummy_region;
|
2019-10-10 21:18:50 +08:00
|
|
|
struct nsim_dev_health health;
|
2020-02-25 18:45:26 +08:00
|
|
|
struct flow_action_cookie *fa_cookie;
|
|
|
|
spinlock_t fa_cookie_lock; /* protects fa_cookie */
|
2020-03-31 03:38:23 +08:00
|
|
|
bool fail_trap_group_set;
|
2020-03-31 03:38:20 +08:00
|
|
|
bool fail_trap_policer_set;
|
|
|
|
bool fail_trap_policer_counter_get;
|
2021-06-17 19:36:32 +08:00
|
|
|
bool fail_trap_drop_counter_get;
|
2020-07-10 08:42:48 +08:00
|
|
|
struct {
|
2020-09-26 08:56:42 +08:00
|
|
|
struct udp_tunnel_nic_shared utn_shared;
|
|
|
|
u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS];
|
2020-07-10 08:42:48 +08:00
|
|
|
bool sync_all;
|
|
|
|
bool open_only;
|
|
|
|
bool ipv4_only;
|
2020-09-26 08:56:42 +08:00
|
|
|
bool shared;
|
2020-09-26 08:56:47 +08:00
|
|
|
bool static_iana_vxlan;
|
2020-07-10 08:42:48 +08:00
|
|
|
u32 sleep;
|
|
|
|
} udp_ports;
|
2021-03-14 20:19:32 +08:00
|
|
|
struct nsim_dev_psample *psample;
|
2021-06-02 20:17:18 +08:00
|
|
|
u16 esw_mode;
|
2019-04-25 21:59:49 +08:00
|
|
|
};
|
|
|
|
|
2021-06-02 20:17:18 +08:00
|
|
|
int nsim_esw_legacy_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack *extack);
|
|
|
|
int nsim_esw_switchdev_enable(struct nsim_dev *nsim_dev, struct netlink_ext_ack *extack);
|
|
|
|
|
|
|
|
static inline bool nsim_esw_mode_is_legacy(struct nsim_dev *nsim_dev)
|
|
|
|
{
|
|
|
|
return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_LEGACY;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool nsim_esw_mode_is_switchdev(struct nsim_dev *nsim_dev)
|
|
|
|
{
|
|
|
|
return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_SWITCHDEV;
|
|
|
|
}
|
|
|
|
|
2019-10-03 17:49:37 +08:00
|
|
|
static inline struct net *nsim_dev_net(struct nsim_dev *nsim_dev)
|
|
|
|
{
|
|
|
|
return devlink_net(priv_to_devlink(nsim_dev));
|
|
|
|
}
|
|
|
|
|
2019-04-25 21:59:50 +08:00
|
|
|
int nsim_dev_init(void);
|
|
|
|
void nsim_dev_exit(void);
|
2019-04-25 21:59:53 +08:00
|
|
|
int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev);
|
|
|
|
void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev);
|
2019-04-25 21:59:54 +08:00
|
|
|
int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
|
2021-06-02 20:17:16 +08:00
|
|
|
enum nsim_dev_port_type type,
|
2019-04-25 21:59:54 +08:00
|
|
|
unsigned int port_index);
|
|
|
|
int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
|
2021-06-02 20:17:16 +08:00
|
|
|
enum nsim_dev_port_type type,
|
2019-04-25 21:59:54 +08:00
|
|
|
unsigned int port_index);
|
2018-03-28 09:22:00 +08:00
|
|
|
|
2019-10-03 17:49:36 +08:00
|
|
|
struct nsim_fib_data *nsim_fib_create(struct devlink *devlink,
|
|
|
|
struct netlink_ext_ack *extack);
|
|
|
|
void nsim_fib_destroy(struct devlink *devlink, struct nsim_fib_data *fib_data);
|
2019-10-03 17:49:26 +08:00
|
|
|
u64 nsim_fib_get_val(struct nsim_fib_data *fib_data,
|
|
|
|
enum nsim_resource_id res_id, bool max);
|
2018-03-28 09:22:00 +08:00
|
|
|
|
2021-06-02 20:17:14 +08:00
|
|
|
ssize_t nsim_bus_dev_max_vfs_read(struct file *file,
|
|
|
|
char __user *data,
|
|
|
|
size_t count, loff_t *ppos);
|
|
|
|
ssize_t nsim_bus_dev_max_vfs_write(struct file *file,
|
|
|
|
const char __user *data,
|
|
|
|
size_t count, loff_t *ppos);
|
2021-06-02 20:17:15 +08:00
|
|
|
void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev);
|
2021-06-02 20:17:14 +08:00
|
|
|
|
2021-06-02 20:17:16 +08:00
|
|
|
static inline bool nsim_dev_port_is_pf(struct nsim_dev_port *nsim_dev_port)
|
|
|
|
{
|
|
|
|
return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_PF;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool nsim_dev_port_is_vf(struct nsim_dev_port *nsim_dev_port)
|
|
|
|
{
|
|
|
|
return nsim_dev_port->port_type == NSIM_DEV_PORT_TYPE_VF;
|
|
|
|
}
|
2018-06-27 01:07:54 +08:00
|
|
|
#if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
|
|
|
|
void nsim_ipsec_init(struct netdevsim *ns);
|
|
|
|
void nsim_ipsec_teardown(struct netdevsim *ns);
|
|
|
|
bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb);
|
|
|
|
#else
|
|
|
|
static inline void nsim_ipsec_init(struct netdevsim *ns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void nsim_ipsec_teardown(struct netdevsim *ns)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-04-25 21:59:45 +08:00
|
|
|
struct nsim_vf_config {
|
|
|
|
int link_state;
|
|
|
|
u16 min_tx_rate;
|
|
|
|
u16 max_tx_rate;
|
|
|
|
u16 vlan;
|
|
|
|
__be16 vlan_proto;
|
|
|
|
u16 qos;
|
|
|
|
u8 vf_mac[ETH_ALEN];
|
|
|
|
bool spoofchk_enabled;
|
|
|
|
bool trusted;
|
|
|
|
bool rss_query_enabled;
|
|
|
|
};
|
2019-04-25 21:59:44 +08:00
|
|
|
|
2019-04-25 21:59:45 +08:00
|
|
|
struct nsim_bus_dev {
|
|
|
|
struct device dev;
|
2019-04-25 21:59:48 +08:00
|
|
|
struct list_head list;
|
|
|
|
unsigned int port_count;
|
2019-10-05 14:10:32 +08:00
|
|
|
struct net *initial_net; /* Purpose of this is to carry net pointer
|
|
|
|
* during the probe time only.
|
|
|
|
*/
|
2021-06-02 20:17:14 +08:00
|
|
|
unsigned int max_vfs;
|
2019-04-25 21:59:45 +08:00
|
|
|
unsigned int num_vfs;
|
2021-06-02 20:17:14 +08:00
|
|
|
struct mutex vfs_lock; /* Protects vfconfigs */
|
2019-04-25 21:59:45 +08:00
|
|
|
struct nsim_vf_config *vfconfigs;
|
2020-02-02 00:43:04 +08:00
|
|
|
/* Lock for devlink->reload_enabled in netdevsim module */
|
|
|
|
struct mutex nsim_bus_reload_lock;
|
netdevsim: fix using uninitialized resources
When module is being initialized, __init() calls bus_register() and
driver_register().
These functions internally create various resources and sysfs files.
The sysfs files are used for basic operations(add/del device).
/sys/bus/netdevsim/new_device
/sys/bus/netdevsim/del_device
These sysfs files use netdevsim resources, they are mostly allocated
and initialized in ->probe() function, which is nsim_dev_probe().
But, sysfs files could be executed before ->probe() is finished.
So, accessing uninitialized data would occur.
Another problem is very similar.
/sys/bus/netdevsim/new_device internally creates sysfs files.
/sys/devices/netdevsim<id>/new_port
/sys/devices/netdevsim<id>/del_port
These sysfs files also use netdevsim resources, they are mostly allocated
and initialized in creating device routine, which is nsim_bus_dev_new().
But they also could be executed before nsim_bus_dev_new() is finished.
So, accessing uninitialized data would occur.
To fix these problems, this patch adds flags, which means whether the
operation is finished or not.
The flag variable 'nsim_bus_enable' means whether netdevsim bus was
initialized or not.
This is protected by nsim_bus_dev_list_lock.
The flag variable 'nsim_bus_dev->init' means whether nsim_bus_dev was
initialized or not.
This could be used in {new/del}_port_store() with no lock.
Test commands:
#SHELL1
modprobe netdevsim
while :
do
echo "1 1" > /sys/bus/netdevsim/new_device
echo "1 1" > /sys/bus/netdevsim/del_device
done
#SHELL2
while :
do
echo 1 > /sys/devices/netdevsim1/new_port
echo 1 > /sys/devices/netdevsim1/del_port
done
Splat looks like:
[ 47.508954][ T1008] general protection fault, probably for non-canonical address 0xdffffc0000000021: 0000 I
[ 47.510793][ T1008] KASAN: null-ptr-deref in range [0x0000000000000108-0x000000000000010f]
[ 47.511963][ T1008] CPU: 2 PID: 1008 Comm: bash Not tainted 5.5.0+ #322
[ 47.512823][ T1008] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 47.514041][ T1008] RIP: 0010:__mutex_lock+0x10a/0x14b0
[ 47.514699][ T1008] Code: 08 84 d2 0f 85 7f 12 00 00 44 8b 0d 10 23 65 02 45 85 c9 75 29 49 8d 7f 68 48 b8 00 00 00 0f
[ 47.517163][ T1008] RSP: 0018:ffff888059b4fbb0 EFLAGS: 00010206
[ 47.517802][ T1008] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 47.518941][ T1008] RDX: 0000000000000021 RSI: ffffffff85926440 RDI: 0000000000000108
[ 47.519732][ T1008] RBP: ffff888059b4fd30 R08: ffffffffc073fad0 R09: 0000000000000000
[ 47.520729][ T1008] R10: ffff888059b4fd50 R11: ffff88804bb38040 R12: 0000000000000000
[ 47.521702][ T1008] R13: dffffc0000000000 R14: ffffffff871976c0 R15: 00000000000000a0
[ 47.522760][ T1008] FS: 00007fd4be05a740(0000) GS:ffff88806c800000(0000) knlGS:0000000000000000
[ 47.523877][ T1008] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 47.524627][ T1008] CR2: 0000561c82b69cf0 CR3: 0000000065dd6004 CR4: 00000000000606e0
[ 47.527662][ T1008] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 47.528604][ T1008] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 47.529531][ T1008] Call Trace:
[ 47.529874][ T1008] ? nsim_dev_port_add+0x50/0x150 [netdevsim]
[ 47.530470][ T1008] ? mutex_lock_io_nested+0x1380/0x1380
[ 47.531018][ T1008] ? _kstrtoull+0x76/0x160
[ 47.531449][ T1008] ? _parse_integer+0xf0/0xf0
[ 47.531874][ T1008] ? kernfs_fop_write+0x1cf/0x410
[ 47.532330][ T1008] ? sysfs_file_ops+0x160/0x160
[ 47.532773][ T1008] ? kstrtouint+0x86/0x110
[ 47.533168][ T1008] ? nsim_dev_port_add+0x50/0x150 [netdevsim]
[ 47.533721][ T1008] nsim_dev_port_add+0x50/0x150 [netdevsim]
[ 47.534336][ T1008] ? sysfs_file_ops+0x160/0x160
[ 47.534858][ T1008] new_port_store+0x99/0xb0 [netdevsim]
[ 47.535439][ T1008] ? del_port_store+0xb0/0xb0 [netdevsim]
[ 47.536035][ T1008] ? sysfs_file_ops+0x112/0x160
[ 47.536544][ T1008] ? sysfs_kf_write+0x3b/0x180
[ 47.537029][ T1008] kernfs_fop_write+0x276/0x410
[ 47.537548][ T1008] ? __sb_start_write+0x215/0x2e0
[ 47.538110][ T1008] vfs_write+0x197/0x4a0
[ ... ]
Fixes: f9d9db47d3ba ("netdevsim: add bus attributes to add new and delete devices")
Fixes: 794b2c05ca1c ("netdevsim: extend device attrs to support port addition and deletion")
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2020-02-02 00:42:54 +08:00
|
|
|
bool init;
|
2019-04-25 21:59:45 +08:00
|
|
|
};
|
2019-04-25 21:59:44 +08:00
|
|
|
|
|
|
|
int nsim_bus_init(void);
|
|
|
|
void nsim_bus_exit(void);
|