mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-05 17:03:47 -04:00
net/mlx5e: fix double free of encap_header
Cited commit introduced potential double free since encap_header can be
destroyed twice in some cases - once by error cleanup sequence in
mlx5e_tc_tun_{create|update}_header_ipv{4|6}(), once by generic
mlx5e_encap_put() that user calls as a result of getting an error from
tunnel create|update. At the same time the point where e->encap_header is
assigned can't be delayed because the function can still return non-error
code 0 as a result of checking for NUD_VALID flag, which will cause
neighbor update to dereference NULL encap_header.
Fix the issue by:
- Nulling local encap_header variables in
mlx5e_tc_tun_{create|update}_header_ipv{4|6}() to make kfree(encap_header)
call in error cleanup sequence noop after that point.
- Assigning reformat_params.data from e->encap_header instead of local
variable encap_header that was set to NULL pointer by previous step. Also
assign reformat_params.size from e->encap_size for uniformity and in order
to make the code less error-prone in the future.
Fixes: d589e785ba ("net/mlx5e: Allow concurrent creation of encap entries")
Reported-by: Dust Li <dust.li@linux.alibaba.com>
Reported-by: Cruz Zhao <cruzzhao@linux.alibaba.com>
Reported-by: Tianchen Ding <dtcccc@linux.alibaba.com>
Signed-off-by: Vlad Buslov <vladbu@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
committed by
Saeed Mahameed
parent
5d089684dc
commit
8e13cd737c
@@ -302,6 +302,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
|
||||
|
||||
e->encap_size = ipv4_encap_size;
|
||||
e->encap_header = encap_header;
|
||||
encap_header = NULL;
|
||||
|
||||
if (!(nud_state & NUD_VALID)) {
|
||||
neigh_event_send(attr.n, NULL);
|
||||
@@ -313,8 +314,8 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
|
||||
|
||||
memset(&reformat_params, 0, sizeof(reformat_params));
|
||||
reformat_params.type = e->reformat_type;
|
||||
reformat_params.size = ipv4_encap_size;
|
||||
reformat_params.data = encap_header;
|
||||
reformat_params.size = e->encap_size;
|
||||
reformat_params.data = e->encap_header;
|
||||
e->pkt_reformat = mlx5_packet_reformat_alloc(priv->mdev, &reformat_params,
|
||||
MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (IS_ERR(e->pkt_reformat)) {
|
||||
@@ -407,6 +408,7 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv,
|
||||
e->encap_size = ipv4_encap_size;
|
||||
kfree(e->encap_header);
|
||||
e->encap_header = encap_header;
|
||||
encap_header = NULL;
|
||||
|
||||
if (!(nud_state & NUD_VALID)) {
|
||||
neigh_event_send(attr.n, NULL);
|
||||
@@ -418,8 +420,8 @@ int mlx5e_tc_tun_update_header_ipv4(struct mlx5e_priv *priv,
|
||||
|
||||
memset(&reformat_params, 0, sizeof(reformat_params));
|
||||
reformat_params.type = e->reformat_type;
|
||||
reformat_params.size = ipv4_encap_size;
|
||||
reformat_params.data = encap_header;
|
||||
reformat_params.size = e->encap_size;
|
||||
reformat_params.data = e->encap_header;
|
||||
e->pkt_reformat = mlx5_packet_reformat_alloc(priv->mdev, &reformat_params,
|
||||
MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (IS_ERR(e->pkt_reformat)) {
|
||||
@@ -570,6 +572,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
|
||||
|
||||
e->encap_size = ipv6_encap_size;
|
||||
e->encap_header = encap_header;
|
||||
encap_header = NULL;
|
||||
|
||||
if (!(nud_state & NUD_VALID)) {
|
||||
neigh_event_send(attr.n, NULL);
|
||||
@@ -581,8 +584,8 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
|
||||
|
||||
memset(&reformat_params, 0, sizeof(reformat_params));
|
||||
reformat_params.type = e->reformat_type;
|
||||
reformat_params.size = ipv6_encap_size;
|
||||
reformat_params.data = encap_header;
|
||||
reformat_params.size = e->encap_size;
|
||||
reformat_params.data = e->encap_header;
|
||||
e->pkt_reformat = mlx5_packet_reformat_alloc(priv->mdev, &reformat_params,
|
||||
MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (IS_ERR(e->pkt_reformat)) {
|
||||
@@ -674,6 +677,7 @@ int mlx5e_tc_tun_update_header_ipv6(struct mlx5e_priv *priv,
|
||||
e->encap_size = ipv6_encap_size;
|
||||
kfree(e->encap_header);
|
||||
e->encap_header = encap_header;
|
||||
encap_header = NULL;
|
||||
|
||||
if (!(nud_state & NUD_VALID)) {
|
||||
neigh_event_send(attr.n, NULL);
|
||||
@@ -685,8 +689,8 @@ int mlx5e_tc_tun_update_header_ipv6(struct mlx5e_priv *priv,
|
||||
|
||||
memset(&reformat_params, 0, sizeof(reformat_params));
|
||||
reformat_params.type = e->reformat_type;
|
||||
reformat_params.size = ipv6_encap_size;
|
||||
reformat_params.data = encap_header;
|
||||
reformat_params.size = e->encap_size;
|
||||
reformat_params.data = e->encap_header;
|
||||
e->pkt_reformat = mlx5_packet_reformat_alloc(priv->mdev, &reformat_params,
|
||||
MLX5_FLOW_NAMESPACE_FDB);
|
||||
if (IS_ERR(e->pkt_reformat)) {
|
||||
|
||||
Reference in New Issue
Block a user