Skip to content

Commit 96b1b05

Browse files
Wer-Wolfij-intel
authored andcommitted
platform/wmi: Extend wmidev_invoke_method() to reject undersized data
WMI drivers using the buffer-based WMI API are expected to reject undersized method return values. Extend wmidev_invoke_method() to enable the WMI driver core to perform this size check internally. Signed-off-by: Armin Wolf <W_Armin@gmx.de> Link: https://patch.msgid.link/20260406203237.2970-5-W_Armin@gmx.de Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
1 parent 204b52f commit 96b1b05

3 files changed

Lines changed: 14 additions & 22 deletions

File tree

drivers/platform/wmi/core.c

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -364,20 +364,23 @@ acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 met
364364
EXPORT_SYMBOL_GPL(wmidev_evaluate_method);
365365

366366
/**
367-
* wmidev_invoke_method - Invoke a WMI method
367+
* wmidev_invoke_method - Invoke a WMI method that returns values
368368
* @wdev: A wmi bus device from a driver
369369
* @instance: Instance index
370370
* @method_id: Method ID to call
371371
* @in: Mandatory WMI buffer containing input for the method call
372-
* @out: Optional WMI buffer to return the method results
372+
* @out: Mandatory WMI buffer to return the method results
373+
* @min_size: Minimum size of the method result data in bytes
373374
*
374-
* Invoke a WMI method, the caller must free the resulting data inside @out.
375-
* Said data is guaranteed to be aligned on a 8-byte boundary.
375+
* Invoke a WMI method that returns values, the caller must free the resulting
376+
* data inside @out using kfree(). Said data is guaranteed to be aligned on a
377+
* 8-byte boundary. Use wmidev_invoke_procedure() for WMI methods that
378+
* return no values.
376379
*
377380
* Return: 0 on success or negative error code on failure.
378381
*/
379382
int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
380-
const struct wmi_buffer *in, struct wmi_buffer *out)
383+
const struct wmi_buffer *in, struct wmi_buffer *out, size_t min_size)
381384
{
382385
struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
383386
struct acpi_buffer aout = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -398,20 +401,14 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
398401
ain.pointer = in->data;
399402
}
400403

401-
if (out)
402-
status = wmidev_evaluate_method(wdev, instance, method_id, &ain, &aout);
403-
else
404-
status = wmidev_evaluate_method(wdev, instance, method_id, &ain, NULL);
404+
status = wmidev_evaluate_method(wdev, instance, method_id, &ain, &aout);
405405

406406
if (wblock->gblock.flags & ACPI_WMI_STRING)
407407
kfree(ain.pointer);
408408

409409
if (ACPI_FAILURE(status))
410410
return -EIO;
411411

412-
if (!out)
413-
return 0;
414-
415412
obj = aout.pointer;
416413
if (!obj) {
417414
out->length = 0;
@@ -420,7 +417,7 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
420417
return 0;
421418
}
422419

423-
ret = wmi_unmarshal_acpi_object(obj, out, 0);
420+
ret = wmi_unmarshal_acpi_object(obj, out, min_size);
424421
kfree(obj);
425422

426423
return ret;

drivers/platform/x86/bitland-mifs-wmi.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <linux/acpi.h>
1111
#include <linux/array_size.h>
1212
#include <linux/bits.h>
13-
#include <linux/cleanup.h>
1413
#include <linux/container_of.h>
1514
#include <linux/dev_printk.h>
1615
#include <linux/device.h>
@@ -167,7 +166,6 @@ static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data,
167166
struct bitland_mifs_output *output)
168167
{
169168
struct wmi_buffer in_buf = { .length = sizeof(*input), .data = (void *)input };
170-
void *out_data __free(kfree) = NULL;
171169
struct wmi_buffer out_buf = { 0 };
172170
int ret;
173171

@@ -176,15 +174,12 @@ static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data,
176174
if (!output)
177175
return wmidev_invoke_procedure(data->wdev, 0, 1, &in_buf);
178176

179-
ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf);
177+
ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, sizeof(*output));
180178
if (ret)
181179
return ret;
182180

183-
out_data = out_buf.data;
184-
if (out_buf.length < sizeof(*output))
185-
return -EIO;
186-
187-
memcpy(output, out_data, sizeof(*output));
181+
memcpy(output, out_buf.data, sizeof(*output));
182+
kfree(out_buf.data);
188183

189184
return 0;
190185
}

include/linux/wmi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ ssize_t wmi_string_from_utf8s(struct wmi_string *str, size_t max_chars, const u8
6868
size_t src_length);
6969

7070
int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
71-
const struct wmi_buffer *in, struct wmi_buffer *out);
71+
const struct wmi_buffer *in, struct wmi_buffer *out, size_t min_size);
7272

7373
int wmidev_invoke_procedure(struct wmi_device *wdev, u8 instance, u32 method_id,
7474
const struct wmi_buffer *in);

0 commit comments

Comments
 (0)