[PATCH 2/2] hp-wmi: use modern cleanup and refactor allocation functions
yahia <[email protected]>
| Newsgroups | org.kernel.vger.platform-driver-x86 |
|---|---|
| Message-ID | <[email protected]> |
From: yahia ahmed <[email protected]> Refactor hp_wmi_perform_query() and encode_outsize_for_pvsz() to improve readability, ensure memory zeroing, and verify bounds. Replace the brittle if condition tree in encode_outsize_for_pvsz() with a switch statement, replace the manual out_free label in hp_wmi_perform_query() to free args and obj variables with compiler provided cleanup __free(), replace kmalloc with kzalloc_flex to ensure that memory is zeroed before use, and add a bounds check for obj->buffer.length to attest that it is larger than sizeof(struct bios_return). Reported-by: [email protected] Link: https://sashiko.dev/#/patchset/20260712191130.41183-1-yahia.a.abdrabou%40gmail.com Signed-off-by: yahia ahmed <[email protected]> --- drivers/platform/x86/hp/hp-wmi.c | 49 ++++++++++++++------------------ 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 5845b169df39..67bd3d6825f4 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -552,16 +552,20 @@ static inline u8 pwm_to_rpm(u8 pwm, struct hp_wmi_hwmon_priv *priv) /* map output size to the corresponding WMI method id */ static inline int encode_outsize_for_pvsz(int outsize) { - if (outsize > 4096) + if (unlikely(outsize > 4096 || outsize < 0)) return -EINVAL; - if (outsize > 1024) - return 5; - if (outsize > 128) - return 4; - if (outsize > 4) - return 3; - if (outsize > 0) + switch (outsize) { + case 1 ... 4: return 2; + case 5 ... 128: + return 3; + case 129 ... 1024: + return 4; + case 1025 ... 4096: + return 5; + default: + break; + } return 1; } @@ -590,8 +594,8 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, { struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL }; struct bios_return *bios_return; - union acpi_object *obj = NULL; - struct bios_args *args = NULL; + union acpi_object *obj __free(kfree) = NULL; + struct bios_args *args __free(kfree) = NULL; int mid, actual_insize, actual_outsize; size_t bios_args_size; int ret; @@ -602,7 +606,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, actual_insize = max(insize, 128); bios_args_size = struct_size(args, data, actual_insize); - args = kmalloc(bios_args_size, GFP_KERNEL); + args = kzalloc_flex(*args, data, actual_insize, GFP_KERNEL); if (!args) return -ENOMEM; @@ -617,19 +621,12 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, ret = wmidev_evaluate_method(hp_wmi_wdev, 0, mid, &input, &output); if (ret) - goto out_free; + return ret; obj = output.pointer; - if (!obj) { - ret = -EINVAL; - goto out_free; - } - - if (obj->type != ACPI_TYPE_BUFFER) { - pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); - ret = -EINVAL; - goto out_free; - } + if (!obj || obj->type != ACPI_TYPE_BUFFER || + obj->buffer.length < sizeof(struct bios_return)) + return -EINVAL; bios_return = (struct bios_return *)obj->buffer.pointer; ret = bios_return->return_code; @@ -638,20 +635,16 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, if (ret != HPWMI_RET_UNKNOWN_COMMAND && ret != HPWMI_RET_UNKNOWN_CMDTYPE) pr_warn("query 0x%x returned error 0x%x\n", query, ret); - goto out_free; + return ret; } /* Ignore output data of zero size */ if (!outsize) - goto out_free; + return 0; actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); memset(buffer + actual_outsize, 0, outsize - actual_outsize); - -out_free: - kfree(obj); - kfree(args); return ret; } -- 2.55.0