Commit 2cd5e70f authored by Junhao He's avatar Junhao He
Browse files

coresight: Fix memory leak in acpi_buffer->pointer

mainline inclusion
from mainline-v6.5-rc1
commit 1a9e0267
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8BC14
CVE: NA

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



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

There are memory leaks reported by kmemleak:
...
unreferenced object 0xffff00213c141000 (size 1024):
  comm "systemd-udevd", pid 2123, jiffies 4294909467 (age 6062.160s)
  hex dump (first 32 bytes):
    04 00 00 00 02 00 00 00 18 10 14 3c 21 00 ff ff  ...........<!...
    00 00 00 00 00 00 00 00 03 00 00 00 10 00 00 00  ................
  backtrace:
    [<000000004b7c9001>] __kmem_cache_alloc_node+0x2f8/0x348
    [<00000000b0fc7ceb>] __kmalloc+0x58/0x108
    [<0000000064ff4695>] acpi_os_allocate+0x2c/0x68
    [<000000007d57d116>] acpi_ut_initialize_buffer+0x54/0xe0
    [<0000000024583908>] acpi_evaluate_object+0x388/0x438
    [<0000000017b2e72b>] acpi_evaluate_object_typed+0xe8/0x240
    [<000000005df0eac2>] coresight_get_platform_data+0x1b4/0x988 [coresight]
...

The ACPI buffer memory (buf.pointer) should be freed. But the buffer
is also used after returning from acpi_get_dsd_graph().
Move the temporary variables buf to acpi_coresight_parse_graph(),
and free it before the function return to prevent memory leak.

Fixes: 76ffa5ab ("coresight: Support for ACPI bindings")
Signed-off-by: default avatarJunhao He <hejunhao3@huawei.com>
Reviewed-by: default avatarJames Clark <james.clark@arm.com>
Signed-off-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20230817085937.55590-2-hejunhao3@huawei.com
parent 3c9b2713
Loading
Loading
Loading
Loading
+30 −16
Original line number Diff line number Diff line
@@ -518,19 +518,18 @@ static inline bool acpi_validate_dsd_graph(const union acpi_object *graph)

/* acpi_get_dsd_graph	- Find the _DSD Graph property for the given device. */
static const union acpi_object *
acpi_get_dsd_graph(struct acpi_device *adev)
acpi_get_dsd_graph(struct acpi_device *adev, struct acpi_buffer *buf)
{
	int i;
	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
	acpi_status status;
	const union acpi_object *dsd;

	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL,
					    &buf, ACPI_TYPE_PACKAGE);
					    buf, ACPI_TYPE_PACKAGE);
	if (ACPI_FAILURE(status))
		return NULL;

	dsd = buf.pointer;
	dsd = buf->pointer;

	/*
	 * _DSD property consists tuples { Prop_UUID, Package() }
@@ -581,12 +580,12 @@ acpi_validate_coresight_graph(const union acpi_object *cs_graph)
 * returns NULL.
 */
static const union acpi_object *
acpi_get_coresight_graph(struct acpi_device *adev)
acpi_get_coresight_graph(struct acpi_device *adev, struct acpi_buffer *buf)
{
	const union acpi_object *graph_list, *graph;
	int i, nr_graphs;

	graph_list = acpi_get_dsd_graph(adev);
	graph_list = acpi_get_dsd_graph(adev, buf);
	if (!graph_list)
		return graph_list;

@@ -686,22 +685,24 @@ static int acpi_coresight_parse_link(struct acpi_device *adev,
static int acpi_coresight_parse_graph(struct acpi_device *adev,
				      struct coresight_platform_data *pdata)
{
	int ret = 0;
	int rc, i, nlinks;
	const union acpi_object *graph;
	struct coresight_connection *conns, *ptr;
	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };

	pdata->nr_inport = pdata->nr_outport = 0;
	graph = acpi_get_coresight_graph(adev);
	graph = acpi_get_coresight_graph(adev, &buf);
	/*
	 * There are no graph connections, which is fine for some components.
	 * e.g., ETE
	 */
	if (!graph)
		return 0;
		goto free;

	nlinks = graph->package.elements[2].integer.value;
	if (!nlinks)
		return 0;
		goto free;

	/*
	 * To avoid scanning the table twice (once for finding the number of
@@ -710,16 +711,20 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev,
	 * it to the pdata.
	 */
	conns = devm_kcalloc(&adev->dev, nlinks, sizeof(*conns), GFP_KERNEL);
	if (!conns)
		return -ENOMEM;
	if (!conns) {
		ret = -ENOMEM;
		goto free;
	}
	ptr = conns;
	for (i = 0; i < nlinks; i++) {
		const union acpi_object *link = &graph->package.elements[3 + i];
		int dir;

		dir = acpi_coresight_parse_link(adev, link, ptr);
		if (dir < 0)
			return dir;
		if (dir < 0) {
			ret = dir;
			goto free;
		}

		if (dir == ACPI_CORESIGHT_LINK_MASTER) {
			if (ptr->outport >= pdata->nr_outport)
@@ -740,8 +745,10 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev,
	}

	rc = coresight_alloc_conns(&adev->dev, pdata);
	if (rc)
		return rc;
	if (rc) {
		ret = rc;
		goto free;
	}

	/* Copy the connection information to the final location */
	for (i = 0; conns + i < ptr; i++) {
@@ -753,7 +760,14 @@ static int acpi_coresight_parse_graph(struct acpi_device *adev,
	}

	devm_kfree(&adev->dev, conns);
	return 0;
free:
	/*
	 * When ACPI fails to alloc a buffer, it will free the buffer
	 * created via ACPI_ALLOCATE_BUFFER and set to NULL.
	 * ACPI_FREE can handle NULL pointers, so free it directly.
	 */
	ACPI_FREE(buf.pointer);
	return ret;
}

/*