Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Armin Wolf and committed by
Ilpo Järvinen
96b1b053 204b52fa

+14 -22
+10 -13
drivers/platform/wmi/core.c
··· 364 364 EXPORT_SYMBOL_GPL(wmidev_evaluate_method); 365 365 366 366 /** 367 - * wmidev_invoke_method - Invoke a WMI method 367 + * wmidev_invoke_method - Invoke a WMI method that returns values 368 368 * @wdev: A wmi bus device from a driver 369 369 * @instance: Instance index 370 370 * @method_id: Method ID to call 371 371 * @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 373 374 * 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. 376 379 * 377 380 * Return: 0 on success or negative error code on failure. 378 381 */ 379 382 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) 381 384 { 382 385 struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev); 383 386 struct acpi_buffer aout = { ACPI_ALLOCATE_BUFFER, NULL }; ··· 401 398 ain.pointer = in->data; 402 399 } 403 400 404 - if (out) 405 - status = wmidev_evaluate_method(wdev, instance, method_id, &ain, &aout); 406 - else 407 - status = wmidev_evaluate_method(wdev, instance, method_id, &ain, NULL); 401 + status = wmidev_evaluate_method(wdev, instance, method_id, &ain, &aout); 408 402 409 403 if (wblock->gblock.flags & ACPI_WMI_STRING) 410 404 kfree(ain.pointer); 411 405 412 406 if (ACPI_FAILURE(status)) 413 407 return -EIO; 414 - 415 - if (!out) 416 - return 0; 417 408 418 409 obj = aout.pointer; 419 410 if (!obj) { ··· 417 420 return 0; 418 421 } 419 422 420 - ret = wmi_unmarshal_acpi_object(obj, out, 0); 423 + ret = wmi_unmarshal_acpi_object(obj, out, min_size); 421 424 kfree(obj); 422 425 423 426 return ret;
+3 -8
drivers/platform/x86/bitland-mifs-wmi.c
··· 10 10 #include <linux/acpi.h> 11 11 #include <linux/array_size.h> 12 12 #include <linux/bits.h> 13 - #include <linux/cleanup.h> 14 13 #include <linux/container_of.h> 15 14 #include <linux/dev_printk.h> 16 15 #include <linux/device.h> ··· 166 167 struct bitland_mifs_output *output) 167 168 { 168 169 struct wmi_buffer in_buf = { .length = sizeof(*input), .data = (void *)input }; 169 - void *out_data __free(kfree) = NULL; 170 170 struct wmi_buffer out_buf = { 0 }; 171 171 int ret; 172 172 ··· 174 176 if (!output) 175 177 return wmidev_invoke_procedure(data->wdev, 0, 1, &in_buf); 176 178 177 - ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf); 179 + ret = wmidev_invoke_method(data->wdev, 0, 1, &in_buf, &out_buf, sizeof(*output)); 178 180 if (ret) 179 181 return ret; 180 182 181 - out_data = out_buf.data; 182 - if (out_buf.length < sizeof(*output)) 183 - return -EIO; 184 - 185 - memcpy(output, out_data, sizeof(*output)); 183 + memcpy(output, out_buf.data, sizeof(*output)); 184 + kfree(out_buf.data); 186 185 187 186 return 0; 188 187 }
+1 -1
include/linux/wmi.h
··· 68 68 size_t src_length); 69 69 70 70 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); 72 72 73 73 int wmidev_invoke_procedure(struct wmi_device *wdev, u8 instance, u32 method_id, 74 74 const struct wmi_buffer *in);