VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45900

CVE-2026-45900

Description

In the Linux kernel, the following vulnerability has been resolved:

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

When commit 0e1a4d427f58 ("crypto: caam: Unembed net_dev structure in dpaa2") converted embedded net_device to dynamically allocated pointers, it added cleanup in dpaa2_dpseci_disable() but missed adding cleanup in dpaa2_dpseci_free() for error paths.

This causes memory leaks when dpaa2_dpseci_dpio_setup() fails during probe due to DPIO devices not being ready yet. The kernel's deferred probe mechanism handles the retry successfully, but the netdevs allocated during the failed probe attempt are never freed, resulting in kmemleak reports showing multiple leaked netdev-related allocations all traced back to dpaa2_caam_probe().

Fix this by preserving the CPU mask of allocated netdevs during setup and using it for cleanup in dpaa2_dpseci_free(). This approach ensures that only the CPUs that actually had netdevs allocated will be cleaned up, avoiding potential issues with CPU hotplug scenarios.

Affected products

1

Patches

8
d5c6f254528c

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJianpeng ChangJan 20, 2026Fixed in 6.12.75via kernel-cna
4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index e809d030ab1135..ece9f1e5a689f6 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4813,7 +4813,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4821,6 +4822,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5006,16 +5013,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5117,7 +5123,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5125,18 +5131,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5181,7 +5185,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index e809d030ab1135..ece9f1e5a689f6 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4813,7 +4813,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4821,6 +4822,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5006,16 +5013,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5117,7 +5123,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5125,18 +5131,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5181,7 +5185,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
d7decb572b55

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJianpeng ChangJan 20, 2026Fixed in 6.18.14via kernel-cna
4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
e144cce29851

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJianpeng ChangJan 20, 2026Fixed in 6.19.4via kernel-cna
4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
7d43252b3060

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitJianpeng ChangJan 20, 2026Fixed in 7.0via kernel-cna
4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
e144cce29851

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
7d43252b3060

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
d5c6f254528c

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index e809d030ab1135..ece9f1e5a689f6 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4813,7 +4813,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4821,6 +4822,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5006,16 +5013,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5117,7 +5123,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5125,18 +5131,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5181,7 +5185,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index e809d030ab1135..ece9f1e5a689f6 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4813,7 +4813,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4821,6 +4822,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5006,16 +5013,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5117,7 +5123,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5125,18 +5131,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5181,7 +5185,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
d7decb572b55

crypto: caam - fix netdev memory leak in dpaa2_caam_probe

4 files changed · +34 26
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.c+15 12 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.c b/drivers/crypto/caam/caamalg_qi2.c
    index 107ccb2ade4205..c6117c23eb25b0 100644
    --- a/drivers/crypto/caam/caamalg_qi2.c
    +++ b/drivers/crypto/caam/caamalg_qi2.c
    @@ -4814,7 +4814,8 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     {
     	struct device *dev = priv->dev;
     	struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev);
    -	int err;
    +	struct dpaa2_caam_priv_per_cpu *ppriv;
    +	int i, err;
     
     	if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) {
     		err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle);
    @@ -4822,6 +4823,12 @@ static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv)
     			dev_err(dev, "dpseci_reset() failed\n");
     	}
     
    +	for_each_cpu(i, priv->clean_mask) {
    +		ppriv = per_cpu_ptr(priv->ppriv, i);
    +		free_netdev(ppriv->net_dev);
    +	}
    +	free_cpumask_var(priv->clean_mask);
    +
     	dpaa2_dpseci_congestion_free(priv);
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     }
    @@ -5007,16 +5014,15 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     	struct device *dev = &ls_dev->dev;
     	struct dpaa2_caam_priv *priv;
     	struct dpaa2_caam_priv_per_cpu *ppriv;
    -	cpumask_var_t clean_mask;
     	int err, cpu;
     	u8 i;
     
     	err = -ENOMEM;
    -	if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL))
    -		goto err_cpumask;
    -
     	priv = dev_get_drvdata(dev);
     
    +	if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL))
    +		goto err_cpumask;
    +
     	priv->dev = dev;
     	priv->dpsec_id = ls_dev->obj_desc.id;
     
    @@ -5118,7 +5124,7 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     			err = -ENOMEM;
     			goto err_alloc_netdev;
     		}
    -		cpumask_set_cpu(cpu, clean_mask);
    +		cpumask_set_cpu(cpu, priv->clean_mask);
     		ppriv->net_dev->dev = *dev;
     
     		netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi,
    @@ -5126,18 +5132,16 @@ static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev)
     					 DPAA2_CAAM_NAPI_WEIGHT);
     	}
     
    -	err = 0;
    -	goto free_cpumask;
    +	return 0;
     
     err_alloc_netdev:
    -	free_dpaa2_pcpu_netdev(priv, clean_mask);
    +	free_dpaa2_pcpu_netdev(priv, priv->clean_mask);
     err_get_rx_queue:
     	dpaa2_dpseci_congestion_free(priv);
     err_get_vers:
     	dpseci_close(priv->mc_io, 0, ls_dev->mc_handle);
     err_open:
    -free_cpumask:
    -	free_cpumask_var(clean_mask);
    +	free_cpumask_var(priv->clean_mask);
     err_cpumask:
     	return err;
     }
    @@ -5182,7 +5186,6 @@ static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv)
     		ppriv = per_cpu_ptr(priv->ppriv, i);
     		napi_disable(&ppriv->napi);
     		netif_napi_del(&ppriv->napi);
    -		free_netdev(ppriv->net_dev);
     	}
     
     	return 0;
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    
  • drivers/crypto/caam/caamalg_qi2.h+2 1 modified
    diff --git a/drivers/crypto/caam/caamalg_qi2.h b/drivers/crypto/caam/caamalg_qi2.h
    index 61d1219a202fcb..8e65b4b28c7bab 100644
    --- a/drivers/crypto/caam/caamalg_qi2.h
    +++ b/drivers/crypto/caam/caamalg_qi2.h
    @@ -42,6 +42,7 @@
      * @mc_io: pointer to MC portal's I/O object
      * @domain: IOMMU domain
      * @ppriv: per CPU pointers to privata data
    + * @clean_mask: CPU mask of CPUs that have allocated netdevs
      */
     struct dpaa2_caam_priv {
     	int dpsec_id;
    @@ -65,6 +66,7 @@ struct dpaa2_caam_priv {
     
     	struct dpaa2_caam_priv_per_cpu __percpu *ppriv;
     	struct dentry *dfs_root;
    +	cpumask_var_t clean_mask;
     };
     
     /**
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing cleanup of dynamically allocated per-CPU net_device structures in dpaa2_dpseci_free() for error paths during probe."

Attack vector

No network-facing attack vector exists; this is a kernel memory leak triggered during device probe. When the kernel's deferred probe mechanism retries `dpaa2_caam_probe()` after `dpaa2_dpseci_dpio_setup()` fails (e.g. DPIO devices not ready), the net_device structures allocated per CPU in the failed probe attempt are never freed [patch_id=2661545]. The leak is visible via kmemleak but does not require attacker interaction — it occurs during normal boot or device enumeration when DPIO dependencies are not yet satisfied.

Affected code

The bug is in `drivers/crypto/caam/caamalg_qi2.c` in the functions `dpaa2_dpseci_setup()` and `dpaa2_dpseci_free()`, and the fix also modifies the header `drivers/crypto/caam/caamalg_qi2.h` to add a `clean_mask` field to `struct dpaa2_caam_priv` [patch_id=2661545]. The error path in `dpaa2_dpseci_setup()` previously used a local `clean_mask` variable that was freed without freeing the netdevs, and `dpaa2_dpseci_free()` had no netdev cleanup at all.

What the fix does

The patch moves the `clean_mask` cpumask from a local variable in `dpaa2_dpseci_setup()` to a persistent field (`priv->clean_mask`) in `struct dpaa2_caam_priv` [patch_id=2661545]. During setup, each CPU that successfully allocates a netdev has its bit set in `priv->clean_mask`. The `dpaa2_dpseci_free()` function now iterates over `priv->clean_mask` and calls `free_netdev()` for each allocated netdev before freeing the mask itself. Additionally, `free_netdev()` was removed from `dpaa2_dpseci_disable()` to avoid double-free, since the netdevs are now freed in `dpaa2_dpseci_free()` instead. This ensures that all error paths and the normal teardown path properly release the dynamically allocated net_device structures.

Preconditions

  • configThe kernel must have the CAAM DPSECI driver built and the DPAA2 crypto hardware present.
  • inputDPIO devices must not be ready at the time of the first probe attempt, causing dpaa2_dpseci_dpio_setup() to fail and trigger deferred probe.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.