mirror of
https://github.com/torvalds/linux.git
synced 2024-11-29 07:31:29 +00:00
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:
parent
a4621fd1d4
commit
1a9e02673e
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user