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

platform/wmi: Prepare to reject undersized unmarshalling results



Driver using the buffer-based WMI API usually reject buffers resulting
from WMI method calls or block queries if they contain not enough data.
Prepare the WMI core for assisting in this by automatically rejecting
undersized unmarshalling results.

Signed-off-by: default avatarArmin Wolf <W_Armin@gmx.de>
Link: https://patch.msgid.link/20260406203237.2970-4-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 578bc2a5
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -420,7 +420,7 @@ int wmidev_invoke_method(struct wmi_device *wdev, u8 instance, u32 method_id,
		return 0;
	}

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

	return ret;
@@ -583,7 +583,7 @@ int wmidev_query_block(struct wmi_device *wdev, u8 instance, struct wmi_buffer *
	if (!obj)
		return -EIO;

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

	return ret;
@@ -1416,7 +1416,7 @@ static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj)
			return;
		}

		ret = wmi_unmarshal_acpi_object(obj, &buffer);
		ret = wmi_unmarshal_acpi_object(obj, &buffer, 0);
		if (ret < 0) {
			dev_warn(&wblock->dev.dev, "Failed to unmarshal event data: %d\n", ret);
			return;
+2 −1
Original line number Diff line number Diff line
@@ -11,7 +11,8 @@
union acpi_object;
struct wmi_buffer;

int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer);
int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer,
			      size_t min_size);
int wmi_marshal_string(const struct wmi_buffer *buffer, struct acpi_buffer *out);

#endif /* _WMI_INTERNAL_H_ */
+5 −1
Original line number Diff line number Diff line
@@ -151,7 +151,8 @@ static int wmi_obj_transform(const union acpi_object *obj, u8 *buffer)
	return 0;
}

int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer)
int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *buffer,
			      size_t min_size)
{
	size_t length, alloc_length;
	u8 *data;
@@ -161,6 +162,9 @@ int wmi_unmarshal_acpi_object(const union acpi_object *obj, struct wmi_buffer *b
	if (ret < 0)
		return ret;

	if (length < min_size)
		return -ENODATA;

	if (ARCH_KMALLOC_MINALIGN < 8) {
		/*
		 * kmalloc() guarantees that the alignment of the resulting memory allocation is at
+22 −2
Original line number Diff line number Diff line
@@ -372,7 +372,7 @@ static void wmi_unmarshal_acpi_object_test(struct kunit *test)
	struct wmi_buffer result;
	int ret;

	ret = wmi_unmarshal_acpi_object(&param->obj, &result);
	ret = wmi_unmarshal_acpi_object(&param->obj, &result, param->buffer.length);
	if (ret < 0)
		KUNIT_FAIL_AND_ABORT(test, "Unmarshalling of ACPI object failed\n");

@@ -389,7 +389,7 @@ static void wmi_unmarshal_acpi_object_failure_test(struct kunit *test)
	struct wmi_buffer result;
	int ret;

	ret = wmi_unmarshal_acpi_object(&param->obj, &result);
	ret = wmi_unmarshal_acpi_object(&param->obj, &result, 0);
	if (ret < 0)
		return;

@@ -427,6 +427,25 @@ static void wmi_marshal_string_failure_test(struct kunit *test)
	KUNIT_FAIL(test, "Invalid string was not rejected\n");
}

static void wmi_unmarshal_acpi_object_undersized_test(struct kunit *test)
{
	const union acpi_object obj = {
		.integer = {
			.type = ACPI_TYPE_INTEGER,
			.value = 0xdeadbeef,
		},
	};
	struct wmi_buffer result;
	int ret;

	ret = wmi_unmarshal_acpi_object(&obj, &result, sizeof(expected_single_integer) + 1);
	if (ret < 0)
		return;

	kfree(result.data);
	KUNIT_FAIL(test, "Undersized unmarshalling result was not rejected\n");
}

static struct kunit_case wmi_marshalling_test_cases[] = {
	KUNIT_CASE_PARAM(wmi_unmarshal_acpi_object_test,
			 wmi_unmarshal_acpi_object_gen_params),
@@ -436,6 +455,7 @@ static struct kunit_case wmi_marshalling_test_cases[] = {
			 wmi_unmarshal_acpi_object_failure_gen_params),
	KUNIT_CASE_PARAM(wmi_marshal_string_failure_test,
			 wmi_marshal_string_failure_gen_params),
	KUNIT_CASE(wmi_unmarshal_acpi_object_undersized_test),
	{}
};