From: Hans de Goede <hdegoede@redhat.com>
To: Jorge Lopez <jorgealtxwork@gmail.com>,
platform-driver-x86@vger.kernel.org
Subject: Re: [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated
Date: Mon, 14 Mar 2022 11:51:42 +0100 [thread overview]
Message-ID: <85bb25b0-32f1-e7a1-c94c-012dc8f2dbec@redhat.com> (raw)
In-Reply-To: <20220310210853.28367-5-jorge.lopez2@hp.com>
Hi,
On 3/10/22 22:08, Jorge Lopez wrote:
> The purpose of this patch is to remove 128 bytes buffer limitation
> imposed in bios_args structure.
>
> A limiting factor discovered during this investigation was the struct
> bios_args.data size restriction. The data member size limits all
> possible WMI commands to those requiring buffer size of 128 bytes or
> less. Several WMI commands and queries require a buffer size larger
> than 128 bytes hence limiting current and feature supported by the
> driver. It is for this reason, struct bios_args.data changed and is
> dynamically allocated. hp_wmi_perform_query function changed to
> handle the memory allocation and release of any required buffer size.
>
> All changes were validated on a HP ZBook Workstation notebook,
> HP EliteBook x360, and HP EliteBook 850 G8. Additional
> validation was included in the test process to ensure no other
> commands were incorrectly handled.
>
> Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com>
>
> ---
> Based on the latest platform-drivers-x86.git/for-next
> ---
> drivers/platform/x86/hp-wmi.c | 64 +++++++++++++++++++++++------------
> 1 file changed, 42 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
> index e76bd4bef6b5..cc5c4f637328 100644
> --- a/drivers/platform/x86/hp-wmi.c
> +++ b/drivers/platform/x86/hp-wmi.c
> @@ -82,12 +82,17 @@ enum hp_wmi_event_ids {
> HPWMI_BATTERY_CHARGE_PERIOD = 0x10,
> };
>
> +/**
> + * struct bios_args buffer is dynamically allocated. New WMI command types
> + * were introduced that exceeds 128-byte data size. Changes to handle
> + * the data size allocation scheme were kept in hp_wmi_perform_qurey function.
> + */
> struct bios_args {
> u32 signature;
> u32 command;
> u32 commandtype;
> u32 datasize;
> - u8 data[128];
> + u8 data[];
> };
>
> enum hp_wmi_commandtype {
> @@ -268,34 +273,40 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
> int mid;
> struct bios_return *bios_return;
> int actual_outsize;
> - union acpi_object *obj;
> - struct bios_args args = {
> - .signature = 0x55434553,
> - .command = command,
> - .commandtype = query,
> - .datasize = insize,
> - .data = { 0 },
> - };
> - struct acpi_buffer input = { sizeof(struct bios_args), &args };
> + union acpi_object *obj = NULL;
> + struct bios_args *args = NULL;
> + size_t bios_args_size = struct_size(args, data, insize);
> +
> + struct acpi_buffer input;
> struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
> int ret = 0;
>
> - mid = encode_outsize_for_pvsz(outsize);
> - if (WARN_ON(mid < 0))
> - return mid;
> + args = kmalloc(bios_args_size, GFP_KERNEL);
> + if (!args)
> + return -ENOMEM;
The variable declaration here again looks a bit messy, also
there is no reason to move the block setting + checking mid,
that just makes the diff unnecessarily large.
I've cleaned this up while mergin (no functional changes).
>
> - if (WARN_ON(insize > sizeof(args.data)))
> - return -EINVAL;
> - memcpy(&args.data[0], buffer, insize);
> + input.length = bios_args_size;
> + input.pointer = args;
>
> - wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
> + mid = encode_outsize_for_pvsz(outsize);
> + if (WARN_ON(mid < 0)) {
> + ret = mid;
> + goto out_free;
> + }
>
> - obj = output.pointer;
> + memcpy(args->data, buffer, flex_array_size(args, data, insize));
>
> - if (!obj)
> - return -EINVAL;
> + args->signature = 0x55434553;
> + args->command = command;
> + args->commandtype = query;
> + args->datasize = insize;
>
> - if (obj->type != ACPI_TYPE_BUFFER) {
> + ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
> + if (ret)
> + goto out_free;
> +
> + obj = output.pointer;
> + if (!obj) {
> ret = -EINVAL;
> goto out_free;
> }
> @@ -310,9 +321,17 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
> 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;
> + }
> +
You have now moved the obj->type != ACPI_TYPE_BUFFER check to after the:
bios_return = (struct bios_return *)obj->buffer.pointer;
Statement, which dereferences the buffer member of the obj union. That check
MUST be done before looking at the buffer member, so I have moved it back to
its old place, this also makes the diff/patch smaller. Note this one is
a functional change to your patch.
The changed initial block of the function now looks like this:
static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
void *buffer, int insize, int outsize)
{
struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL };
size_t bios_args_size = struct_size(args, data, insize);
struct bios_return *bios_return;
union acpi_object *obj = NULL;
struct bios_args *args = NULL;
int mid, actual_outsize, ret;
mid = encode_outsize_for_pvsz(outsize);
if (WARN_ON(mid < 0))
return mid;
args = kmalloc(bios_args_size, GFP_KERNEL);
if (!args)
return -ENOMEM;
input.length = bios_args_size;
input.pointer = args;
args->signature = 0x55434553;
args->command = command;
args->commandtype = query;
args->datasize = insize;
memcpy(args->data, buffer, flex_array_size(args, data, insize));
ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
if (ret)
goto out_free;
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;
}
bios_return = (struct bios_return *)obj->buffer.pointer;
And the new diff for this chunk of the patch now is:
@@ -266,37 +271,42 @@ static inline int encode_outsize_for_pvsz(int outsize)
static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
void *buffer, int insize, int outsize)
{
- int mid;
+ struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL };
+ size_t bios_args_size = struct_size(args, data, insize);
struct bios_return *bios_return;
- int actual_outsize;
- union acpi_object *obj;
- struct bios_args args = {
- .signature = 0x55434553,
- .command = command,
- .commandtype = query,
- .datasize = insize,
- .data = { 0 },
- };
- struct acpi_buffer input = { sizeof(struct bios_args), &args };
- struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
- int ret = 0;
+ union acpi_object *obj = NULL;
+ struct bios_args *args = NULL;
+ int mid, actual_outsize, ret;
mid = encode_outsize_for_pvsz(outsize);
if (WARN_ON(mid < 0))
return mid;
- if (WARN_ON(insize > sizeof(args.data)))
- return -EINVAL;
- memcpy(&args.data[0], buffer, insize);
+ args = kmalloc(bios_args_size, GFP_KERNEL);
+ if (!args)
+ return -ENOMEM;
- wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
+ input.length = bios_args_size;
+ input.pointer = args;
- obj = output.pointer;
+ args->signature = 0x55434553;
+ args->command = command;
+ args->commandtype = query;
+ args->datasize = insize;
+ memcpy(args->data, buffer, flex_array_size(args, data, insize));
- if (!obj)
- return -EINVAL;
+ ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output);
+ if (ret)
+ goto out_free;
+
+ 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;
}
@@ ...
I've merged this patch with the above changes:
Thank you for your patch, I've applied this patch to my review-hans
branch:
https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans
Note it will show up in my review-hans branch once I've pushed my
local branch there, which might take a while.
Once I've run some tests on this branch the patches there will be
added to the platform-drivers-x86/for-next branch and eventually
will be included in the pdx86 pull-request to Linus for the next
merge-window.
Regards,
Hans
> /* Ignore output data of zero size */
> - if (!outsize)
> + if (!outsize) {
> + ret = 0;
> goto out_free;
> + }
>
> actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
> memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
> @@ -320,6 +339,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command,
>
> out_free:
> kfree(obj);
> + kfree(args);
> return ret;
> }
>
next prev parent reply other threads:[~2022-03-14 10:52 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-10 21:08 [PATCH v5 0/4] Fix SW_TABLET_MODE detection method Jorge Lopez
2022-03-10 21:08 ` [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) Jorge Lopez
2022-03-14 10:41 ` Hans de Goede
2022-03-10 21:08 ` [PATCH v5 2/4] Fix SW_TABLET_MODE detection method Jorge Lopez
2022-03-14 10:44 ` Hans de Goede
2024-08-08 21:46 ` Stefan Sichler
2024-08-13 14:34 ` Ilpo Järvinen
2024-08-19 16:41 ` Stefan Sichler
2022-03-10 21:08 ` [PATCH v5 3/4] Fix 0x05 error code reported by several WMI calls Jorge Lopez
2022-03-14 10:44 ` Hans de Goede
2022-03-10 21:08 ` [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated Jorge Lopez
2022-03-14 10:51 ` Hans de Goede [this message]
2022-03-14 11:33 ` Hans de Goede
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=85bb25b0-32f1-e7a1-c94c-012dc8f2dbec@redhat.com \
--to=hdegoede@redhat.com \
--cc=jorgealtxwork@gmail.com \
--cc=platform-driver-x86@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).