Unverified Commit 96b1b053 authored by Armin Wolf's avatar Armin Wolf Committed by Ilpo Järvinen
Browse files

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: default avatarArmin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20260406203237.2970-5-W_Armin@gmx.de


Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
parent 204b52fa
Loading
Loading
Loading
Loading
+10 −13
Original line number Diff line number Diff line
@@ -364,20 +364,23 @@ acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 met
EXPORT_SYMBOL_GPL(wmidev_evaluate_method);

/**
 * wmidev_invoke_method - Invoke a WMI method
 * wmidev_invoke_method - Invoke a WMI method that returns values
 * @wdev: A wmi bus device from a driver
 * @instance: Instance index
 * @method_id: Method ID to call
 * @in: Mandatory WMI buffer containing input for the method call
 * @out: Optional WMI buffer to return the method results
 * @out: Mandatory WMI buffer to return the method results
 * @min_size: Minimum size of the method result data in bytes
 *
 * Invoke a WMI method, the caller must free the resulting data inside @out.
 * Said data is guaranteed to be aligned on a 8-byte boundary.
 * Invoke a WMI method that returns values, the caller must free the resulting
 * data inside @out using kfree(). Said data is guaranteed to be aligned on a
 * 8-byte boundary. Use wmidev_invoke_procedure() for WMI methods that
 * return no values.
 *
 * Return: 0 on success or negative error code on failure.
 */
int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
			 const struct wmi_buffer *in, struct wmi_buffer *out)
			 const struct wmi_buffer *in, struct wmi_buffer *out, size_t min_size)
{
	struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
	struct acpi_buffer aout = { ACPI_ALLOCATE_BUFFER, NULL };
@@ -398,10 +401,7 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
		ain.pointer = in->data;
	}

	if (out)
	status = wmidev_evaluate_method(wdev, instance, method_id, &ain, &aout);
	else
		status = wmidev_evaluate_method(wdev, instance, method_id, &ain, NULL);

	if (wblock->gblock.flags & ACPI_WMI_STRING)
		kfree(ain.pointer);
@@ -409,9 +409,6 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
	if (ACPI_FAILURE(status))
		return -EIO;

	if (!out)
		return 0;

	obj = aout.pointer;
	if (!obj) {
		out->length = 0;
@@ -420,7 +417,7 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
		return 0;
	}

	ret = wmi_unmarshal_acpi_object(obj, out, 0);
	ret = wmi_unmarshal_acpi_object(obj, out, min_size);
	kfree(obj);

	return ret;
+3 −8
Original line number Diff line number Diff line
@@ -10,7 +10,6 @@
#include <linux/acpi.h>
#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/container_of.h>
#include <linux/dev_printk.h>
#include <linux/device.h>
@@ -167,7 +166,6 @@ static int bitland_mifs_wmi_call(struct bitland_mifs_wmi_data *data,
				 struct bitland_mifs_output *output)
{
	struct wmi_buffer in_buf = { .length = sizeof(*input), .data = (void *)input };
	void *out_data __free(kfree) = NULL;
	struct wmi_buffer out_buf = { 0 };
	int ret;

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

	ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf);
	ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, sizeof(*output));
	if (ret)
		return ret;

	out_data = out_buf.data;
	if (out_buf.length < sizeof(*output))
		return -EIO;

	memcpy(output, out_data, sizeof(*output));
	memcpy(output, out_buf.data, sizeof(*output));
	kfree(out_buf.data);

	return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -68,7 +68,7 @@ ssize_t wmi_string_from_utf8s(struct wmi_string *str, size_t max_chars, const u8
			      size_t src_length);

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

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