Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14c472f2 authored by Pooja Kumari's avatar Pooja Kumari
Browse files

msm: ipa3: Fix memleak issue for IPv6 NAT and IPA CT device



Currently tmp memory is deleted in device destroy method, but
there is no check for NULL. So it can cause for double free issue.

Change-Id: Ide8d8d24c0f9cea68597ecbf6b6b84269062384a
Signed-off-by: default avatarPooja Kumari <kumarip@codeaurora.org>
parent 111ea99f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1084,6 +1084,7 @@ struct ipa3_nat_ipv6ct_common_mem {
 * @index_table_expansion_addr: index expansion table address
 * @public_ip_addr: ip address of nat table
 * @pdn_mem: pdn config table SW cache memory structure
 * @is_tmp_mem_allocated: indicate if tmp mem has been allocated
 */
struct ipa3_nat_mem {
	struct ipa3_nat_ipv6ct_common_mem dev;
@@ -1091,6 +1092,7 @@ struct ipa3_nat_mem {
	char *index_table_expansion_addr;
	u32 public_ip_addr;
	struct ipa_mem_buffer pdn_mem;
	bool is_tmp_mem_allocated;
};

/**
+20 −7
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/device.h>
@@ -272,14 +272,21 @@ static void ipa3_nat_ipv6ct_destroy_device(

	mutex_lock(&dev->lock);

	if (dev->tmp_mem != NULL &&
		!(ipa3_ctx->nat_mem.is_tmp_mem_allocated)) {
		dev->tmp_mem = NULL;
	} else if (dev->tmp_mem != NULL &&
		ipa3_ctx->nat_mem.is_tmp_mem_allocated) {
		dma_free_coherent(ipa3_ctx->pdev, IPA_NAT_IPV6CT_TEMP_MEM_SIZE,
			dev->tmp_mem->vaddr, dev->tmp_mem->dma_handle);
		kfree(dev->tmp_mem);
		dev->tmp_mem = NULL;
		ipa3_ctx->nat_mem.is_tmp_mem_allocated = false;
	}
	device_destroy(dev->class, dev->dev_num);
	unregister_chrdev_region(dev->dev_num, 1);
	class_destroy(dev->class);
	dev->is_dev_init = false;

	mutex_unlock(&dev->lock);

	IPADBG("return\n");
@@ -302,10 +309,15 @@ int ipa3_nat_ipv6ct_init_devices(void)
	/*
	 * Allocate NAT/IPv6CT temporary memory. The memory is never deleted,
	 * because provided to HW once NAT or IPv6CT table is deleted.
	 * NULL is a legal value
	 */
	tmp_mem = ipa3_nat_ipv6ct_allocate_tmp_memory();

	if (tmp_mem == NULL) {
		IPAERR("unable to allocate tmp_mem\n");
		return -ENOMEM;
	}
	ipa3_ctx->nat_mem.is_tmp_mem_allocated = true;

	if (ipa3_nat_ipv6ct_init_device(
		&ipa3_ctx->nat_mem.dev,
		IPA_NAT_DEV_NAME,
@@ -334,10 +346,11 @@ int ipa3_nat_ipv6ct_init_devices(void)
fail_init_ipv6ct_dev:
	ipa3_nat_ipv6ct_destroy_device(&ipa3_ctx->nat_mem.dev);
fail_init_nat_dev:
	if (tmp_mem != NULL) {
	if (tmp_mem != NULL && ipa3_ctx->nat_mem.is_tmp_mem_allocated) {
		dma_free_coherent(ipa3_ctx->pdev, IPA_NAT_IPV6CT_TEMP_MEM_SIZE,
			tmp_mem->vaddr, tmp_mem->dma_handle);
		kfree(tmp_mem);
		ipa3_ctx->nat_mem.is_tmp_mem_allocated = false;
	}
	return result;
}