Commit af025b6b authored by Hangbin Liu's avatar Hangbin Liu Committed by Zhengchao Shao
Browse files

ipv6: sr: fix memleak in seg6_hmac_init_algo

stable inclusion
from stable-v4.19.316
commit afd5730969aec960a2fee4e5ee839a6014643976
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAC3N0
CVE: CVE-2024-39489

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=afd5730969aec960a2fee4e5ee839a6014643976



---------------------------

[ Upstream commit efb9f4f19f8e37fde43dfecebc80292d179f56c6 ]

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.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarZhengchao Shao <shaozhengchao@huawei.com>
parent 07c988f0
Loading
Loading
Loading
Loading
+28 −14
Original line number Diff line number Diff line
@@ -361,6 +361,7 @@ static int seg6_hmac_init_algo(void)
	struct crypto_shash *tfm;
	struct shash_desc *shash;
	int i, alg_count, cpu;
	int ret = -ENOMEM;

	alg_count = ARRAY_SIZE(hmac_algos);

@@ -371,12 +372,14 @@ static int seg6_hmac_init_algo(void)
		algo = &hmac_algos[i];
		algo->tfms = alloc_percpu(struct crypto_shash *);
		if (!algo->tfms)
			return -ENOMEM;
			goto error_out;

		for_each_possible_cpu(cpu) {
			tfm = crypto_alloc_shash(algo->name, 0, 0);
			if (IS_ERR(tfm))
				return PTR_ERR(tfm);
			if (IS_ERR(tfm)) {
				ret = PTR_ERR(tfm);
				goto error_out;
			}
			p_tfm = per_cpu_ptr(algo->tfms, cpu);
			*p_tfm = tfm;
		}
@@ -388,18 +391,22 @@ static int seg6_hmac_init_algo(void)

		algo->shashs = alloc_percpu(struct shash_desc *);
		if (!algo->shashs)
			return -ENOMEM;
			goto error_out;

		for_each_possible_cpu(cpu) {
			shash = kzalloc_node(shsize, GFP_KERNEL,
					     cpu_to_node(cpu));
			if (!shash)
				return -ENOMEM;
				goto error_out;
			*per_cpu_ptr(algo->shashs, cpu) = shash;
		}
	}

	return 0;

error_out:
	seg6_hmac_exit();
	return ret;
}

int __init seg6_hmac_init(void)
@@ -421,22 +428,29 @@ EXPORT_SYMBOL(seg6_hmac_net_init);
void seg6_hmac_exit(void)
{
	struct seg6_hmac_algo *algo = NULL;
	struct crypto_shash *tfm;
	struct shash_desc *shash;
	int i, alg_count, cpu;

	alg_count = ARRAY_SIZE(hmac_algos);
	for (i = 0; i < alg_count; i++) {
		algo = &hmac_algos[i];
		for_each_possible_cpu(cpu) {
			struct crypto_shash *tfm;
			struct shash_desc *shash;

		if (algo->shashs) {
			for_each_possible_cpu(cpu) {
				shash = *per_cpu_ptr(algo->shashs, cpu);
				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->shashs);
		}
	}
}
EXPORT_SYMBOL(seg6_hmac_exit);