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: 76ffa5ab5b ("coresight: Support for ACPI bindings")
Signed-off-by: Junhao He <hejunhao3@huawei.com>
Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Link: https://lore.kernel.org/r/20230817085937.55590-2-hejunhao3@huawei.com
This commit is contained in:
Junhao He 2023-08-17 16:59:36 +08:00 committed by Suzuki K Poulose
parent a4621fd1d4
commit 1a9e02673e

View file

@ -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;
}
/*