Commit efb9f4f1 authored by Hangbin Liu's avatar Hangbin Liu Committed by Paolo Abeni

ipv6: sr: fix memleak in seg6_hmac_init_algo

seg6_hmac_init_algo returns without cleaning up the previous allocations
if one fails, so it's going to leak all that memory and the crypto tfms.

Update seg6_hmac_exit to only free the memory when allocated, so we can
reuse the code directly.

Fixes: bf355b8d ("ipv6: sr: add core files for SR HMAC support")
Reported-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Closes: https://lore.kernel.org/netdev/Zj3bh-gE7eT6V6aH@hog/Signed-off-by: default avatarHangbin Liu <liuhangbin@gmail.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Reviewed-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Link: https://lore.kernel.org/r/20240517005435.2600277-1-liuhangbin@gmail.comSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 9841991a
...@@ -356,6 +356,7 @@ static int seg6_hmac_init_algo(void) ...@@ -356,6 +356,7 @@ static int seg6_hmac_init_algo(void)
struct crypto_shash *tfm; struct crypto_shash *tfm;
struct shash_desc *shash; struct shash_desc *shash;
int i, alg_count, cpu; int i, alg_count, cpu;
int ret = -ENOMEM;
alg_count = ARRAY_SIZE(hmac_algos); alg_count = ARRAY_SIZE(hmac_algos);
...@@ -366,12 +367,14 @@ static int seg6_hmac_init_algo(void) ...@@ -366,12 +367,14 @@ static int seg6_hmac_init_algo(void)
algo = &hmac_algos[i]; algo = &hmac_algos[i];
algo->tfms = alloc_percpu(struct crypto_shash *); algo->tfms = alloc_percpu(struct crypto_shash *);
if (!algo->tfms) if (!algo->tfms)
return -ENOMEM; goto error_out;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
tfm = crypto_alloc_shash(algo->name, 0, 0); tfm = crypto_alloc_shash(algo->name, 0, 0);
if (IS_ERR(tfm)) if (IS_ERR(tfm)) {
return PTR_ERR(tfm); ret = PTR_ERR(tfm);
goto error_out;
}
p_tfm = per_cpu_ptr(algo->tfms, cpu); p_tfm = per_cpu_ptr(algo->tfms, cpu);
*p_tfm = tfm; *p_tfm = tfm;
} }
...@@ -383,18 +386,22 @@ static int seg6_hmac_init_algo(void) ...@@ -383,18 +386,22 @@ static int seg6_hmac_init_algo(void)
algo->shashs = alloc_percpu(struct shash_desc *); algo->shashs = alloc_percpu(struct shash_desc *);
if (!algo->shashs) if (!algo->shashs)
return -ENOMEM; goto error_out;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
shash = kzalloc_node(shsize, GFP_KERNEL, shash = kzalloc_node(shsize, GFP_KERNEL,
cpu_to_node(cpu)); cpu_to_node(cpu));
if (!shash) if (!shash)
return -ENOMEM; goto error_out;
*per_cpu_ptr(algo->shashs, cpu) = shash; *per_cpu_ptr(algo->shashs, cpu) = shash;
} }
} }
return 0; return 0;
error_out:
seg6_hmac_exit();
return ret;
} }
int __init seg6_hmac_init(void) int __init seg6_hmac_init(void)
...@@ -412,22 +419,29 @@ int __net_init seg6_hmac_net_init(struct net *net) ...@@ -412,22 +419,29 @@ int __net_init seg6_hmac_net_init(struct net *net)
void seg6_hmac_exit(void) void seg6_hmac_exit(void)
{ {
struct seg6_hmac_algo *algo = NULL; struct seg6_hmac_algo *algo = NULL;
struct crypto_shash *tfm;
struct shash_desc *shash;
int i, alg_count, cpu; int i, alg_count, cpu;
alg_count = ARRAY_SIZE(hmac_algos); alg_count = ARRAY_SIZE(hmac_algos);
for (i = 0; i < alg_count; i++) { for (i = 0; i < alg_count; i++) {
algo = &hmac_algos[i]; algo = &hmac_algos[i];
for_each_possible_cpu(cpu) {
struct crypto_shash *tfm;
struct shash_desc *shash;
shash = *per_cpu_ptr(algo->shashs, cpu); if (algo->shashs) {
kfree(shash); for_each_possible_cpu(cpu) {
tfm = *per_cpu_ptr(algo->tfms, cpu); shash = *per_cpu_ptr(algo->shashs, cpu);
crypto_free_shash(tfm); kfree(shash);
}
free_percpu(algo->shashs);
}
if (algo->tfms) {
for_each_possible_cpu(cpu) {
tfm = *per_cpu_ptr(algo->tfms, cpu);
crypto_free_shash(tfm);
}
free_percpu(algo->tfms);
} }
free_percpu(algo->tfms);
free_percpu(algo->shashs);
} }
} }
EXPORT_SYMBOL(seg6_hmac_exit); EXPORT_SYMBOL(seg6_hmac_exit);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment