Commit 1a9e0267 authored by Junhao He's avatar Junhao He Committed by Suzuki K Poulose
Browse files

coresight: Fix memory leak in acpi_buffer->pointer



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 a4621fd1
Loading
Loading
Loading
Loading
+26 −14
Original line number Diff line number Diff line
@@ -492,19 +492,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() }
@@ -555,12 +554,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;

@@ -661,22 +660,24 @@ static int acpi_coresight_parse_graph(struct device *dev,
				      struct acpi_device *adev,
				      struct coresight_platform_data *pdata)
{
	int ret = 0;
	int i, nlinks;
	const union acpi_object *graph;
	struct coresight_connection conn, zero_conn = {};
	struct coresight_connection *new_conn;
	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };

	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;

	for (i = 0; i < nlinks; i++) {
		const union acpi_object *link = &graph->package.elements[3 + i];
@@ -684,17 +685,28 @@ static int acpi_coresight_parse_graph(struct device *dev,

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

		if (dir == ACPI_CORESIGHT_LINK_MASTER) {
			new_conn = coresight_add_out_conn(dev, pdata, &conn);
			if (IS_ERR(new_conn))
				return PTR_ERR(new_conn);
			if (IS_ERR(new_conn)) {
				ret = PTR_ERR(new_conn);
				goto free;
			}
		}
	}

	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;
}

/*