mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 02:39:48 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Daniel Borkmann says: ==================== pull-request: bpf 2019-12-19 The following pull-request contains BPF updates for your *net* tree. We've added 10 non-merge commits during the last 8 day(s) which contain a total of 21 files changed, 269 insertions(+), 108 deletions(-). The main changes are: 1) Fix lack of synchronization between xsk wakeup and destroying resources used by xsk wakeup, from Maxim Mikityanskiy. 2) Fix pruning with tail call patching, untrack programs in case of verifier error and fix a cgroup local storage tracking bug, from Daniel Borkmann. 3) Fix clearing skb->tstamp in bpf_redirect() when going from ingress to egress which otherwise cause issues e.g. on fq qdisc, from Lorenz Bauer. 4) Fix compile warning of unused proc_dointvec_minmax_bpf_restricted() when only cBPF is present, from Alexander Lobakin. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
0fd260056e
21 changed files with 276 additions and 115 deletions
|
@ -1152,7 +1152,7 @@ void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags);
|
|||
|
||||
static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi)
|
||||
{
|
||||
return !!vsi->xdp_prog;
|
||||
return !!READ_ONCE(vsi->xdp_prog);
|
||||
}
|
||||
|
||||
int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch);
|
||||
|
|
|
@ -6823,8 +6823,8 @@ void i40e_down(struct i40e_vsi *vsi)
|
|||
for (i = 0; i < vsi->num_queue_pairs; i++) {
|
||||
i40e_clean_tx_ring(vsi->tx_rings[i]);
|
||||
if (i40e_enabled_xdp_vsi(vsi)) {
|
||||
/* Make sure that in-progress ndo_xdp_xmit
|
||||
* calls are completed.
|
||||
/* Make sure that in-progress ndo_xdp_xmit and
|
||||
* ndo_xsk_wakeup calls are completed.
|
||||
*/
|
||||
synchronize_rcu();
|
||||
i40e_clean_tx_ring(vsi->xdp_rings[i]);
|
||||
|
@ -12546,8 +12546,12 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi,
|
|||
|
||||
old_prog = xchg(&vsi->xdp_prog, prog);
|
||||
|
||||
if (need_reset)
|
||||
if (need_reset) {
|
||||
if (!prog)
|
||||
/* Wait until ndo_xsk_wakeup completes. */
|
||||
synchronize_rcu();
|
||||
i40e_reset_and_rebuild(pf, true, true);
|
||||
}
|
||||
|
||||
for (i = 0; i < vsi->num_queue_pairs; i++)
|
||||
WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
|
||||
|
|
|
@ -787,8 +787,12 @@ int i40e_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
|
|||
{
|
||||
struct i40e_netdev_priv *np = netdev_priv(dev);
|
||||
struct i40e_vsi *vsi = np->vsi;
|
||||
struct i40e_pf *pf = vsi->back;
|
||||
struct i40e_ring *ring;
|
||||
|
||||
if (test_bit(__I40E_CONFIG_BUSY, pf->state))
|
||||
return -ENETDOWN;
|
||||
|
||||
if (test_bit(__I40E_VSI_DOWN, vsi->state))
|
||||
return -ENETDOWN;
|
||||
|
||||
|
|
|
@ -10261,7 +10261,12 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
|
|||
|
||||
/* If transitioning XDP modes reconfigure rings */
|
||||
if (need_reset) {
|
||||
int err = ixgbe_setup_tc(dev, adapter->hw_tcs);
|
||||
int err;
|
||||
|
||||
if (!prog)
|
||||
/* Wait until ndo_xsk_wakeup completes. */
|
||||
synchronize_rcu();
|
||||
err = ixgbe_setup_tc(dev, adapter->hw_tcs);
|
||||
|
||||
if (err) {
|
||||
rcu_assign_pointer(adapter->xdp_prog, old_prog);
|
||||
|
|
|
@ -709,10 +709,14 @@ int ixgbe_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
|
|||
if (qid >= adapter->num_xdp_queues)
|
||||
return -ENXIO;
|
||||
|
||||
if (!adapter->xdp_ring[qid]->xsk_umem)
|
||||
ring = adapter->xdp_ring[qid];
|
||||
|
||||
if (test_bit(__IXGBE_TX_DISABLED, &ring->state))
|
||||
return -ENETDOWN;
|
||||
|
||||
if (!ring->xsk_umem)
|
||||
return -ENXIO;
|
||||
|
||||
ring = adapter->xdp_ring[qid];
|
||||
if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
|
||||
u64 eics = BIT_ULL(ring->q_vector->v_idx);
|
||||
|
||||
|
|
|
@ -760,7 +760,7 @@ enum {
|
|||
MLX5E_STATE_OPENED,
|
||||
MLX5E_STATE_DESTROYING,
|
||||
MLX5E_STATE_XDP_TX_ENABLED,
|
||||
MLX5E_STATE_XDP_OPEN,
|
||||
MLX5E_STATE_XDP_ACTIVE,
|
||||
};
|
||||
|
||||
struct mlx5e_rqt {
|
||||
|
|
|
@ -75,12 +75,18 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
|
|||
static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
|
||||
{
|
||||
set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
|
||||
|
||||
if (priv->channels.params.xdp_prog)
|
||||
set_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
|
||||
}
|
||||
|
||||
static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
|
||||
{
|
||||
if (priv->channels.params.xdp_prog)
|
||||
clear_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
|
||||
|
||||
clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
|
||||
/* let other device's napi(s) see our new state */
|
||||
/* Let other device's napi(s) and XSK wakeups see our new state. */
|
||||
synchronize_rcu();
|
||||
}
|
||||
|
||||
|
@ -89,19 +95,9 @@ static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
|
|||
return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
|
||||
}
|
||||
|
||||
static inline void mlx5e_xdp_set_open(struct mlx5e_priv *priv)
|
||||
static inline bool mlx5e_xdp_is_active(struct mlx5e_priv *priv)
|
||||
{
|
||||
set_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
|
||||
}
|
||||
|
||||
static inline void mlx5e_xdp_set_closed(struct mlx5e_priv *priv)
|
||||
{
|
||||
clear_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
|
||||
}
|
||||
|
||||
static inline bool mlx5e_xdp_is_open(struct mlx5e_priv *priv)
|
||||
{
|
||||
return test_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
|
||||
return test_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
|
||||
}
|
||||
|
||||
static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
|
||||
|
|
|
@ -144,6 +144,7 @@ void mlx5e_close_xsk(struct mlx5e_channel *c)
|
|||
{
|
||||
clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
|
||||
napi_synchronize(&c->napi);
|
||||
synchronize_rcu(); /* Sync with the XSK wakeup. */
|
||||
|
||||
mlx5e_close_rq(&c->xskrq);
|
||||
mlx5e_close_cq(&c->xskrq.cq);
|
||||
|
|
|
@ -14,7 +14,7 @@ int mlx5e_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
|
|||
struct mlx5e_channel *c;
|
||||
u16 ix;
|
||||
|
||||
if (unlikely(!mlx5e_xdp_is_open(priv)))
|
||||
if (unlikely(!mlx5e_xdp_is_active(priv)))
|
||||
return -ENETDOWN;
|
||||
|
||||
if (unlikely(!mlx5e_qid_get_ch_if_in_group(params, qid, MLX5E_RQ_GROUP_XSK, &ix)))
|
||||
|
|
|
@ -3000,12 +3000,9 @@ void mlx5e_timestamp_init(struct mlx5e_priv *priv)
|
|||
int mlx5e_open_locked(struct net_device *netdev)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
bool is_xdp = priv->channels.params.xdp_prog;
|
||||
int err;
|
||||
|
||||
set_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
if (is_xdp)
|
||||
mlx5e_xdp_set_open(priv);
|
||||
|
||||
err = mlx5e_open_channels(priv, &priv->channels);
|
||||
if (err)
|
||||
|
@ -3020,8 +3017,6 @@ int mlx5e_open_locked(struct net_device *netdev)
|
|||
return 0;
|
||||
|
||||
err_clear_state_opened_flag:
|
||||
if (is_xdp)
|
||||
mlx5e_xdp_set_closed(priv);
|
||||
clear_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
return err;
|
||||
}
|
||||
|
@ -3053,8 +3048,6 @@ int mlx5e_close_locked(struct net_device *netdev)
|
|||
if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
|
||||
return 0;
|
||||
|
||||
if (priv->channels.params.xdp_prog)
|
||||
mlx5e_xdp_set_closed(priv);
|
||||
clear_bit(MLX5E_STATE_OPENED, &priv->state);
|
||||
|
||||
netif_carrier_off(priv->netdev);
|
||||
|
@ -4371,16 +4364,6 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_xdp_update_state(struct mlx5e_priv *priv)
|
||||
{
|
||||
if (priv->channels.params.xdp_prog)
|
||||
mlx5e_xdp_set_open(priv);
|
||||
else
|
||||
mlx5e_xdp_set_closed(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
|
@ -4415,7 +4398,7 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
|
|||
mlx5e_set_rq_type(priv->mdev, &new_channels.params);
|
||||
old_prog = priv->channels.params.xdp_prog;
|
||||
|
||||
err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_xdp_update_state);
|
||||
err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
|
||||
if (err)
|
||||
goto unlock;
|
||||
} else {
|
||||
|
|
|
@ -157,8 +157,8 @@ void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage,
|
|||
struct cgroup *cgroup,
|
||||
enum bpf_attach_type type);
|
||||
void bpf_cgroup_storage_unlink(struct bpf_cgroup_storage *storage);
|
||||
int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *map);
|
||||
void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *map);
|
||||
int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *map);
|
||||
void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *map);
|
||||
|
||||
int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, void *value);
|
||||
int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
|
||||
|
@ -360,9 +360,9 @@ static inline int cgroup_bpf_prog_query(const union bpf_attr *attr,
|
|||
|
||||
static inline void bpf_cgroup_storage_set(
|
||||
struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE]) {}
|
||||
static inline int bpf_cgroup_storage_assign(struct bpf_prog *prog,
|
||||
static inline int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux,
|
||||
struct bpf_map *map) { return 0; }
|
||||
static inline void bpf_cgroup_storage_release(struct bpf_prog *prog,
|
||||
static inline void bpf_cgroup_storage_release(struct bpf_prog_aux *aux,
|
||||
struct bpf_map *map) {}
|
||||
static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(
|
||||
struct bpf_prog *prog, enum bpf_cgroup_storage_type stype) { return NULL; }
|
||||
|
|
|
@ -818,6 +818,8 @@ struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog);
|
|||
void bpf_prog_put(struct bpf_prog *prog);
|
||||
int __bpf_prog_charge(struct user_struct *user, u32 pages);
|
||||
void __bpf_prog_uncharge(struct user_struct *user, u32 pages);
|
||||
void __bpf_free_used_maps(struct bpf_prog_aux *aux,
|
||||
struct bpf_map **used_maps, u32 len);
|
||||
|
||||
void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock);
|
||||
void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock);
|
||||
|
|
|
@ -2043,23 +2043,28 @@ static void bpf_free_cgroup_storage(struct bpf_prog_aux *aux)
|
|||
for_each_cgroup_storage_type(stype) {
|
||||
if (!aux->cgroup_storage[stype])
|
||||
continue;
|
||||
bpf_cgroup_storage_release(aux->prog,
|
||||
aux->cgroup_storage[stype]);
|
||||
bpf_cgroup_storage_release(aux, aux->cgroup_storage[stype]);
|
||||
}
|
||||
}
|
||||
|
||||
void __bpf_free_used_maps(struct bpf_prog_aux *aux,
|
||||
struct bpf_map **used_maps, u32 len)
|
||||
{
|
||||
struct bpf_map *map;
|
||||
u32 i;
|
||||
|
||||
bpf_free_cgroup_storage(aux);
|
||||
for (i = 0; i < len; i++) {
|
||||
map = used_maps[i];
|
||||
if (map->ops->map_poke_untrack)
|
||||
map->ops->map_poke_untrack(map, aux);
|
||||
bpf_map_put(map);
|
||||
}
|
||||
}
|
||||
|
||||
static void bpf_free_used_maps(struct bpf_prog_aux *aux)
|
||||
{
|
||||
struct bpf_map *map;
|
||||
int i;
|
||||
|
||||
bpf_free_cgroup_storage(aux);
|
||||
for (i = 0; i < aux->used_map_cnt; i++) {
|
||||
map = aux->used_maps[i];
|
||||
if (map->ops->map_poke_untrack)
|
||||
map->ops->map_poke_untrack(map, aux);
|
||||
bpf_map_put(map);
|
||||
}
|
||||
__bpf_free_used_maps(aux, aux->used_maps, aux->used_map_cnt);
|
||||
kfree(aux->used_maps);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ struct bpf_cgroup_storage_map {
|
|||
struct bpf_map map;
|
||||
|
||||
spinlock_t lock;
|
||||
struct bpf_prog *prog;
|
||||
struct bpf_prog_aux *aux;
|
||||
struct rb_root root;
|
||||
struct list_head list;
|
||||
};
|
||||
|
@ -420,7 +420,7 @@ const struct bpf_map_ops cgroup_storage_map_ops = {
|
|||
.map_seq_show_elem = cgroup_storage_seq_show_elem,
|
||||
};
|
||||
|
||||
int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
|
||||
int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *_map)
|
||||
{
|
||||
enum bpf_cgroup_storage_type stype = cgroup_storage_type(_map);
|
||||
struct bpf_cgroup_storage_map *map = map_to_storage(_map);
|
||||
|
@ -428,14 +428,14 @@ int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
|
|||
|
||||
spin_lock_bh(&map->lock);
|
||||
|
||||
if (map->prog && map->prog != prog)
|
||||
if (map->aux && map->aux != aux)
|
||||
goto unlock;
|
||||
if (prog->aux->cgroup_storage[stype] &&
|
||||
prog->aux->cgroup_storage[stype] != _map)
|
||||
if (aux->cgroup_storage[stype] &&
|
||||
aux->cgroup_storage[stype] != _map)
|
||||
goto unlock;
|
||||
|
||||
map->prog = prog;
|
||||
prog->aux->cgroup_storage[stype] = _map;
|
||||
map->aux = aux;
|
||||
aux->cgroup_storage[stype] = _map;
|
||||
ret = 0;
|
||||
unlock:
|
||||
spin_unlock_bh(&map->lock);
|
||||
|
@ -443,16 +443,16 @@ int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
|
|||
return ret;
|
||||
}
|
||||
|
||||
void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *_map)
|
||||
void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *_map)
|
||||
{
|
||||
enum bpf_cgroup_storage_type stype = cgroup_storage_type(_map);
|
||||
struct bpf_cgroup_storage_map *map = map_to_storage(_map);
|
||||
|
||||
spin_lock_bh(&map->lock);
|
||||
if (map->prog == prog) {
|
||||
WARN_ON(prog->aux->cgroup_storage[stype] != _map);
|
||||
map->prog = NULL;
|
||||
prog->aux->cgroup_storage[stype] = NULL;
|
||||
if (map->aux == aux) {
|
||||
WARN_ON(aux->cgroup_storage[stype] != _map);
|
||||
map->aux = NULL;
|
||||
aux->cgroup_storage[stype] = NULL;
|
||||
}
|
||||
spin_unlock_bh(&map->lock);
|
||||
}
|
||||
|
|
|
@ -4134,6 +4134,7 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
|
|||
struct bpf_map *map = meta->map_ptr;
|
||||
struct tnum range;
|
||||
u64 val;
|
||||
int err;
|
||||
|
||||
if (func_id != BPF_FUNC_tail_call)
|
||||
return 0;
|
||||
|
@ -4150,6 +4151,10 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
|
|||
return 0;
|
||||
}
|
||||
|
||||
err = mark_chain_precision(env, BPF_REG_3);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
val = reg->var_off.value;
|
||||
if (bpf_map_key_unseen(aux))
|
||||
bpf_map_key_store(aux, val);
|
||||
|
@ -8268,7 +8273,7 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env)
|
|||
env->used_maps[env->used_map_cnt++] = map;
|
||||
|
||||
if (bpf_map_is_cgroup_storage(map) &&
|
||||
bpf_cgroup_storage_assign(env->prog, map)) {
|
||||
bpf_cgroup_storage_assign(env->prog->aux, map)) {
|
||||
verbose(env, "only one cgroup storage of each type is allowed\n");
|
||||
fdput(f);
|
||||
return -EBUSY;
|
||||
|
@ -8298,18 +8303,8 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env)
|
|||
/* drop refcnt of maps used by the rejected program */
|
||||
static void release_maps(struct bpf_verifier_env *env)
|
||||
{
|
||||
enum bpf_cgroup_storage_type stype;
|
||||
int i;
|
||||
|
||||
for_each_cgroup_storage_type(stype) {
|
||||
if (!env->prog->aux->cgroup_storage[stype])
|
||||
continue;
|
||||
bpf_cgroup_storage_release(env->prog,
|
||||
env->prog->aux->cgroup_storage[stype]);
|
||||
}
|
||||
|
||||
for (i = 0; i < env->used_map_cnt; i++)
|
||||
bpf_map_put(env->used_maps[i]);
|
||||
__bpf_free_used_maps(env->prog->aux, env->used_maps,
|
||||
env->used_map_cnt);
|
||||
}
|
||||
|
||||
/* convert pseudo BPF_LD_IMM64 into generic BPF_LD_IMM64 */
|
||||
|
@ -9282,7 +9277,8 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
|
|||
insn->code = BPF_JMP | BPF_TAIL_CALL;
|
||||
|
||||
aux = &env->insn_aux_data[i + delta];
|
||||
if (prog->jit_requested && !expect_blinding &&
|
||||
if (env->allow_ptr_leaks && !expect_blinding &&
|
||||
prog->jit_requested &&
|
||||
!bpf_map_key_poisoned(aux) &&
|
||||
!bpf_map_ptr_poisoned(aux) &&
|
||||
!bpf_map_ptr_unpriv(aux)) {
|
||||
|
|
|
@ -2055,6 +2055,7 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
skb->dev = dev;
|
||||
skb->tstamp = 0;
|
||||
|
||||
dev_xmit_recursion_inc();
|
||||
ret = dev_queue_xmit(skb);
|
||||
|
|
|
@ -288,6 +288,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write,
|
|||
return ret;
|
||||
}
|
||||
|
||||
# ifdef CONFIG_HAVE_EBPF_JIT
|
||||
static int
|
||||
proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
|
@ -298,6 +299,7 @@ proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write,
|
|||
|
||||
return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
||||
}
|
||||
# endif /* CONFIG_HAVE_EBPF_JIT */
|
||||
|
||||
static int
|
||||
proc_dolongvec_minmax_bpf_restricted(struct ctl_table *table, int write,
|
||||
|
|
|
@ -334,12 +334,21 @@ bool xsk_umem_consume_tx(struct xdp_umem *umem, struct xdp_desc *desc)
|
|||
}
|
||||
EXPORT_SYMBOL(xsk_umem_consume_tx);
|
||||
|
||||
static int xsk_zc_xmit(struct xdp_sock *xs)
|
||||
static int xsk_wakeup(struct xdp_sock *xs, u8 flags)
|
||||
{
|
||||
struct net_device *dev = xs->dev;
|
||||
int err;
|
||||
|
||||
return dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id,
|
||||
XDP_WAKEUP_TX);
|
||||
rcu_read_lock();
|
||||
err = dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, flags);
|
||||
rcu_read_unlock();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int xsk_zc_xmit(struct xdp_sock *xs)
|
||||
{
|
||||
return xsk_wakeup(xs, XDP_WAKEUP_TX);
|
||||
}
|
||||
|
||||
static void xsk_destruct_skb(struct sk_buff *skb)
|
||||
|
@ -453,19 +462,16 @@ static __poll_t xsk_poll(struct file *file, struct socket *sock,
|
|||
__poll_t mask = datagram_poll(file, sock, wait);
|
||||
struct sock *sk = sock->sk;
|
||||
struct xdp_sock *xs = xdp_sk(sk);
|
||||
struct net_device *dev;
|
||||
struct xdp_umem *umem;
|
||||
|
||||
if (unlikely(!xsk_is_bound(xs)))
|
||||
return mask;
|
||||
|
||||
dev = xs->dev;
|
||||
umem = xs->umem;
|
||||
|
||||
if (umem->need_wakeup) {
|
||||
if (dev->netdev_ops->ndo_xsk_wakeup)
|
||||
dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id,
|
||||
umem->need_wakeup);
|
||||
if (xs->zc)
|
||||
xsk_wakeup(xs, umem->need_wakeup);
|
||||
else
|
||||
/* Poll needs to drive Tx also in copy mode */
|
||||
__xsk_sendmsg(sk);
|
||||
|
|
|
@ -408,10 +408,10 @@ static void update_map(int fd, int index)
|
|||
assert(!bpf_map_update_elem(fd, &index, &value, 0));
|
||||
}
|
||||
|
||||
static int create_prog_dummy1(enum bpf_prog_type prog_type)
|
||||
static int create_prog_dummy_simple(enum bpf_prog_type prog_type, int ret)
|
||||
{
|
||||
struct bpf_insn prog[] = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 42),
|
||||
BPF_MOV64_IMM(BPF_REG_0, ret),
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
|
||||
|
@ -419,14 +419,15 @@ static int create_prog_dummy1(enum bpf_prog_type prog_type)
|
|||
ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
|
||||
}
|
||||
|
||||
static int create_prog_dummy2(enum bpf_prog_type prog_type, int mfd, int idx)
|
||||
static int create_prog_dummy_loop(enum bpf_prog_type prog_type, int mfd,
|
||||
int idx, int ret)
|
||||
{
|
||||
struct bpf_insn prog[] = {
|
||||
BPF_MOV64_IMM(BPF_REG_3, idx),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, mfd),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
|
||||
BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 41),
|
||||
BPF_MOV64_IMM(BPF_REG_0, ret),
|
||||
BPF_EXIT_INSN(),
|
||||
};
|
||||
|
||||
|
@ -435,10 +436,9 @@ static int create_prog_dummy2(enum bpf_prog_type prog_type, int mfd, int idx)
|
|||
}
|
||||
|
||||
static int create_prog_array(enum bpf_prog_type prog_type, uint32_t max_elem,
|
||||
int p1key)
|
||||
int p1key, int p2key, int p3key)
|
||||
{
|
||||
int p2key = 1;
|
||||
int mfd, p1fd, p2fd;
|
||||
int mfd, p1fd, p2fd, p3fd;
|
||||
|
||||
mfd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
|
||||
sizeof(int), max_elem, 0);
|
||||
|
@ -449,23 +449,24 @@ static int create_prog_array(enum bpf_prog_type prog_type, uint32_t max_elem,
|
|||
return -1;
|
||||
}
|
||||
|
||||
p1fd = create_prog_dummy1(prog_type);
|
||||
p2fd = create_prog_dummy2(prog_type, mfd, p2key);
|
||||
if (p1fd < 0 || p2fd < 0)
|
||||
goto out;
|
||||
p1fd = create_prog_dummy_simple(prog_type, 42);
|
||||
p2fd = create_prog_dummy_loop(prog_type, mfd, p2key, 41);
|
||||
p3fd = create_prog_dummy_simple(prog_type, 24);
|
||||
if (p1fd < 0 || p2fd < 0 || p3fd < 0)
|
||||
goto err;
|
||||
if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0)
|
||||
goto out;
|
||||
goto err;
|
||||
if (bpf_map_update_elem(mfd, &p2key, &p2fd, BPF_ANY) < 0)
|
||||
goto out;
|
||||
goto err;
|
||||
if (bpf_map_update_elem(mfd, &p3key, &p3fd, BPF_ANY) < 0) {
|
||||
err:
|
||||
close(mfd);
|
||||
mfd = -1;
|
||||
}
|
||||
close(p3fd);
|
||||
close(p2fd);
|
||||
close(p1fd);
|
||||
|
||||
return mfd;
|
||||
out:
|
||||
close(p2fd);
|
||||
close(p1fd);
|
||||
close(mfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int create_map_in_map(void)
|
||||
|
@ -684,7 +685,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
|
|||
}
|
||||
|
||||
if (*fixup_prog1) {
|
||||
map_fds[4] = create_prog_array(prog_type, 4, 0);
|
||||
map_fds[4] = create_prog_array(prog_type, 4, 0, 1, 2);
|
||||
do {
|
||||
prog[*fixup_prog1].imm = map_fds[4];
|
||||
fixup_prog1++;
|
||||
|
@ -692,7 +693,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
|
|||
}
|
||||
|
||||
if (*fixup_prog2) {
|
||||
map_fds[5] = create_prog_array(prog_type, 8, 7);
|
||||
map_fds[5] = create_prog_array(prog_type, 8, 7, 1, 2);
|
||||
do {
|
||||
prog[*fixup_prog2].imm = map_fds[5];
|
||||
fixup_prog2++;
|
||||
|
|
|
@ -455,7 +455,7 @@
|
|||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
|
||||
BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 7),
|
||||
/* bpf_tail_call() */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 3),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
|
@ -478,7 +478,7 @@
|
|||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
|
||||
BPF_EMIT_CALL(BPF_FUNC_sk_release),
|
||||
/* bpf_tail_call() */
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 3),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
|
@ -497,7 +497,7 @@
|
|||
BPF_SK_LOOKUP(sk_lookup_tcp),
|
||||
/* bpf_tail_call() */
|
||||
BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 3),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
{
|
||||
"runtime/jit: tail_call within bounds, no prog",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 3),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
|
@ -37,6 +37,157 @@
|
|||
.result = ACCEPT,
|
||||
.retval = 1,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call within bounds, key 2",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_prog1 = { 1 },
|
||||
.result = ACCEPT,
|
||||
.retval = 24,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call within bounds, key 2 / key 2, first branch",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 13),
|
||||
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_prog1 = { 5, 9 },
|
||||
.result = ACCEPT,
|
||||
.retval = 24,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call within bounds, key 2 / key 2, second branch",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 14),
|
||||
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_prog1 = { 5, 9 },
|
||||
.result = ACCEPT,
|
||||
.retval = 24,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call within bounds, key 0 / key 2, first branch",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 13),
|
||||
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_prog1 = { 5, 9 },
|
||||
.result = ACCEPT,
|
||||
.retval = 24,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call within bounds, key 0 / key 2, second branch",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 14),
|
||||
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 2),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_prog1 = { 5, 9 },
|
||||
.result = ACCEPT,
|
||||
.retval = 42,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call within bounds, different maps, first branch",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 13),
|
||||
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_prog1 = { 5 },
|
||||
.fixup_prog2 = { 9 },
|
||||
.result_unpriv = REJECT,
|
||||
.errstr_unpriv = "tail_call abusing map_ptr",
|
||||
.result = ACCEPT,
|
||||
.retval = 1,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call within bounds, different maps, second branch",
|
||||
.insns = {
|
||||
BPF_MOV64_IMM(BPF_REG_0, 14),
|
||||
BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
|
||||
offsetof(struct __sk_buff, cb[0])),
|
||||
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_JMP_IMM(BPF_JA, 0, 0, 3),
|
||||
BPF_MOV64_IMM(BPF_REG_3, 0),
|
||||
BPF_LD_MAP_FD(BPF_REG_2, 0),
|
||||
BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
|
||||
BPF_MOV64_IMM(BPF_REG_0, 1),
|
||||
BPF_EXIT_INSN(),
|
||||
},
|
||||
.fixup_prog1 = { 5 },
|
||||
.fixup_prog2 = { 9 },
|
||||
.result_unpriv = REJECT,
|
||||
.errstr_unpriv = "tail_call abusing map_ptr",
|
||||
.result = ACCEPT,
|
||||
.retval = 42,
|
||||
},
|
||||
{
|
||||
"runtime/jit: tail_call out of bounds",
|
||||
.insns = {
|
||||
|
|
Loading…
Reference in a new issue