mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 15:22:21 -04:00
platform/x86: asus-armoury: fix Use-After-Free and memory leak in driver init
In init_rog_tunables(), if dc_limits are defined and allocating dc_rog_tunables fails, the already allocated ac_rog_tunables gets freed but the pointer stored in asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC] is not cleared. Since init_rog_tunables() returns void, the driver initialization continues, which can lead to a Use-After-Free (UAF) when asus_fw_attr_add() accesses the freed AC tunables pointer. Additionally, if init_rog_tunables() succeeds but asus_fw_attr_add() fails, the allocated tunables are not freed, resulting in a memory leak. Fix these issues by making init_rog_tunables() return an error code and propagating it in asus_fw_init(). Defer setting the global pointers in asus_armoury.rog_tunables until both tunables have been successfully allocated. If asus_fw_attr_add() fails, release the allocated resources using a standard goto rollback block in asus_fw_init(). Assisted-by: Antigravity:gemini-3.5-flash Signed-off-by: Marco Scardovi <scardracs@disroot.org> Link: https://patch.msgid.link/20260707213741.6515-2-scardracs@disroot.org Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
committed by
Ilpo Järvinen
parent
543efc52be
commit
76708233b4
@@ -1007,7 +1007,7 @@ static int asus_fw_attr_add(void)
|
||||
/* Init / exit ****************************************************************/
|
||||
|
||||
/* Set up the min/max and defaults for ROG tunables */
|
||||
static void init_rog_tunables(void)
|
||||
static int init_rog_tunables(void)
|
||||
{
|
||||
const struct power_limits *ac_limits, *dc_limits;
|
||||
struct rog_tunables *ac_rog_tunables = NULL, *dc_rog_tunables = NULL;
|
||||
@@ -1018,14 +1018,14 @@ static void init_rog_tunables(void)
|
||||
dmi_id = dmi_first_match(power_limits);
|
||||
if (!dmi_id) {
|
||||
pr_warn("No matching power limits found for this system\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the power data for this system */
|
||||
power_data = dmi_id->driver_data;
|
||||
if (!power_data) {
|
||||
pr_info("No power data available for this system\n");
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
asus_armoury.requires_fan_curve = power_data->requires_fan_curve;
|
||||
@@ -1033,11 +1033,10 @@ static void init_rog_tunables(void)
|
||||
/* Initialize AC power tunables */
|
||||
ac_limits = power_data->ac_data;
|
||||
if (ac_limits) {
|
||||
ac_rog_tunables = kzalloc_obj(*asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC]);
|
||||
ac_rog_tunables = kzalloc_obj(*ac_rog_tunables);
|
||||
if (!ac_rog_tunables)
|
||||
goto err_nomem;
|
||||
return -ENOMEM;
|
||||
|
||||
asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC] = ac_rog_tunables;
|
||||
ac_rog_tunables->power_limits = ac_limits;
|
||||
|
||||
/* Set initial AC values */
|
||||
@@ -1080,13 +1079,12 @@ static void init_rog_tunables(void)
|
||||
/* Initialize DC power tunables */
|
||||
dc_limits = power_data->dc_data;
|
||||
if (dc_limits) {
|
||||
dc_rog_tunables = kzalloc_obj(*asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC]);
|
||||
dc_rog_tunables = kzalloc_obj(*dc_rog_tunables);
|
||||
if (!dc_rog_tunables) {
|
||||
kfree(ac_rog_tunables);
|
||||
goto err_nomem;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC] = dc_rog_tunables;
|
||||
dc_rog_tunables->power_limits = dc_limits;
|
||||
|
||||
/* Set initial DC values */
|
||||
@@ -1126,15 +1124,16 @@ static void init_rog_tunables(void)
|
||||
pr_debug("No DC PPT limits defined\n");
|
||||
}
|
||||
|
||||
return;
|
||||
asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC] = ac_rog_tunables;
|
||||
asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC] = dc_rog_tunables;
|
||||
|
||||
err_nomem:
|
||||
pr_err("Failed to allocate memory for tunables\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __init asus_fw_init(void)
|
||||
{
|
||||
char *wmi_uid;
|
||||
int err;
|
||||
|
||||
wmi_uid = wmi_get_acpi_device_uid(ASUS_WMI_MGMT_GUID);
|
||||
if (!wmi_uid)
|
||||
@@ -1147,10 +1146,21 @@ static int __init asus_fw_init(void)
|
||||
if (!strcmp(wmi_uid, ASUS_ACPI_UID_ASUSWMI))
|
||||
return -ENODEV;
|
||||
|
||||
init_rog_tunables();
|
||||
err = init_rog_tunables();
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Must always be last step to ensure data is available */
|
||||
return asus_fw_attr_add();
|
||||
err = asus_fw_attr_add();
|
||||
if (err)
|
||||
goto err_free_tunables;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_tunables:
|
||||
kfree(asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_AC]);
|
||||
kfree(asus_armoury.rog_tunables[ASUS_ROG_TUNABLE_DC]);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit asus_fw_exit(void)
|
||||
|
||||
Reference in New Issue
Block a user