Unverified Commit 86f2d0b2 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!8911 net/mlx5e: Fix use-after-free of encap entry in neigh update handler

parents 6d232c2e 7143a2b5
Loading
Loading
Loading
Loading
+6 −9
Original line number Diff line number Diff line
@@ -129,9 +129,8 @@ static void mlx5e_rep_neigh_update(struct work_struct *work)
							     work);
	struct mlx5e_neigh_hash_entry *nhe = update_work->nhe;
	struct neighbour *n = update_work->n;
	struct mlx5e_encap_entry *e;
	struct mlx5e_encap_entry *e = NULL;
	unsigned char ha[ETH_ALEN];
	struct mlx5e_priv *priv;
	bool neigh_connected;
	u8 nud_state, dead;

@@ -152,14 +151,12 @@ static void mlx5e_rep_neigh_update(struct work_struct *work)

	trace_mlx5e_rep_neigh_update(nhe, ha, neigh_connected);

	list_for_each_entry(e, &nhe->encap_list, encap_list) {
		if (!mlx5e_encap_take(e))
			continue;
	/* mlx5e_get_next_init_encap() releases previous encap before returning
	 * the next one.
	 */
	while ((e = mlx5e_get_next_init_encap(nhe, e)) != NULL)
		mlx5e_rep_update_flows(netdev_priv(e->out_dev), e, neigh_connected, ha);

		priv = netdev_priv(e->out_dev);
		mlx5e_rep_update_flows(priv, e, neigh_connected, ha);
		mlx5e_encap_put(priv, e);
	}
	rtnl_unlock();
	mlx5e_release_neigh_update_work(update_work);
}
+1 −5
Original line number Diff line number Diff line
@@ -91,13 +91,9 @@ void mlx5e_rep_update_flows(struct mlx5e_priv *priv,

	ASSERT_RTNL();

	/* wait for encap to be fully initialized */
	wait_for_completion(&e->res_ready);

	mutex_lock(&esw->offloads.encap_tbl_lock);
	encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID);
	if (e->compl_result < 0 || (encap_connected == neigh_connected &&
				    ether_addr_equal(e->h_dest, ha)))
	if (encap_connected == neigh_connected && ether_addr_equal(e->h_dest, ha))
		goto unlock;

	mlx5e_take_all_encap_flows(e, &flow_list);
+30 −3
Original line number Diff line number Diff line
@@ -1647,9 +1647,12 @@ void mlx5e_put_encap_flow_list(struct mlx5e_priv *priv, struct list_head *flow_l
		mlx5e_flow_put(priv, flow);
}

typedef bool (match_cb)(struct mlx5e_encap_entry *);

static struct mlx5e_encap_entry *
mlx5e_get_next_valid_encap(struct mlx5e_neigh_hash_entry *nhe,
			   struct mlx5e_encap_entry *e)
mlx5e_get_next_matching_encap(struct mlx5e_neigh_hash_entry *nhe,
			      struct mlx5e_encap_entry *e,
			      match_cb match)
{
	struct mlx5e_encap_entry *next = NULL;

@@ -1684,7 +1687,7 @@ mlx5e_get_next_valid_encap(struct mlx5e_neigh_hash_entry *nhe,
	/* wait for encap to be fully initialized */
	wait_for_completion(&next->res_ready);
	/* continue searching if encap entry is not in valid state after completion */
	if (!(next->flags & MLX5_ENCAP_ENTRY_VALID)) {
	if (!match(next)) {
		e = next;
		goto retry;
	}
@@ -1692,6 +1695,30 @@ mlx5e_get_next_valid_encap(struct mlx5e_neigh_hash_entry *nhe,
	return next;
}

static bool mlx5e_encap_valid(struct mlx5e_encap_entry *e)
{
	return e->flags & MLX5_ENCAP_ENTRY_VALID;
}

static struct mlx5e_encap_entry *
mlx5e_get_next_valid_encap(struct mlx5e_neigh_hash_entry *nhe,
			   struct mlx5e_encap_entry *e)
{
	return mlx5e_get_next_matching_encap(nhe, e, mlx5e_encap_valid);
}

static bool mlx5e_encap_initialized(struct mlx5e_encap_entry *e)
{
	return e->compl_result >= 0;
}

struct mlx5e_encap_entry *
mlx5e_get_next_init_encap(struct mlx5e_neigh_hash_entry *nhe,
			  struct mlx5e_encap_entry *e)
{
	return mlx5e_get_next_matching_encap(nhe, e, mlx5e_encap_initialized);
}

void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
{
	struct mlx5e_neigh *m_neigh = &nhe->m_neigh;
+3 −0
Original line number Diff line number Diff line
@@ -161,6 +161,9 @@ void mlx5e_take_all_encap_flows(struct mlx5e_encap_entry *e, struct list_head *f
void mlx5e_put_encap_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list);

struct mlx5e_neigh_hash_entry;
struct mlx5e_encap_entry *
mlx5e_get_next_init_encap(struct mlx5e_neigh_hash_entry *nhe,
			  struct mlx5e_encap_entry *e);
void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe);

void mlx5e_tc_reoffload_flows_work(struct work_struct *work);