Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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.

Fixes: 0e1a4d427f58 ("crypto: caam: Unembed net_dev structure in dpaa2")
Signed-off-by: Jianpeng Chang <jianpeng.chang.cn@windriver.com>
Reviewed-by: Breno Leitao <leitao@debian.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Jianpeng Chang and committed by
Herbert Xu
7d43252b 6d0de601

+17 -12
+15 -12
drivers/crypto/caam/caamalg_qi2.c
··· 4814 4814 { 4815 4815 struct device *dev = priv->dev; 4816 4816 struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev); 4817 - int err; 4817 + struct dpaa2_caam_priv_per_cpu *ppriv; 4818 + int i, err; 4818 4819 4819 4820 if (DPSECI_VER(priv->major_ver, priv->minor_ver) > DPSECI_VER(5, 3)) { 4820 4821 err = dpseci_reset(priv->mc_io, 0, ls_dev->mc_handle); 4821 4822 if (err) 4822 4823 dev_err(dev, "dpseci_reset() failed\n"); 4823 4824 } 4825 + 4826 + for_each_cpu(i, priv->clean_mask) { 4827 + ppriv = per_cpu_ptr(priv->ppriv, i); 4828 + free_netdev(ppriv->net_dev); 4829 + } 4830 + free_cpumask_var(priv->clean_mask); 4824 4831 4825 4832 dpaa2_dpseci_congestion_free(priv); 4826 4833 dpseci_close(priv->mc_io, 0, ls_dev->mc_handle); ··· 5014 5007 struct device *dev = &ls_dev->dev; 5015 5008 struct dpaa2_caam_priv *priv; 5016 5009 struct dpaa2_caam_priv_per_cpu *ppriv; 5017 - cpumask_var_t clean_mask; 5018 5010 int err, cpu; 5019 5011 u8 i; 5020 5012 5021 5013 err = -ENOMEM; 5022 - if (!zalloc_cpumask_var(&clean_mask, GFP_KERNEL)) 5023 - goto err_cpumask; 5024 - 5025 5014 priv = dev_get_drvdata(dev); 5015 + 5016 + if (!zalloc_cpumask_var(&priv->clean_mask, GFP_KERNEL)) 5017 + goto err_cpumask; 5026 5018 5027 5019 priv->dev = dev; 5028 5020 priv->dpsec_id = ls_dev->obj_desc.id; ··· 5124 5118 err = -ENOMEM; 5125 5119 goto err_alloc_netdev; 5126 5120 } 5127 - cpumask_set_cpu(cpu, clean_mask); 5121 + cpumask_set_cpu(cpu, priv->clean_mask); 5128 5122 ppriv->net_dev->dev = *dev; 5129 5123 5130 5124 netif_napi_add_tx_weight(ppriv->net_dev, &ppriv->napi, ··· 5132 5126 DPAA2_CAAM_NAPI_WEIGHT); 5133 5127 } 5134 5128 5135 - err = 0; 5136 - goto free_cpumask; 5129 + return 0; 5137 5130 5138 5131 err_alloc_netdev: 5139 - free_dpaa2_pcpu_netdev(priv, clean_mask); 5132 + free_dpaa2_pcpu_netdev(priv, priv->clean_mask); 5140 5133 err_get_rx_queue: 5141 5134 dpaa2_dpseci_congestion_free(priv); 5142 5135 err_get_vers: 5143 5136 dpseci_close(priv->mc_io, 0, ls_dev->mc_handle); 5144 5137 err_open: 5145 - free_cpumask: 5146 - free_cpumask_var(clean_mask); 5138 + free_cpumask_var(priv->clean_mask); 5147 5139 err_cpumask: 5148 5140 return err; 5149 5141 } ··· 5186 5182 ppriv = per_cpu_ptr(priv->ppriv, i); 5187 5183 napi_disable(&ppriv->napi); 5188 5184 netif_napi_del(&ppriv->napi); 5189 - free_netdev(ppriv->net_dev); 5190 5185 } 5191 5186 5192 5187 return 0;
+2
drivers/crypto/caam/caamalg_qi2.h
··· 42 42 * @mc_io: pointer to MC portal's I/O object 43 43 * @domain: IOMMU domain 44 44 * @ppriv: per CPU pointers to privata data 45 + * @clean_mask: CPU mask of CPUs that have allocated netdevs 45 46 */ 46 47 struct dpaa2_caam_priv { 47 48 int dpsec_id; ··· 66 65 67 66 struct dpaa2_caam_priv_per_cpu __percpu *ppriv; 68 67 struct dentry *dfs_root; 68 + cpumask_var_t clean_mask; 69 69 }; 70 70 71 71 /**