All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI
@ 2017-10-04 22:48 Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 01/14] platform/x86: wmi: Add new method wmidev_evaluate_method Mario Limonciello
                   ` (14 more replies)
  0 siblings, 15 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

The existing way that the dell-smbios helper module and associated
other drivers (dell-laptop, dell-wmi) communicate with the platform
really isn't secure.  It requires creating a buffer in physical
DMA32 memory space and passing that to the platform via SMM.

Since the platform got a physical memory pointer, you've just got
to trust that the platform has only modified (and accessed) memory
within that buffer.

Dell Platform designers recognize this security risk and offer a
safer way to communicate with the platform over ACPI.  This is
in turn exposed via a WMI interface to the OS.

When communicating over WMI-ACPI the communication doesn't occur
with physical memory pointers.  When the ASL is invoked, the fixed
length ACPI buffer is copied to a small operating region.  The ASL
will invoke the SMI, and SMM will only have access to this operating
region.  When the ASL returns the buffer is copied back for the OS
to process.

This method of communication should also deprecate the usage of the
dcdbas kernel module and software dependent upon it's interface.
Instead offer a character device interface for communicating with this
ASL method to allow userspace to use instead.

To faciliate that this patch series introduces a generic way for WMI
drivers to be able to create discoverable character devices with
a predictable IOCTL interface through the WMI bus when desired.
Requiring WMI drivers to explicitly ask for this functionality will
act as an effective vendor whitelist to character device creation.

Some of this work is the basis for what will be a proper interpreter
of MOF in the kernel and controls for what drivers will be able to
do with that MOF.

NOTE: This patch is intended to go on top of the 6 patches already in
Darren's review tree.

For convenience the entire series including those is also available here:
https://github.com/dell/linux/tree/wmi-smbios

I also have some PoC application use around this here:
https://github.com/superm1/smbios-wmi-poc

changes between v3 and v4:
 * Make Dell WMI notifications driver fail notifications fail
   when WMI descriptor driver is unavailable.
 * Add a patch to check for Dell OEM string to stop dell-smbios 
   module from being loaded in unsupported systems manually.
 * Split Dell WMI descriptor into it's own driver for others to
   query.
 * Test the misc BIOS flags table to decide whether to run in WMI
   or SMI mode.
 * s/dell-wmi-smbios/dell-smbios/ in a few patch titles
 * Add missing Suggested-by to a patch from v2 (Sorry Andy S!)
 * Adjust cleanup order of wmi character device.
 * Fix a remaining reference to /dev/wmi-$driver
 * Use get_order to get size for pages
 * Split up dell-smbios into 3 drivers:
   dell-smbios
   -> dell-smbios-smm
   -> dell-smbios-wmi
   If either of the two dispatcher drivers is unloaded but
   the other still works, gracefully fall back to that driver
 * Remove unneded open and release on file operations in WMI
   driver
 * Switch to misc character device in WMI bus.
 * Query the size of the calling interface buffer from WMI
   descriptor driver.
 * Require userspace to use this information to build an
   appropriately sized buffer.
 * Verify the size of buffer passed from userspace matches
   expectation of buffer processed in kernel.
 * Add more documentation about the IOCTL API.
 * Add in a recommendation from Andy S about outputing tokens
 * Add a patch to test for non-functional SMM due to WSMT
 * Define macros for IOCTL's through the WMI bus.
 * Pass all IOCTL calls for WMI drivers through WMI bus
   WMI bus will guarantee instance count matches and prevent
   creating too many more IOCTLs.
changes between v2 and v3:
 * Drop patches 1-7, they're in Darren's review tree now
 * Add missing newline on new Documentation
 * Add Reviewed by from Edward O'Callaghan
 * Adjust path of character device from /dev/wmi-$driver to
   /dev/wmi/$driver
 * Store wmi_device pointer rather than using a boolean has_wmi
   to indicate driver is running in WMI mode
 * Don't guard free_page from freeing NULL (this is OK)
 * New patch: add wmidev_evaluate_method to wmi bus as recommended
   by Andy L
 * Adjust ACPI-WMI interface for this patch change ^
 * Add back in sysfs token patch, drop 2nd and 3rd ioctls per discussion
   on mailing list.
 * On sysfs interface: adjust the delimiter to be tabs
 * Drop the rename dell-smbios -> dell-wmi-smbios patch
 * Remove/move some unnecessary tests for CONFIG_DCDBAS
 * Reword s/platform/SMM/ in the WMI-ACPI patch.
 * Update Kconfig to recommend using CONFIG_DCDBAS on old machines.
 * Allocate buffer to the same pointer regardless of the struct 
   assigned to it.  Keep track of the buffer size for cleaning up.
 * Explain policy around character device creation in commit message
changes between v1 and v2:
 * Introduce another patch to sort the includes in wmi.c
 * Introduce another patch to cleanup dell_wmi_check_descriptor_buffer
   checks.
 * Add a commit message to the pr_fmt commit
 * Introduce includes to wmi.c in proper location
 * Add Reviewed-by to relevant patches from Pali
 * Make the WMI introduction patch fallback to legacy SMI
   if compiled with CONFIG_DCDBAS
 * Separate format of WMI and SMI buffers.  WMI buffer supports more
   arguments and data.
 * Adjust the rename patch for changes to fallback
 * Drop sysfs token creation patch
 * Adjust WMI descriptor check patch for changes to fallback
 * introduce another patch to remove needless includes in dell-smbios.c
 * Add token ioctl interface to character device.
   - Can query number of tokens
   - Can query values in all tokens
 * Expose format of all buffers and IOCTL commands to uapi header
 * Drop the read interface from character device.  It doesn't make
   sense with multiple different ioctl methods.
 * Default WMI interface to 32k (This would normally be queried via
   MOF, but that's not possible yet)
 * Create separate buffers for WMI and SMI.  If WMI is available,
   free the SMI buffer.
 * Reorder patches so all fixups come first in the series.



Mario Limonciello (14):
  platform/x86: wmi: Add new method wmidev_evaluate_method
  platform/x86: dell-wmi: clean up wmi descriptor check
  platform/x86: dell-wmi: allow 32k return size in the descriptor
  platform/x86: dell-wmi: increase severity of some failures
  platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own
    driver
  platform/x86: wmi: Don't allow drivers to get each other's GUIDs
  platform/x86: dell-smbios: only run if proper oem string is detected
  platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens
  platform/x86: dell-smbios: Introduce dispatcher for SMM calls
  platform/x86: dell-smbios-smm: test for WSMT
  platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  platform/x86: wmi: create character devices when requested by drivers
  platform/x86: dell-smbios-wmi: introduce userspace interface
  platform/x86: Kconfig: Set default for dell-smbios to ACPI_WMI

 Documentation/ABI/testing/dell-smbios-wmi          |  43 +++
 .../ABI/testing/sysfs-platform-dell-smbios         |  16 ++
 .../ABI/testing/sysfs-platform-dell-smbios-wmi     |  10 +
 MAINTAINERS                                        |  26 ++
 drivers/platform/x86/Kconfig                       |  44 ++-
 drivers/platform/x86/Makefile                      |   3 +
 drivers/platform/x86/dell-laptop.c                 | 191 +++++++------
 drivers/platform/x86/dell-smbios-smm.c             | 172 +++++++++++
 drivers/platform/x86/dell-smbios-smm.h             |  22 ++
 drivers/platform/x86/dell-smbios-wmi.c             | 313 +++++++++++++++++++++
 drivers/platform/x86/dell-smbios-wmi.h             |  18 ++
 drivers/platform/x86/dell-smbios.c                 | 183 +++++++++---
 drivers/platform/x86/dell-smbios.h                 |  13 +-
 drivers/platform/x86/dell-wmi-descriptor.c         | 162 +++++++++++
 drivers/platform/x86/dell-wmi-descriptor.h         |  18 ++
 drivers/platform/x86/dell-wmi.c                    |  96 +------
 drivers/platform/x86/wmi.c                         | 112 ++++++--
 include/linux/wmi.h                                |  12 +-
 include/uapi/linux/dell-smbios-wmi.h               |  25 ++
 include/uapi/linux/wmi.h                           |  10 +
 20 files changed, 1233 insertions(+), 256 deletions(-)
 create mode 100644 Documentation/ABI/testing/dell-smbios-wmi
 create mode 100644 Documentation/ABI/testing/sysfs-platform-dell-smbios
 create mode 100644 Documentation/ABI/testing/sysfs-platform-dell-smbios-wmi
 create mode 100644 drivers/platform/x86/dell-smbios-smm.c
 create mode 100644 drivers/platform/x86/dell-smbios-smm.h
 create mode 100644 drivers/platform/x86/dell-smbios-wmi.c
 create mode 100644 drivers/platform/x86/dell-smbios-wmi.h
 create mode 100644 drivers/platform/x86/dell-wmi-descriptor.c
 create mode 100644 drivers/platform/x86/dell-wmi-descriptor.h
 create mode 100644 include/uapi/linux/dell-smbios-wmi.h
 create mode 100644 include/uapi/linux/wmi.h

-- 
2.14.1

^ permalink raw reply	[flat|nested] 93+ messages in thread

* [PATCH v4 01/14] platform/x86: wmi: Add new method wmidev_evaluate_method
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 02/14] platform/x86: dell-wmi: clean up wmi descriptor check Mario Limonciello
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

Drivers properly using the wmibus can pass their wmi_device
pointer rather than the GUID back to the WMI bus to evaluate
the proper methods.

Any "new" drivers added that use the WMI bus should use this
rather than the old wmi_evaluate_method that would take the
GUID.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 drivers/platform/x86/wmi.c | 28 ++++++++++++++++++++++++----
 include/linux/wmi.h        |  6 ++++++
 2 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 7a05843aff19..4d73a87c2ddf 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -200,6 +200,28 @@ static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
  */
 acpi_status wmi_evaluate_method(const char *guid_string, u8 instance,
 u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
+{
+	struct wmi_block *wblock = NULL;
+
+	if (!find_guid(guid_string, &wblock))
+		return AE_ERROR;
+	return wmidev_evaluate_method(&wblock->dev, instance, method_id,
+				      in, out);
+}
+EXPORT_SYMBOL_GPL(wmi_evaluate_method);
+
+/**
+ * wmidev_evaluate_method - Evaluate a WMI method
+ * @wdev: A wmi bus device from a driver
+ * @instance: Instance index
+ * @method_id: Method ID to call
+ * &in: Buffer containing input for the method call
+ * &out: Empty buffer to return the method results
+ *
+ * Call an ACPI-WMI method
+ */
+acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance,
+	u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
 {
 	struct guid_block *block = NULL;
 	struct wmi_block *wblock = NULL;
@@ -209,9 +231,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
 	union acpi_object params[3];
 	char method[5] = "WM";
 
-	if (!find_guid(guid_string, &wblock))
-		return AE_ERROR;
-
+	wblock = container_of(wdev, struct wmi_block, dev);
 	block = &wblock->gblock;
 	handle = wblock->acpi_device->handle;
 
@@ -246,7 +266,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
 
 	return status;
 }
-EXPORT_SYMBOL_GPL(wmi_evaluate_method);
+EXPORT_SYMBOL_GPL(wmidev_evaluate_method);
 
 static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
 				 struct acpi_buffer *out)
diff --git a/include/linux/wmi.h b/include/linux/wmi.h
index cd0d7734dc49..2cd10c3b89e9 100644
--- a/include/linux/wmi.h
+++ b/include/linux/wmi.h
@@ -26,6 +26,12 @@ struct wmi_device {
 	bool setable;
 };
 
+/* evaluate the ACPI method associated with this device */
+extern acpi_status wmidev_evaluate_method(struct wmi_device *wdev,
+					  u8 instance, u32 method_id,
+					  const struct acpi_buffer *in,
+					  struct acpi_buffer *out);
+
 /* Caller must kfree the result. */
 extern union acpi_object *wmidev_block_query(struct wmi_device *wdev,
 					     u8 instance);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 02/14] platform/x86: dell-wmi: clean up wmi descriptor check
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 01/14] platform/x86: wmi: Add new method wmidev_evaluate_method Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 03/14] platform/x86: dell-wmi: allow 32k return size in the descriptor Mario Limonciello
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

Some cases the wrong type was used for errors and checks can be
done more cleanly.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
Reviewed-by: Edward O'Callaghan <quasisec@google.com>
Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
 drivers/platform/x86/dell-wmi.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 1fbef560ca67..5973aa20f10e 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -665,16 +665,16 @@ static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev)
 
 	buffer = (u32 *)obj->buffer.pointer;
 
-	if (buffer[0] != 0x4C4C4544 && buffer[1] != 0x494D5720)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature (%*ph)\n",
-			8, buffer);
+	if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0)
+		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
+			buffer);
 
 	if (buffer[2] != 0 && buffer[2] != 1)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%d)\n",
+		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%u)\n",
 			buffer[2]);
 
 	if (buffer[3] != 4096)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%d)\n",
+		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%u)\n",
 			buffer[3]);
 
 	priv->interface_version = buffer[2];
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 03/14] platform/x86: dell-wmi: allow 32k return size in the descriptor
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 01/14] platform/x86: wmi: Add new method wmidev_evaluate_method Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 02/14] platform/x86: dell-wmi: clean up wmi descriptor check Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures Mario Limonciello
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

Some platforms this year will be adopting 32k WMI buffer, so don't
complain when encountering those.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 drivers/platform/x86/dell-wmi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 5973aa20f10e..4807ec4a2e8f 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -624,7 +624,7 @@ static void dell_wmi_input_destroy(struct wmi_device *wdev)
  * Vendor Signature          0       4    "DELL"
  * Object Signature          4       4    " WMI"
  * WMI Interface Version     8       4    <version>
- * WMI buffer length        12       4    4096
+ * WMI buffer length        12       4    4096 or 32768
  */
 static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev)
 {
@@ -673,7 +673,7 @@ static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev)
 		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%u)\n",
 			buffer[2]);
 
-	if (buffer[3] != 4096)
+	if (desc_buffer[3] != 4096 && desc_buffer[3] != 32768)
 		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%u)\n",
 			buffer[3]);
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (2 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 03/14] platform/x86: dell-wmi: allow 32k return size in the descriptor Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  5:20   ` Andy Shevchenko
  2017-10-04 22:48 ` [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver Mario Limonciello
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

There is a lot of error checking in place for the format of the WMI
descriptor buffer, but some of the potentially raised issues should
be considered critical failures.

If the buffer size or header don't match, this is a good indication
that the buffer format changed in a way that the rest of the data
should not be relied upon.

For the remaining data set vectors, continue to notate a warning
in undefined results, but as those are fields that the descriptor
intended to refer to other applications, don't fail if they're new
values.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 drivers/platform/x86/dell-wmi.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 4807ec4a2e8f..1366bccdf275 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -657,18 +657,18 @@ static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev)
 		dev_err(&wdev->dev,
 			"Dell descriptor buffer has invalid length (%d)\n",
 			obj->buffer.length);
-		if (obj->buffer.length < 16) {
-			ret = -EINVAL;
-			goto out;
-		}
+		ret = -EINVAL;
+		goto out;
 	}
 
 	buffer = (u32 *)obj->buffer.pointer;
 
-	if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
+	if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
+		dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
 			buffer);
-
+		ret = -EINVAL;
+		goto out;
+	}
 	if (buffer[2] != 0 && buffer[2] != 1)
 		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%u)\n",
 			buffer[2]);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (3 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  1:09   ` Darren Hart
  2017-10-05  5:34   ` Andy Shevchenko
  2017-10-04 22:48 ` [PATCH v4 06/14] platform/x86: wmi: Don't allow drivers to get each other's GUIDs Mario Limonciello
                   ` (9 subsequent siblings)
  14 siblings, 2 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

All communication on individual GUIDs should occur in separate drivers.
Allowing a driver to communicate with the bus to another GUID is just
a hack that discourages drivers to adopt the bus model.

The information found from the WMI descriptor driver is now exported
for use by other drivers.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 MAINTAINERS                                |   5 +
 drivers/platform/x86/Kconfig               |  12 +++
 drivers/platform/x86/Makefile              |   1 +
 drivers/platform/x86/dell-wmi-descriptor.c | 162 +++++++++++++++++++++++++++++
 drivers/platform/x86/dell-wmi-descriptor.h |  18 ++++
 drivers/platform/x86/dell-wmi.c            |  88 ++--------------
 6 files changed, 205 insertions(+), 81 deletions(-)
 create mode 100644 drivers/platform/x86/dell-wmi-descriptor.c
 create mode 100644 drivers/platform/x86/dell-wmi-descriptor.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 08b96f77f618..659dbeec4191 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4002,6 +4002,11 @@ M:	Pali Rohár <pali.rohar@gmail.com>
 S:	Maintained
 F:	drivers/platform/x86/dell-wmi.c
 
+DELL WMI DESCRIPTOR DRIVER
+M:	Mario Limonciello <mario.limonciello@dell.com>
+S:	Maintained
+F:	drivers/platform/x86/dell-wmi-descriptor.c
+
 DELTA ST MEDIA DRIVER
 M:	Hugues Fruchet <hugues.fruchet@st.com>
 L:	linux-media@vger.kernel.org
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1f7959ff055c..bc347c326d87 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -121,6 +121,7 @@ config DELL_WMI
 	depends on DMI
 	depends on INPUT
 	depends on ACPI_VIDEO || ACPI_VIDEO = n
+	depends on DELL_WMI_DESCRIPTOR
 	select DELL_SMBIOS
 	select INPUT_SPARSEKMAP
 	---help---
@@ -129,6 +130,17 @@ config DELL_WMI
 	  To compile this driver as a module, choose M here: the module will
 	  be called dell-wmi.
 
+config DELL_WMI_DESCRIPTOR
+	tristate "Dell WMI descriptor"
+	depends on ACPI_WMI
+	default ACPI_WMI
+	---help---
+	  Say Y here if you want to be able to read the format of WMI
+	  communications on some Dell laptops, desktops and IoT gateways.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called dell-wmi-descriptor.
+
 config DELL_WMI_AIO
 	tristate "WMI Hotkeys for Dell All-In-One series"
 	depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2b315d0df3b7..8636f5d3424f 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_COMPAL_LAPTOP)	+= compal-laptop.o
 obj-$(CONFIG_DELL_SMBIOS)	+= dell-smbios.o
 obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_DELL_WMI)		+= dell-wmi.o
+obj-$(CONFIG_DELL_WMI_DESCRIPTOR)	+= dell-wmi-descriptor.o
 obj-$(CONFIG_DELL_WMI_AIO)	+= dell-wmi-aio.o
 obj-$(CONFIG_DELL_WMI_LED)	+= dell-wmi-led.o
 obj-$(CONFIG_DELL_SMO8800)	+= dell-smo8800.o
diff --git a/drivers/platform/x86/dell-wmi-descriptor.c b/drivers/platform/x86/dell-wmi-descriptor.c
new file mode 100644
index 000000000000..5c2bdda11916
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi-descriptor.c
@@ -0,0 +1,162 @@
+/*
+ * Dell WMI descriptor driver
+ *
+ * Copyright (C) 2017 Dell Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/acpi.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/wmi.h>
+#include "dell-wmi-descriptor.h"
+
+#define DELL_WMI_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
+
+struct descriptor_priv {
+	struct list_head list;
+	u32 interface_version;
+	u32 size;
+};
+static LIST_HEAD(wmi_list);
+
+bool dell_wmi_get_interface_version(u32 *version)
+{
+	struct descriptor_priv *priv;
+
+	priv = list_first_entry_or_null(&wmi_list,
+					struct descriptor_priv,
+					list);
+	if (!priv)
+		return false;
+	*version = priv->interface_version;
+	return true;
+}
+EXPORT_SYMBOL_GPL(dell_wmi_get_interface_version);
+
+bool dell_wmi_get_size(u32 *size)
+{
+	struct descriptor_priv *priv;
+
+	priv = list_first_entry_or_null(&wmi_list,
+					struct descriptor_priv,
+					list);
+	if (!priv)
+		return false;
+	*size = priv->size;
+	return true;
+}
+EXPORT_SYMBOL_GPL(dell_wmi_get_size);
+
+/*
+ * Descriptor buffer is 128 byte long and contains:
+ *
+ *       Name             Offset  Length  Value
+ * Vendor Signature          0       4    "DELL"
+ * Object Signature          4       4    " WMI"
+ * WMI Interface Version     8       4    <version>
+ * WMI buffer length        12       4    4096 or 32768
+ */
+static int dell_wmi_descriptor_probe(struct wmi_device *wdev)
+{
+	union acpi_object *obj = NULL;
+	struct descriptor_priv *priv;
+	u32 *buffer;
+	int ret;
+
+	obj = wmidev_block_query(wdev, 0);
+	if (!obj) {
+		dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n");
+		ret = -EIO;
+		goto out;
+	}
+
+	if (obj->type != ACPI_TYPE_BUFFER) {
+		dev_err(&wdev->dev, "Dell descriptor has wrong type\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Although it's not technically a failure, this would lead to
+	 * unexpected behavior
+	 */
+	if (obj->buffer.length != 128) {
+		dev_err(&wdev->dev,
+			"Dell descriptor buffer has unexpected length (%d)\n",
+			obj->buffer.length);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	buffer = (u32 *)obj->buffer.pointer;
+
+	if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
+		dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
+			buffer);
+		ret = -EINVAL;
+		goto out;
+	}
+	if (buffer[2] != 0 && buffer[2] != 1)
+		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%u)\n",
+			buffer[2]);
+
+	if (buffer[3] != 4096 && buffer[3] != 32768)
+		dev_warn(&wdev->dev, "Dell descriptor buffer has unexpected buffer length (%u)\n",
+			buffer[3]);
+
+	priv = devm_kzalloc(&wdev->dev, sizeof(struct descriptor_priv),
+	GFP_KERNEL);
+
+	priv->interface_version = buffer[2];
+	priv->size = buffer[3];
+	ret = 0;
+	dev_set_drvdata(&wdev->dev, priv);
+	list_add_tail(&priv->list, &wmi_list);
+
+	/* remove me */
+	dev_info(&wdev->dev, "Detected Dell WMI interface version %u and buffer size %u\n",
+		priv->interface_version, priv->size);
+
+out:
+	kfree(obj);
+	return ret;
+}
+
+static int dell_wmi_descriptor_remove(struct wmi_device *wdev)
+{
+	struct descriptor_priv *priv = dev_get_drvdata(&wdev->dev);
+
+	list_del(&priv->list);
+	return 0;
+}
+
+static const struct wmi_device_id dell_wmi_descriptor_id_table[] = {
+	{ .guid_string = DELL_WMI_DESCRIPTOR_GUID },
+	{ },
+};
+
+static struct wmi_driver dell_wmi_descriptor_driver = {
+	.driver = {
+		.name = "dell-wmi-descriptor",
+	},
+	.probe = dell_wmi_descriptor_probe,
+	.remove = dell_wmi_descriptor_remove,
+	.id_table = dell_wmi_descriptor_id_table,
+};
+
+module_wmi_driver(dell_wmi_descriptor_driver);
+
+MODULE_ALIAS("wmi:" DELL_WMI_DESCRIPTOR_GUID);
+MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
+MODULE_DESCRIPTION("Dell WMI descriptor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell-wmi-descriptor.h b/drivers/platform/x86/dell-wmi-descriptor.h
new file mode 100644
index 000000000000..3e652c6da034
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi-descriptor.h
@@ -0,0 +1,18 @@
+/*
+ *
+ *  Copyright (c) 2017 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef _DELL_WMI_DESCRIPTOR_H_
+#define _DELL_WMI_DESCRIPTOR_H_
+
+#include <linux/wmi.h>
+
+bool dell_wmi_get_interface_version(u32 *version);
+bool dell_wmi_get_size(u32 *size);
+
+#endif
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 1366bccdf275..90d7e8e55e9b 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -39,6 +39,7 @@
 #include <linux/wmi.h>
 #include <acpi/video.h>
 #include "dell-smbios.h"
+#include "dell-wmi-descriptor.h"
 
 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
 MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
@@ -46,7 +47,6 @@ MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
 MODULE_LICENSE("GPL");
 
 #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
-#define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
 
 static bool wmi_requires_smbios_request;
 
@@ -54,7 +54,6 @@ MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
 struct dell_wmi_priv {
 	struct input_dev *input_dev;
-	u32 interface_version;
 };
 
 static int __init dmi_matched(const struct dmi_system_id *dmi)
@@ -347,9 +346,9 @@ static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code)
 static void dell_wmi_notify(struct wmi_device *wdev,
 			    union acpi_object *obj)
 {
-	struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
 	u16 *buffer_entry, *buffer_end;
 	acpi_size buffer_size;
+	u32 interface_version;
 	int len, i;
 
 	if (obj->type != ACPI_TYPE_BUFFER) {
@@ -376,7 +375,11 @@ static void dell_wmi_notify(struct wmi_device *wdev,
 	 * So to prevent reading garbage from buffer we will process only first
 	 * one event on devices with WMI interface version 0.
 	 */
-	if (priv->interface_version == 0 && buffer_entry < buffer_end)
+	if (!dell_wmi_get_interface_version(&interface_version)) {
+		pr_warn("WMI descriptor driver not ready or unavailable");
+		return;
+	}
+	if (interface_version == 0 && buffer_entry < buffer_end)
 		if (buffer_end > buffer_entry + buffer_entry[0] + 1)
 			buffer_end = buffer_entry + buffer_entry[0] + 1;
 
@@ -617,78 +620,6 @@ static void dell_wmi_input_destroy(struct wmi_device *wdev)
 	input_unregister_device(priv->input_dev);
 }
 
-/*
- * Descriptor buffer is 128 byte long and contains:
- *
- *       Name             Offset  Length  Value
- * Vendor Signature          0       4    "DELL"
- * Object Signature          4       4    " WMI"
- * WMI Interface Version     8       4    <version>
- * WMI buffer length        12       4    4096 or 32768
- */
-static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev)
-{
-	struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
-	union acpi_object *obj = NULL;
-	struct wmi_device *desc_dev;
-	u32 *buffer;
-	int ret;
-
-	desc_dev = wmidev_get_other_guid(wdev, DELL_DESCRIPTOR_GUID);
-	if (!desc_dev) {
-		dev_err(&wdev->dev, "Dell WMI descriptor does not exist\n");
-		return -ENODEV;
-	}
-
-	obj = wmidev_block_query(desc_dev, 0);
-	if (!obj) {
-		dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n");
-		ret = -EIO;
-		goto out;
-	}
-
-	if (obj->type != ACPI_TYPE_BUFFER) {
-		dev_err(&wdev->dev, "Dell descriptor has wrong type\n");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (obj->buffer.length != 128) {
-		dev_err(&wdev->dev,
-			"Dell descriptor buffer has invalid length (%d)\n",
-			obj->buffer.length);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	buffer = (u32 *)obj->buffer.pointer;
-
-	if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
-		dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
-			buffer);
-		ret = -EINVAL;
-		goto out;
-	}
-	if (buffer[2] != 0 && buffer[2] != 1)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%u)\n",
-			buffer[2]);
-
-	if (desc_buffer[3] != 4096 && desc_buffer[3] != 32768)
-		dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%u)\n",
-			buffer[3]);
-
-	priv->interface_version = buffer[2];
-	ret = 0;
-
-	dev_info(&wdev->dev, "Detected Dell WMI interface version %u\n",
-		priv->interface_version);
-
-out:
-	kfree(obj);
-	put_device(&desc_dev->dev);
-	return ret;
-}
-
 /*
  * According to Dell SMBIOS documentation:
  *
@@ -724,7 +655,6 @@ static int dell_wmi_events_set_enabled(bool enable)
 static int dell_wmi_probe(struct wmi_device *wdev)
 {
 	struct dell_wmi_priv *priv;
-	int err;
 
 	priv = devm_kzalloc(
 		&wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL);
@@ -732,10 +662,6 @@ static int dell_wmi_probe(struct wmi_device *wdev)
 		return -ENOMEM;
 	dev_set_drvdata(&wdev->dev, priv);
 
-	err = dell_wmi_check_descriptor_buffer(wdev);
-	if (err)
-		return err;
-
 	return dell_wmi_input_setup(wdev);
 }
 
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 06/14] platform/x86: wmi: Don't allow drivers to get each other's GUIDs
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (4 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 07/14] platform/x86: dell-smbios: only run if proper oem string is detected Mario Limonciello
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

The only driver using this was dell-wmi, and it really was a hack.
The driver was getting a data attribute from another driver and this
type of action should not be encouraged.

Rather drivers that need to interact with one another should pass
data back and forth via exported functions.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 drivers/platform/x86/wmi.c | 17 -----------------
 include/linux/wmi.h        |  4 ----
 2 files changed, 21 deletions(-)

diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 4d73a87c2ddf..bcb41c1c7f52 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -368,23 +368,6 @@ union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance)
 }
 EXPORT_SYMBOL_GPL(wmidev_block_query);
 
-struct wmi_device *wmidev_get_other_guid(struct wmi_device *wdev,
-					 const char *guid_string)
-{
-	struct wmi_block *this_wb = container_of(wdev, struct wmi_block, dev);
-	struct wmi_block *other_wb;
-
-	if (!find_guid(guid_string, &other_wb))
-		return NULL;
-
-	if (other_wb->acpi_device != this_wb->acpi_device)
-		return NULL;
-
-	get_device(&other_wb->dev.dev);
-	return &other_wb->dev;
-}
-EXPORT_SYMBOL_GPL(wmidev_get_other_guid);
-
 /**
  * wmi_set_block - Write to a WMI block
  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
diff --git a/include/linux/wmi.h b/include/linux/wmi.h
index 2cd10c3b89e9..ddee427e0721 100644
--- a/include/linux/wmi.h
+++ b/include/linux/wmi.h
@@ -36,10 +36,6 @@ extern acpi_status wmidev_evaluate_method(struct wmi_device *wdev,
 extern union acpi_object *wmidev_block_query(struct wmi_device *wdev,
 					     u8 instance);
 
-/* Gets another device on the same bus.  Caller must put_device the result. */
-extern struct wmi_device *wmidev_get_other_guid(struct wmi_device *wdev,
-						const char *guid_string);
-
 struct wmi_device_id {
 	const char *guid_string;
 };
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 07/14] platform/x86: dell-smbios: only run if proper oem string is detected
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (5 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 06/14] platform/x86: wmi: Don't allow drivers to get each other's GUIDs Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-04 22:48 ` [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens Mario Limonciello
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

The proper way to indicate that a system is a 'supported' Dell System
is by the presence of this string in OEM strings.

Allowing the driver to load on non-Dell systems will have undefined
results.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 drivers/platform/x86/dell-smbios.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c
index e9b1ca07c872..873d1c3f7641 100644
--- a/drivers/platform/x86/dell-smbios.c
+++ b/drivers/platform/x86/dell-smbios.c
@@ -172,8 +172,15 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy)
 
 static int __init dell_smbios_init(void)
 {
+	const struct dmi_device *valid;
 	int ret;
 
+	valid = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL);
+	if (!valid) {
+		pr_info("Unable to run on non-Dell system\n");
+		return -ENODEV;
+	}
+
 	dmi_walk(find_tokens, NULL);
 
 	if (!da_tokens)  {
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (6 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 07/14] platform/x86: dell-smbios: only run if proper oem string is detected Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  8:49   ` Andy Shevchenko
  2017-10-04 22:48 ` [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls Mario Limonciello
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

Currently userspace tools can access system tokens via the dcdbas
kernel module and a SMI call that will cause the platform to execute
SMM code.

With a goal in mind of deprecating the dcdbas kernel module a different
method for accessing these tokens from userspace needs to be created.

This is intentionally marked to only be readable as root as it can
contain sensitive information about the platform's configuration.

MAINTAINERS was missing for this driver.  Add myself and Pali to
maintainers list for it.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
 .../ABI/testing/sysfs-platform-dell-smbios         | 16 ++++++
 MAINTAINERS                                        |  7 +++
 drivers/platform/x86/dell-smbios.c                 | 64 ++++++++++++++++++++++
 3 files changed, 87 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-dell-smbios

diff --git a/Documentation/ABI/testing/sysfs-platform-dell-smbios b/Documentation/ABI/testing/sysfs-platform-dell-smbios
new file mode 100644
index 000000000000..d97f4bd5bd91
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-dell-smbios
@@ -0,0 +1,16 @@
+What:		/sys/devices/platform/<platform>/tokens
+Date:		November 2017
+KernelVersion:	4.15
+Contact:	"Mario Limonciello" <mario.limonciello@dell.com>
+Description:
+		A read-only description of Dell platform tokens
+		available on the machine.
+
+		The tokens will be displayed in the following
+		machine readable format with each token on a
+		new line:
+
+		ID	Location	value
+
+		For example token:
+		5	5	3
diff --git a/MAINTAINERS b/MAINTAINERS
index 659dbeec4191..2e3f2aea0370 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3967,6 +3967,13 @@ M:	"Maciej W. Rozycki" <macro@linux-mips.org>
 S:	Maintained
 F:	drivers/net/fddi/defxx.*
 
+DELL SMBIOS DRIVER
+M:	Pali Rohár <pali.rohar@gmail.com>
+M:	Mario Limonciello <mario.limonciello@dell.com>
+L:	platform-driver-x86@vger.kernel.org
+S:	Maintained
+F:	drivers/platform/x86/dell-smbios.*
+
 DELL LAPTOP DRIVER
 M:	Matthew Garrett <mjg59@srcf.ucam.org>
 M:	Pali Rohár <pali.rohar@gmail.com>
diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c
index 873d1c3f7641..7275d1d48190 100644
--- a/drivers/platform/x86/dell-smbios.c
+++ b/drivers/platform/x86/dell-smbios.c
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/io.h>
 #include "../../firmware/dcdbas.h"
+#include <linux/platform_device.h>
 #include "dell-smbios.h"
 
 struct calling_interface_structure {
@@ -39,6 +40,7 @@ static DEFINE_MUTEX(buffer_mutex);
 static int da_command_address;
 static int da_command_code;
 static int da_num_tokens;
+static struct platform_device *platform_device;
 static struct calling_interface_token *da_tokens;
 
 int dell_smbios_error(int value)
@@ -170,6 +172,40 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy)
 	}
 }
 
+static ssize_t tokens_show(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	size_t off = 0;
+	int to_print;
+	int i;
+
+	to_print = min(da_num_tokens, (int)(PAGE_SIZE - 1) / 15);
+	for (i = 0; i < to_print; i++) {
+		off += scnprintf(buf+off, PAGE_SIZE-off, "%04x\t%04x\t%04x\n",
+		da_tokens[i].tokenID, da_tokens[i].location,
+		da_tokens[i].value);
+	}
+
+	return off;
+}
+
+DEVICE_ATTR(tokens, 0400, tokens_show, NULL);
+
+static struct attribute *smbios_attrs[] = {
+	&dev_attr_tokens.attr,
+	NULL
+};
+
+static const struct attribute_group smbios_attribute_group = {
+	.attrs = smbios_attrs,
+};
+
+static struct platform_driver platform_driver = {
+	.driver = {
+		.name = "dell-smbios",
+	},
+};
+
 static int __init dell_smbios_init(void)
 {
 	const struct dmi_device *valid;
@@ -197,9 +233,37 @@ static int __init dell_smbios_init(void)
 		ret = -ENOMEM;
 		goto fail_buffer;
 	}
+	ret = platform_driver_register(&platform_driver);
+	if (ret)
+		goto fail_platform_driver;
+
+	platform_device = platform_device_alloc("dell-smbios", 0);
+	if (!platform_device) {
+		ret = -ENOMEM;
+		goto fail_platform_device_alloc;
+	}
+	ret = platform_device_add(platform_device);
+	if (ret)
+		goto fail_platform_device_add;
+	ret = sysfs_create_group(&platform_device->dev.kobj,
+				 &smbios_attribute_group);
+	if (ret)
+		goto fail_create_group;
 
 	return 0;
 
+fail_create_group:
+	platform_device_del(platform_device);
+
+fail_platform_device_add:
+	platform_device_put(platform_device);
+
+fail_platform_device_alloc:
+	platform_driver_unregister(&platform_driver);
+
+fail_platform_driver:
+	free_page((unsigned long)buffer);
+
 fail_buffer:
 	kfree(da_tokens);
 	return ret;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (7 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  1:57   ` Darren Hart
  2017-10-04 22:48 ` [PATCH v4 10/14] platform/x86: dell-smbios-smm: test for WSMT Mario Limonciello
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

This splits up the dell-smbios driver into two drivers:
* dell-smbios
* dell-smbios-smm

dell-smbios can operate with multiple different dispatcher drivers to
perform SMBIOS operations.

Also modify the interface that dell-laptop and dell-wmi use align to this
model more closely.  Rather than a single global buffer being allocated
for all drivers, each driver will allocate and be responsible for it's own
buffer. The pointer will be passed to the calling function and each
dispatcher driver will then internally copy it to the proper location to
perform it's call.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 MAINTAINERS                            |   6 ++
 drivers/platform/x86/Kconfig           |  17 ++-
 drivers/platform/x86/Makefile          |   1 +
 drivers/platform/x86/dell-laptop.c     | 191 ++++++++++++++++-----------------
 drivers/platform/x86/dell-smbios-smm.c | 136 +++++++++++++++++++++++
 drivers/platform/x86/dell-smbios-smm.h |  22 ++++
 drivers/platform/x86/dell-smbios.c     | 120 +++++++++++++--------
 drivers/platform/x86/dell-smbios.h     |  13 ++-
 drivers/platform/x86/dell-wmi.c        |   8 +-
 9 files changed, 361 insertions(+), 153 deletions(-)
 create mode 100644 drivers/platform/x86/dell-smbios-smm.c
 create mode 100644 drivers/platform/x86/dell-smbios-smm.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 2e3f2aea0370..a8fcb4a4e195 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3974,6 +3974,12 @@ L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
 F:	drivers/platform/x86/dell-smbios.*
 
+DELL SMBIOS SMM DRIVER
+M:	Mario Limonciello <mario.limonciello@dell.com>
+L:	platform-driver-x86@vger.kernel.org
+S:	Maintained
+F:	drivers/platform/x86/dell-smbios-smm.*
+
 DELL LAPTOP DRIVER
 M:	Matthew Garrett <mjg59@srcf.ucam.org>
 M:	Pali Rohár <pali.rohar@gmail.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index bc347c326d87..f0b97cb8e449 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -92,14 +92,27 @@ config ASUS_LAPTOP
 	  If you have an ACPI-compatible ASUS laptop, say Y or M here.
 
 config DELL_SMBIOS
-	tristate
-	select DCDBAS
+	tristate "Dell SMBIOS calling interface"
+	depends on DELL_SMBIOS_SMM
 	---help---
 	This module provides common functions for kernel modules using
 	Dell SMBIOS.
 
 	If you have a Dell laptop, say Y or M here.
 
+config DELL_SMBIOS_SMM
+	tristate "Dell SMBIOS calling interface (SMM implementation)"
+	depends on DCDBAS
+	default DCDBAS
+	select DELL_SMBIOS
+	---help---
+	This provides an implementation for the Dell SMBIOS calling interface
+	communicated over ACPI-WMI.
+
+	If you have a Dell computer from >2007 you should say Y or M here.
+	If you aren't sure and this module doesn't work for your computer
+	it just won't load.
+
 config DELL_LAPTOP
 	tristate "Dell Laptop Extras"
 	depends on DMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 8636f5d3424f..e743615241f8 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MSI_LAPTOP)	+= msi-laptop.o
 obj-$(CONFIG_ACPI_CMPC)		+= classmate-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)	+= compal-laptop.o
 obj-$(CONFIG_DELL_SMBIOS)	+= dell-smbios.o
+obj-$(CONFIG_DELL_SMBIOS_SMM)	+= dell-smbios-smm.o
 obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_DELL_WMI)		+= dell-wmi.o
 obj-$(CONFIG_DELL_WMI_DESCRIPTOR)	+= dell-wmi-descriptor.o
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index f42159fd2031..c648bbfcc394 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -85,6 +85,7 @@ static struct platform_driver platform_driver = {
 	}
 };
 
+static struct calling_interface_buffer *buffer;
 static struct platform_device *platform_device;
 static struct backlight_device *dell_backlight_device;
 static struct rfkill *wifi_rfkill;
@@ -405,7 +406,6 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
 
 static int dell_rfkill_set(void *data, bool blocked)
 {
-	struct calling_interface_buffer *buffer;
 	int disable = blocked ? 1 : 0;
 	unsigned long radio = (unsigned long)data;
 	int hwswitch_bit = (unsigned long)data - 1;
@@ -413,19 +413,21 @@ static int dell_rfkill_set(void *data, bool blocked)
 	int status;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
-
-	dell_smbios_send_request(17, 11);
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	status = buffer->output[1];
 
 	if (ret != 0)
 		goto out;
 
-	dell_smbios_clear_buffer();
-
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
 	buffer->input[0] = 0x2;
-	dell_smbios_send_request(17, 11);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	hwswitch = buffer->output[1];
 
@@ -435,28 +437,29 @@ static int dell_rfkill_set(void *data, bool blocked)
 	    (status & BIT(0)) && !(status & BIT(16)))
 		disable = 1;
 
-	dell_smbios_clear_buffer();
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
 
 	buffer->input[0] = (1 | (radio<<8) | (disable << 16));
-	dell_smbios_send_request(17, 11);
+	buffer->class = 17;
+	buffer->select = 11;
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 
  out:
-	dell_smbios_release_buffer();
 	return dell_smbios_error(ret);
 }
 
-/* Must be called with the buffer held */
 static void dell_rfkill_update_sw_state(struct rfkill *rfkill, int radio,
-					int status,
-					struct calling_interface_buffer *buffer)
+					int status)
 {
 	if (status & BIT(0)) {
 		/* Has hw-switch, sync sw_state to BIOS */
 		int block = rfkill_blocked(rfkill);
-		dell_smbios_clear_buffer();
+		memset(buffer, 0, sizeof(struct calling_interface_buffer));
+		buffer->class = 17;
+		buffer->select = 11;
 		buffer->input[0] = (1 | (radio << 8) | (block << 16));
-		dell_smbios_send_request(17, 11);
+		dell_smbios_call(buffer);
 	} else {
 		/* No hw-switch, sync BIOS state to sw_state */
 		rfkill_set_sw_state(rfkill, !!(status & BIT(radio + 16)));
@@ -472,32 +475,30 @@ static void dell_rfkill_update_hw_state(struct rfkill *rfkill, int radio,
 
 static void dell_rfkill_query(struct rfkill *rfkill, void *data)
 {
-	struct calling_interface_buffer *buffer;
 	int radio = ((unsigned long)data & 0xF);
 	int hwswitch;
 	int status;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
-
-	dell_smbios_send_request(17, 11);
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	status = buffer->output[1];
 
 	if (ret != 0 || !(status & BIT(0))) {
-		dell_smbios_release_buffer();
 		return;
 	}
 
-	dell_smbios_clear_buffer();
-
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
 	buffer->input[0] = 0x2;
-	dell_smbios_send_request(17, 11);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	hwswitch = buffer->output[1];
 
-	dell_smbios_release_buffer();
-
 	if (ret != 0)
 		return;
 
@@ -513,27 +514,26 @@ static struct dentry *dell_laptop_dir;
 
 static int dell_debugfs_show(struct seq_file *s, void *data)
 {
-	struct calling_interface_buffer *buffer;
 	int hwswitch_state;
 	int hwswitch_ret;
 	int status;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
-
-	dell_smbios_send_request(17, 11);
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	status = buffer->output[1];
 
-	dell_smbios_clear_buffer();
-
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
 	buffer->input[0] = 0x2;
-	dell_smbios_send_request(17, 11);
+	dell_smbios_call(buffer);
 	hwswitch_ret = buffer->output[0];
 	hwswitch_state = buffer->output[1];
 
-	dell_smbios_release_buffer();
-
 	seq_printf(s, "return:\t%d\n", ret);
 	seq_printf(s, "status:\t0x%X\n", status);
 	seq_printf(s, "Bit 0 : Hardware switch supported:   %lu\n",
@@ -613,24 +613,25 @@ static const struct file_operations dell_debugfs_fops = {
 
 static void dell_update_rfkill(struct work_struct *ignored)
 {
-	struct calling_interface_buffer *buffer;
 	int hwswitch = 0;
 	int status;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
-
-	dell_smbios_send_request(17, 11);
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	status = buffer->output[1];
 
 	if (ret != 0)
-		goto out;
-
-	dell_smbios_clear_buffer();
+		return;
 
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
 	buffer->input[0] = 0x2;
-	dell_smbios_send_request(17, 11);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 
 	if (ret == 0 && (status & BIT(0)))
@@ -638,21 +639,17 @@ static void dell_update_rfkill(struct work_struct *ignored)
 
 	if (wifi_rfkill) {
 		dell_rfkill_update_hw_state(wifi_rfkill, 1, status, hwswitch);
-		dell_rfkill_update_sw_state(wifi_rfkill, 1, status, buffer);
+		dell_rfkill_update_sw_state(wifi_rfkill, 1, status);
 	}
 	if (bluetooth_rfkill) {
 		dell_rfkill_update_hw_state(bluetooth_rfkill, 2, status,
 					    hwswitch);
-		dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status,
-					    buffer);
+		dell_rfkill_update_sw_state(bluetooth_rfkill, 2, status);
 	}
 	if (wwan_rfkill) {
 		dell_rfkill_update_hw_state(wwan_rfkill, 3, status, hwswitch);
-		dell_rfkill_update_sw_state(wwan_rfkill, 3, status, buffer);
+		dell_rfkill_update_sw_state(wwan_rfkill, 3, status);
 	}
-
- out:
-	dell_smbios_release_buffer();
 }
 static DECLARE_DELAYED_WORK(dell_rfkill_work, dell_update_rfkill);
 
@@ -696,7 +693,6 @@ static struct notifier_block dell_laptop_rbtn_notifier = {
 
 static int __init dell_setup_rfkill(void)
 {
-	struct calling_interface_buffer *buffer;
 	int status, ret, whitelisted;
 	const char *product;
 
@@ -712,11 +708,12 @@ static int __init dell_setup_rfkill(void)
 	if (!force_rfkill && !whitelisted)
 		return 0;
 
-	buffer = dell_smbios_get_buffer();
-	dell_smbios_send_request(17, 11);
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 17;
+	buffer->select = 11;
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	status = buffer->output[1];
-	dell_smbios_release_buffer();
 
 	/* dell wireless info smbios call is not supported */
 	if (ret != 0)
@@ -869,7 +866,6 @@ static void dell_cleanup_rfkill(void)
 
 static int dell_send_intensity(struct backlight_device *bd)
 {
-	struct calling_interface_buffer *buffer;
 	struct calling_interface_token *token;
 	int ret;
 
@@ -877,24 +873,22 @@ static int dell_send_intensity(struct backlight_device *bd)
 	if (!token)
 		return -ENODEV;
 
-	buffer = dell_smbios_get_buffer();
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
 	buffer->input[0] = token->location;
 	buffer->input[1] = bd->props.brightness;
-
+	buffer->class = 1;
 	if (power_supply_is_system_supplied() > 0)
-		dell_smbios_send_request(1, 2);
+		buffer->select = 2;
 	else
-		dell_smbios_send_request(1, 1);
-
+		buffer->select = 1;
+	dell_smbios_call(buffer);
 	ret = dell_smbios_error(buffer->output[0]);
 
-	dell_smbios_release_buffer();
 	return ret;
 }
 
 static int dell_get_intensity(struct backlight_device *bd)
 {
-	struct calling_interface_buffer *buffer;
 	struct calling_interface_token *token;
 	int ret;
 
@@ -902,20 +896,20 @@ static int dell_get_intensity(struct backlight_device *bd)
 	if (!token)
 		return -ENODEV;
 
-	buffer = dell_smbios_get_buffer();
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
 	buffer->input[0] = token->location;
-
+	buffer->class = 0;
 	if (power_supply_is_system_supplied() > 0)
-		dell_smbios_send_request(0, 2);
+		buffer->select = 2;
 	else
-		dell_smbios_send_request(0, 1);
+		buffer->select = 1;
+	dell_smbios_call(buffer);
 
 	if (buffer->output[0])
 		ret = dell_smbios_error(buffer->output[0]);
 	else
 		ret = buffer->output[1];
 
-	dell_smbios_release_buffer();
 	return ret;
 }
 
@@ -1179,14 +1173,14 @@ static DEFINE_MUTEX(kbd_led_mutex);
 
 static int kbd_get_info(struct kbd_info *info)
 {
-	struct calling_interface_buffer *buffer;
 	u8 units;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
-
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 4;
+	buffer->select = 11;
 	buffer->input[0] = 0x0;
-	dell_smbios_send_request(4, 11);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 
 	if (ret) {
@@ -1210,7 +1204,6 @@ static int kbd_get_info(struct kbd_info *info)
 		info->days = (buffer->output[3] >> 24) & 0xFF;
 
  out:
-	dell_smbios_release_buffer();
 	return ret;
 }
 
@@ -1269,13 +1262,13 @@ static int kbd_set_level(struct kbd_state *state, u8 level)
 
 static int kbd_get_state(struct kbd_state *state)
 {
-	struct calling_interface_buffer *buffer;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
-
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 4;
+	buffer->select = 11;
 	buffer->input[0] = 0x1;
-	dell_smbios_send_request(4, 11);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 
 	if (ret) {
@@ -1297,16 +1290,16 @@ static int kbd_get_state(struct kbd_state *state)
 	state->timeout_unit_ac = (buffer->output[2] >> 30) & 0x3;
 
  out:
-	dell_smbios_release_buffer();
 	return ret;
 }
 
 static int kbd_set_state(struct kbd_state *state)
 {
-	struct calling_interface_buffer *buffer;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 4;
+	buffer->select = 11;
 	buffer->input[0] = 0x2;
 	buffer->input[1] = BIT(state->mode_bit) & 0xFFFF;
 	buffer->input[1] |= (state->triggers & 0xFF) << 16;
@@ -1316,9 +1309,8 @@ static int kbd_set_state(struct kbd_state *state)
 	buffer->input[2] |= (state->level & 0xFF) << 16;
 	buffer->input[2] |= (state->timeout_value_ac & 0x3F) << 24;
 	buffer->input[2] |= (state->timeout_unit_ac & 0x3) << 30;
-	dell_smbios_send_request(4, 11);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
-	dell_smbios_release_buffer();
 
 	return dell_smbios_error(ret);
 }
@@ -1345,7 +1337,6 @@ static int kbd_set_state_safe(struct kbd_state *state, struct kbd_state *old)
 
 static int kbd_set_token_bit(u8 bit)
 {
-	struct calling_interface_buffer *buffer;
 	struct calling_interface_token *token;
 	int ret;
 
@@ -1356,19 +1347,19 @@ static int kbd_set_token_bit(u8 bit)
 	if (!token)
 		return -EINVAL;
 
-	buffer = dell_smbios_get_buffer();
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
 	buffer->input[0] = token->location;
 	buffer->input[1] = token->value;
-	dell_smbios_send_request(1, 0);
+	buffer->class = 1;
+	buffer->select = 0;
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
-	dell_smbios_release_buffer();
 
 	return dell_smbios_error(ret);
 }
 
 static int kbd_get_token_bit(u8 bit)
 {
-	struct calling_interface_buffer *buffer;
 	struct calling_interface_token *token;
 	int ret;
 	int val;
@@ -1380,12 +1371,14 @@ static int kbd_get_token_bit(u8 bit)
 	if (!token)
 		return -EINVAL;
 
-	buffer = dell_smbios_get_buffer();
+
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 0;
+	buffer->select = 0;
 	buffer->input[0] = token->location;
-	dell_smbios_send_request(0, 0);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
 	val = buffer->output[1];
-	dell_smbios_release_buffer();
 
 	if (ret)
 		return dell_smbios_error(ret);
@@ -2102,7 +2095,6 @@ static struct notifier_block dell_laptop_notifier = {
 
 int dell_micmute_led_set(int state)
 {
-	struct calling_interface_buffer *buffer;
 	struct calling_interface_token *token;
 
 	if (state == 0)
@@ -2115,11 +2107,12 @@ int dell_micmute_led_set(int state)
 	if (!token)
 		return -ENODEV;
 
-	buffer = dell_smbios_get_buffer();
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->class = 1;
+	buffer->select = 0;
 	buffer->input[0] = token->location;
 	buffer->input[1] = token->value;
-	dell_smbios_send_request(1, 0);
-	dell_smbios_release_buffer();
+	dell_smbios_call(buffer);
 
 	return state;
 }
@@ -2127,7 +2120,6 @@ EXPORT_SYMBOL_GPL(dell_micmute_led_set);
 
 static int __init dell_init(void)
 {
-	struct calling_interface_buffer *buffer;
 	struct calling_interface_token *token;
 	int max_intensity = 0;
 	int ret;
@@ -2158,6 +2150,10 @@ static int __init dell_init(void)
 		goto fail_rfkill;
 	}
 
+	buffer = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!buffer)
+		goto fail_buffer;
+
 	if (quirks && quirks->touchpad_led)
 		touchpad_led_init(&platform_device->dev);
 
@@ -2175,12 +2171,12 @@ static int __init dell_init(void)
 
 	token = dell_smbios_find_token(BRIGHTNESS_TOKEN);
 	if (token) {
-		buffer = dell_smbios_get_buffer();
 		buffer->input[0] = token->location;
-		dell_smbios_send_request(0, 2);
+		buffer->class = 0;
+		buffer->select = 2;
+		dell_smbios_call(buffer);
 		if (buffer->output[0] == 0)
 			max_intensity = buffer->output[3];
-		dell_smbios_release_buffer();
 	}
 
 	if (max_intensity) {
@@ -2214,6 +2210,8 @@ static int __init dell_init(void)
 fail_get_brightness:
 	backlight_device_unregister(dell_backlight_device);
 fail_backlight:
+	free_page((unsigned long)buffer);
+fail_buffer:
 	dell_cleanup_rfkill();
 fail_rfkill:
 	platform_device_del(platform_device);
@@ -2233,6 +2231,7 @@ static void __exit dell_exit(void)
 		touchpad_led_exit();
 	kbd_led_exit();
 	backlight_device_unregister(dell_backlight_device);
+	free_page((unsigned long)buffer);
 	dell_cleanup_rfkill();
 	if (platform_device) {
 		platform_device_unregister(platform_device);
diff --git a/drivers/platform/x86/dell-smbios-smm.c b/drivers/platform/x86/dell-smbios-smm.c
new file mode 100644
index 000000000000..2e1c5d2dfd61
--- /dev/null
+++ b/drivers/platform/x86/dell-smbios-smm.c
@@ -0,0 +1,136 @@
+/*
+ *  SMI methods for use with dell-smbios
+ *
+ *  Copyright (c) Red Hat <mjg@redhat.com>
+ *  Copyright (c) 2014 Gabriele Mazzotta <gabriele.mzt@gmail.com>
+ *  Copyright (c) 2014 Pali Rohár <pali.rohar@gmail.com>
+ *  Copyright (c) 2017 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/gfp.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include "../../firmware/dcdbas.h"
+#include "dell-smbios.h"
+
+static int da_command_address;
+static int da_command_code;
+static struct calling_interface_buffer *buffer;
+struct platform_device *platform_device;
+static DEFINE_MUTEX(smm_mutex);
+
+static const struct dmi_system_id dell_device_table[] __initconst = {
+	{
+		.ident = "Dell laptop",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /*Laptop*/
+		},
+	},
+	{
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /*Notebook*/
+		},
+	},
+	{
+		.ident = "Dell Computer Corporation",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"),
+			DMI_MATCH(DMI_CHASSIS_TYPE, "8"),
+		},
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(dmi, dell_device_table);
+
+void dell_smbios_smm_call(struct calling_interface_buffer *input)
+{
+	struct smi_cmd command;
+	size_t size;
+
+	size = sizeof(struct calling_interface_buffer);
+	command.magic = SMI_CMD_MAGIC;
+	command.command_address = da_command_address;
+	command.command_code = da_command_code;
+	command.ebx = virt_to_phys(buffer);
+	command.ecx = 0x42534931;
+
+	mutex_lock(&smm_mutex);
+	memcpy(buffer, input, size);
+	dcdbas_smi_request(&command);
+	memcpy(input, buffer, size);
+	mutex_unlock(&smm_mutex);
+}
+EXPORT_SYMBOL_GPL(dell_smbios_smm_call);
+
+static int __init dell_smbios_smm_init(void)
+{
+	int ret;
+	/*
+	 * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
+	 * is passed to SMI handler.
+	 */
+	buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
+	if (!buffer)
+		return -ENOMEM;
+	dell_smbios_get_smm_address(&da_command_address, &da_command_code);
+
+	platform_device = platform_device_alloc("dell-smbios", 1);
+	if (!platform_device) {
+		ret = -ENOMEM;
+		goto fail_platform_device_alloc;
+	}
+
+	ret = platform_device_add(platform_device);
+	if (ret)
+		goto fail_platform_device_add;
+
+	ret = dell_smbios_register_device(&platform_device->dev,
+					  &dell_smbios_smm_call);
+	if (ret)
+		goto fail_register;
+
+	return 0;
+
+fail_register:
+	platform_device_del(platform_device);
+
+fail_platform_device_add:
+	platform_device_put(platform_device);
+
+fail_platform_device_alloc:
+	free_page((unsigned long)buffer);
+	return ret;
+}
+
+static void __exit dell_smbios_smm_exit(void)
+{
+	if (platform_device) {
+		dell_smbios_unregister_device(&platform_device->dev);
+		platform_device_unregister(platform_device);
+		free_page((unsigned long)buffer);
+	}
+}
+
+subsys_initcall(dell_smbios_smm_init);
+module_exit(dell_smbios_smm_exit);
+
+MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
+MODULE_AUTHOR("Gabriele Mazzotta <gabriele.mzt@gmail.com>");
+MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
+MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
+MODULE_DESCRIPTION("Dell SMBIOS communications over SMI");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell-smbios-smm.h b/drivers/platform/x86/dell-smbios-smm.h
new file mode 100644
index 000000000000..3bbf716a1bdb
--- /dev/null
+++ b/drivers/platform/x86/dell-smbios-smm.h
@@ -0,0 +1,22 @@
+/*
+ *  SMI methods for use with dell-smbios
+ *
+ *  Copyright (c) Red Hat <mjg@redhat.com>
+ *  Copyright (c) 2014 Gabriele Mazzotta <gabriele.mzt@gmail.com>
+ *  Copyright (c) 2014 Pali Rohár <pali.rohar@gmail.com>
+ *  Copyright (c) 2017 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef _DELL_SMBIOS_SMI_H_
+#define _DELL_SMBIOS_SMI_H_
+
+#include "dell-smbios.h"
+
+void dell_smbios_smm_call(struct calling_interface_buffer *input);
+//extern struct platform_driver dell_smbios_smm_platform_driver;
+
+#endif
diff --git a/drivers/platform/x86/dell-smbios.c b/drivers/platform/x86/dell-smbios.c
index 7275d1d48190..cdfea9e9610b 100644
--- a/drivers/platform/x86/dell-smbios.c
+++ b/drivers/platform/x86/dell-smbios.c
@@ -18,11 +18,9 @@
 #include <linux/module.h>
 #include <linux/dmi.h>
 #include <linux/err.h>
-#include <linux/gfp.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/io.h>
-#include "../../firmware/dcdbas.h"
 #include <linux/platform_device.h>
 #include "dell-smbios.h"
 
@@ -34,14 +32,27 @@ struct calling_interface_structure {
 	struct calling_interface_token tokens[];
 } __packed;
 
-static struct calling_interface_buffer *buffer;
-static DEFINE_MUTEX(buffer_mutex);
-
 static int da_command_address;
 static int da_command_code;
 static int da_num_tokens;
 static struct platform_device *platform_device;
 static struct calling_interface_token *da_tokens;
+static DEFINE_MUTEX(smbios_mutex);
+
+struct smbios_device {
+	struct list_head list;
+	struct device *device;
+	void (*call_fn)(struct calling_interface_buffer *);
+};
+
+static LIST_HEAD(smbios_device_list);
+
+void dell_smbios_get_smm_address(int *address, int *code)
+{
+	*address = da_command_address;
+	*code = da_command_code;
+}
+EXPORT_SYMBOL_GPL(dell_smbios_get_smm_address);
 
 int dell_smbios_error(int value)
 {
@@ -58,42 +69,64 @@ int dell_smbios_error(int value)
 }
 EXPORT_SYMBOL_GPL(dell_smbios_error);
 
-struct calling_interface_buffer *dell_smbios_get_buffer(void)
-{
-	mutex_lock(&buffer_mutex);
-	dell_smbios_clear_buffer();
-	return buffer;
-}
-EXPORT_SYMBOL_GPL(dell_smbios_get_buffer);
-
-void dell_smbios_clear_buffer(void)
+int dell_smbios_register_device(struct device *d, void *call_fn)
 {
-	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	struct smbios_device *priv;
+
+	pr_debug("Added device: %s:%s\n", d->driver->name, dev_name(d));
+	priv = devm_kzalloc(d, sizeof(struct smbios_device), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	get_device(d);
+	priv->device = d;
+	priv->call_fn = call_fn;
+	mutex_lock(&smbios_mutex);
+	list_add_tail(&priv->list, &smbios_device_list);
+	mutex_unlock(&smbios_mutex);
+	return 0;
 }
-EXPORT_SYMBOL_GPL(dell_smbios_clear_buffer);
+EXPORT_SYMBOL_GPL(dell_smbios_register_device);
 
-void dell_smbios_release_buffer(void)
+void dell_smbios_unregister_device(struct device *d)
 {
-	mutex_unlock(&buffer_mutex);
+	struct smbios_device *priv;
+
+	pr_debug("Remove device: %s:%s\n", d->driver->name, dev_name(d));
+	mutex_lock(&smbios_mutex);
+	list_for_each_entry(priv, &smbios_device_list, list) {
+		if (priv->device == d) {
+			list_del(&priv->list);
+			put_device(d);
+			break;
+		}
+	};
+	mutex_unlock(&smbios_mutex);
 }
-EXPORT_SYMBOL_GPL(dell_smbios_release_buffer);
+EXPORT_SYMBOL_GPL(dell_smbios_unregister_device);
 
-void dell_smbios_send_request(int class, int select)
+void dell_smbios_call(struct calling_interface_buffer *buffer)
 {
-	struct smi_cmd command;
-
-	command.magic = SMI_CMD_MAGIC;
-	command.command_address = da_command_address;
-	command.command_code = da_command_code;
-	command.ebx = virt_to_phys(buffer);
-	command.ecx = 0x42534931;
-
-	buffer->class = class;
-	buffer->select = select;
-
-	dcdbas_smi_request(&command);
+	void (*call_fn)(struct calling_interface_buffer *) = NULL;
+	struct smbios_device *priv;
+	int id = 0;
+
+	mutex_lock(&smbios_mutex);
+	list_for_each_entry(priv, &smbios_device_list, list) {
+		if (priv->device->id >= id) {
+			pr_debug("Setting %s (ID: %d)\n",
+				 dev_name(priv->device), priv->device->id);
+			call_fn = priv->call_fn;
+			id = priv->device->id;
+		}
+	};
+
+	if (call_fn)
+		call_fn(buffer);
+	else
+		pr_err("No dell-smbios drivers are loaded\n");
+	mutex_unlock(&smbios_mutex);
 }
-EXPORT_SYMBOL_GPL(dell_smbios_send_request);
+EXPORT_SYMBOL_GPL(dell_smbios_call);
 
 struct calling_interface_token *dell_smbios_find_token(int tokenid)
 {
@@ -224,15 +257,6 @@ static int __init dell_smbios_init(void)
 		return -ENODEV;
 	}
 
-	/*
-	 * Allocate buffer below 4GB for SMI data--only 32-bit physical addr
-	 * is passed to SMI handler.
-	 */
-	buffer = (void *)__get_free_page(GFP_KERNEL | GFP_DMA32);
-	if (!buffer) {
-		ret = -ENOMEM;
-		goto fail_buffer;
-	}
 	ret = platform_driver_register(&platform_driver);
 	if (ret)
 		goto fail_platform_driver;
@@ -262,17 +286,19 @@ static int __init dell_smbios_init(void)
 	platform_driver_unregister(&platform_driver);
 
 fail_platform_driver:
-	free_page((unsigned long)buffer);
-
-fail_buffer:
 	kfree(da_tokens);
 	return ret;
 }
 
 static void __exit dell_smbios_exit(void)
 {
-	kfree(da_tokens);
-	free_page((unsigned long)buffer);
+	if (platform_device) {
+		sysfs_remove_group(&platform_device->dev.kobj,
+				   &smbios_attribute_group);
+		platform_device_unregister(platform_device);
+		platform_driver_unregister(&platform_driver);
+		kfree(da_tokens);
+	}
 }
 
 subsys_initcall(dell_smbios_init);
diff --git a/drivers/platform/x86/dell-smbios.h b/drivers/platform/x86/dell-smbios.h
index 45cbc2292cd3..33eb8633a1c1 100644
--- a/drivers/platform/x86/dell-smbios.h
+++ b/drivers/platform/x86/dell-smbios.h
@@ -16,6 +16,8 @@
 #ifndef _DELL_SMBIOS_H_
 #define _DELL_SMBIOS_H_
 
+#include <linux/device.h>
+
 struct notifier_block;
 
 /* This structure will be modified by the firmware when we enter
@@ -37,12 +39,13 @@ struct calling_interface_token {
 	};
 };
 
-int dell_smbios_error(int value);
 
-struct calling_interface_buffer *dell_smbios_get_buffer(void);
-void dell_smbios_clear_buffer(void);
-void dell_smbios_release_buffer(void);
-void dell_smbios_send_request(int class, int select);
+int dell_smbios_register_device(struct device *d, void *call_fn);
+void dell_smbios_unregister_device(struct device *d);
+
+void dell_smbios_get_smm_address(int *address, int *command);
+int dell_smbios_error(int value);
+void dell_smbios_call(struct calling_interface_buffer *buffer);
 
 struct calling_interface_token *dell_smbios_find_token(int tokenid);
 
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 90d7e8e55e9b..5e04e202d928 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -641,13 +641,15 @@ static int dell_wmi_events_set_enabled(bool enable)
 	struct calling_interface_buffer *buffer;
 	int ret;
 
-	buffer = dell_smbios_get_buffer();
+	buffer = (void *)get_zeroed_page(GFP_KERNEL);
+	buffer->class = 17;
+	buffer->select = 3;
 	buffer->input[0] = 0x10000;
 	buffer->input[1] = 0x51534554;
 	buffer->input[3] = enable;
-	dell_smbios_send_request(17, 3);
+	dell_smbios_call(buffer);
 	ret = buffer->output[0];
-	dell_smbios_release_buffer();
+	free_page((unsigned long)buffer);
 
 	return dell_smbios_error(ret);
 }
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 10/14] platform/x86: dell-smbios-smm: test for WSMT
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (8 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  1:59   ` Darren Hart
  2017-10-04 22:48 ` [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver Mario Limonciello
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

WSMT is as an attestation to the OS that the platform won't
modify memory outside of pre-defined areas.

If a platform has WSMT enabled in BIOS setup, SMM calls through
dcdbas will fail.  The only way to access platform data in these
instances is through the WMI SMBIOS calling interface.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 drivers/platform/x86/dell-smbios-smm.c | 36 ++++++++++++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/drivers/platform/x86/dell-smbios-smm.c b/drivers/platform/x86/dell-smbios-smm.c
index 2e1c5d2dfd61..3271e9a876e9 100644
--- a/drivers/platform/x86/dell-smbios-smm.c
+++ b/drivers/platform/x86/dell-smbios-smm.c
@@ -25,6 +25,8 @@ static struct calling_interface_buffer *buffer;
 struct platform_device *platform_device;
 static DEFINE_MUTEX(smm_mutex);
 
+#define WSMT_EN_TOKEN	0x04EC
+
 static const struct dmi_system_id dell_device_table[] __initconst = {
 	{
 		.ident = "Dell laptop",
@@ -76,6 +78,32 @@ void dell_smbios_smm_call(struct calling_interface_buffer *input)
 }
 EXPORT_SYMBOL_GPL(dell_smbios_smm_call);
 
+static int test_wsmt_enabled(void)
+{
+	struct calling_interface_token *token;
+	int ret;
+
+	/* if token doesn't exist, SMM will work */
+	token = dell_smbios_find_token(WSMT_EN_TOKEN);
+	if (!token)
+		return 0;
+
+	/* if token exists, try to access over SMM */
+	buffer->class = 0;
+	buffer->select = 0;
+	memset(buffer, 0, sizeof(struct calling_interface_buffer));
+	buffer->input[0] = token->location;
+	dell_smbios_smm_call(buffer);
+
+	/* if lookup failed, we know WSMT was enabled */
+	if (buffer->output[0] != 0)
+		return 1;
+
+	/* query token status if it didn't fail */
+	ret = (buffer->output[1] == token->value);
+	return ret;
+}
+
 static int __init dell_smbios_smm_init(void)
 {
 	int ret;
@@ -88,6 +116,13 @@ static int __init dell_smbios_smm_init(void)
 		return -ENOMEM;
 	dell_smbios_get_smm_address(&da_command_address, &da_command_code);
 
+	ret = test_wsmt_enabled();
+	pr_debug("WSMT enable test: %d\n", ret);
+	if (ret) {
+		ret = -ENODEV;
+		goto fail_wsmt;
+	}
+
 	platform_device = platform_device_alloc("dell-smbios", 1);
 	if (!platform_device) {
 		ret = -ENOMEM;
@@ -111,6 +146,7 @@ static int __init dell_smbios_smm_init(void)
 fail_platform_device_add:
 	platform_device_put(platform_device);
 
+fail_wsmt:
 fail_platform_device_alloc:
 	free_page((unsigned long)buffer);
 	return ret;
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (9 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 10/14] platform/x86: dell-smbios-smm: test for WSMT Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  2:14   ` Darren Hart
  2017-10-04 22:48 ` [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers Mario Limonciello
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

The dell-smbios stack only currently uses an SMI interface which grants
direct access to physical memory to the firmware SMM methods via a pointer.

This dispatcher driver adds a WMI-ACPI interface that is detected by WMI
probe and preferred over the SMI interface in dell-smbios.

Changing this to operate over WMI-ACPI will use an ACPI OperationRegion
for a buffer of data storage when SMM calls are performed.

This is a safer approach to use in kernel drivers as the SMM will
only have access to that OperationRegion.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 MAINTAINERS                            |   6 +
 drivers/platform/x86/Kconfig           |  16 ++-
 drivers/platform/x86/Makefile          |   1 +
 drivers/platform/x86/dell-smbios-wmi.c | 215 +++++++++++++++++++++++++++++++++
 drivers/platform/x86/dell-smbios-wmi.h |  28 +++++
 5 files changed, 265 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/x86/dell-smbios-wmi.c
 create mode 100644 drivers/platform/x86/dell-smbios-wmi.h

diff --git a/MAINTAINERS b/MAINTAINERS
index a8fcb4a4e195..0357e9b1cfaf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3980,6 +3980,12 @@ L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
 F:	drivers/platform/x86/dell-smbios-smm.*
 
+DELL SMBIOS WMI DRIVER
+M:	Mario Limonciello <mario.limonciello@dell.com>
+L:	platform-driver-x86@vger.kernel.org
+S:	Maintained
+F:	drivers/platform/x86/dell-smbios-wmi.*
+
 DELL LAPTOP DRIVER
 M:	Matthew Garrett <mjg59@srcf.ucam.org>
 M:	Pali Rohár <pali.rohar@gmail.com>
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index f0b97cb8e449..ef597f440d2e 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -93,13 +93,27 @@ config ASUS_LAPTOP
 
 config DELL_SMBIOS
 	tristate "Dell SMBIOS calling interface"
-	depends on DELL_SMBIOS_SMM
+	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
 	---help---
 	This module provides common functions for kernel modules using
 	Dell SMBIOS.
 
 	If you have a Dell laptop, say Y or M here.
 
+config DELL_SMBIOS_WMI
+	tristate "Dell SMBIOS calling interface (WMI implementation)"
+	depends on ACPI_WMI
+	depends on DELL_WMI_DESCRIPTOR
+	default ACPI_WMI
+	select DELL_SMBIOS
+	---help---
+	This provides an implementation for the Dell SMBIOS calling interface
+	communicated over ACPI-WMI.
+
+	If you have a Dell computer from >2007 you should say Y or M here.
+	If you aren't sure and this module doesn't work for your computer
+	it just won't load.
+
 config DELL_SMBIOS_SMM
 	tristate "Dell SMBIOS calling interface (SMM implementation)"
 	depends on DCDBAS
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index e743615241f8..1c4234861de0 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MSI_LAPTOP)	+= msi-laptop.o
 obj-$(CONFIG_ACPI_CMPC)		+= classmate-laptop.o
 obj-$(CONFIG_COMPAL_LAPTOP)	+= compal-laptop.o
 obj-$(CONFIG_DELL_SMBIOS)	+= dell-smbios.o
+obj-$(CONFIG_DELL_SMBIOS_WMI)	+= dell-smbios-wmi.o
 obj-$(CONFIG_DELL_SMBIOS_SMM)	+= dell-smbios-smm.o
 obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_DELL_WMI)		+= dell-wmi.o
diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c
new file mode 100644
index 000000000000..32e4e7dbf575
--- /dev/null
+++ b/drivers/platform/x86/dell-smbios-wmi.c
@@ -0,0 +1,215 @@
+/*
+ *  WMI methods for use with dell-smbios
+ *
+ *  Copyright (c) 2017 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/dmi.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/wmi.h>
+#include "dell-smbios-wmi.h"
+#include "dell-wmi-descriptor.h"
+static DEFINE_MUTEX(wmi_mutex);
+static int wmi_supported;
+
+struct misc_bios_flags_structure {
+	struct dmi_header header;
+	u32 flags0;
+} __packed;
+#define FLAG_HAS_ACPI_WMI 0x02
+
+#define DELL_WMI_SMBIOS_GUID "A80593CE-A997-11DA-B012-B622A1EF5492"
+
+struct wmi_smbios_priv {
+	struct wmi_calling_interface_buffer *buf;
+	struct list_head list;
+	struct wmi_device *wdev;
+	struct device *child;
+	u32 buffer_size;
+};
+static LIST_HEAD(wmi_list);
+
+static struct wmi_device *get_first_wmi_device(void)
+{
+	struct wmi_smbios_priv *priv;
+
+	priv = list_first_entry_or_null(&wmi_list,
+					struct wmi_smbios_priv,
+					list);
+	return priv ? priv->wdev : NULL;
+}
+
+static int run_smbios_call(struct wmi_device *wdev)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	struct wmi_smbios_priv *priv;
+	struct acpi_buffer input;
+	union acpi_object *obj;
+	acpi_status status;
+
+	priv = dev_get_drvdata(&wdev->dev);
+	input.length = priv->buffer_size;
+	input.pointer = priv->buf;
+
+	status = wmidev_evaluate_method(wdev, 0, 1, &input, &output);
+	if (ACPI_FAILURE(status)) {
+		pr_err("%x/%x [%x,%x,%x,%x] call failed\n",
+			priv->buf->class, priv->buf->select,
+			priv->buf->input[0], priv->buf->input[1],
+			priv->buf->input[2], priv->buf->input[3]);
+			return -EIO;
+	}
+	obj = (union acpi_object *)output.pointer;
+	if (obj->type != ACPI_TYPE_BUFFER) {
+		if (obj->type == ACPI_TYPE_INTEGER)
+			pr_err("SMBIOS call failed: %llu\n",
+				obj->integer.value);
+		else
+			pr_err("invalid type: %d\n", obj->type);
+		return -EIO;
+	}
+	memcpy(priv->buf, obj->buffer.pointer, input.length);
+
+	return 0;
+}
+
+void dell_smbios_wmi_call(struct calling_interface_buffer *buffer)
+{
+	struct wmi_smbios_priv *priv;
+	struct wmi_device *wdev;
+	size_t difference;
+	size_t size;
+	u8 *start;
+
+	wdev = get_first_wmi_device();
+	if (!wdev) {
+		pr_info("No WMI devices bound");
+		return;
+	}
+	priv = dev_get_drvdata(&wdev->dev);
+	size = sizeof(struct calling_interface_buffer);
+	difference = priv->buffer_size - size;
+	start = (u8 *) priv->buf + size;
+	mutex_lock(&wmi_mutex);
+	memset(start, 0, difference);
+	memcpy(priv->buf, buffer, size);
+	run_smbios_call(wdev);
+	memcpy(buffer, priv->buf, size);
+	mutex_unlock(&wmi_mutex);
+}
+EXPORT_SYMBOL_GPL(dell_smbios_wmi_call);
+
+static int dell_smbios_wmi_probe(struct wmi_device *wdev)
+{
+	struct wmi_smbios_priv *priv;
+	int count;
+	int ret;
+
+	priv = devm_kzalloc(&wdev->dev, sizeof(struct wmi_smbios_priv),
+			    GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	/* WMI buffer size will be either 4k or 32k depending on machine */
+	if (!dell_wmi_get_size(&priv->buffer_size))
+		return -EINVAL;
+
+	count = get_order(priv->buffer_size);
+	priv->buf = (void *)__get_free_pages(GFP_KERNEL, count);
+	if (!priv->buf)
+		return -ENOMEM;
+
+	/* ID is used by dell-smbios to set priority of drivers */
+	wdev->dev.id = 1;
+	ret = dell_smbios_register_device(&wdev->dev, &dell_smbios_wmi_call);
+	if (ret)
+		goto fail_register;
+
+	priv->wdev = wdev;
+	dev_set_drvdata(&wdev->dev, priv);
+	list_add_tail(&priv->list, &wmi_list);
+
+	return 0;
+
+fail_register:
+	free_pages((unsigned long)priv->buf, count);
+	return ret;
+}
+
+static int dell_smbios_wmi_remove(struct wmi_device *wdev)
+{
+	struct wmi_smbios_priv *priv = dev_get_drvdata(&wdev->dev);
+	int count;
+
+	list_del(&priv->list);
+	dell_smbios_unregister_device(&wdev->dev);
+	count = get_order(priv->buffer_size);
+	free_pages((unsigned long)priv->buf, count);
+	return 0;
+}
+
+static const struct wmi_device_id dell_smbios_wmi_id_table[] = {
+	{ .guid_string = DELL_WMI_SMBIOS_GUID },
+	{ },
+};
+
+static void __init parse_b1_table(const struct dmi_header *dm)
+{
+	struct misc_bios_flags_structure *flags =
+	container_of(dm, struct misc_bios_flags_structure, header);
+
+	/* 4 bytes header, and one word of flags */
+	if (dm->length < 12)
+		return;
+	if ((flags->flags0 & FLAG_HAS_ACPI_WMI))
+		wmi_supported = 1;
+}
+
+static void __init find_b1(const struct dmi_header *dm, void *dummy)
+{
+	switch (dm->type) {
+	case 0xb1: /* misc bios flags */
+		parse_b1_table(dm);
+		break;
+	}
+}
+
+static struct wmi_driver dell_smbios_wmi_driver = {
+	.driver = {
+		.name = "dell-smbios",
+	},
+	.probe = dell_smbios_wmi_probe,
+	.remove = dell_smbios_wmi_remove,
+	.id_table = dell_smbios_wmi_id_table,
+};
+
+static int __init init_dell_smbios_wmi(void)
+{
+	dmi_walk(find_b1, NULL);
+
+	if (!wmi_supported)
+		return -ENODEV;
+
+	return wmi_driver_register(&dell_smbios_wmi_driver);
+}
+
+static void __exit exit_dell_smbios_wmi(void)
+{
+	wmi_driver_unregister(&dell_smbios_wmi_driver);
+}
+
+module_init(init_dell_smbios_wmi);
+module_exit(exit_dell_smbios_wmi);
+
+MODULE_ALIAS("wmi:" DELL_WMI_SMBIOS_GUID);
+MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
+MODULE_DESCRIPTION("Dell SMBIOS communications over WMI");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell-smbios-wmi.h b/drivers/platform/x86/dell-smbios-wmi.h
new file mode 100644
index 000000000000..5dd91d8ff3d8
--- /dev/null
+++ b/drivers/platform/x86/dell-smbios-wmi.h
@@ -0,0 +1,28 @@
+/*
+ *  WMI methods for use with dell-smbios
+ *
+ *  Copyright (c) 2017 Dell Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#ifndef _DELL_SMBIOS_WMI_H_
+#define _DELL_SMBIOS_WMI_H_
+
+#include "dell-smbios.h"
+
+struct wmi_calling_interface_buffer {
+	u16 class;
+	u16 select;
+	u32 input[4];
+	u32 output[4];
+	u32 argattrib;
+	u32 blength;
+	u8 *data;
+} __packed;
+
+void dell_smbios_wmi_call(struct calling_interface_buffer *buffer);
+
+#endif
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (10 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  2:33   ` Darren Hart
  2017-10-05  7:16   ` Greg KH
  2017-10-04 22:48 ` [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface Mario Limonciello
                   ` (2 subsequent siblings)
  14 siblings, 2 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

For WMI operations that are only Set or Query read or write sysfs
attributes created by WMI vendor drivers make sense.

For other WMI operations that are run on Method, there needs to be a
way to guarantee to userspace that the results from the method call
belong to the data request to the method call.  Sysfs attributes don't
work well in this scenario because two userspace processes may be
competing at reading/writing an attribute and step on each other's
data.

When a WMI vendor driver declares an ioctl in a file_operations object
the WMI bus driver will create a character device that maps to those
file operations.

That character device will correspond to this path:
/dev/wmi/$driver

The WMI bus driver will interpret the IOCTL calls, test them for
a valid instance and pass them on to the vendor driver to run.

This creates an implicit policy that only driver per character
device.  If a module matches multiple GUID's, the wmi_devices
will need to be all handled by the same wmi_driver if the same
character device is used.

The WMI vendor drivers will be responsible for managing access to
this character device and proper locking on it.

When a WMI vendor driver is unloaded the WMI bus driver will clean
up the character device.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 MAINTAINERS                |  1 +
 drivers/platform/x86/wmi.c | 67 +++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/wmi.h        |  2 ++
 include/uapi/linux/wmi.h   | 10 +++++++
 4 files changed, 79 insertions(+), 1 deletion(-)
 create mode 100644 include/uapi/linux/wmi.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 0357e9b1cfaf..6db1d84999bc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -372,6 +372,7 @@ ACPI WMI DRIVER
 L:	platform-driver-x86@vger.kernel.org
 S:	Orphan
 F:	drivers/platform/x86/wmi.c
+F:	include/uapi/linux/wmi.h
 
 AD1889 ALSA SOUND DRIVER
 M:	Thibaut Varene <T-Bone@parisc-linux.org>
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index bcb41c1c7f52..5aef052b4aab 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -38,6 +38,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -69,6 +70,7 @@ struct wmi_block {
 	struct wmi_device dev;
 	struct list_head list;
 	struct guid_block gblock;
+	struct miscdevice misc_dev;
 	struct acpi_device *acpi_device;
 	wmi_notify_handler handler;
 	void *handler_data;
@@ -765,22 +767,80 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
 	return 0;
 }
 
+static long wmi_ioctl(struct file *filp, unsigned int cmd,
+		      unsigned long arg)
+{
+	struct wmi_driver *wdriver;
+	struct wmi_block *wblock;
+	const char *driver_name;
+	struct list_head *p;
+	bool found = false;
+
+	if (_IOC_TYPE(cmd) != WMI_IOC)
+		return -ENOTTY;
+
+	driver_name = filp->f_path.dentry->d_iname;
+
+	list_for_each(p, &wmi_block_list) {
+		wblock = list_entry(p, struct wmi_block, list);
+		wdriver = container_of(wblock->dev.dev.driver,
+			struct wmi_driver, driver);
+		if (strcmp(driver_name, wdriver->driver.name) == 0) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found ||
+	    !wdriver->file_operations ||
+	    !wdriver->file_operations->unlocked_ioctl)
+		return -ENODEV;
+
+	/* make sure we're not calling a higher instance */
+	if (_IOC_NR(cmd) > wblock->gblock.instance_count)
+		return -EINVAL;
+
+	return wdriver->file_operations->unlocked_ioctl(filp, cmd, arg);
+}
+
+static const struct file_operations wmi_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= wmi_ioctl,
+};
+
 static int wmi_dev_probe(struct device *dev)
 {
 	struct wmi_block *wblock = dev_to_wblock(dev);
 	struct wmi_driver *wdriver =
 		container_of(dev->driver, struct wmi_driver, driver);
 	int ret = 0;
+	char *buf;
 
 	if (ACPI_FAILURE(wmi_method_enable(wblock, 1)))
 		dev_warn(dev, "failed to enable device -- probing anyway\n");
 
+	/* driver wants a character device made */
+	if (wdriver->file_operations) {
+		buf = kmalloc(strlen(wdriver->driver.name) + 4, GFP_KERNEL);
+		if (!buf)
+			return -ENOMEM;
+		strcpy(buf, "wmi/");
+		strcpy(buf + 4, wdriver->driver.name);
+		wblock->misc_dev.minor = MISC_DYNAMIC_MINOR;
+		wblock->misc_dev.name = buf;
+		wblock->misc_dev.fops = &wmi_fops;
+		ret = misc_register(&wblock->misc_dev);
+		if (ret) {
+			dev_warn(dev, "failed to register char dev: %d", ret);
+			kfree(buf);
+		}
+	}
+
 	if (wdriver->probe) {
 		ret = wdriver->probe(dev_to_wdev(dev));
 		if (ret != 0 && ACPI_FAILURE(wmi_method_enable(wblock, 0)))
 			dev_warn(dev, "failed to disable device\n");
 	}
-
 	return ret;
 }
 
@@ -791,6 +851,11 @@ static int wmi_dev_remove(struct device *dev)
 		container_of(dev->driver, struct wmi_driver, driver);
 	int ret = 0;
 
+	if (wdriver->file_operations) {
+		kfree(wblock->misc_dev.name);
+		misc_deregister(&wblock->misc_dev);
+	}
+
 	if (wdriver->remove)
 		ret = wdriver->remove(dev_to_wdev(dev));
 
diff --git a/include/linux/wmi.h b/include/linux/wmi.h
index ddee427e0721..c84db3e8038d 100644
--- a/include/linux/wmi.h
+++ b/include/linux/wmi.h
@@ -18,6 +18,7 @@
 
 #include <linux/device.h>
 #include <linux/acpi.h>
+#include <uapi/linux/wmi.h>
 
 struct wmi_device {
 	struct device dev;
@@ -43,6 +44,7 @@ struct wmi_device_id {
 struct wmi_driver {
 	struct device_driver driver;
 	const struct wmi_device_id *id_table;
+	const struct file_operations *file_operations;
 
 	int (*probe)(struct wmi_device *wdev);
 	int (*remove)(struct wmi_device *wdev);
diff --git a/include/uapi/linux/wmi.h b/include/uapi/linux/wmi.h
new file mode 100644
index 000000000000..6a811ead7db8
--- /dev/null
+++ b/include/uapi/linux/wmi.h
@@ -0,0 +1,10 @@
+#ifndef _UAPI_LINUX_WMI_H
+#define _UAPI_LINUX_WMI_H
+
+#define WMI_IOC 'W'
+#define WMI_IO(instance)	_IO(WMI_IOC, instance)
+#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
+#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
+#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)
+
+#endif
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (11 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  7:23   ` Greg KH
                     ` (2 more replies)
  2017-10-04 22:48 ` [PATCH v4 14/14] platform/x86: Kconfig: Set default for dell-smbios to ACPI_WMI Mario Limonciello
  2017-10-05  0:09 ` [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Darren Hart
  14 siblings, 3 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

This userspace character device will be used to perform SMBIOS calls
from any applications.

It provides an ioctl that will allow passing the 32k WMI calling
interface buffer between userspace and kernel space.

This character device is intended to deprecate the dcdbas kernel module
and the interface that it provides to userspace.

It's important for the driver to provide a R/W ioctl to ensure that
two competing userspace processes don't race to provide or read each
others data.

The API for interacting with this interface is defined in documentation
as well as a uapi header provides the format of the structures.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 Documentation/ABI/testing/dell-smbios-wmi          | 43 ++++++++++
 .../ABI/testing/sysfs-platform-dell-smbios-wmi     | 10 +++
 MAINTAINERS                                        |  1 +
 drivers/platform/x86/dell-smbios-wmi.c             | 98 ++++++++++++++++++++++
 drivers/platform/x86/dell-smbios-wmi.h             | 10 ---
 include/uapi/linux/dell-smbios-wmi.h               | 25 ++++++
 6 files changed, 177 insertions(+), 10 deletions(-)
 create mode 100644 Documentation/ABI/testing/dell-smbios-wmi
 create mode 100644 Documentation/ABI/testing/sysfs-platform-dell-smbios-wmi
 create mode 100644 include/uapi/linux/dell-smbios-wmi.h

diff --git a/Documentation/ABI/testing/dell-smbios-wmi b/Documentation/ABI/testing/dell-smbios-wmi
new file mode 100644
index 000000000000..86ded18b41f7
--- /dev/null
+++ b/Documentation/ABI/testing/dell-smbios-wmi
@@ -0,0 +1,43 @@
+What:		/dev/wmi/dell-smbios
+Date:		November 2017
+KernelVersion:	4.15
+Contact:	"Mario Limonciello" <mario.limonciello@dell.com>
+Description:
+		Perform SMBIOS calls on supported Dell machines.
+		through the Dell ACPI-WMI interface.
+
+		IOCTL's and buffer formats are defined in:
+		<uapi/linux/dell-wmi-smbios.h>
+
+		1) To perform a call from userspace, you'll need to first
+		determine the size of the buffer for your machine.
+		Platforms that contain larger buffers can return larger
+		objects from the system firmware.
+		Commonly this size is either 4k or 32k.
+
+		To determine the size of the buffer, refer to:
+		sysfs-platform-dell-smbios-wmi
+
+		2) After you've determined the size of the calling interface
+		buffer, you can allocate a structure that represents the
+		ioctl struct documented above.
+
+		3) In the 'length' object store the size of the buffer you
+		determined above.
+
+		4) Then use this size to allocate an appropriately sized
+		calling interface buffer to assign to 'buf' object.
+
+		5) In this buf object, prepare as necessary for the SMBIOS
+		call you're interested in.  Typically SMBIOS buffers have
+		"class", "select", and "input" defined to values that coincide
+		with the data you are interested in.
+		Documenting class/select/input values is outside of the scope
+		of this documentation. Check with the libsmbios project for
+		further documentation on these values.
+
+		6) Run the call by using ioctl() as described in the header.
+
+		7) The output will be returned in the buf object.
+
+		8) Be sure to free up both of your allocated objects.
diff --git a/Documentation/ABI/testing/sysfs-platform-dell-smbios-wmi b/Documentation/ABI/testing/sysfs-platform-dell-smbios-wmi
new file mode 100644
index 000000000000..6a0513703a3c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-dell-smbios-wmi
@@ -0,0 +1,10 @@
+What:		/sys/devices/platform/<platform>/buffer_size
+Date:		November 2017
+KernelVersion:	4.15
+Contact:	"Mario Limonciello" <mario.limonciello@dell.com>
+Description:
+		A read-only description of the size of a calling
+		interface buffer that can be passed to Dell
+		firmware.
+
+		Commonly this size is either 4k or 32k.
diff --git a/MAINTAINERS b/MAINTAINERS
index 6db1d84999bc..0dd373cf7280 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3986,6 +3986,7 @@ M:	Mario Limonciello <mario.limonciello@dell.com>
 L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
 F:	drivers/platform/x86/dell-smbios-wmi.*
+F:	include/uapi/linux/dell-smbios-wmi.h
 
 DELL LAPTOP DRIVER
 M:	Matthew Garrett <mjg59@srcf.ucam.org>
diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c
index 32e4e7dbf575..3156864e65e0 100644
--- a/drivers/platform/x86/dell-smbios-wmi.c
+++ b/drivers/platform/x86/dell-smbios-wmi.c
@@ -15,6 +15,7 @@
 #include <linux/mutex.h>
 #include <linux/uaccess.h>
 #include <linux/wmi.h>
+#include <uapi/linux/dell-smbios-wmi.h>
 #include "dell-smbios-wmi.h"
 #include "dell-wmi-descriptor.h"
 static DEFINE_MUTEX(wmi_mutex);
@@ -107,6 +108,87 @@ void dell_smbios_wmi_call(struct calling_interface_buffer *buffer)
 }
 EXPORT_SYMBOL_GPL(dell_smbios_wmi_call);
 
+static long dell_smbios_wmi_ioctl(struct file *filp, unsigned int cmd,
+	unsigned long arg)
+{
+	void __user *p = (void __user *) arg;
+	struct wmi_smbios_ioctl *input;
+	struct wmi_smbios_priv *priv;
+	struct wmi_device *wdev;
+	size_t ioctl_size;
+	int ret = 0;
+
+	switch (cmd) {
+	/* we only operate on first instance */
+	case DELL_WMI_SMBIOS_CMD:
+		wdev = get_first_wmi_device();
+		if (!wdev) {
+			pr_err("No WMI devices bound\n");
+			return -ENODEV;
+		}
+		ioctl_size = sizeof(struct wmi_smbios_ioctl);
+		priv = dev_get_drvdata(&wdev->dev);
+		input = kmalloc(ioctl_size, GFP_KERNEL);
+		if (!input)
+			return -ENOMEM;
+		mutex_lock(&wmi_mutex);
+		if (!access_ok(VERIFY_READ, p, ioctl_size)) {
+			pr_err("Unsafe userspace pointer passed\n");
+			return -EFAULT;
+		}
+		if (copy_from_user(input, p, ioctl_size)) {
+			ret = -EFAULT;
+			goto fail_smbios_cmd;
+		}
+		if (input->length != priv->buffer_size) {
+			pr_err("Got buffer size %d expected %d\n",
+				input->length, priv->buffer_size);
+			ret = -EINVAL;
+			goto fail_smbios_cmd;
+		}
+		if (!access_ok(VERIFY_WRITE, input->buf, priv->buffer_size)) {
+			pr_err("Unsafe userspace pointer passed\n");
+			ret = -EFAULT;
+			goto fail_smbios_cmd;
+		}
+		if (copy_from_user(priv->buf, input->buf, priv->buffer_size)) {
+			ret = -EFAULT;
+			goto fail_smbios_cmd;
+		}
+		ret = run_smbios_call(wdev);
+		if (ret != 0)
+			goto fail_smbios_cmd;
+		if (copy_to_user(input->buf, priv->buf, priv->buffer_size))
+			ret = -EFAULT;
+fail_smbios_cmd:
+		kfree(input);
+		mutex_unlock(&wmi_mutex);
+		break;
+	default:
+		pr_err("unsupported ioctl: %d.\n", cmd);
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static ssize_t buffer_size_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct wmi_smbios_priv *priv = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%d\n", priv->buffer_size);
+}
+static DEVICE_ATTR_RO(buffer_size);
+
+static struct attribute *smbios_wmi_attrs[] = {
+	&dev_attr_buffer_size.attr,
+	NULL
+};
+
+static const struct attribute_group smbios_wmi_attribute_group = {
+	.attrs = smbios_wmi_attrs,
+};
+
 static int dell_smbios_wmi_probe(struct wmi_device *wdev)
 {
 	struct wmi_smbios_priv *priv;
@@ -127,6 +209,11 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev)
 	if (!priv->buf)
 		return -ENOMEM;
 
+	ret = sysfs_create_group(&wdev->dev.kobj,
+				 &smbios_wmi_attribute_group);
+	if (ret)
+		goto fail_create_group;
+
 	/* ID is used by dell-smbios to set priority of drivers */
 	wdev->dev.id = 1;
 	ret = dell_smbios_register_device(&wdev->dev, &dell_smbios_wmi_call);
@@ -140,6 +227,10 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev)
 	return 0;
 
 fail_register:
+	sysfs_remove_group(&wdev->dev.kobj,
+			   &smbios_wmi_attribute_group);
+
+fail_create_group:
 	free_pages((unsigned long)priv->buf, count);
 	return ret;
 }
@@ -151,6 +242,7 @@ static int dell_smbios_wmi_remove(struct wmi_device *wdev)
 
 	list_del(&priv->list);
 	dell_smbios_unregister_device(&wdev->dev);
+	sysfs_remove_group(&wdev->dev.kobj, &smbios_wmi_attribute_group);
 	count = get_order(priv->buffer_size);
 	free_pages((unsigned long)priv->buf, count);
 	return 0;
@@ -161,6 +253,11 @@ static const struct wmi_device_id dell_smbios_wmi_id_table[] = {
 	{ },
 };
 
+static const struct file_operations dell_smbios_wmi_fops = {
+	.owner		= THIS_MODULE,
+	.unlocked_ioctl	= dell_smbios_wmi_ioctl,
+};
+
 static void __init parse_b1_table(const struct dmi_header *dm)
 {
 	struct misc_bios_flags_structure *flags =
@@ -189,6 +286,7 @@ static struct wmi_driver dell_smbios_wmi_driver = {
 	.probe = dell_smbios_wmi_probe,
 	.remove = dell_smbios_wmi_remove,
 	.id_table = dell_smbios_wmi_id_table,
+	.file_operations = &dell_smbios_wmi_fops,
 };
 
 static int __init init_dell_smbios_wmi(void)
diff --git a/drivers/platform/x86/dell-smbios-wmi.h b/drivers/platform/x86/dell-smbios-wmi.h
index 5dd91d8ff3d8..40a3666ea87a 100644
--- a/drivers/platform/x86/dell-smbios-wmi.h
+++ b/drivers/platform/x86/dell-smbios-wmi.h
@@ -13,16 +13,6 @@
 
 #include "dell-smbios.h"
 
-struct wmi_calling_interface_buffer {
-	u16 class;
-	u16 select;
-	u32 input[4];
-	u32 output[4];
-	u32 argattrib;
-	u32 blength;
-	u8 *data;
-} __packed;
-
 void dell_smbios_wmi_call(struct calling_interface_buffer *buffer);
 
 #endif
diff --git a/include/uapi/linux/dell-smbios-wmi.h b/include/uapi/linux/dell-smbios-wmi.h
new file mode 100644
index 000000000000..0d0d09b04021
--- /dev/null
+++ b/include/uapi/linux/dell-smbios-wmi.h
@@ -0,0 +1,25 @@
+#ifndef _UAPI_DELL_SMBIOS_WMI_H_
+#define _UAPI_DELL_SMBIOS_WMI_H_
+
+#include <linux/ioctl.h>
+#include <linux/wmi.h>
+
+struct wmi_calling_interface_buffer {
+	u16 class;
+	u16 select;
+	u32 input[4];
+	u32 output[4];
+	u32 argattrib;
+	u32 blength;
+	u8 *data;
+} __packed;
+
+struct wmi_smbios_ioctl {
+	u32 length;
+	struct wmi_calling_interface_buffer *buf;
+};
+
+/* only offers on the single instance */
+#define DELL_WMI_SMBIOS_CMD		WMI_IOWR(0)
+
+#endif /* _UAPI_DELL_WMI_SMBIOS_H_ */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* [PATCH v4 14/14] platform/x86: Kconfig: Set default for dell-smbios to ACPI_WMI
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (12 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface Mario Limonciello
@ 2017-10-04 22:48 ` Mario Limonciello
  2017-10-05  0:09 ` [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Darren Hart
  14 siblings, 0 replies; 93+ messages in thread
From: Mario Limonciello @ 2017-10-04 22:48 UTC (permalink / raw)
  To: dvhart, Andy Shevchenko
  Cc: LKML, platform-driver-x86, Andy Lutomirski, quasisec, pali.rohar,
	rjw, mjg59, hch, Greg KH, Mario Limonciello

The dell-smbios driver no longer depends on dcdbas, and it should
now be offered with the preferred WMI backend when the WMI bus is
enabled.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
 drivers/platform/x86/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index ef597f440d2e..cd9399572156 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -94,6 +94,7 @@ config ASUS_LAPTOP
 config DELL_SMBIOS
 	tristate "Dell SMBIOS calling interface"
 	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
+	default ACPI_WMI
 	---help---
 	This module provides common functions for kernel modules using
 	Dell SMBIOS.
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI
  2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
                   ` (13 preceding siblings ...)
  2017-10-04 22:48 ` [PATCH v4 14/14] platform/x86: Kconfig: Set default for dell-smbios to ACPI_WMI Mario Limonciello
@ 2017-10-05  0:09 ` Darren Hart
  2017-10-05  9:00   ` Andy Shevchenko
  14 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05  0:09 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Andy Shevchenko, LKML, platform-driver-x86, Andy Lutomirski,
	quasisec, pali.rohar, rjw, mjg59, hch, Greg KH

On Wed, Oct 04, 2017 at 05:48:26PM -0500, Mario Limonciello wrote:
> 
> NOTE: This patch is intended to go on top of the 6 patches already in
> Darren's review tree.

I pushed these to for-next today, they should be available in linux-next
shortly.

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-04 22:48 ` [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver Mario Limonciello
@ 2017-10-05  1:09   ` Darren Hart
  2017-10-05  5:29     ` Andy Shevchenko
  2017-10-05  5:34   ` Andy Shevchenko
  1 sibling, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05  1:09 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Andy Shevchenko, LKML, platform-driver-x86, Andy Lutomirski,
	quasisec, pali.rohar, rjw, mjg59, hch, Greg KH

On Wed, Oct 04, 2017 at 05:48:31PM -0500, Mario Limonciello wrote:
> All communication on individual GUIDs should occur in separate drivers.
> Allowing a driver to communicate with the bus to another GUID is just
> a hack that discourages drivers to adopt the bus model.
> 
> The information found from the WMI descriptor driver is now exported
> for use by other drivers.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> ---
>  MAINTAINERS                                |   5 +
>  drivers/platform/x86/Kconfig               |  12 +++
>  drivers/platform/x86/Makefile              |   1 +
>  drivers/platform/x86/dell-wmi-descriptor.c | 162 +++++++++++++++++++++++++++++
>  drivers/platform/x86/dell-wmi-descriptor.h |  18 ++++
>  drivers/platform/x86/dell-wmi.c            |  88 ++--------------
>  6 files changed, 205 insertions(+), 81 deletions(-)
>  create mode 100644 drivers/platform/x86/dell-wmi-descriptor.c
>  create mode 100644 drivers/platform/x86/dell-wmi-descriptor.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 08b96f77f618..659dbeec4191 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -4002,6 +4002,11 @@ M:	Pali Rohár <pali.rohar@gmail.com>
>  S:	Maintained
>  F:	drivers/platform/x86/dell-wmi.c
>  
> +DELL WMI DESCRIPTOR DRIVER
> +M:	Mario Limonciello <mario.limonciello@dell.com>
> +S:	Maintained
> +F:	drivers/platform/x86/dell-wmi-descriptor.c
> +
>  DELTA ST MEDIA DRIVER
>  M:	Hugues Fruchet <hugues.fruchet@st.com>
>  L:	linux-media@vger.kernel.org
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index 1f7959ff055c..bc347c326d87 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -121,6 +121,7 @@ config DELL_WMI
>  	depends on DMI
>  	depends on INPUT
>  	depends on ACPI_VIDEO || ACPI_VIDEO = n
> +	depends on DELL_WMI_DESCRIPTOR

We have to be careful with the use of "select", but I think in this case it
makes sense.

If you "select DELL_WMI_DESCRIPTOR" here, and maintain depends on
ACPI_WMI (not shown in context here), then...

>  	select DELL_SMBIOS
>  	select INPUT_SPARSEKMAP
>  	---help---
> @@ -129,6 +130,17 @@ config DELL_WMI
>  	  To compile this driver as a module, choose M here: the module will
>  	  be called dell-wmi.
>  
> +config DELL_WMI_DESCRIPTOR
> +	tristate "Dell WMI descriptor"
> +	depends on ACPI_WMI
> +	default ACPI_WMI

This default can be dropped, the dependency will be met if DELL_WMI can
be enabled...

> +	---help---
> +	  Say Y here if you want to be able to read the format of WMI
> +	  communications on some Dell laptops, desktops and IoT gateways.
> +
> +	  To compile this driver as a module, choose M here: the module will
> +	  be called dell-wmi-descriptor.

... and this can be converted to an invisible option and eliminate some
Kconfig clutter.

...


> diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
> index 1366bccdf275..90d7e8e55e9b 100644
...
> @@ -376,7 +375,11 @@ static void dell_wmi_notify(struct wmi_device *wdev,
>  	 * So to prevent reading garbage from buffer we will process only first
>  	 * one event on devices with WMI interface version 0.
>  	 */
> -	if (priv->interface_version == 0 && buffer_entry < buffer_end)
> +	if (!dell_wmi_get_interface_version(&interface_version)) {

You've introduced a dependency on another module here and haven't
guaranteed that dell-wmi-descriptor will have been loaded prior to this
one.

You'll want to add something like:

#ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
	if (request_module("dell_wmi_descriptor"))
		/* FAIL */
#endif

During init.

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls
  2017-10-04 22:48 ` [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls Mario Limonciello
@ 2017-10-05  1:57   ` Darren Hart
  2017-10-05 15:04       ` Mario.Limonciello
  0 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05  1:57 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Andy Shevchenko, LKML, platform-driver-x86, Andy Lutomirski,
	quasisec, pali.rohar, rjw, mjg59, hch, Greg KH

On Wed, Oct 04, 2017 at 05:48:35PM -0500, Mario Limonciello wrote:
> This splits up the dell-smbios driver into two drivers:
> * dell-smbios
> * dell-smbios-smm
> 
> dell-smbios can operate with multiple different dispatcher drivers to
> perform SMBIOS operations.
> 
> Also modify the interface that dell-laptop and dell-wmi use align to this
> model more closely.  Rather than a single global buffer being allocated
> for all drivers, each driver will allocate and be responsible for it's own
> buffer. The pointer will be passed to the calling function and each
> dispatcher driver will then internally copy it to the proper location to
> perform it's call.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> ---
>  MAINTAINERS                            |   6 ++
>  drivers/platform/x86/Kconfig           |  17 ++-
>  drivers/platform/x86/Makefile          |   1 +
>  drivers/platform/x86/dell-laptop.c     | 191 ++++++++++++++++-----------------
>  drivers/platform/x86/dell-smbios-smm.c | 136 +++++++++++++++++++++++
>  drivers/platform/x86/dell-smbios-smm.h |  22 ++++
>  drivers/platform/x86/dell-smbios.c     | 120 +++++++++++++--------
>  drivers/platform/x86/dell-smbios.h     |  13 ++-
>  drivers/platform/x86/dell-wmi.c        |   8 +-
>  9 files changed, 361 insertions(+), 153 deletions(-)
>  create mode 100644 drivers/platform/x86/dell-smbios-smm.c
>  create mode 100644 drivers/platform/x86/dell-smbios-smm.h
> 
...

> +config DELL_SMBIOS_SMM
> +       tristate "Dell SMBIOS calling interface (SMM implementation)"
> +       depends on DCDBAS
> +       default DCDBAS
> +       select DELL_SMBIOS
> +       ---help---
> +       This provides an implementation for the Dell SMBIOS calling interface
> +       communicated over ACPI-WMI.

Not over ACPI-WMI... over SMM.... right?



> diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
> index f42159fd2031..c648bbfcc394 100644
> --- a/drivers/platform/x86/dell-laptop.c
> +++ b/drivers/platform/x86/dell-laptop.c
> @@ -85,6 +85,7 @@ static struct platform_driver platform_driver = {
>  	}
>  };
>  
> +static struct calling_interface_buffer *buffer;
>  static struct platform_device *platform_device;
>  static struct backlight_device *dell_backlight_device;
>  static struct rfkill *wifi_rfkill;
> @@ -405,7 +406,6 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
>  
>  static int dell_rfkill_set(void *data, bool blocked)
>  {
> -	struct calling_interface_buffer *buffer;
>  	int disable = blocked ? 1 : 0;
>  	unsigned long radio = (unsigned long)data;
>  	int hwswitch_bit = (unsigned long)data - 1;
> @@ -413,19 +413,21 @@ static int dell_rfkill_set(void *data, bool blocked)
>  	int status;
>  	int ret;
>  
> -	buffer = dell_smbios_get_buffer();
> -
> -	dell_smbios_send_request(17, 11);
> +	memset(buffer, 0, sizeof(struct calling_interface_buffer));
> +	buffer->class = 17;
> +	buffer->select = 11;

Please move these three lines into a function, it's used far far too
often to be open coded. The dell_smbios_send_request is a reasonable
wrapper which you could just define here as well. This would minimize
the change to the driver.


-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 10/14] platform/x86: dell-smbios-smm: test for WSMT
  2017-10-04 22:48 ` [PATCH v4 10/14] platform/x86: dell-smbios-smm: test for WSMT Mario Limonciello
@ 2017-10-05  1:59   ` Darren Hart
  0 siblings, 0 replies; 93+ messages in thread
From: Darren Hart @ 2017-10-05  1:59 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Andy Shevchenko, LKML, platform-driver-x86, Andy Lutomirski,
	quasisec, pali.rohar, rjw, mjg59, hch, Greg KH

On Wed, Oct 04, 2017 at 05:48:36PM -0500, Mario Limonciello wrote:
> WSMT is as an attestation to the OS that the platform won't
> modify memory outside of pre-defined areas.
> 
> If a platform has WSMT enabled in BIOS setup, SMM calls through
> dcdbas will fail.  The only way to access platform data in these
> instances is through the WMI SMBIOS calling interface.

Nit: This should probably come after 11/14 where the WMI SMBIOS calling
interface is introduced.

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  2017-10-04 22:48 ` [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver Mario Limonciello
@ 2017-10-05  2:14   ` Darren Hart
  2017-10-05 15:12       ` Mario.Limonciello
  0 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05  2:14 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Andy Shevchenko, LKML, platform-driver-x86, Andy Lutomirski,
	quasisec, pali.rohar, rjw, mjg59, hch, Greg KH

On Wed, Oct 04, 2017 at 05:48:37PM -0500, Mario Limonciello wrote:
> The dell-smbios stack only currently uses an SMI interface which grants
> direct access to physical memory to the firmware SMM methods via a pointer.
> 
> This dispatcher driver adds a WMI-ACPI interface that is detected by WMI
> probe and preferred over the SMI interface in dell-smbios.
> 
> Changing this to operate over WMI-ACPI will use an ACPI OperationRegion
> for a buffer of data storage when SMM calls are performed.
> 
> This is a safer approach to use in kernel drivers as the SMM will
> only have access to that OperationRegion.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> ---
>  MAINTAINERS                            |   6 +
>  drivers/platform/x86/Kconfig           |  16 ++-
>  drivers/platform/x86/Makefile          |   1 +
>  drivers/platform/x86/dell-smbios-wmi.c | 215 +++++++++++++++++++++++++++++++++
>  drivers/platform/x86/dell-smbios-wmi.h |  28 +++++
>  5 files changed, 265 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/platform/x86/dell-smbios-wmi.c
>  create mode 100644 drivers/platform/x86/dell-smbios-wmi.h
> 
...
> diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> index f0b97cb8e449..ef597f440d2e 100644
> --- a/drivers/platform/x86/Kconfig
> +++ b/drivers/platform/x86/Kconfig
> @@ -93,13 +93,27 @@ config ASUS_LAPTOP
>  
>  config DELL_SMBIOS
>  	tristate "Dell SMBIOS calling interface"
> -	depends on DELL_SMBIOS_SMM
> +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
>  	---help---
>  	This module provides common functions for kernel modules using
>  	Dell SMBIOS.

You use select DELL_SMBIOS below, which implies this modules should be
invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
option at all now, they can select DELL_SMBIOS_WMI and or
DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.

> diff --git a/drivers/platform/x86/dell-smbios-wmi.c b/drivers/platform/x86/dell-smbios-wmi.c
> +static void __init parse_b1_table(const struct dmi_header *dm)
> +{
> +	struct misc_bios_flags_structure *flags =
> +	container_of(dm, struct misc_bios_flags_structure, header);
> +
> +	/* 4 bytes header, and one word of flags */

Assuming specifically 8 bytes of flags, independent of arch?

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-04 22:48 ` [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers Mario Limonciello
@ 2017-10-05  2:33   ` Darren Hart
  2017-10-05  7:16   ` Greg KH
  1 sibling, 0 replies; 93+ messages in thread
From: Darren Hart @ 2017-10-05  2:33 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Andy Shevchenko, LKML, platform-driver-x86, Andy Lutomirski,
	quasisec, pali.rohar, rjw, mjg59, hch, Greg KH

On Wed, Oct 04, 2017 at 05:48:38PM -0500, Mario Limonciello wrote:
> For WMI operations that are only Set or Query read or write sysfs
> attributes created by WMI vendor drivers make sense.
> 
> For other WMI operations that are run on Method, there needs to be a
> way to guarantee to userspace that the results from the method call
> belong to the data request to the method call.  Sysfs attributes don't
> work well in this scenario because two userspace processes may be
> competing at reading/writing an attribute and step on each other's
> data.
> 
> When a WMI vendor driver declares an ioctl in a file_operations object
> the WMI bus driver will create a character device that maps to those
> file operations.
> 
> That character device will correspond to this path:
> /dev/wmi/$driver
> 
> The WMI bus driver will interpret the IOCTL calls, test them for
> a valid instance and pass them on to the vendor driver to run.
> 
> This creates an implicit policy that only driver per character
> device.  If a module matches multiple GUID's, the wmi_devices
> will need to be all handled by the same wmi_driver if the same
> character device is used.
> 
> The WMI vendor drivers will be responsible for managing access to
> this character device and proper locking on it.
> 
> When a WMI vendor driver is unloaded the WMI bus driver will clean
> up the character device.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> ---
>  MAINTAINERS                |  1 +
>  drivers/platform/x86/wmi.c | 67 +++++++++++++++++++++++++++++++++++++++++++++-
>  include/linux/wmi.h        |  2 ++
>  include/uapi/linux/wmi.h   | 10 +++++++
>  4 files changed, 79 insertions(+), 1 deletion(-)
>  create mode 100644 include/uapi/linux/wmi.h
> 
> diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
...
> +static long wmi_ioctl(struct file *filp, unsigned int cmd,
> +		      unsigned long arg)
> +{
> +	struct wmi_driver *wdriver;
> +	struct wmi_block *wblock;
> +	const char *driver_name;
> +	struct list_head *p;
> +	bool found = false;
> +
> +	if (_IOC_TYPE(cmd) != WMI_IOC)
> +		return -ENOTTY;
> +
> +	driver_name = filp->f_path.dentry->d_iname;
> +
> +	list_for_each(p, &wmi_block_list) {
> +		wblock = list_entry(p, struct wmi_block, list);
> +		wdriver = container_of(wblock->dev.dev.driver,
> +			struct wmi_driver, driver);
> +		if (strcmp(driver_name, wdriver->driver.name) == 0) {
> +			found = true;
> +			break;

A bit of a nitpic, but the "found" variable isn't necessary. The wdriver
pointer is sufficient:

		if (strcmp(driver_name, wdriver->driver.name) == 0)
			break;
		wdriver = NULL;

> +	if (!found ||

	if (wdriver || ...

And you save a local variable and a couple lines.

...

>  static int wmi_dev_probe(struct device *dev)
>  {
>  	struct wmi_block *wblock = dev_to_wblock(dev);
>  	struct wmi_driver *wdriver =
>  		container_of(dev->driver, struct wmi_driver, driver);
>  	int ret = 0;
> +	char *buf;
>  
>  	if (ACPI_FAILURE(wmi_method_enable(wblock, 1)))
>  		dev_warn(dev, "failed to enable device -- probing anyway\n");
>  
> +	/* driver wants a character device made */
> +	if (wdriver->file_operations) {
> +		buf = kmalloc(strlen(wdriver->driver.name) + 4, GFP_KERNEL);
> +		if (!buf)
> +			return -ENOMEM;
> +		strcpy(buf, "wmi/");
> +		strcpy(buf + 4, wdriver->driver.name);

sprintf(buf, "wmi/%s", wdriver->driver.name)

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures
  2017-10-04 22:48 ` [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures Mario Limonciello
@ 2017-10-05  5:20   ` Andy Shevchenko
  2017-10-05 15:02       ` Mario.Limonciello
  0 siblings, 1 reply; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05  5:20 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, LKML, Platform Driver, Andy Lutomirski, quasisec,
	Pali Rohár, Rafael J. Wysocki, mjg59, Christoph Hellwig,
	Greg KH

On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
<mario.limonciello@dell.com> wrote:
> There is a lot of error checking in place for the format of the WMI
> descriptor buffer, but some of the potentially raised issues should
> be considered critical failures.
>
> If the buffer size or header don't match, this is a good indication
> that the buffer format changed in a way that the rest of the data
> should not be relied upon.
>
> For the remaining data set vectors, continue to notate a warning
> in undefined results, but as those are fields that the descriptor
> intended to refer to other applications, don't fail if they're new
> values.

> -       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0)
> -               dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
> +       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
> +               dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",

A nit: ping-pong programming detected.
Looks like current patch 2 should go at least after this one.


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05  1:09   ` Darren Hart
@ 2017-10-05  5:29     ` Andy Shevchenko
  2017-10-05  7:11       ` Darren Hart
  0 siblings, 1 reply; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05  5:29 UTC (permalink / raw)
  To: Darren Hart
  Cc: Mario Limonciello, LKML, Platform Driver, Andy Lutomirski,
	quasisec, Pali Rohár, Rafael J. Wysocki, mjg59,
	Christoph Hellwig, Greg KH

On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> On Wed, Oct 04, 2017 at 05:48:31PM -0500, Mario Limonciello wrote:
>> All communication on individual GUIDs should occur in separate drivers.
>> Allowing a driver to communicate with the bus to another GUID is just
>> a hack that discourages drivers to adopt the bus model.
>>
>> The information found from the WMI descriptor driver is now exported
>> for use by other drivers.

> You'll want to add something like:
>
> #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
>         if (request_module("dell_wmi_descriptor"))
>                 /* FAIL */
> #endif
>
> During init.

I don't think #ifdef is needed.

We may just request module.

But looking in the code it seems that we simple need to select that
module. No request_module will be needed.
Did I miss something?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-04 22:48 ` [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver Mario Limonciello
  2017-10-05  1:09   ` Darren Hart
@ 2017-10-05  5:34   ` Andy Shevchenko
  2017-10-05 17:04       ` Mario.Limonciello
  1 sibling, 1 reply; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05  5:34 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, LKML, Platform Driver, Andy Lutomirski, quasisec,
	Pali Rohár, Rafael J. Wysocki, mjg59, Christoph Hellwig,
	Greg KH

On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
<mario.limonciello@dell.com> wrote:
> All communication on individual GUIDs should occur in separate drivers.
> Allowing a driver to communicate with the bus to another GUID is just
> a hack that discourages drivers to adopt the bus model.
>
> The information found from the WMI descriptor driver is now exported
> for use by other drivers.

> +       priv = list_first_entry_or_null(&wmi_list,
> +                                       struct descriptor_priv,
> +                                       list);

> +       priv = list_first_entry_or_null(&wmi_list,
> +                                       struct descriptor_priv,
> +                                       list);

static inline ...to_priv(...)
{
 return list_first_entry_...();
}

> +       list_add_tail(&priv->list, &wmi_list);

> +       list_del(&priv->list);

Do these need locking?

> +bool dell_wmi_get_interface_version(u32 *version);
> +bool dell_wmi_get_size(u32 *size);

This might need stubs when module is not selected (when functionality
is optional if it would be the case), otherwise all users should
select it explicitly.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05  5:29     ` Andy Shevchenko
@ 2017-10-05  7:11       ` Darren Hart
  2017-10-05  8:47         ` Andy Shevchenko
  0 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05  7:11 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Mario Limonciello, LKML, Platform Driver, Andy Lutomirski,
	quasisec, Pali Rohár, Rafael J. Wysocki, mjg59,
	Christoph Hellwig, Greg KH

On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> > On Wed, Oct 04, 2017 at 05:48:31PM -0500, Mario Limonciello wrote:
> >> All communication on individual GUIDs should occur in separate drivers.
> >> Allowing a driver to communicate with the bus to another GUID is just
> >> a hack that discourages drivers to adopt the bus model.
> >>
> >> The information found from the WMI descriptor driver is now exported
> >> for use by other drivers.
> 
> > You'll want to add something like:
> >
> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> >         if (request_module("dell_wmi_descriptor"))
> >                 /* FAIL */
> > #endif
> >
> > During init.
> 
> I don't think #ifdef is needed.

Without the ifdef, we can't distinguish between request_module failing
to load the module because it isn't available and because it is
built-in.

> 
> We may just request module.
> 
> But looking in the code it seems that we simple need to select that
> module. No request_module will be needed.

The select will ensure the module is built, but there is not guarantee
to module load order. The intent of the above is to ensure the symbols
from the required module are loaded.

> Did I miss something?

Or I did :-) Is there something about this module which ensures
dell_wmi_descriptor is loaded first?

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-04 22:48 ` [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers Mario Limonciello
  2017-10-05  2:33   ` Darren Hart
@ 2017-10-05  7:16   ` Greg KH
  2017-10-05 14:35       ` Mario.Limonciello
  1 sibling, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05  7:16 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, Andy Shevchenko, LKML, platform-driver-x86,
	Andy Lutomirski, quasisec, pali.rohar, rjw, mjg59, hch

On Wed, Oct 04, 2017 at 05:48:38PM -0500, Mario Limonciello wrote:
> For WMI operations that are only Set or Query read or write sysfs
> attributes created by WMI vendor drivers make sense.
> 
> For other WMI operations that are run on Method, there needs to be a
> way to guarantee to userspace that the results from the method call
> belong to the data request to the method call.  Sysfs attributes don't
> work well in this scenario because two userspace processes may be
> competing at reading/writing an attribute and step on each other's
> data.

And you protect this from happening in the ioctl?  I didn't see it, but
ok, I'll take your word for it :)

> When a WMI vendor driver declares an ioctl in a file_operations object
> the WMI bus driver will create a character device that maps to those
> file operations.
> 
> That character device will correspond to this path:
> /dev/wmi/$driver
> 
> The WMI bus driver will interpret the IOCTL calls, test them for
> a valid instance and pass them on to the vendor driver to run.
> 
> This creates an implicit policy that only driver per character
> device.  If a module matches multiple GUID's, the wmi_devices
> will need to be all handled by the same wmi_driver if the same
> character device is used.

Interesting "way out" but ok, I can buy it...

> The WMI vendor drivers will be responsible for managing access to
> this character device and proper locking on it.
> 
> When a WMI vendor driver is unloaded the WMI bus driver will clean
> up the character device.
> 
> Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> ---
>  MAINTAINERS                |  1 +
>  drivers/platform/x86/wmi.c | 67 +++++++++++++++++++++++++++++++++++++++++++++-
>  include/linux/wmi.h        |  2 ++
>  include/uapi/linux/wmi.h   | 10 +++++++
>  4 files changed, 79 insertions(+), 1 deletion(-)
>  create mode 100644 include/uapi/linux/wmi.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 0357e9b1cfaf..6db1d84999bc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -372,6 +372,7 @@ ACPI WMI DRIVER
>  L:	platform-driver-x86@vger.kernel.org
>  S:	Orphan
>  F:	drivers/platform/x86/wmi.c
> +F:	include/uapi/linux/wmi.h
>  
>  AD1889 ALSA SOUND DRIVER
>  M:	Thibaut Varene <T-Bone@parisc-linux.org>
> diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
> index bcb41c1c7f52..5aef052b4aab 100644
> --- a/drivers/platform/x86/wmi.c
> +++ b/drivers/platform/x86/wmi.c
> @@ -38,6 +38,7 @@
>  #include <linux/init.h>
>  #include <linux/kernel.h>
>  #include <linux/list.h>
> +#include <linux/miscdevice.h>
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include <linux/slab.h>
> @@ -69,6 +70,7 @@ struct wmi_block {
>  	struct wmi_device dev;
>  	struct list_head list;
>  	struct guid_block gblock;
> +	struct miscdevice misc_dev;
>  	struct acpi_device *acpi_device;
>  	wmi_notify_handler handler;
>  	void *handler_data;
> @@ -765,22 +767,80 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
>  	return 0;
>  }
>  
> +static long wmi_ioctl(struct file *filp, unsigned int cmd,
> +		      unsigned long arg)
> +{
> +	struct wmi_driver *wdriver;
> +	struct wmi_block *wblock;
> +	const char *driver_name;
> +	struct list_head *p;
> +	bool found = false;
> +
> +	if (_IOC_TYPE(cmd) != WMI_IOC)
> +		return -ENOTTY;
> +
> +	driver_name = filp->f_path.dentry->d_iname;
> +
> +	list_for_each(p, &wmi_block_list) {
> +		wblock = list_entry(p, struct wmi_block, list);
> +		wdriver = container_of(wblock->dev.dev.driver,
> +			struct wmi_driver, driver);
> +		if (strcmp(driver_name, wdriver->driver.name) == 0) {
> +			found = true;
> +			break;
> +		}
> +	}

You can provide an open() call to handle this type of logic for you, so
you don't have to do it on every ioctl() call, but I guess it's not
really a big deal, right?

> +	if (!found ||
> +	    !wdriver->file_operations ||
> +	    !wdriver->file_operations->unlocked_ioctl)
> +		return -ENODEV;

Shouldn't you check for unlocked_ioctl() already?  No need to check it
here, right?

And if you are only passing down unlocked_ioctl, there's no need for a
whole empty file_operations structure in the driver, right?  Just have
an ioctl callback to make things smaller and simpler to understand.

> +	/* make sure we're not calling a higher instance */
> +	if (_IOC_NR(cmd) > wblock->gblock.instance_count)
> +		return -EINVAL;

What exactly does this protect from?

> +	/* driver wants a character device made */
> +	if (wdriver->file_operations) {

Check for unlocked_ioctl here, actually, drop the file_operations
entirely, and just have that one callback.

> +		buf = kmalloc(strlen(wdriver->driver.name) + 4, GFP_KERNEL);
> +		if (!buf)
> +			return -ENOMEM;

No unwinding of other logic needed?

> +		strcpy(buf, "wmi/");
> +		strcpy(buf + 4, wdriver->driver.name);
> +		wblock->misc_dev.minor = MISC_DYNAMIC_MINOR;
> +		wblock->misc_dev.name = buf;
> +		wblock->misc_dev.fops = &wmi_fops;
> +		ret = misc_register(&wblock->misc_dev);
> +		if (ret) {
> +			dev_warn(dev, "failed to register char dev: %d", ret);
> +			kfree(buf);

Again, no unwinding needed?  Error message value returned?

> +		}
> +	}
> +
>  	if (wdriver->probe) {
>  		ret = wdriver->probe(dev_to_wdev(dev));
>  		if (ret != 0 && ACPI_FAILURE(wmi_method_enable(wblock, 0)))
>  			dev_warn(dev, "failed to disable device\n");
>  	}
> -
>  	return ret;
>  }
>  
> @@ -791,6 +851,11 @@ static int wmi_dev_remove(struct device *dev)
>  		container_of(dev->driver, struct wmi_driver, driver);
>  	int ret = 0;
>  
> +	if (wdriver->file_operations) {
> +		kfree(wblock->misc_dev.name);
> +		misc_deregister(&wblock->misc_dev);

Unregister before freeing the device name, right?

> --- /dev/null
> +++ b/include/uapi/linux/wmi.h
> @@ -0,0 +1,10 @@
> +#ifndef _UAPI_LINUX_WMI_H
> +#define _UAPI_LINUX_WMI_H
> +
> +#define WMI_IOC 'W'
> +#define WMI_IO(instance)	_IO(WMI_IOC, instance)
> +#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
> +#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
> +#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)

Ugh, void *, this is going to be "fun"...

My comments on just how fun is left for the actual driver that attempted
to implement these...

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-04 22:48 ` [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface Mario Limonciello
@ 2017-10-05  7:23   ` Greg KH
  2017-10-05 16:28       ` Mario.Limonciello
  2017-10-05  7:33   ` Greg KH
  2017-10-05 13:59   ` Alan Cox
  2 siblings, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05  7:23 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, Andy Shevchenko, LKML, platform-driver-x86,
	Andy Lutomirski, quasisec, pali.rohar, rjw, mjg59, hch

On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> This userspace character device will be used to perform SMBIOS calls
> from any applications.
> 
> It provides an ioctl that will allow passing the 32k WMI calling
> interface buffer between userspace and kernel space.

{sigh}  Did you really test this?  It feels like it wasn't, due to the
api you are using here.  Did you run it with a 32bit userspace and 64bit
kernel?  32bit kernel/userspace?  How well did your userspace developer
fall down crying when you tried that?  :)

> This character device is intended to deprecate the dcdbas kernel module
> and the interface that it provides to userspace.

At least that driver has a well-documented api to userspace, you are
throwing all of that away here, are you _sure_ you want to do that?
Seems like you just made things much harder.

> It's important for the driver to provide a R/W ioctl to ensure that
> two competing userspace processes don't race to provide or read each
> others data.

The whole goal of this patch is to provide that ioctl, right?  So of
course it is "important" :)

> The API for interacting with this interface is defined in documentation
> as well as a uapi header provides the format of the structures.

Ok, let's _just_ review that api please:

> diff --git a/include/uapi/linux/dell-smbios-wmi.h b/include/uapi/linux/dell-smbios-wmi.h
> new file mode 100644
> index 000000000000..0d0d09b04021
> --- /dev/null
> +++ b/include/uapi/linux/dell-smbios-wmi.h
> @@ -0,0 +1,25 @@
> +#ifndef _UAPI_DELL_SMBIOS_WMI_H_
> +#define _UAPI_DELL_SMBIOS_WMI_H_
> +
> +#include <linux/ioctl.h>
> +#include <linux/wmi.h>
> +
> +struct wmi_calling_interface_buffer {
> +	u16 class;
> +	u16 select;
> +	u32 input[4];
> +	u32 output[4];
> +	u32 argattrib;
> +	u32 blength;
> +	u8 *data;
> +} __packed;

{sigh}

For structures that cross the user/kernel boundry, you _HAVE_ to use the
correct types.  For some things, that is easy, u16 needs to be __u16,
u32 needs to be __u32, but u8*?  Hah, good luck!  Remember what I
mentioned above about 32/64 bit issues?

Why do you need a pointer here at all?  You are providing a huge chunk
of memory to the ioctl, what's the use of a pointer?  How are you
dereferenceing this pointer (remember, it's a userspace pointer, which
you are not saying here, so odds are the kernel code is wrong...)


> +struct wmi_smbios_ioctl {
> +	u32 length;

__u32.

And why not __u64?  Is 32 bits always going to be ok?

> +	struct wmi_calling_interface_buffer *buf;

Another pointer?  2 pointer dereferences in the same ioctl structure?
Crazy, you are wanting to make your life harder than it has to be...


> +};
> +
> +/* only offers on the single instance */
> +#define DELL_WMI_SMBIOS_CMD		WMI_IOWR(0)

I don't understand the comment, please explain it better.

Please sit down and work out your api here, I don't think you have
thought it through properly, given the number of pointers alone.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-04 22:48 ` [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface Mario Limonciello
  2017-10-05  7:23   ` Greg KH
@ 2017-10-05  7:33   ` Greg KH
  2017-10-05 16:37       ` Mario.Limonciello
  2017-10-05 13:59   ` Alan Cox
  2 siblings, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05  7:33 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, Andy Shevchenko, LKML, platform-driver-x86,
	Andy Lutomirski, quasisec, pali.rohar, rjw, mjg59, hch

On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> +static long dell_smbios_wmi_ioctl(struct file *filp, unsigned int cmd,
> +	unsigned long arg)
> +{
> +	void __user *p = (void __user *) arg;
> +	struct wmi_smbios_ioctl *input;
> +	struct wmi_smbios_priv *priv;
> +	struct wmi_device *wdev;
> +	size_t ioctl_size;
> +	int ret = 0;
> +
> +	switch (cmd) {
> +	/* we only operate on first instance */
> +	case DELL_WMI_SMBIOS_CMD:
> +		wdev = get_first_wmi_device();
> +		if (!wdev) {
> +			pr_err("No WMI devices bound\n");

dev_err(), you are a driver, never use "raw" pr_ calls.

> +			return -ENODEV;
> +		}
> +		ioctl_size = sizeof(struct wmi_smbios_ioctl);
> +		priv = dev_get_drvdata(&wdev->dev);
> +		input = kmalloc(ioctl_size, GFP_KERNEL);
> +		if (!input)
> +			return -ENOMEM;
> +		mutex_lock(&wmi_mutex);
> +		if (!access_ok(VERIFY_READ, p, ioctl_size)) {

Hm, any time I see an access_ok() call, I get scared.  You should almost
never need to make that call if you are using the correct kernel apis.

> +			pr_err("Unsafe userspace pointer passed\n");

dev_err().

> +			return -EFAULT;

Memory leak!


> +		}
> +		if (copy_from_user(input, p, ioctl_size)) {
> +			ret = -EFAULT;

So, why did you call access_ok() followed by copy_from_user()?
copy_from/to() handle all of that for you automatically.

> +			goto fail_smbios_cmd;
> +		}
> +		if (input->length != priv->buffer_size) {
> +			pr_err("Got buffer size %d expected %d\n",
> +				input->length, priv->buffer_size);

length is user provided, it can be whatever anyone sets it to.  I don't
understand this error.

> +			ret = -EINVAL;
> +			goto fail_smbios_cmd;
> +		}
> +		if (!access_ok(VERIFY_WRITE, input->buf, priv->buffer_size)) {
> +			pr_err("Unsafe userspace pointer passed\n");

Again, don't need this.

> +			ret = -EFAULT;
> +			goto fail_smbios_cmd;
> +		}
> +		if (copy_from_user(priv->buf, input->buf, priv->buffer_size)) {

Wait, input->buf is a user pointer?  Ick, see my previous email about
your crazy api here being a mess.  This should not be needed.

And as you "know" the buffer size already, why do you have userspace
specify it?  What good is it?

> +			ret = -EFAULT;
> +			goto fail_smbios_cmd;
> +		}
> +		ret = run_smbios_call(wdev);

No other checking of the values in the structure?  You just "trust"
userspace to get it all right?  Hah!

> +		if (ret != 0)
> +			goto fail_smbios_cmd;

You didn't run this through checkpatch :(


> +		if (copy_to_user(input->buf, priv->buf, priv->buffer_size))
> +			ret = -EFAULT;
> +fail_smbios_cmd:
> +		kfree(input);
> +		mutex_unlock(&wmi_mutex);
> +		break;
> +	default:
> +		pr_err("unsupported ioctl: %d.\n", cmd);
> +		ret = -ENOIOCTLCMD;
> +	}
> +	return ret;
> +}
> +
> +static ssize_t buffer_size_show(struct device *dev,
> +				struct device_attribute *attr, char *buf)
> +{
> +	struct wmi_smbios_priv *priv = dev_get_drvdata(dev);
> +
> +	return sprintf(buf, "%d\n", priv->buffer_size);
> +}
> +static DEVICE_ATTR_RO(buffer_size);
> +
> +static struct attribute *smbios_wmi_attrs[] = {
> +	&dev_attr_buffer_size.attr,
> +	NULL
> +};
> +
> +static const struct attribute_group smbios_wmi_attribute_group = {
> +	.attrs = smbios_wmi_attrs,
> +};
> +
>  static int dell_smbios_wmi_probe(struct wmi_device *wdev)
>  {
>  	struct wmi_smbios_priv *priv;
> @@ -127,6 +209,11 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev)
>  	if (!priv->buf)
>  		return -ENOMEM;
>  
> +	ret = sysfs_create_group(&wdev->dev.kobj,
> +				 &smbios_wmi_attribute_group);

Hint, if a driver ever makes a call to sysfs_*(), something is wrong, it
should never be needed.

Also, you just raced with userspace and lost :(

There is a way to fix all of this, in a simple way, I'll leave that as
an exercise for the reader, I've reviewed enough of this code for
today...

> +static const struct file_operations dell_smbios_wmi_fops = {
> +	.owner		= THIS_MODULE,

And who uses that field?  Hint, no one is, which is another issue that I
forgot to review in your previous patch where you use this structure.
What is protecting this module from being unloaded while the ioctl call
is running?  (hint, nothing...)

I need more coffee...

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05  7:11       ` Darren Hart
@ 2017-10-05  8:47         ` Andy Shevchenko
  2017-10-05 13:59             ` Mario.Limonciello
  0 siblings, 1 reply; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05  8:47 UTC (permalink / raw)
  To: Darren Hart
  Cc: Mario Limonciello, LKML, Platform Driver, Andy Lutomirski,
	quasisec, Pali Rohár, Rafael J. Wysocki, mjg59,
	Christoph Hellwig, Greg KH

On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
>> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:

>> > You'll want to add something like:
>> >
>> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
>> >         if (request_module("dell_wmi_descriptor"))
>> >                 /* FAIL */
>> > #endif
>> >
>> > During init.
>>
>> I don't think #ifdef is needed.
>
> Without the ifdef, we can't distinguish between request_module failing
> to load the module because it isn't available and because it is
> built-in.
>
>>
>> We may just request module.
>>
>> But looking in the code it seems that we simple need to select that
>> module. No request_module will be needed.
>
> The select will ensure the module is built, but there is not guarantee
> to module load order. The intent of the above is to ensure the symbols
> from the required module are loaded.
>
>> Did I miss something?
>
> Or I did :-) Is there something about this module which ensures
> dell_wmi_descriptor is loaded first?

If there is an optional *run-time* dependency we need to use somelike
request_module(). For example, this is the case for idma64
(drivers/dma) vs intel-lpss (drivers/mfd).

If it's mandatory run-time dependency, then we need to add stubs to
the header and select the callee's module in Kconfig.

In case they are both modules, depmod keeps an ordering.

So, the corner case here is when the caller is builtin while callee is module.

This is a bit tricky to add to Kconfig (we also have such cases
between I2C DesignWare and acpi_lpss AFAIR).

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens
  2017-10-04 22:48 ` [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens Mario Limonciello
@ 2017-10-05  8:49   ` Andy Shevchenko
  2017-10-05 13:58       ` Mario.Limonciello
  0 siblings, 1 reply; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05  8:49 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, LKML, Platform Driver, Andy Lutomirski, quasisec,
	Pali Rohár, Rafael J. Wysocki, mjg59, Christoph Hellwig,
	Greg KH

On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
<mario.limonciello@dell.com> wrote:
> Currently userspace tools can access system tokens via the dcdbas
> kernel module and a SMI call that will cause the platform to execute
> SMM code.
>
> With a goal in mind of deprecating the dcdbas kernel module a different
> method for accessing these tokens from userspace needs to be created.
>
> This is intentionally marked to only be readable as root as it can
> contain sensitive information about the platform's configuration.
>
> MAINTAINERS was missing for this driver.  Add myself and Pali to
> maintainers list for it.
>
> Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>

> Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>

To be clear I just suggested the output format in ->show() callback.


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI
  2017-10-05  0:09 ` [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Darren Hart
@ 2017-10-05  9:00   ` Andy Shevchenko
  0 siblings, 0 replies; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05  9:00 UTC (permalink / raw)
  To: Darren Hart
  Cc: Mario Limonciello, LKML, Platform Driver, Andy Lutomirski,
	quasisec, Pali Rohár, Rafael J. Wysocki, mjg59,
	Christoph Hellwig, Greg KH

On Thu, Oct 5, 2017 at 3:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> On Wed, Oct 04, 2017 at 05:48:26PM -0500, Mario Limonciello wrote:
>>
>> NOTE: This patch is intended to go on top of the 6 patches already in
>> Darren's review tree.
>
> I pushed these to for-next today, they should be available in linux-next
> shortly.

Not before beginning of November.

P.S. This month no linux-next.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens
  2017-10-05  8:49   ` Andy Shevchenko
@ 2017-10-05 13:58       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 13:58 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: dvhart, linux-kernel, platform-driver-x86, luto, quasisec,
	pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 3:50 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for
> SMBIOS tokens
> 
> On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
> <mario.limonciello@dell.com> wrote:
> > Currently userspace tools can access system tokens via the dcdbas
> > kernel module and a SMI call that will cause the platform to execute
> > SMM code.
> >
> > With a goal in mind of deprecating the dcdbas kernel module a different
> > method for accessing these tokens from userspace needs to be created.
> >
> > This is intentionally marked to only be readable as root as it can
> > contain sensitive information about the platform's configuration.
> >
> > MAINTAINERS was missing for this driver.  Add myself and Pali to
> > maintainers list for it.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> 
> > Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> 
> To be clear I just suggested the output format in ->show() callback.

Andy, do you mean you would prefer not to be attributed in the description,
or should I be clearer that was your suggestion?

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens
@ 2017-10-05 13:58       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 13:58 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: dvhart, linux-kernel, platform-driver-x86, luto, quasisec,
	pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 3:50 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for
> SMBIOS tokens
> 
> On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
> <mario.limonciello@dell.com> wrote:
> > Currently userspace tools can access system tokens via the dcdbas
> > kernel module and a SMI call that will cause the platform to execute
> > SMM code.
> >
> > With a goal in mind of deprecating the dcdbas kernel module a different
> > method for accessing these tokens from userspace needs to be created.
> >
> > This is intentionally marked to only be readable as root as it can
> > contain sensitive information about the platform's configuration.
> >
> > MAINTAINERS was missing for this driver.  Add myself and Pali to
> > maintainers list for it.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> 
> > Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> 
> To be clear I just suggested the output format in ->show() callback.

Andy, do you mean you would prefer not to be attributed in the description,
or should I be clearer that was your suggestion?


^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-04 22:48 ` [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface Mario Limonciello
  2017-10-05  7:23   ` Greg KH
  2017-10-05  7:33   ` Greg KH
@ 2017-10-05 13:59   ` Alan Cox
  2017-10-05 14:22       ` Mario.Limonciello
  2 siblings, 1 reply; 93+ messages in thread
From: Alan Cox @ 2017-10-05 13:59 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, Andy Shevchenko, LKML, platform-driver-x86,
	Andy Lutomirski, quasisec, pali.rohar, rjw, mjg59, hch, Greg KH

On Wed,  4 Oct 2017 17:48:39 -0500
Mario Limonciello <mario.limonciello@dell.com> wrote:

> This userspace character device will be used to perform SMBIOS calls
> from any applications.
> 
> It provides an ioctl that will allow passing the 32k WMI calling
> interface buffer between userspace and kernel space.

What is your security model for firing 32K of random crap at the BIOS ?
Do you fuzz test the BIOS interface ?

How do we know that between now and the end of the universe every call is
safe to execute as any random user without upsetting other users on the
same PC ?

Right now this patch is scary. U've fuzzed tested BIOS firmware in thepast
and it almost universally ended up in reaching for the power cord because
PC firmware is usually closed and usually crap.

In addition you are assuming that every function you ever provide via
that ioctl has the same securiy model. So if one of them should only be
usable by the user logged in on the console the system would have to
enforce that for all. If you have two conflicting security policies we'd
have to make it root only and owned by a daemon. If a BIOS turns out to
have a hole then we have to make it CAP_SYS_RAWIO.

/dev/dorandomvendorspecificshit is not an API and not a security policy.

Alan

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05  8:47         ` Andy Shevchenko
@ 2017-10-05 13:59             ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 13:59 UTC (permalink / raw)
  To: andy.shevchenko, dvhart
  Cc: linux-kernel, platform-driver-x86, luto, quasisec, pali.rohar,
	rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 3:48 AM
> To: Darren Hart <dvhart@infradead.org>
> Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-
> kernel@vger.kernel.org>; Platform Driver <platform-driver-
> x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> 
> >> > You'll want to add something like:
> >> >
> >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> >> >         if (request_module("dell_wmi_descriptor"))
> >> >                 /* FAIL */
> >> > #endif
> >> >
> >> > During init.
> >>
> >> I don't think #ifdef is needed.
> >
> > Without the ifdef, we can't distinguish between request_module failing
> > to load the module because it isn't available and because it is
> > built-in.
> >
> >>
> >> We may just request module.
> >>
> >> But looking in the code it seems that we simple need to select that
> >> module. No request_module will be needed.
> >
> > The select will ensure the module is built, but there is not guarantee
> > to module load order. The intent of the above is to ensure the symbols
> > from the required module are loaded.
> >
> >> Did I miss something?
> >
> > Or I did :-) Is there something about this module which ensures
> > dell_wmi_descriptor is loaded first?
> 
> If there is an optional *run-time* dependency we need to use somelike
> request_module(). For example, this is the case for idma64
> (drivers/dma) vs intel-lpss (drivers/mfd).
> 
> If it's mandatory run-time dependency, then we need to add stubs to
> the header and select the callee's module in Kconfig.
> 
> In case they are both modules, depmod keeps an ordering.
> 
> So, the corner case here is when the caller is builtin while callee is module.
> 
> This is a bit tricky to add to Kconfig (we also have such cases
> between I2C DesignWare and acpi_lpss AFAIR).
> 
> --
> With Best Regards,
> Andy Shevchenko

So I believe it should be a mandatory runtime dependency due to needing
the symbol dell_wmi_get_interface_version.  Depmod should be handling
this then no?

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
@ 2017-10-05 13:59             ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 13:59 UTC (permalink / raw)
  To: andy.shevchenko, dvhart
  Cc: linux-kernel, platform-driver-x86, luto, quasisec, pali.rohar,
	rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 3:48 AM
> To: Darren Hart <dvhart@infradead.org>
> Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-
> kernel@vger.kernel.org>; Platform Driver <platform-driver-
> x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> 
> >> > You'll want to add something like:
> >> >
> >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> >> >         if (request_module("dell_wmi_descriptor"))
> >> >                 /* FAIL */
> >> > #endif
> >> >
> >> > During init.
> >>
> >> I don't think #ifdef is needed.
> >
> > Without the ifdef, we can't distinguish between request_module failing
> > to load the module because it isn't available and because it is
> > built-in.
> >
> >>
> >> We may just request module.
> >>
> >> But looking in the code it seems that we simple need to select that
> >> module. No request_module will be needed.
> >
> > The select will ensure the module is built, but there is not guarantee
> > to module load order. The intent of the above is to ensure the symbols
> > from the required module are loaded.
> >
> >> Did I miss something?
> >
> > Or I did :-) Is there something about this module which ensures
> > dell_wmi_descriptor is loaded first?
> 
> If there is an optional *run-time* dependency we need to use somelike
> request_module(). For example, this is the case for idma64
> (drivers/dma) vs intel-lpss (drivers/mfd).
> 
> If it's mandatory run-time dependency, then we need to add stubs to
> the header and select the callee's module in Kconfig.
> 
> In case they are both modules, depmod keeps an ordering.
> 
> So, the corner case here is when the caller is builtin while callee is module.
> 
> This is a bit tricky to add to Kconfig (we also have such cases
> between I2C DesignWare and acpi_lpss AFAIR).
> 
> --
> With Best Regards,
> Andy Shevchenko

So I believe it should be a mandatory runtime dependency due to needing
the symbol dell_wmi_get_interface_version.  Depmod should be handling
this then no?

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05 13:59             ` Mario.Limonciello
  (?)
@ 2017-10-05 14:14             ` Darren Hart
  2017-10-05 14:47                 ` Mario.Limonciello
  -1 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05 14:14 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

On Thu, Oct 05, 2017 at 01:59:36PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> > Sent: Thursday, October 5, 2017 3:48 AM
> > To: Darren Hart <dvhart@infradead.org>
> > Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-
> > kernel@vger.kernel.org>; Platform Driver <platform-driver-
> > x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> > quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> > <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> > Greg KH <greg@kroah.com>
> > Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> > descriptor into it's own driver
> > 
> > On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> > > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> > >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org> wrote:
> > 
> > >> > You'll want to add something like:
> > >> >
> > >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> > >> >         if (request_module("dell_wmi_descriptor"))
> > >> >                 /* FAIL */
> > >> > #endif
> > >> >
> > >> > During init.
> > >>
> > >> I don't think #ifdef is needed.
> > >
> > > Without the ifdef, we can't distinguish between request_module failing
> > > to load the module because it isn't available and because it is
> > > built-in.
> > >
> > >>
> > >> We may just request module.
> > >>
> > >> But looking in the code it seems that we simple need to select that
> > >> module. No request_module will be needed.
> > >
> > > The select will ensure the module is built, but there is not guarantee
> > > to module load order. The intent of the above is to ensure the symbols
> > > from the required module are loaded.
> > >
> > >> Did I miss something?
> > >
> > > Or I did :-) Is there something about this module which ensures
> > > dell_wmi_descriptor is loaded first?
> > 
> > If there is an optional *run-time* dependency we need to use somelike
> > request_module(). For example, this is the case for idma64
> > (drivers/dma) vs intel-lpss (drivers/mfd).
> > 
> > If it's mandatory run-time dependency, then we need to add stubs to
> > the header and select the callee's module in Kconfig.
> > 
> > In case they are both modules, depmod keeps an ordering.
> > 
> > So, the corner case here is when the caller is builtin while callee is module.
> > 
> > This is a bit tricky to add to Kconfig (we also have such cases
> > between I2C DesignWare and acpi_lpss AFAIR).
> > 
> > --
> > With Best Regards,
> > Andy Shevchenko
> 
> So I believe it should be a mandatory runtime dependency due to needing
> the symbol dell_wmi_get_interface_version.  Depmod should be handling
> this then no?

This was nagging me all night, and I was thinking the last time I had to
use this it was indeed a runtime dependency. Sorry for the noise on
this.

The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
module if the dependent drivers are modules.

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens
  2017-10-05 13:58       ` Mario.Limonciello
  (?)
@ 2017-10-05 14:22       ` Andy Shevchenko
  -1 siblings, 0 replies; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05 14:22 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, linux-kernel, Platform Driver, Andy Lutomirski, quasisec,
	Pali Rohár, Rafael J. Wysocki, mjg59, Christoph Hellwig,
	Greg KH

On Thu, Oct 5, 2017 at 4:58 PM,  <Mario.Limonciello@dell.com> wrote:

>> > Suggested-by: Andy Shevchenko <andy.shevchenko@gmail.com>
>>
>> To be clear I just suggested the output format in ->show() callback.
>
> Andy, do you mean you would prefer not to be attributed in the description,
> or should I be clearer that was your suggestion?

I think that there is bigger threshold for being included one's name
in Suggested-by tag. You have few dozens of lines changed and only one
is suggested by me. And that one doesn't influence the initial idea,
just a format change.

So, I'm not against it per se, I just think it confuses more than attributes.

Summarize: I would not put it in this patch.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 13:59   ` Alan Cox
@ 2017-10-05 14:22       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 14:22 UTC (permalink / raw)
  To: gnomes
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> Sent: Thursday, October 5, 2017 8:59 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg
> KH <greg@kroah.com>
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Wed,  4 Oct 2017 17:48:39 -0500
> Mario Limonciello <mario.limonciello@dell.com> wrote:
> 
> > This userspace character device will be used to perform SMBIOS calls
> > from any applications.
> >
> > It provides an ioctl that will allow passing the 32k WMI calling
> > interface buffer between userspace and kernel space.
> 
> What is your security model for firing 32K of random crap at the BIOS ?

Adding new class and select methods requires a review with the security
team.  They will do STRIDE analysis and threat modeling.

> Do you fuzz test the BIOS interface ?

Yes there has been internal fuzz testing classes and selects used in the 
ACPI interface in the past.  I can't comment on how regularly that is done.
I do think it's interesting is to use the interface in Linux for further fuzz
testing though.

> 
> How do we know that between now and the end of the universe every call is
> safe to execute as any random user without upsetting other users on the
> same PC ?

Any random user shouldn't be executing the ioctl.
Only root should be executing any of these calls.

If there is a particular call that is deemed too dangerous to have available the ioctl
call can be filtered by the kernel module.

> 
> Right now this patch is scary. U've fuzzed tested BIOS firmware in thepast
> and it almost universally ended up in reaching for the power cord because
> PC firmware is usually closed and usually crap.
>

Can you please share more context?

> In addition you are assuming that every function you ever provide via
> that ioctl has the same securiy model. So if one of them should only be
> usable by the user logged in on the console the system would have to
> enforce that for all. If you have two conflicting security policies we'd
> have to make it root only and owned by a daemon. If a BIOS turns out to
> have a hole then we have to make it CAP_SYS_RAWIO.
> 
> /dev/dorandomvendorspecificshit is not an API and not a security policy.
> 
> Alan

All functionality offered through this interface has the same security model.
This should only be made available to root, but I don't see the need for a
daemon to further sit between calls.  The two applications that I see using
this in the short term (fwupd and fwupdate) both run as root and would
directly use this interface.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
@ 2017-10-05 14:22       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 14:22 UTC (permalink / raw)
  To: gnomes
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> Sent: Thursday, October 5, 2017 8:59 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg
> KH <greg@kroah.com>
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Wed,  4 Oct 2017 17:48:39 -0500
> Mario Limonciello <mario.limonciello@dell.com> wrote:
> 
> > This userspace character device will be used to perform SMBIOS calls
> > from any applications.
> >
> > It provides an ioctl that will allow passing the 32k WMI calling
> > interface buffer between userspace and kernel space.
> 
> What is your security model for firing 32K of random crap at the BIOS ?

Adding new class and select methods requires a review with the security
team.  They will do STRIDE analysis and threat modeling.

> Do you fuzz test the BIOS interface ?

Yes there has been internal fuzz testing classes and selects used in the 
ACPI interface in the past.  I can't comment on how regularly that is done.
I do think it's interesting is to use the interface in Linux for further fuzz
testing though.

> 
> How do we know that between now and the end of the universe every call is
> safe to execute as any random user without upsetting other users on the
> same PC ?

Any random user shouldn't be executing the ioctl.
Only root should be executing any of these calls.

If there is a particular call that is deemed too dangerous to have available the ioctl
call can be filtered by the kernel module.

> 
> Right now this patch is scary. U've fuzzed tested BIOS firmware in thepast
> and it almost universally ended up in reaching for the power cord because
> PC firmware is usually closed and usually crap.
>

Can you please share more context?

> In addition you are assuming that every function you ever provide via
> that ioctl has the same securiy model. So if one of them should only be
> usable by the user logged in on the console the system would have to
> enforce that for all. If you have two conflicting security policies we'd
> have to make it root only and owned by a daemon. If a BIOS turns out to
> have a hole then we have to make it CAP_SYS_RAWIO.
> 
> /dev/dorandomvendorspecificshit is not an API and not a security policy.
> 
> Alan

All functionality offered through this interface has the same security model.
This should only be made available to root, but I don't see the need for a
daemon to further sit between calls.  The two applications that I see using
this in the short term (fwupd and fwupdate) both run as root and would
directly use this interface.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05  7:16   ` Greg KH
@ 2017-10-05 14:35       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 14:35 UTC (permalink / raw)
  To: greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:16 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> On Wed, Oct 04, 2017 at 05:48:38PM -0500, Mario Limonciello wrote:
> > For WMI operations that are only Set or Query read or write sysfs
> > attributes created by WMI vendor drivers make sense.
> >
> > For other WMI operations that are run on Method, there needs to be a
> > way to guarantee to userspace that the results from the method call
> > belong to the data request to the method call.  Sysfs attributes don't
> > work well in this scenario because two userspace processes may be
> > competing at reading/writing an attribute and step on each other's
> > data.
> 
> And you protect this from happening in the ioctl?  I didn't see it, but
> ok, I'll take your word for it :)

The ioctl does take a mutex.

> 
> > When a WMI vendor driver declares an ioctl in a file_operations object
> > the WMI bus driver will create a character device that maps to those
> > file operations.
> >
> > That character device will correspond to this path:
> > /dev/wmi/$driver
> >
> > The WMI bus driver will interpret the IOCTL calls, test them for
> > a valid instance and pass them on to the vendor driver to run.
> >
> > This creates an implicit policy that only driver per character
> > device.  If a module matches multiple GUID's, the wmi_devices
> > will need to be all handled by the same wmi_driver if the same
> > character device is used.
> 
> Interesting "way out" but ok, I can buy it...
> 
> > The WMI vendor drivers will be responsible for managing access to
> > this character device and proper locking on it.
> >
> > When a WMI vendor driver is unloaded the WMI bus driver will clean
> > up the character device.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> > ---
> >  MAINTAINERS                |  1 +
> >  drivers/platform/x86/wmi.c | 67
> +++++++++++++++++++++++++++++++++++++++++++++-
> >  include/linux/wmi.h        |  2 ++
> >  include/uapi/linux/wmi.h   | 10 +++++++
> >  4 files changed, 79 insertions(+), 1 deletion(-)
> >  create mode 100644 include/uapi/linux/wmi.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 0357e9b1cfaf..6db1d84999bc 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -372,6 +372,7 @@ ACPI WMI DRIVER
> >  L:	platform-driver-x86@vger.kernel.org
> >  S:	Orphan
> >  F:	drivers/platform/x86/wmi.c
> > +F:	include/uapi/linux/wmi.h
> >
> >  AD1889 ALSA SOUND DRIVER
> >  M:	Thibaut Varene <T-Bone@parisc-linux.org>
> > diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
> > index bcb41c1c7f52..5aef052b4aab 100644
> > --- a/drivers/platform/x86/wmi.c
> > +++ b/drivers/platform/x86/wmi.c
> > @@ -38,6 +38,7 @@
> >  #include <linux/init.h>
> >  #include <linux/kernel.h>
> >  #include <linux/list.h>
> > +#include <linux/miscdevice.h>
> >  #include <linux/module.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/slab.h>
> > @@ -69,6 +70,7 @@ struct wmi_block {
> >  	struct wmi_device dev;
> >  	struct list_head list;
> >  	struct guid_block gblock;
> > +	struct miscdevice misc_dev;
> >  	struct acpi_device *acpi_device;
> >  	wmi_notify_handler handler;
> >  	void *handler_data;
> > @@ -765,22 +767,80 @@ static int wmi_dev_match(struct device *dev, struct
> device_driver *driver)
> >  	return 0;
> >  }
> >
> > +static long wmi_ioctl(struct file *filp, unsigned int cmd,
> > +		      unsigned long arg)
> > +{
> > +	struct wmi_driver *wdriver;
> > +	struct wmi_block *wblock;
> > +	const char *driver_name;
> > +	struct list_head *p;
> > +	bool found = false;
> > +
> > +	if (_IOC_TYPE(cmd) != WMI_IOC)
> > +		return -ENOTTY;
> > +
> > +	driver_name = filp->f_path.dentry->d_iname;
> > +
> > +	list_for_each(p, &wmi_block_list) {
> > +		wblock = list_entry(p, struct wmi_block, list);
> > +		wdriver = container_of(wblock->dev.dev.driver,
> > +			struct wmi_driver, driver);
> > +		if (strcmp(driver_name, wdriver->driver.name) == 0) {
> > +			found = true;
> > +			break;
> > +		}
> > +	}
> 
> You can provide an open() call to handle this type of logic for you, so
> you don't have to do it on every ioctl() call, but I guess it's not
> really a big deal, right?
> 
> > +	if (!found ||
> > +	    !wdriver->file_operations ||
> > +	    !wdriver->file_operations->unlocked_ioctl)
> > +		return -ENODEV;
> 
> Shouldn't you check for unlocked_ioctl() already?  No need to check it
> here, right?

You're right.  I'll move the check earlier in the initialization.

> 
> And if you are only passing down unlocked_ioctl, there's no need for a
> whole empty file_operations structure in the driver, right?  Just have
> an ioctl callback to make things smaller and simpler to understand.
> 

> > +	/* make sure we're not calling a higher instance */
> > +	if (_IOC_NR(cmd) > wblock->gblock.instance_count)
> > +		return -EINVAL;
> 
> What exactly does this protect from?

I'll clarify the comment, but essentially if userspace tries to make
an ioctl call on an instance that doesn't exist it should fail.

> 
> > +	/* driver wants a character device made */
> > +	if (wdriver->file_operations) {
> 
> Check for unlocked_ioctl here, actually, drop the file_operations
> entirely, and just have that one callback.

OK.

> 
> > +		buf = kmalloc(strlen(wdriver->driver.name) + 4, GFP_KERNEL);
> > +		if (!buf)
> > +			return -ENOMEM;
> 
> No unwinding of other logic needed?

There shouldn't be.  The stuff earlier is optional.

> 
> > +		strcpy(buf, "wmi/");
> > +		strcpy(buf + 4, wdriver->driver.name);
> > +		wblock->misc_dev.minor = MISC_DYNAMIC_MINOR;
> > +		wblock->misc_dev.name = buf;
> > +		wblock->misc_dev.fops = &wmi_fops;
> > +		ret = misc_register(&wblock->misc_dev);
> > +		if (ret) {
> > +			dev_warn(dev, "failed to register char dev: %d", ret);
> > +			kfree(buf);
> 
> Again, no unwinding needed?  Error message value returned?

It comes down to if the character device should be considered optional.  I'll
make it fail if it can't create it.

> 
> > +		}
> > +	}
> > +
> >  	if (wdriver->probe) {
> >  		ret = wdriver->probe(dev_to_wdev(dev));
> >  		if (ret != 0 && ACPI_FAILURE(wmi_method_enable(wblock, 0)))
> >  			dev_warn(dev, "failed to disable device\n");
> >  	}
> > -
> >  	return ret;
> >  }
> >
> > @@ -791,6 +851,11 @@ static int wmi_dev_remove(struct device *dev)
> >  		container_of(dev->driver, struct wmi_driver, driver);
> >  	int ret = 0;
> >
> > +	if (wdriver->file_operations) {
> > +		kfree(wblock->misc_dev.name);
> > +		misc_deregister(&wblock->misc_dev);
> 
> Unregister before freeing the device name, right?

Well if you unregister and then free the name you'll have lost the pointer.
So isn't that the right order?

> 
> > --- /dev/null
> > +++ b/include/uapi/linux/wmi.h
> > @@ -0,0 +1,10 @@
> > +#ifndef _UAPI_LINUX_WMI_H
> > +#define _UAPI_LINUX_WMI_H
> > +
> > +#define WMI_IOC 'W'
> > +#define WMI_IO(instance)	_IO(WMI_IOC, instance)
> > +#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
> > +#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
> > +#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)
> 
> Ugh, void *, this is going to be "fun"...
> 
> My comments on just how fun is left for the actual driver that attempted
> to implement these...
> 

So until in kernel MOF parsing is available you can't predict the format of
what an individual ACPI method will expect for its input.  Even when the in
kernel MOF parsing is made available the data types may be complex structures.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
@ 2017-10-05 14:35       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 14:35 UTC (permalink / raw)
  To: greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:16 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> On Wed, Oct 04, 2017 at 05:48:38PM -0500, Mario Limonciello wrote:
> > For WMI operations that are only Set or Query read or write sysfs
> > attributes created by WMI vendor drivers make sense.
> >
> > For other WMI operations that are run on Method, there needs to be a
> > way to guarantee to userspace that the results from the method call
> > belong to the data request to the method call.  Sysfs attributes don't
> > work well in this scenario because two userspace processes may be
> > competing at reading/writing an attribute and step on each other's
> > data.
> 
> And you protect this from happening in the ioctl?  I didn't see it, but
> ok, I'll take your word for it :)

The ioctl does take a mutex.

> 
> > When a WMI vendor driver declares an ioctl in a file_operations object
> > the WMI bus driver will create a character device that maps to those
> > file operations.
> >
> > That character device will correspond to this path:
> > /dev/wmi/$driver
> >
> > The WMI bus driver will interpret the IOCTL calls, test them for
> > a valid instance and pass them on to the vendor driver to run.
> >
> > This creates an implicit policy that only driver per character
> > device.  If a module matches multiple GUID's, the wmi_devices
> > will need to be all handled by the same wmi_driver if the same
> > character device is used.
> 
> Interesting "way out" but ok, I can buy it...
> 
> > The WMI vendor drivers will be responsible for managing access to
> > this character device and proper locking on it.
> >
> > When a WMI vendor driver is unloaded the WMI bus driver will clean
> > up the character device.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> > ---
> >  MAINTAINERS                |  1 +
> >  drivers/platform/x86/wmi.c | 67
> +++++++++++++++++++++++++++++++++++++++++++++-
> >  include/linux/wmi.h        |  2 ++
> >  include/uapi/linux/wmi.h   | 10 +++++++
> >  4 files changed, 79 insertions(+), 1 deletion(-)
> >  create mode 100644 include/uapi/linux/wmi.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 0357e9b1cfaf..6db1d84999bc 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -372,6 +372,7 @@ ACPI WMI DRIVER
> >  L:	platform-driver-x86@vger.kernel.org
> >  S:	Orphan
> >  F:	drivers/platform/x86/wmi.c
> > +F:	include/uapi/linux/wmi.h
> >
> >  AD1889 ALSA SOUND DRIVER
> >  M:	Thibaut Varene <T-Bone@parisc-linux.org>
> > diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
> > index bcb41c1c7f52..5aef052b4aab 100644
> > --- a/drivers/platform/x86/wmi.c
> > +++ b/drivers/platform/x86/wmi.c
> > @@ -38,6 +38,7 @@
> >  #include <linux/init.h>
> >  #include <linux/kernel.h>
> >  #include <linux/list.h>
> > +#include <linux/miscdevice.h>
> >  #include <linux/module.h>
> >  #include <linux/platform_device.h>
> >  #include <linux/slab.h>
> > @@ -69,6 +70,7 @@ struct wmi_block {
> >  	struct wmi_device dev;
> >  	struct list_head list;
> >  	struct guid_block gblock;
> > +	struct miscdevice misc_dev;
> >  	struct acpi_device *acpi_device;
> >  	wmi_notify_handler handler;
> >  	void *handler_data;
> > @@ -765,22 +767,80 @@ static int wmi_dev_match(struct device *dev, struct
> device_driver *driver)
> >  	return 0;
> >  }
> >
> > +static long wmi_ioctl(struct file *filp, unsigned int cmd,
> > +		      unsigned long arg)
> > +{
> > +	struct wmi_driver *wdriver;
> > +	struct wmi_block *wblock;
> > +	const char *driver_name;
> > +	struct list_head *p;
> > +	bool found = false;
> > +
> > +	if (_IOC_TYPE(cmd) != WMI_IOC)
> > +		return -ENOTTY;
> > +
> > +	driver_name = filp->f_path.dentry->d_iname;
> > +
> > +	list_for_each(p, &wmi_block_list) {
> > +		wblock = list_entry(p, struct wmi_block, list);
> > +		wdriver = container_of(wblock->dev.dev.driver,
> > +			struct wmi_driver, driver);
> > +		if (strcmp(driver_name, wdriver->driver.name) == 0) {
> > +			found = true;
> > +			break;
> > +		}
> > +	}
> 
> You can provide an open() call to handle this type of logic for you, so
> you don't have to do it on every ioctl() call, but I guess it's not
> really a big deal, right?
> 
> > +	if (!found ||
> > +	    !wdriver->file_operations ||
> > +	    !wdriver->file_operations->unlocked_ioctl)
> > +		return -ENODEV;
> 
> Shouldn't you check for unlocked_ioctl() already?  No need to check it
> here, right?

You're right.  I'll move the check earlier in the initialization.

> 
> And if you are only passing down unlocked_ioctl, there's no need for a
> whole empty file_operations structure in the driver, right?  Just have
> an ioctl callback to make things smaller and simpler to understand.
> 

> > +	/* make sure we're not calling a higher instance */
> > +	if (_IOC_NR(cmd) > wblock->gblock.instance_count)
> > +		return -EINVAL;
> 
> What exactly does this protect from?

I'll clarify the comment, but essentially if userspace tries to make
an ioctl call on an instance that doesn't exist it should fail.

> 
> > +	/* driver wants a character device made */
> > +	if (wdriver->file_operations) {
> 
> Check for unlocked_ioctl here, actually, drop the file_operations
> entirely, and just have that one callback.

OK.

> 
> > +		buf = kmalloc(strlen(wdriver->driver.name) + 4, GFP_KERNEL);
> > +		if (!buf)
> > +			return -ENOMEM;
> 
> No unwinding of other logic needed?

There shouldn't be.  The stuff earlier is optional.

> 
> > +		strcpy(buf, "wmi/");
> > +		strcpy(buf + 4, wdriver->driver.name);
> > +		wblock->misc_dev.minor = MISC_DYNAMIC_MINOR;
> > +		wblock->misc_dev.name = buf;
> > +		wblock->misc_dev.fops = &wmi_fops;
> > +		ret = misc_register(&wblock->misc_dev);
> > +		if (ret) {
> > +			dev_warn(dev, "failed to register char dev: %d", ret);
> > +			kfree(buf);
> 
> Again, no unwinding needed?  Error message value returned?

It comes down to if the character device should be considered optional.  I'll
make it fail if it can't create it.

> 
> > +		}
> > +	}
> > +
> >  	if (wdriver->probe) {
> >  		ret = wdriver->probe(dev_to_wdev(dev));
> >  		if (ret != 0 && ACPI_FAILURE(wmi_method_enable(wblock, 0)))
> >  			dev_warn(dev, "failed to disable device\n");
> >  	}
> > -
> >  	return ret;
> >  }
> >
> > @@ -791,6 +851,11 @@ static int wmi_dev_remove(struct device *dev)
> >  		container_of(dev->driver, struct wmi_driver, driver);
> >  	int ret = 0;
> >
> > +	if (wdriver->file_operations) {
> > +		kfree(wblock->misc_dev.name);
> > +		misc_deregister(&wblock->misc_dev);
> 
> Unregister before freeing the device name, right?

Well if you unregister and then free the name you'll have lost the pointer.
So isn't that the right order?

> 
> > --- /dev/null
> > +++ b/include/uapi/linux/wmi.h
> > @@ -0,0 +1,10 @@
> > +#ifndef _UAPI_LINUX_WMI_H
> > +#define _UAPI_LINUX_WMI_H
> > +
> > +#define WMI_IOC 'W'
> > +#define WMI_IO(instance)	_IO(WMI_IOC, instance)
> > +#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
> > +#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
> > +#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)
> 
> Ugh, void *, this is going to be "fun"...
> 
> My comments on just how fun is left for the actual driver that attempted
> to implement these...
> 

So until in kernel MOF parsing is available you can't predict the format of
what an individual ACPI method will expect for its input.  Even when the in
kernel MOF parsing is made available the data types may be complex structures.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05 14:14             ` Darren Hart
@ 2017-10-05 14:47                 ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 14:47 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 9:15 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 05, 2017 at 01:59:36PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> > > Sent: Thursday, October 5, 2017 3:48 AM
> > > To: Darren Hart <dvhart@infradead.org>
> > > Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-
> > > kernel@vger.kernel.org>; Platform Driver <platform-driver-
> > > x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> > > quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> > > <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> > > Greg KH <greg@kroah.com>
> > > Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> > > descriptor into it's own driver
> > >
> > > On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> > > > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> > > >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org>
> wrote:
> > >
> > > >> > You'll want to add something like:
> > > >> >
> > > >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> > > >> >         if (request_module("dell_wmi_descriptor"))
> > > >> >                 /* FAIL */
> > > >> > #endif
> > > >> >
> > > >> > During init.
> > > >>
> > > >> I don't think #ifdef is needed.
> > > >
> > > > Without the ifdef, we can't distinguish between request_module failing
> > > > to load the module because it isn't available and because it is
> > > > built-in.
> > > >
> > > >>
> > > >> We may just request module.
> > > >>
> > > >> But looking in the code it seems that we simple need to select that
> > > >> module. No request_module will be needed.
> > > >
> > > > The select will ensure the module is built, but there is not guarantee
> > > > to module load order. The intent of the above is to ensure the symbols
> > > > from the required module are loaded.
> > > >
> > > >> Did I miss something?
> > > >
> > > > Or I did :-) Is there something about this module which ensures
> > > > dell_wmi_descriptor is loaded first?
> > >
> > > If there is an optional *run-time* dependency we need to use somelike
> > > request_module(). For example, this is the case for idma64
> > > (drivers/dma) vs intel-lpss (drivers/mfd).
> > >
> > > If it's mandatory run-time dependency, then we need to add stubs to
> > > the header and select the callee's module in Kconfig.
> > >
> > > In case they are both modules, depmod keeps an ordering.
> > >
> > > So, the corner case here is when the caller is builtin while callee is module.
> > >
> > > This is a bit tricky to add to Kconfig (we also have such cases
> > > between I2C DesignWare and acpi_lpss AFAIR).
> > >
> > > --
> > > With Best Regards,
> > > Andy Shevchenko
> >
> > So I believe it should be a mandatory runtime dependency due to needing
> > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > this then no?
> 
> This was nagging me all night, and I was thinking the last time I had to
> use this it was indeed a runtime dependency. Sorry for the noise on
> this.
> 
> The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> module if the dependent drivers are modules.
> 
> --
> Darren Hart
> VMware Open Source Technology Center

Even if the others are modules shouldn't module ordering from depmod still DTRT?
You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was loaded.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
@ 2017-10-05 14:47                 ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 14:47 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 9:15 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 05, 2017 at 01:59:36PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> > > Sent: Thursday, October 5, 2017 3:48 AM
> > > To: Darren Hart <dvhart@infradead.org>
> > > Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; LKML <linux-
> > > kernel@vger.kernel.org>; Platform Driver <platform-driver-
> > > x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> > > quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> > > <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> > > Greg KH <greg@kroah.com>
> > > Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> > > descriptor into it's own driver
> > >
> > > On Thu, Oct 5, 2017 at 10:11 AM, Darren Hart <dvhart@infradead.org> wrote:
> > > > On Thu, Oct 05, 2017 at 08:29:10AM +0300, Andy Shevchenko wrote:
> > > >> On Thu, Oct 5, 2017 at 4:09 AM, Darren Hart <dvhart@infradead.org>
> wrote:
> > >
> > > >> > You'll want to add something like:
> > > >> >
> > > >> > #ifdef CONFIG_DELL_WMI_DESCRIPTOR_MODULE
> > > >> >         if (request_module("dell_wmi_descriptor"))
> > > >> >                 /* FAIL */
> > > >> > #endif
> > > >> >
> > > >> > During init.
> > > >>
> > > >> I don't think #ifdef is needed.
> > > >
> > > > Without the ifdef, we can't distinguish between request_module failing
> > > > to load the module because it isn't available and because it is
> > > > built-in.
> > > >
> > > >>
> > > >> We may just request module.
> > > >>
> > > >> But looking in the code it seems that we simple need to select that
> > > >> module. No request_module will be needed.
> > > >
> > > > The select will ensure the module is built, but there is not guarantee
> > > > to module load order. The intent of the above is to ensure the symbols
> > > > from the required module are loaded.
> > > >
> > > >> Did I miss something?
> > > >
> > > > Or I did :-) Is there something about this module which ensures
> > > > dell_wmi_descriptor is loaded first?
> > >
> > > If there is an optional *run-time* dependency we need to use somelike
> > > request_module(). For example, this is the case for idma64
> > > (drivers/dma) vs intel-lpss (drivers/mfd).
> > >
> > > If it's mandatory run-time dependency, then we need to add stubs to
> > > the header and select the callee's module in Kconfig.
> > >
> > > In case they are both modules, depmod keeps an ordering.
> > >
> > > So, the corner case here is when the caller is builtin while callee is module.
> > >
> > > This is a bit tricky to add to Kconfig (we also have such cases
> > > between I2C DesignWare and acpi_lpss AFAIR).
> > >
> > > --
> > > With Best Regards,
> > > Andy Shevchenko
> >
> > So I believe it should be a mandatory runtime dependency due to needing
> > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > this then no?
> 
> This was nagging me all night, and I was thinking the last time I had to
> use this it was indeed a runtime dependency. Sorry for the noise on
> this.
> 
> The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> module if the dependent drivers are modules.
> 
> --
> Darren Hart
> VMware Open Source Technology Center

Even if the others are modules shouldn't module ordering from depmod still DTRT?
You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was loaded.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures
  2017-10-05  5:20   ` Andy Shevchenko
@ 2017-10-05 15:02       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 15:02 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: dvhart, linux-kernel, platform-driver-x86, luto, quasisec,
	pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 12:21 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some
> failures
> 
> On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
> <mario.limonciello@dell.com> wrote:
> > There is a lot of error checking in place for the format of the WMI
> > descriptor buffer, but some of the potentially raised issues should
> > be considered critical failures.
> >
> > If the buffer size or header don't match, this is a good indication
> > that the buffer format changed in a way that the rest of the data
> > should not be relied upon.
> >
> > For the remaining data set vectors, continue to notate a warning
> > in undefined results, but as those are fields that the descriptor
> > intended to refer to other applications, don't fail if they're new
> > values.
> 
> > -       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0)
> > -               dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature
> (%8ph)\n",
> > +       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
> > +               dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature
> (%8ph)\n",
> 
> A nit: ping-pong programming detected.
> Looks like current patch 2 should go at least after this one.
> 
> 
> --

I'll re-order them, but either way both patches are touching these lines in some
way.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures
@ 2017-10-05 15:02       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 15:02 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: dvhart, linux-kernel, platform-driver-x86, luto, quasisec,
	pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 12:21 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some
> failures
> 
> On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
> <mario.limonciello@dell.com> wrote:
> > There is a lot of error checking in place for the format of the WMI
> > descriptor buffer, but some of the potentially raised issues should
> > be considered critical failures.
> >
> > If the buffer size or header don't match, this is a good indication
> > that the buffer format changed in a way that the rest of the data
> > should not be relied upon.
> >
> > For the remaining data set vectors, continue to notate a warning
> > in undefined results, but as those are fields that the descriptor
> > intended to refer to other applications, don't fail if they're new
> > values.
> 
> > -       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0)
> > -               dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature
> (%8ph)\n",
> > +       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
> > +               dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature
> (%8ph)\n",
> 
> A nit: ping-pong programming detected.
> Looks like current patch 2 should go at least after this one.
> 
> 
> --

I'll re-order them, but either way both patches are touching these lines in some
way.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls
  2017-10-05  1:57   ` Darren Hart
@ 2017-10-05 15:04       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 15:04 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Wednesday, October 4, 2017 8:58 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: Andy Shevchenko <andy.shevchenko@gmail.com>; LKML <linux-
> kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org; Andy Lutomirski
> <luto@kernel.org>; quasisec@google.com; pali.rohar@gmail.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg KH
> <greg@kroah.com>
> Subject: Re: [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for
> SMM calls
> 
> On Wed, Oct 04, 2017 at 05:48:35PM -0500, Mario Limonciello wrote:
> > This splits up the dell-smbios driver into two drivers:
> > * dell-smbios
> > * dell-smbios-smm
> >
> > dell-smbios can operate with multiple different dispatcher drivers to
> > perform SMBIOS operations.
> >
> > Also modify the interface that dell-laptop and dell-wmi use align to this
> > model more closely.  Rather than a single global buffer being allocated
> > for all drivers, each driver will allocate and be responsible for it's own
> > buffer. The pointer will be passed to the calling function and each
> > dispatcher driver will then internally copy it to the proper location to
> > perform it's call.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> > ---
> >  MAINTAINERS                            |   6 ++
> >  drivers/platform/x86/Kconfig           |  17 ++-
> >  drivers/platform/x86/Makefile          |   1 +
> >  drivers/platform/x86/dell-laptop.c     | 191 ++++++++++++++++-----------------
> >  drivers/platform/x86/dell-smbios-smm.c | 136 +++++++++++++++++++++++
> >  drivers/platform/x86/dell-smbios-smm.h |  22 ++++
> >  drivers/platform/x86/dell-smbios.c     | 120 +++++++++++++--------
> >  drivers/platform/x86/dell-smbios.h     |  13 ++-
> >  drivers/platform/x86/dell-wmi.c        |   8 +-
> >  9 files changed, 361 insertions(+), 153 deletions(-)
> >  create mode 100644 drivers/platform/x86/dell-smbios-smm.c
> >  create mode 100644 drivers/platform/x86/dell-smbios-smm.h
> >
> ...
> 
> > +config DELL_SMBIOS_SMM
> > +       tristate "Dell SMBIOS calling interface (SMM implementation)"
> > +       depends on DCDBAS
> > +       default DCDBAS
> > +       select DELL_SMBIOS
> > +       ---help---
> > +       This provides an implementation for the Dell SMBIOS calling interface
> > +       communicated over ACPI-WMI.
> 
> Not over ACPI-WMI... over SMM.... right?

Yep, copy paste error.

> 
> 
> 
> > diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-
> laptop.c
> > index f42159fd2031..c648bbfcc394 100644
> > --- a/drivers/platform/x86/dell-laptop.c
> > +++ b/drivers/platform/x86/dell-laptop.c
> > @@ -85,6 +85,7 @@ static struct platform_driver platform_driver = {
> >  	}
> >  };
> >
> > +static struct calling_interface_buffer *buffer;
> >  static struct platform_device *platform_device;
> >  static struct backlight_device *dell_backlight_device;
> >  static struct rfkill *wifi_rfkill;
> > @@ -405,7 +406,6 @@ static const struct dmi_system_id dell_quirks[]
> __initconst = {
> >
> >  static int dell_rfkill_set(void *data, bool blocked)
> >  {
> > -	struct calling_interface_buffer *buffer;
> >  	int disable = blocked ? 1 : 0;
> >  	unsigned long radio = (unsigned long)data;
> >  	int hwswitch_bit = (unsigned long)data - 1;
> > @@ -413,19 +413,21 @@ static int dell_rfkill_set(void *data, bool blocked)
> >  	int status;
> >  	int ret;
> >
> > -	buffer = dell_smbios_get_buffer();
> > -
> > -	dell_smbios_send_request(17, 11);
> > +	memset(buffer, 0, sizeof(struct calling_interface_buffer));
> > +	buffer->class = 17;
> > +	buffer->select = 11;
> 
> Please move these three lines into a function, it's used far far too
> often to be open coded. The dell_smbios_send_request is a reasonable
> wrapper which you could just define here as well. This would minimize
> the change to the driver.
> 
OK I'll clean this up and make some functions.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls
@ 2017-10-05 15:04       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 15:04 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Wednesday, October 4, 2017 8:58 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: Andy Shevchenko <andy.shevchenko@gmail.com>; LKML <linux-
> kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org; Andy Lutomirski
> <luto@kernel.org>; quasisec@google.com; pali.rohar@gmail.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg KH
> <greg@kroah.com>
> Subject: Re: [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for
> SMM calls
> 
> On Wed, Oct 04, 2017 at 05:48:35PM -0500, Mario Limonciello wrote:
> > This splits up the dell-smbios driver into two drivers:
> > * dell-smbios
> > * dell-smbios-smm
> >
> > dell-smbios can operate with multiple different dispatcher drivers to
> > perform SMBIOS operations.
> >
> > Also modify the interface that dell-laptop and dell-wmi use align to this
> > model more closely.  Rather than a single global buffer being allocated
> > for all drivers, each driver will allocate and be responsible for it's own
> > buffer. The pointer will be passed to the calling function and each
> > dispatcher driver will then internally copy it to the proper location to
> > perform it's call.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> > ---
> >  MAINTAINERS                            |   6 ++
> >  drivers/platform/x86/Kconfig           |  17 ++-
> >  drivers/platform/x86/Makefile          |   1 +
> >  drivers/platform/x86/dell-laptop.c     | 191 ++++++++++++++++-----------------
> >  drivers/platform/x86/dell-smbios-smm.c | 136 +++++++++++++++++++++++
> >  drivers/platform/x86/dell-smbios-smm.h |  22 ++++
> >  drivers/platform/x86/dell-smbios.c     | 120 +++++++++++++--------
> >  drivers/platform/x86/dell-smbios.h     |  13 ++-
> >  drivers/platform/x86/dell-wmi.c        |   8 +-
> >  9 files changed, 361 insertions(+), 153 deletions(-)
> >  create mode 100644 drivers/platform/x86/dell-smbios-smm.c
> >  create mode 100644 drivers/platform/x86/dell-smbios-smm.h
> >
> ...
> 
> > +config DELL_SMBIOS_SMM
> > +       tristate "Dell SMBIOS calling interface (SMM implementation)"
> > +       depends on DCDBAS
> > +       default DCDBAS
> > +       select DELL_SMBIOS
> > +       ---help---
> > +       This provides an implementation for the Dell SMBIOS calling interface
> > +       communicated over ACPI-WMI.
> 
> Not over ACPI-WMI... over SMM.... right?

Yep, copy paste error.

> 
> 
> 
> > diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-
> laptop.c
> > index f42159fd2031..c648bbfcc394 100644
> > --- a/drivers/platform/x86/dell-laptop.c
> > +++ b/drivers/platform/x86/dell-laptop.c
> > @@ -85,6 +85,7 @@ static struct platform_driver platform_driver = {
> >  	}
> >  };
> >
> > +static struct calling_interface_buffer *buffer;
> >  static struct platform_device *platform_device;
> >  static struct backlight_device *dell_backlight_device;
> >  static struct rfkill *wifi_rfkill;
> > @@ -405,7 +406,6 @@ static const struct dmi_system_id dell_quirks[]
> __initconst = {
> >
> >  static int dell_rfkill_set(void *data, bool blocked)
> >  {
> > -	struct calling_interface_buffer *buffer;
> >  	int disable = blocked ? 1 : 0;
> >  	unsigned long radio = (unsigned long)data;
> >  	int hwswitch_bit = (unsigned long)data - 1;
> > @@ -413,19 +413,21 @@ static int dell_rfkill_set(void *data, bool blocked)
> >  	int status;
> >  	int ret;
> >
> > -	buffer = dell_smbios_get_buffer();
> > -
> > -	dell_smbios_send_request(17, 11);
> > +	memset(buffer, 0, sizeof(struct calling_interface_buffer));
> > +	buffer->class = 17;
> > +	buffer->select = 11;
> 
> Please move these three lines into a function, it's used far far too
> often to be open coded. The dell_smbios_send_request is a reasonable
> wrapper which you could just define here as well. This would minimize
> the change to the driver.
> 
OK I'll clean this up and make some functions.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  2017-10-05  2:14   ` Darren Hart
@ 2017-10-05 15:12       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 15:12 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Wednesday, October 4, 2017 9:15 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: Andy Shevchenko <andy.shevchenko@gmail.com>; LKML <linux-
> kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org; Andy Lutomirski
> <luto@kernel.org>; quasisec@google.com; pali.rohar@gmail.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg KH
> <greg@kroah.com>
> Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> dispatcher driver
> 
> On Wed, Oct 04, 2017 at 05:48:37PM -0500, Mario Limonciello wrote:
> > The dell-smbios stack only currently uses an SMI interface which grants
> > direct access to physical memory to the firmware SMM methods via a pointer.
> >
> > This dispatcher driver adds a WMI-ACPI interface that is detected by WMI
> > probe and preferred over the SMI interface in dell-smbios.
> >
> > Changing this to operate over WMI-ACPI will use an ACPI OperationRegion
> > for a buffer of data storage when SMM calls are performed.
> >
> > This is a safer approach to use in kernel drivers as the SMM will
> > only have access to that OperationRegion.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> > ---
> >  MAINTAINERS                            |   6 +
> >  drivers/platform/x86/Kconfig           |  16 ++-
> >  drivers/platform/x86/Makefile          |   1 +
> >  drivers/platform/x86/dell-smbios-wmi.c | 215
> +++++++++++++++++++++++++++++++++
> >  drivers/platform/x86/dell-smbios-wmi.h |  28 +++++
> >  5 files changed, 265 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/platform/x86/dell-smbios-wmi.c
> >  create mode 100644 drivers/platform/x86/dell-smbios-wmi.h
> >
> ...
> > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > index f0b97cb8e449..ef597f440d2e 100644
> > --- a/drivers/platform/x86/Kconfig
> > +++ b/drivers/platform/x86/Kconfig
> > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> >
> >  config DELL_SMBIOS
> >  	tristate "Dell SMBIOS calling interface"
> > -	depends on DELL_SMBIOS_SMM
> > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> >  	---help---
> >  	This module provides common functions for kernel modules using
> >  	Dell SMBIOS.
> 
> You use select DELL_SMBIOS below, which implies this modules should be
> invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> option at all now, they can select DELL_SMBIOS_WMI and or
> DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> 
So when you say make invisible, does that mean that it should never show
up in make menuconfig and just be implicitly selected?

When I was adjusting Kconfig for your other feedback I noticed setting something
to "select $DRIVER" that invisible driver does show up just can't be turned off.
Is that what you mean?

> > diff --git a/drivers/platform/x86/dell-smbios-wmi.c
> b/drivers/platform/x86/dell-smbios-wmi.c
> > +static void __init parse_b1_table(const struct dmi_header *dm)
> > +{
> > +	struct misc_bios_flags_structure *flags =
> > +	container_of(dm, struct misc_bios_flags_structure, header);
> > +
> > +	/* 4 bytes header, and one word of flags */
> 
> Assuming specifically 8 bytes of flags, independent of arch?

Well platform/drivers/*x86*...

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
@ 2017-10-05 15:12       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 15:12 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Wednesday, October 4, 2017 9:15 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: Andy Shevchenko <andy.shevchenko@gmail.com>; LKML <linux-
> kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org; Andy Lutomirski
> <luto@kernel.org>; quasisec@google.com; pali.rohar@gmail.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg KH
> <greg@kroah.com>
> Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> dispatcher driver
> 
> On Wed, Oct 04, 2017 at 05:48:37PM -0500, Mario Limonciello wrote:
> > The dell-smbios stack only currently uses an SMI interface which grants
> > direct access to physical memory to the firmware SMM methods via a pointer.
> >
> > This dispatcher driver adds a WMI-ACPI interface that is detected by WMI
> > probe and preferred over the SMI interface in dell-smbios.
> >
> > Changing this to operate over WMI-ACPI will use an ACPI OperationRegion
> > for a buffer of data storage when SMM calls are performed.
> >
> > This is a safer approach to use in kernel drivers as the SMM will
> > only have access to that OperationRegion.
> >
> > Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
> > ---
> >  MAINTAINERS                            |   6 +
> >  drivers/platform/x86/Kconfig           |  16 ++-
> >  drivers/platform/x86/Makefile          |   1 +
> >  drivers/platform/x86/dell-smbios-wmi.c | 215
> +++++++++++++++++++++++++++++++++
> >  drivers/platform/x86/dell-smbios-wmi.h |  28 +++++
> >  5 files changed, 265 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/platform/x86/dell-smbios-wmi.c
> >  create mode 100644 drivers/platform/x86/dell-smbios-wmi.h
> >
> ...
> > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > index f0b97cb8e449..ef597f440d2e 100644
> > --- a/drivers/platform/x86/Kconfig
> > +++ b/drivers/platform/x86/Kconfig
> > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> >
> >  config DELL_SMBIOS
> >  	tristate "Dell SMBIOS calling interface"
> > -	depends on DELL_SMBIOS_SMM
> > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> >  	---help---
> >  	This module provides common functions for kernel modules using
> >  	Dell SMBIOS.
> 
> You use select DELL_SMBIOS below, which implies this modules should be
> invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> option at all now, they can select DELL_SMBIOS_WMI and or
> DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> 
So when you say make invisible, does that mean that it should never show
up in make menuconfig and just be implicitly selected?

When I was adjusting Kconfig for your other feedback I noticed setting something
to "select $DRIVER" that invisible driver does show up just can't be turned off.
Is that what you mean?

> > diff --git a/drivers/platform/x86/dell-smbios-wmi.c
> b/drivers/platform/x86/dell-smbios-wmi.c
> > +static void __init parse_b1_table(const struct dmi_header *dm)
> > +{
> > +	struct misc_bios_flags_structure *flags =
> > +	container_of(dm, struct misc_bios_flags_structure, header);
> > +
> > +	/* 4 bytes header, and one word of flags */
> 
> Assuming specifically 8 bytes of flags, independent of arch?

Well platform/drivers/*x86*...

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 14:35       ` Mario.Limonciello
  (?)
@ 2017-10-05 15:42       ` Greg KH
  2017-10-05 15:51         ` Pali Rohár
  -1 siblings, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05 15:42 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 02:35:43PM +0000, Mario.Limonciello@dell.com wrote:
> > 
> > > +		strcpy(buf, "wmi/");
> > > +		strcpy(buf + 4, wdriver->driver.name);
> > > +		wblock->misc_dev.minor = MISC_DYNAMIC_MINOR;
> > > +		wblock->misc_dev.name = buf;
> > > +		wblock->misc_dev.fops = &wmi_fops;
> > > +		ret = misc_register(&wblock->misc_dev);
> > > +		if (ret) {
> > > +			dev_warn(dev, "failed to register char dev: %d", ret);
> > > +			kfree(buf);
> > 
> > Again, no unwinding needed?  Error message value returned?
> 
> It comes down to if the character device should be considered optional.  I'll
> make it fail if it can't create it.

Given that you are relying on it in this patch, it would be good to fail
if something is going wrong.

> > > +	if (wdriver->file_operations) {
> > > +		kfree(wblock->misc_dev.name);
> > > +		misc_deregister(&wblock->misc_dev);
> > 
> > Unregister before freeing the device name, right?
> 
> Well if you unregister and then free the name you'll have lost the pointer.
> So isn't that the right order?

Yes, but save the pointer to the name and then free it after the larger
structure is gone.  misc_deregister() does not free anything, so you
still have the memory around here, no need to even use a temp variable.

> > > --- /dev/null
> > > +++ b/include/uapi/linux/wmi.h
> > > @@ -0,0 +1,10 @@
> > > +#ifndef _UAPI_LINUX_WMI_H
> > > +#define _UAPI_LINUX_WMI_H
> > > +
> > > +#define WMI_IOC 'W'
> > > +#define WMI_IO(instance)	_IO(WMI_IOC, instance)
> > > +#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
> > > +#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
> > > +#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)
> > 
> > Ugh, void *, this is going to be "fun"...
> > 
> > My comments on just how fun is left for the actual driver that attempted
> > to implement these...
> > 
> 
> So until in kernel MOF parsing is available you can't predict the format of
> what an individual ACPI method will expect for its input.  Even when the in
> kernel MOF parsing is made available the data types may be complex structures.


I have no idea what MOF is, what "parsing" is involved, or how in the
world ACPI got involved here...

good luck!

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 14:22       ` Mario.Limonciello
  (?)
@ 2017-10-05 15:44       ` Greg KH
  2017-10-05 15:56         ` Pali Rohár
  -1 siblings, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05 15:44 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: gnomes, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, pali.rohar, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 02:22:37PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> > Sent: Thursday, October 5, 2017 8:59 AM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> > LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg
> > KH <greg@kroah.com>
> > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > userspace interface
> > 
> > On Wed,  4 Oct 2017 17:48:39 -0500
> > Mario Limonciello <mario.limonciello@dell.com> wrote:
> > 
> > > This userspace character device will be used to perform SMBIOS calls
> > > from any applications.
> > >
> > > It provides an ioctl that will allow passing the 32k WMI calling
> > > interface buffer between userspace and kernel space.
> > 
> > What is your security model for firing 32K of random crap at the BIOS ?
> 
> Adding new class and select methods requires a review with the security
> team.  They will do STRIDE analysis and threat modeling.
> 
> > Do you fuzz test the BIOS interface ?
> 
> Yes there has been internal fuzz testing classes and selects used in the 
> ACPI interface in the past.  I can't comment on how regularly that is done.
> I do think it's interesting is to use the interface in Linux for further fuzz
> testing though.

That should be simple, start firing random data at this memory location
and see what happens.  Can you brick the box?  Change the
manufactured-date?  Change the serial number?  Normally these types of
BIOS interfaces allow all sorts of "fun" things like this, which is why
we have the kernel "own" the interface, to protect yourself from
breaking the box.

> > How do we know that between now and the end of the universe every call is
> > safe to execute as any random user without upsetting other users on the
> > same PC ?
> 
> Any random user shouldn't be executing the ioctl.
> Only root should be executing any of these calls.

"only root" isn't the best protection method, you should know better :)

You are going to have to do some kind of parsing/whitelisting here,
trust us...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 15:42       ` Greg KH
@ 2017-10-05 15:51         ` Pali Rohár
  2017-10-05 16:26           ` Greg KH
  0 siblings, 1 reply; 93+ messages in thread
From: Pali Rohár @ 2017-10-05 15:51 UTC (permalink / raw)
  To: Greg KH
  Cc: Mario.Limonciello, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

On Thursday 05 October 2017 17:42:14 Greg KH wrote:
> > > > --- /dev/null
> > > > +++ b/include/uapi/linux/wmi.h
> > > > @@ -0,0 +1,10 @@
> > > > +#ifndef _UAPI_LINUX_WMI_H
> > > > +#define _UAPI_LINUX_WMI_H
> > > > +
> > > > +#define WMI_IOC 'W'
> > > > +#define WMI_IO(instance)	_IO(WMI_IOC, instance)
> > > > +#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
> > > > +#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
> > > > +#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)
> > > 
> > > Ugh, void *, this is going to be "fun"...
> > > 
> > > My comments on just how fun is left for the actual driver that attempted
> > > to implement these...
> > > 
> > 
> > So until in kernel MOF parsing is available you can't predict the format of
> > what an individual ACPI method will expect for its input.  Even when the in
> > kernel MOF parsing is made available the data types may be complex structures.
> 
> 
> I have no idea what MOF is, what "parsing" is involved, or how in the
> world ACPI got involved here...
> 
> good luck!
> 
> greg k-h

Hi Greg! Simple description: In ACPI is stored binary MOF buffer which
describe format (function name, parameters, sizeof and type of
parameters, etc) for all those calls.

Basically it is what should be used for checking if userspace pass
correct "buffer" via ioctl to WMI.

But that binary MOF is undocumented, invented by Microsoft... and
present in every one ACPI BIOS notebook (which uses WMI). It is
de-facto industrial standard, just tools for encoding/decoding it are
only for Microsoft Windows systems.

I was able to decipher that format and wrote simple userspace parser:
https://github.com/pali/bmfdec

Funny part is that format is not encrypted, but compressed by DMSDOS
compatible compression algorithm :-) You probably would remember old
FAT16 days with compression...

Hope that it helps you to understand it.

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 15:44       ` Greg KH
@ 2017-10-05 15:56         ` Pali Rohár
  2017-10-05 16:28           ` Greg KH
  0 siblings, 1 reply; 93+ messages in thread
From: Pali Rohár @ 2017-10-05 15:56 UTC (permalink / raw)
  To: Greg KH
  Cc: Mario.Limonciello, gnomes, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

On Thursday 05 October 2017 17:44:45 Greg KH wrote:
> On Thu, Oct 05, 2017 at 02:22:37PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> > > Sent: Thursday, October 5, 2017 8:59 AM
> > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> > > LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> > > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg
> > > KH <greg@kroah.com>
> > > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > > userspace interface
> > > 
> > > On Wed,  4 Oct 2017 17:48:39 -0500
> > > Mario Limonciello <mario.limonciello@dell.com> wrote:
> > > 
> > > > This userspace character device will be used to perform SMBIOS calls
> > > > from any applications.
> > > >
> > > > It provides an ioctl that will allow passing the 32k WMI calling
> > > > interface buffer between userspace and kernel space.
> > > 
> > > What is your security model for firing 32K of random crap at the BIOS ?
> > 
> > Adding new class and select methods requires a review with the security
> > team.  They will do STRIDE analysis and threat modeling.
> > 
> > > Do you fuzz test the BIOS interface ?
> > 
> > Yes there has been internal fuzz testing classes and selects used in the 
> > ACPI interface in the past.  I can't comment on how regularly that is done.
> > I do think it's interesting is to use the interface in Linux for further fuzz
> > testing though.
> 
> That should be simple, start firing random data at this memory location
> and see what happens.  Can you brick the box?  Change the
> manufactured-date?  Change the serial number?  Normally these types of
> BIOS interfaces allow all sorts of "fun" things like this, which is why
> we have the kernel "own" the interface, to protect yourself from
> breaking the box.

There are also Dell calls to "permanently disable TPM" and similar which
are irreversible. So this can be really a problem.

> > > How do we know that between now and the end of the universe every call is
> > > safe to execute as any random user without upsetting other users on the
> > > same PC ?
> > 
> > Any random user shouldn't be executing the ioctl.
> > Only root should be executing any of these calls.
> 
> "only root" isn't the best protection method, you should know better :)
> 
> You are going to have to do some kind of parsing/whitelisting here,
> trust us...

That is also why I in past suggested to create fully transparent
whitelisting filter for all WMI calls. And properly implement particular
filter in kernel...

But that is of course hard as you need to know all details of internal
structures and data which may be sent via userspace. To prevent e.g.
action "permanently disable TPM" in kernel.

> thanks,
> 
> greg k-h

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 15:51         ` Pali Rohár
@ 2017-10-05 16:26           ` Greg KH
  2017-10-05 17:39             ` Darren Hart
  0 siblings, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05 16:26 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Mario.Limonciello, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 05:51:56PM +0200, Pali Rohár wrote:
> On Thursday 05 October 2017 17:42:14 Greg KH wrote:
> > > > > --- /dev/null
> > > > > +++ b/include/uapi/linux/wmi.h
> > > > > @@ -0,0 +1,10 @@
> > > > > +#ifndef _UAPI_LINUX_WMI_H
> > > > > +#define _UAPI_LINUX_WMI_H
> > > > > +
> > > > > +#define WMI_IOC 'W'
> > > > > +#define WMI_IO(instance)	_IO(WMI_IOC, instance)
> > > > > +#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
> > > > > +#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
> > > > > +#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)
> > > > 
> > > > Ugh, void *, this is going to be "fun"...
> > > > 
> > > > My comments on just how fun is left for the actual driver that attempted
> > > > to implement these...
> > > > 
> > > 
> > > So until in kernel MOF parsing is available you can't predict the format of
> > > what an individual ACPI method will expect for its input.  Even when the in
> > > kernel MOF parsing is made available the data types may be complex structures.
> > 
> > 
> > I have no idea what MOF is, what "parsing" is involved, or how in the
> > world ACPI got involved here...
> > 
> > good luck!
> > 
> > greg k-h
> 
> Hi Greg! Simple description: In ACPI is stored binary MOF buffer which
> describe format (function name, parameters, sizeof and type of
> parameters, etc) for all those calls.
> 
> Basically it is what should be used for checking if userspace pass
> correct "buffer" via ioctl to WMI.
> 
> But that binary MOF is undocumented, invented by Microsoft... and
> present in every one ACPI BIOS notebook (which uses WMI). It is
> de-facto industrial standard, just tools for encoding/decoding it are
> only for Microsoft Windows systems.
> 
> I was able to decipher that format and wrote simple userspace parser:
> https://github.com/pali/bmfdec
> 
> Funny part is that format is not encrypted, but compressed by DMSDOS
> compatible compression algorithm :-) You probably would remember old
> FAT16 days with compression...
> 
> Hope that it helps you to understand it.

It does, thanks.  And as we now understand it (I'm guessing it had to be
semi-understood in the older wmi drivers already), validating it
properly seems to be the key for creating an interface that we "know" to
be safe.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 15:56         ` Pali Rohár
@ 2017-10-05 16:28           ` Greg KH
  2017-10-05 16:48               ` Mario.Limonciello
  0 siblings, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05 16:28 UTC (permalink / raw)
  To: Pali Rohár
  Cc: Mario.Limonciello, gnomes, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 05:56:19PM +0200, Pali Rohár wrote:
> On Thursday 05 October 2017 17:44:45 Greg KH wrote:
> > On Thu, Oct 05, 2017 at 02:22:37PM +0000, Mario.Limonciello@dell.com wrote:
> > > > -----Original Message-----
> > > > From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> > > > Sent: Thursday, October 5, 2017 8:59 AM
> > > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > > Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> > > > LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> > > > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > > > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de; Greg
> > > > KH <greg@kroah.com>
> > > > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > > > userspace interface
> > > > 
> > > > On Wed,  4 Oct 2017 17:48:39 -0500
> > > > Mario Limonciello <mario.limonciello@dell.com> wrote:
> > > > 
> > > > > This userspace character device will be used to perform SMBIOS calls
> > > > > from any applications.
> > > > >
> > > > > It provides an ioctl that will allow passing the 32k WMI calling
> > > > > interface buffer between userspace and kernel space.
> > > > 
> > > > What is your security model for firing 32K of random crap at the BIOS ?
> > > 
> > > Adding new class and select methods requires a review with the security
> > > team.  They will do STRIDE analysis and threat modeling.
> > > 
> > > > Do you fuzz test the BIOS interface ?
> > > 
> > > Yes there has been internal fuzz testing classes and selects used in the 
> > > ACPI interface in the past.  I can't comment on how regularly that is done.
> > > I do think it's interesting is to use the interface in Linux for further fuzz
> > > testing though.
> > 
> > That should be simple, start firing random data at this memory location
> > and see what happens.  Can you brick the box?  Change the
> > manufactured-date?  Change the serial number?  Normally these types of
> > BIOS interfaces allow all sorts of "fun" things like this, which is why
> > we have the kernel "own" the interface, to protect yourself from
> > breaking the box.
> 
> There are also Dell calls to "permanently disable TPM" and similar which
> are irreversible. So this can be really a problem.
> 
> > > > How do we know that between now and the end of the universe every call is
> > > > safe to execute as any random user without upsetting other users on the
> > > > same PC ?
> > > 
> > > Any random user shouldn't be executing the ioctl.
> > > Only root should be executing any of these calls.
> > 
> > "only root" isn't the best protection method, you should know better :)
> > 
> > You are going to have to do some kind of parsing/whitelisting here,
> > trust us...
> 
> That is also why I in past suggested to create fully transparent
> whitelisting filter for all WMI calls. And properly implement particular
> filter in kernel...
> 
> But that is of course hard as you need to know all details of internal
> structures and data which may be sent via userspace. To prevent e.g.
> action "permanently disable TPM" in kernel.

It's not "hard" as userspace would have to know these same things if it
were to just have an clean "pipe" to the BIOS as it has to create and
parse the commands to get the BIOS to do anything.

So I agree with you, whitelisting seems to be the only sane solution,
unless people don't like their TPMs to be erased by root exploits?  :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05  7:23   ` Greg KH
@ 2017-10-05 16:28       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 16:28 UTC (permalink / raw)
  To: greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:23 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> > This userspace character device will be used to perform SMBIOS calls
> > from any applications.
> >
> > It provides an ioctl that will allow passing the 32k WMI calling
> > interface buffer between userspace and kernel space.
> 
> {sigh}  Did you really test this?  It feels like it wasn't, due to the
> api you are using here.  Did you run it with a 32bit userspace and 64bit
> kernel?  32bit kernel/userspace?  How well did your userspace developer
> fall down crying when you tried that?  :)

I tested 64 bit kernel / 64 bit userspace.

> 
> > This character device is intended to deprecate the dcdbas kernel module
> > and the interface that it provides to userspace.
> 
> At least that driver has a well-documented api to userspace, you are
> throwing all of that away here, are you _sure_ you want to do that?
> Seems like you just made things much harder.

Being a well-documented API isn't the same as a "good" API.  Have you
seen how exactly that driver works to userspace?  It's not pretty.

That BIOS <-> OS interface that we use with it will stop working too on new
machines at some point soon too.  With no new interface available
this will just mean no way to get this data from userspace.

> 
> > It's important for the driver to provide a R/W ioctl to ensure that
> > two competing userspace processes don't race to provide or read each
> > others data.
> 
> The whole goal of this patch is to provide that ioctl, right?  So of
> course it is "important" :)
> 
> > The API for interacting with this interface is defined in documentation
> > as well as a uapi header provides the format of the structures.
> 
> Ok, let's _just_ review that api please:
> 
> > diff --git a/include/uapi/linux/dell-smbios-wmi.h b/include/uapi/linux/dell-
> smbios-wmi.h
> > new file mode 100644
> > index 000000000000..0d0d09b04021
> > --- /dev/null
> > +++ b/include/uapi/linux/dell-smbios-wmi.h
> > @@ -0,0 +1,25 @@
> > +#ifndef _UAPI_DELL_SMBIOS_WMI_H_
> > +#define _UAPI_DELL_SMBIOS_WMI_H_
> > +
> > +#include <linux/ioctl.h>
> > +#include <linux/wmi.h>
> > +
> > +struct wmi_calling_interface_buffer {
> > +	u16 class;
> > +	u16 select;
> > +	u32 input[4];
> > +	u32 output[4];
> > +	u32 argattrib;
> > +	u32 blength;
> > +	u8 *data;
> > +} __packed;
> 
> {sigh}
> 
> For structures that cross the user/kernel boundry, you _HAVE_ to use the
> correct types.  For some things, that is easy, u16 needs to be __u16,
> u32 needs to be __u32, but u8*?  Hah, good luck!  Remember what I
> mentioned above about 32/64 bit issues?
> 
> Why do you need a pointer here at all?  You are providing a huge chunk
> of memory to the ioctl, what's the use of a pointer?  How are you
> dereferenceing this pointer (remember, it's a userspace pointer, which
> you are not saying here, so odds are the kernel code is wrong...)

So the part that is probably not obvious here is that the size of this buffer
The BIOS will expect will vary from one machine to another.  The two sizes
that will be encountered are 4k and 32k.  The last 10 years it's been 4k,
we just jumped up to 32k.  Maybe some day it will be 64k, who knows.

This detail of the size is encoded in the MOF, and also available through
the dell-wmi-descriptor driver call I added to look up buffer size.
> 
> 
> > +struct wmi_smbios_ioctl {
> > +	u32 length;
> 
> __u32.
> 
> And why not __u64?  Is 32 bits always going to be ok?

If length stays around, I'll adjust this.

> 
> > +	struct wmi_calling_interface_buffer *buf;
> 
> Another pointer?  2 pointer dereferences in the same ioctl structure?
> Crazy, you are wanting to make your life harder than it has to be...
> 
Well so the way I look at it, if you have to support 4k and 32k, you
want userspace to at least claim that it allocated the right size.

> 
> > +};
> > +
> > +/* only offers on the single instance */
> > +#define DELL_WMI_SMBIOS_CMD		WMI_IOWR(0)
> 
> I don't understand the comment, please explain it better.
> 
> Please sit down and work out your api here, I don't think you have
> thought it through properly, given the number of pointers alone.
> 
> thanks,
> 
> greg k-h

So I did give this some thought, which is why I ended up with where 
I am.

1) Userspace reads buffer size
2) Userspace allocates a structure to pass buffer size and a pointer
3) Userpsace allocates another structure of what buffer size should be and 
fills in the first structure with the length of the pointer.
4) Kernel picks it up, and if it sees that userspace used the wrong length
complains.
5) If it's the right length, kernel unwinds and does stuff.


The other alternative is to just always do 32k to and from userspace
and internally in the kernel copy only the supported size.
the difference in output is just the size of the data section, which
above 4k isn't used by very many calls anyway.

That's obviously a much cleaner API, but what happens if one day this
does need to go to 64k?  I hope it doesn't, but I don't have a crystal ball.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
@ 2017-10-05 16:28       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 16:28 UTC (permalink / raw)
  To: greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:23 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> > This userspace character device will be used to perform SMBIOS calls
> > from any applications.
> >
> > It provides an ioctl that will allow passing the 32k WMI calling
> > interface buffer between userspace and kernel space.
> 
> {sigh}  Did you really test this?  It feels like it wasn't, due to the
> api you are using here.  Did you run it with a 32bit userspace and 64bit
> kernel?  32bit kernel/userspace?  How well did your userspace developer
> fall down crying when you tried that?  :)

I tested 64 bit kernel / 64 bit userspace.

> 
> > This character device is intended to deprecate the dcdbas kernel module
> > and the interface that it provides to userspace.
> 
> At least that driver has a well-documented api to userspace, you are
> throwing all of that away here, are you _sure_ you want to do that?
> Seems like you just made things much harder.

Being a well-documented API isn't the same as a "good" API.  Have you
seen how exactly that driver works to userspace?  It's not pretty.

That BIOS <-> OS interface that we use with it will stop working too on new
machines at some point soon too.  With no new interface available
this will just mean no way to get this data from userspace.

> 
> > It's important for the driver to provide a R/W ioctl to ensure that
> > two competing userspace processes don't race to provide or read each
> > others data.
> 
> The whole goal of this patch is to provide that ioctl, right?  So of
> course it is "important" :)
> 
> > The API for interacting with this interface is defined in documentation
> > as well as a uapi header provides the format of the structures.
> 
> Ok, let's _just_ review that api please:
> 
> > diff --git a/include/uapi/linux/dell-smbios-wmi.h b/include/uapi/linux/dell-
> smbios-wmi.h
> > new file mode 100644
> > index 000000000000..0d0d09b04021
> > --- /dev/null
> > +++ b/include/uapi/linux/dell-smbios-wmi.h
> > @@ -0,0 +1,25 @@
> > +#ifndef _UAPI_DELL_SMBIOS_WMI_H_
> > +#define _UAPI_DELL_SMBIOS_WMI_H_
> > +
> > +#include <linux/ioctl.h>
> > +#include <linux/wmi.h>
> > +
> > +struct wmi_calling_interface_buffer {
> > +	u16 class;
> > +	u16 select;
> > +	u32 input[4];
> > +	u32 output[4];
> > +	u32 argattrib;
> > +	u32 blength;
> > +	u8 *data;
> > +} __packed;
> 
> {sigh}
> 
> For structures that cross the user/kernel boundry, you _HAVE_ to use the
> correct types.  For some things, that is easy, u16 needs to be __u16,
> u32 needs to be __u32, but u8*?  Hah, good luck!  Remember what I
> mentioned above about 32/64 bit issues?
> 
> Why do you need a pointer here at all?  You are providing a huge chunk
> of memory to the ioctl, what's the use of a pointer?  How are you
> dereferenceing this pointer (remember, it's a userspace pointer, which
> you are not saying here, so odds are the kernel code is wrong...)

So the part that is probably not obvious here is that the size of this buffer
The BIOS will expect will vary from one machine to another.  The two sizes
that will be encountered are 4k and 32k.  The last 10 years it's been 4k,
we just jumped up to 32k.  Maybe some day it will be 64k, who knows.

This detail of the size is encoded in the MOF, and also available through
the dell-wmi-descriptor driver call I added to look up buffer size.
> 
> 
> > +struct wmi_smbios_ioctl {
> > +	u32 length;
> 
> __u32.
> 
> And why not __u64?  Is 32 bits always going to be ok?

If length stays around, I'll adjust this.

> 
> > +	struct wmi_calling_interface_buffer *buf;
> 
> Another pointer?  2 pointer dereferences in the same ioctl structure?
> Crazy, you are wanting to make your life harder than it has to be...
> 
Well so the way I look at it, if you have to support 4k and 32k, you
want userspace to at least claim that it allocated the right size.

> 
> > +};
> > +
> > +/* only offers on the single instance */
> > +#define DELL_WMI_SMBIOS_CMD		WMI_IOWR(0)
> 
> I don't understand the comment, please explain it better.
> 
> Please sit down and work out your api here, I don't think you have
> thought it through properly, given the number of pointers alone.
> 
> thanks,
> 
> greg k-h

So I did give this some thought, which is why I ended up with where 
I am.

1) Userspace reads buffer size
2) Userspace allocates a structure to pass buffer size and a pointer
3) Userpsace allocates another structure of what buffer size should be and 
fills in the first structure with the length of the pointer.
4) Kernel picks it up, and if it sees that userspace used the wrong length
complains.
5) If it's the right length, kernel unwinds and does stuff.


The other alternative is to just always do 32k to and from userspace
and internally in the kernel copy only the supported size.
the difference in output is just the size of the data section, which
above 4k isn't used by very many calls anyway.

That's obviously a much cleaner API, but what happens if one day this
does need to go to 64k?  I hope it doesn't, but I don't have a crystal ball.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 16:28       ` Mario.Limonciello
  (?)
@ 2017-10-05 16:34       ` Pali Rohár
  -1 siblings, 0 replies; 93+ messages in thread
From: Pali Rohár @ 2017-10-05 16:34 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: greg, dvhart, andy.shevchenko, linux-kernel, platform-driver-x86,
	luto, quasisec, rjw, mjg59, hch

On Thursday 05 October 2017 16:28:40 Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Greg KH [mailto:greg@kroah.com]
> > Sent: Thursday, October 5, 2017 2:23 AM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> > LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > userspace interface
> > 
> > On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> > > This userspace character device will be used to perform SMBIOS calls
> > > from any applications.
> > >
> > > It provides an ioctl that will allow passing the 32k WMI calling
> > > interface buffer between userspace and kernel space.
> > 
> > {sigh}  Did you really test this?  It feels like it wasn't, due to the
> > api you are using here.  Did you run it with a 32bit userspace and 64bit
> > kernel?  32bit kernel/userspace?  How well did your userspace developer
> > fall down crying when you tried that?  :)
> 
> I tested 64 bit kernel / 64 bit userspace.
> 
> > 
> > > This character device is intended to deprecate the dcdbas kernel module
> > > and the interface that it provides to userspace.
> > 
> > At least that driver has a well-documented api to userspace, you are
> > throwing all of that away here, are you _sure_ you want to do that?
> > Seems like you just made things much harder.
> 
> Being a well-documented API isn't the same as a "good" API.  Have you
> seen how exactly that driver works to userspace?  It's not pretty.
> 
> That BIOS <-> OS interface that we use with it will stop working too on new
> machines at some point soon too.  With no new interface available
> this will just mean no way to get this data from userspace.
> 
> > 
> > > It's important for the driver to provide a R/W ioctl to ensure that
> > > two competing userspace processes don't race to provide or read each
> > > others data.
> > 
> > The whole goal of this patch is to provide that ioctl, right?  So of
> > course it is "important" :)
> > 
> > > The API for interacting with this interface is defined in documentation
> > > as well as a uapi header provides the format of the structures.
> > 
> > Ok, let's _just_ review that api please:
> > 
> > > diff --git a/include/uapi/linux/dell-smbios-wmi.h b/include/uapi/linux/dell-
> > smbios-wmi.h
> > > new file mode 100644
> > > index 000000000000..0d0d09b04021
> > > --- /dev/null
> > > +++ b/include/uapi/linux/dell-smbios-wmi.h
> > > @@ -0,0 +1,25 @@
> > > +#ifndef _UAPI_DELL_SMBIOS_WMI_H_
> > > +#define _UAPI_DELL_SMBIOS_WMI_H_
> > > +
> > > +#include <linux/ioctl.h>
> > > +#include <linux/wmi.h>
> > > +
> > > +struct wmi_calling_interface_buffer {
> > > +	u16 class;
> > > +	u16 select;
> > > +	u32 input[4];
> > > +	u32 output[4];
> > > +	u32 argattrib;
> > > +	u32 blength;
> > > +	u8 *data;
> > > +} __packed;
> > 
> > {sigh}
> > 
> > For structures that cross the user/kernel boundry, you _HAVE_ to use the
> > correct types.  For some things, that is easy, u16 needs to be __u16,
> > u32 needs to be __u32, but u8*?  Hah, good luck!  Remember what I
> > mentioned above about 32/64 bit issues?
> > 
> > Why do you need a pointer here at all?  You are providing a huge chunk
> > of memory to the ioctl, what's the use of a pointer?  How are you
> > dereferenceing this pointer (remember, it's a userspace pointer, which
> > you are not saying here, so odds are the kernel code is wrong...)
> 
> So the part that is probably not obvious here is that the size of this buffer
> The BIOS will expect will vary from one machine to another.  The two sizes
> that will be encountered are 4k and 32k.  The last 10 years it's been 4k,
> we just jumped up to 32k.  Maybe some day it will be 64k, who knows.
> 
> This detail of the size is encoded in the MOF, and also available through
> the dell-wmi-descriptor driver call I added to look up buffer size.
> > 
> > 
> > > +struct wmi_smbios_ioctl {
> > > +	u32 length;
> > 
> > __u32.
> > 
> > And why not __u64?  Is 32 bits always going to be ok?
> 
> If length stays around, I'll adjust this.
> 
> > 
> > > +	struct wmi_calling_interface_buffer *buf;
> > 
> > Another pointer?  2 pointer dereferences in the same ioctl structure?
> > Crazy, you are wanting to make your life harder than it has to be...
> > 
> Well so the way I look at it, if you have to support 4k and 32k, you
> want userspace to at least claim that it allocated the right size.
> 
> > 
> > > +};
> > > +
> > > +/* only offers on the single instance */
> > > +#define DELL_WMI_SMBIOS_CMD		WMI_IOWR(0)
> > 
> > I don't understand the comment, please explain it better.
> > 
> > Please sit down and work out your api here, I don't think you have
> > thought it through properly, given the number of pointers alone.
> > 
> > thanks,
> > 
> > greg k-h
> 
> So I did give this some thought, which is why I ended up with where 
> I am.
> 
> 1) Userspace reads buffer size
> 2) Userspace allocates a structure to pass buffer size and a pointer
> 3) Userpsace allocates another structure of what buffer size should be and 
> fills in the first structure with the length of the pointer.
> 4) Kernel picks it up, and if it sees that userspace used the wrong length
> complains.
> 5) If it's the right length, kernel unwinds and does stuff.
> 
> 
> The other alternative is to just always do 32k to and from userspace
> and internally in the kernel copy only the supported size.
> the difference in output is just the size of the data section, which
> above 4k isn't used by very many calls anyway.
> 
> That's obviously a much cleaner API, but what happens if one day this
> does need to go to 64k?  I hope it doesn't, but I don't have a crystal ball.

I hope that buffer itself is zero padded when passed to firmware. If
this is true, should not API/ABI looks like that userspace pass buffer
length + buffer itself and then kernel copy userspace buffer to kernel
buffer which would have right size (with possibility to zero pad it)?
And in case kernel buffer is smaller, userspace would get error.

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05  7:33   ` Greg KH
@ 2017-10-05 16:37       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 16:37 UTC (permalink / raw)
  To: greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:33 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> > +static long dell_smbios_wmi_ioctl(struct file *filp, unsigned int cmd,
> > +	unsigned long arg)
> > +{
> > +	void __user *p = (void __user *) arg;
> > +	struct wmi_smbios_ioctl *input;
> > +	struct wmi_smbios_priv *priv;
> > +	struct wmi_device *wdev;
> > +	size_t ioctl_size;
> > +	int ret = 0;
> > +
> > +	switch (cmd) {
> > +	/* we only operate on first instance */
> > +	case DELL_WMI_SMBIOS_CMD:
> > +		wdev = get_first_wmi_device();
> > +		if (!wdev) {
> > +			pr_err("No WMI devices bound\n");
> 
> dev_err(), you are a driver, never use "raw" pr_ calls.
>
This particular error was if a device wasn't found.  It's a codepath I don't
really know can happen from the ioctl, but wanted to be sure.  I'll just remove
this error message.
 
> > +			return -ENODEV;
> > +		}
> > +		ioctl_size = sizeof(struct wmi_smbios_ioctl);
> > +		priv = dev_get_drvdata(&wdev->dev);
> > +		input = kmalloc(ioctl_size, GFP_KERNEL);
> > +		if (!input)
> > +			return -ENOMEM;
> > +		mutex_lock(&wmi_mutex);
> > +		if (!access_ok(VERIFY_READ, p, ioctl_size)) {
> 
> Hm, any time I see an access_ok() call, I get scared.  You should almost
> never need to make that call if you are using the correct kernel apis.
> 
> > +			pr_err("Unsafe userspace pointer passed\n");
> 
> dev_err().
>

Yep got it.
 
> > +			return -EFAULT;
> 
> Memory leak!

Doh, thanks.

> 
> 
> > +		}
> > +		if (copy_from_user(input, p, ioctl_size)) {
> > +			ret = -EFAULT;
> 
> So, why did you call access_ok() followed by copy_from_user()?
> copy_from/to() handle all of that for you automatically.
> 

I wasn't aware access_ok was handled in copy_from/to.  I'll remove this.

> > +			goto fail_smbios_cmd;
> > +		}
> > +		if (input->length != priv->buffer_size) {
> > +			pr_err("Got buffer size %d expected %d\n",
> > +				input->length, priv->buffer_size);
> 
> length is user provided, it can be whatever anyone sets it to.  I don't
> understand this error.
> 
> > +			ret = -EINVAL;
> > +			goto fail_smbios_cmd;
> > +		}
> > +		if (!access_ok(VERIFY_WRITE, input->buf, priv->buffer_size)) {
> > +			pr_err("Unsafe userspace pointer passed\n");
> 
> Again, don't need this.
> 
> > +			ret = -EFAULT;
> > +			goto fail_smbios_cmd;
> > +		}
> > +		if (copy_from_user(priv->buf, input->buf, priv->buffer_size)) {
> 
> Wait, input->buf is a user pointer?  Ick, see my previous email about
> your crazy api here being a mess.  This should not be needed.
> 
> And as you "know" the buffer size already, why do you have userspace
> specify it?  What good is it?

I mentioned this in the other mail, but the thing is buffer size is not consistent
from machine to machine.

It's convenient that this change happened now because otherwise there would
have been assumptions about it always being 4k that needed to be thrown away.

> 
> > +			ret = -EFAULT;
> > +			goto fail_smbios_cmd;
> > +		}
> > +		ret = run_smbios_call(wdev);
> 
> No other checking of the values in the structure?  You just "trust"
> userspace to get it all right?  Hah!
> 
> > +		if (ret != 0)
> > +			goto fail_smbios_cmd;
> 
> You didn't run this through checkpatch :(
> 
I did..

$ ~/src/linux/scripts/checkpatch.pl 0013-platform-x86-dell-smbios-wmi-
introduce-userspace-int.patch 
total: 0 errors, 0 warnings, 241 lines checked

0013-platform-x86-dell-smbios-wmi-introduce-userspace-int.patch has no obvious 
style problems and is ready for submission.

> 
> > +		if (copy_to_user(input->buf, priv->buf, priv->buffer_size))
> > +			ret = -EFAULT;
> > +fail_smbios_cmd:
> > +		kfree(input);
> > +		mutex_unlock(&wmi_mutex);
> > +		break;
> > +	default:
> > +		pr_err("unsupported ioctl: %d.\n", cmd);
> > +		ret = -ENOIOCTLCMD;
> > +	}
> > +	return ret;
> > +}
> > +
> > +static ssize_t buffer_size_show(struct device *dev,
> > +				struct device_attribute *attr, char *buf)
> > +{
> > +	struct wmi_smbios_priv *priv = dev_get_drvdata(dev);
> > +
> > +	return sprintf(buf, "%d\n", priv->buffer_size);
> > +}
> > +static DEVICE_ATTR_RO(buffer_size);
> > +
> > +static struct attribute *smbios_wmi_attrs[] = {
> > +	&dev_attr_buffer_size.attr,
> > +	NULL
> > +};
> > +
> > +static const struct attribute_group smbios_wmi_attribute_group = {
> > +	.attrs = smbios_wmi_attrs,
> > +};
> > +
> >  static int dell_smbios_wmi_probe(struct wmi_device *wdev)
> >  {
> >  	struct wmi_smbios_priv *priv;
> > @@ -127,6 +209,11 @@ static int dell_smbios_wmi_probe(struct wmi_device
> *wdev)
> >  	if (!priv->buf)
> >  		return -ENOMEM;
> >
> > +	ret = sysfs_create_group(&wdev->dev.kobj,
> > +				 &smbios_wmi_attribute_group);
> 
> Hint, if a driver ever makes a call to sysfs_*(), something is wrong, it
> should never be needed.
> 
> Also, you just raced with userspace and lost :(
> 
> There is a way to fix all of this, in a simple way, I'll leave that as
> an exercise for the reader, I've reviewed enough of this code for
> today...
> 

Thanks, I see what I should do instead, I'll make changes.

> > +static const struct file_operations dell_smbios_wmi_fops = {
> > +	.owner		= THIS_MODULE,
> 
> And who uses that field?  Hint, no one is, which is another issue that I
> forgot to review in your previous patch where you use this structure.
> What is protecting this module from being unloaded while the ioctl call
> is running?  (hint, nothing...)
> 

Thanks, I'll add locking.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
@ 2017-10-05 16:37       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 16:37 UTC (permalink / raw)
  To: greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:33 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> > +static long dell_smbios_wmi_ioctl(struct file *filp, unsigned int cmd,
> > +	unsigned long arg)
> > +{
> > +	void __user *p = (void __user *) arg;
> > +	struct wmi_smbios_ioctl *input;
> > +	struct wmi_smbios_priv *priv;
> > +	struct wmi_device *wdev;
> > +	size_t ioctl_size;
> > +	int ret = 0;
> > +
> > +	switch (cmd) {
> > +	/* we only operate on first instance */
> > +	case DELL_WMI_SMBIOS_CMD:
> > +		wdev = get_first_wmi_device();
> > +		if (!wdev) {
> > +			pr_err("No WMI devices bound\n");
> 
> dev_err(), you are a driver, never use "raw" pr_ calls.
>
This particular error was if a device wasn't found.  It's a codepath I don't
really know can happen from the ioctl, but wanted to be sure.  I'll just remove
this error message.
 
> > +			return -ENODEV;
> > +		}
> > +		ioctl_size = sizeof(struct wmi_smbios_ioctl);
> > +		priv = dev_get_drvdata(&wdev->dev);
> > +		input = kmalloc(ioctl_size, GFP_KERNEL);
> > +		if (!input)
> > +			return -ENOMEM;
> > +		mutex_lock(&wmi_mutex);
> > +		if (!access_ok(VERIFY_READ, p, ioctl_size)) {
> 
> Hm, any time I see an access_ok() call, I get scared.  You should almost
> never need to make that call if you are using the correct kernel apis.
> 
> > +			pr_err("Unsafe userspace pointer passed\n");
> 
> dev_err().
>

Yep got it.
 
> > +			return -EFAULT;
> 
> Memory leak!

Doh, thanks.

> 
> 
> > +		}
> > +		if (copy_from_user(input, p, ioctl_size)) {
> > +			ret = -EFAULT;
> 
> So, why did you call access_ok() followed by copy_from_user()?
> copy_from/to() handle all of that for you automatically.
> 

I wasn't aware access_ok was handled in copy_from/to.  I'll remove this.

> > +			goto fail_smbios_cmd;
> > +		}
> > +		if (input->length != priv->buffer_size) {
> > +			pr_err("Got buffer size %d expected %d\n",
> > +				input->length, priv->buffer_size);
> 
> length is user provided, it can be whatever anyone sets it to.  I don't
> understand this error.
> 
> > +			ret = -EINVAL;
> > +			goto fail_smbios_cmd;
> > +		}
> > +		if (!access_ok(VERIFY_WRITE, input->buf, priv->buffer_size)) {
> > +			pr_err("Unsafe userspace pointer passed\n");
> 
> Again, don't need this.
> 
> > +			ret = -EFAULT;
> > +			goto fail_smbios_cmd;
> > +		}
> > +		if (copy_from_user(priv->buf, input->buf, priv->buffer_size)) {
> 
> Wait, input->buf is a user pointer?  Ick, see my previous email about
> your crazy api here being a mess.  This should not be needed.
> 
> And as you "know" the buffer size already, why do you have userspace
> specify it?  What good is it?

I mentioned this in the other mail, but the thing is buffer size is not consistent
from machine to machine.

It's convenient that this change happened now because otherwise there would
have been assumptions about it always being 4k that needed to be thrown away.

> 
> > +			ret = -EFAULT;
> > +			goto fail_smbios_cmd;
> > +		}
> > +		ret = run_smbios_call(wdev);
> 
> No other checking of the values in the structure?  You just "trust"
> userspace to get it all right?  Hah!
> 
> > +		if (ret != 0)
> > +			goto fail_smbios_cmd;
> 
> You didn't run this through checkpatch :(
> 
I did..

$ ~/src/linux/scripts/checkpatch.pl 0013-platform-x86-dell-smbios-wmi-
introduce-userspace-int.patch 
total: 0 errors, 0 warnings, 241 lines checked

0013-platform-x86-dell-smbios-wmi-introduce-userspace-int.patch has no obvious 
style problems and is ready for submission.

> 
> > +		if (copy_to_user(input->buf, priv->buf, priv->buffer_size))
> > +			ret = -EFAULT;
> > +fail_smbios_cmd:
> > +		kfree(input);
> > +		mutex_unlock(&wmi_mutex);
> > +		break;
> > +	default:
> > +		pr_err("unsupported ioctl: %d.\n", cmd);
> > +		ret = -ENOIOCTLCMD;
> > +	}
> > +	return ret;
> > +}
> > +
> > +static ssize_t buffer_size_show(struct device *dev,
> > +				struct device_attribute *attr, char *buf)
> > +{
> > +	struct wmi_smbios_priv *priv = dev_get_drvdata(dev);
> > +
> > +	return sprintf(buf, "%d\n", priv->buffer_size);
> > +}
> > +static DEVICE_ATTR_RO(buffer_size);
> > +
> > +static struct attribute *smbios_wmi_attrs[] = {
> > +	&dev_attr_buffer_size.attr,
> > +	NULL
> > +};
> > +
> > +static const struct attribute_group smbios_wmi_attribute_group = {
> > +	.attrs = smbios_wmi_attrs,
> > +};
> > +
> >  static int dell_smbios_wmi_probe(struct wmi_device *wdev)
> >  {
> >  	struct wmi_smbios_priv *priv;
> > @@ -127,6 +209,11 @@ static int dell_smbios_wmi_probe(struct wmi_device
> *wdev)
> >  	if (!priv->buf)
> >  		return -ENOMEM;
> >
> > +	ret = sysfs_create_group(&wdev->dev.kobj,
> > +				 &smbios_wmi_attribute_group);
> 
> Hint, if a driver ever makes a call to sysfs_*(), something is wrong, it
> should never be needed.
> 
> Also, you just raced with userspace and lost :(
> 
> There is a way to fix all of this, in a simple way, I'll leave that as
> an exercise for the reader, I've reviewed enough of this code for
> today...
> 

Thanks, I see what I should do instead, I'll make changes.

> > +static const struct file_operations dell_smbios_wmi_fops = {
> > +	.owner		= THIS_MODULE,
> 
> And who uses that field?  Hint, no one is, which is another issue that I
> forgot to review in your previous patch where you use this structure.
> What is protecting this module from being unloaded while the ioctl call
> is running?  (hint, nothing...)
> 

Thanks, I'll add locking.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 16:28       ` Mario.Limonciello
@ 2017-10-05 16:40         ` Greg KH
  -1 siblings, 0 replies; 93+ messages in thread
From: Greg KH @ 2017-10-05 16:40 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 04:28:40PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Greg KH [mailto:greg@kroah.com]
> > Sent: Thursday, October 5, 2017 2:23 AM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> > LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > userspace interface
> > 
> > On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> > > This userspace character device will be used to perform SMBIOS calls
> > > from any applications.
> > >
> > > It provides an ioctl that will allow passing the 32k WMI calling
> > > interface buffer between userspace and kernel space.
> > 
> > {sigh}  Did you really test this?  It feels like it wasn't, due to the
> > api you are using here.  Did you run it with a 32bit userspace and 64bit
> > kernel?  32bit kernel/userspace?  How well did your userspace developer
> > fall down crying when you tried that?  :)
> 
> I tested 64 bit kernel / 64 bit userspace.

It showed :(

> > > This character device is intended to deprecate the dcdbas kernel module
> > > and the interface that it provides to userspace.
> > 
> > At least that driver has a well-documented api to userspace, you are
> > throwing all of that away here, are you _sure_ you want to do that?
> > Seems like you just made things much harder.
> 
> Being a well-documented API isn't the same as a "good" API.  Have you
> seen how exactly that driver works to userspace?  It's not pretty.
> 
> That BIOS <-> OS interface that we use with it will stop working too on new
> machines at some point soon too.  With no new interface available
> this will just mean no way to get this data from userspace.

Sure it will stop, if you change the BIOS to use a different interface.
I don't understand the comparison here, you will have to do _something_,
right?  Giving a "raw pipe" to userspace doesn't feel like a good
solution given the issues involved (see the other emails in this
thread...)

> > > It's important for the driver to provide a R/W ioctl to ensure that
> > > two competing userspace processes don't race to provide or read each
> > > others data.
> > 
> > The whole goal of this patch is to provide that ioctl, right?  So of
> > course it is "important" :)
> > 
> > > The API for interacting with this interface is defined in documentation
> > > as well as a uapi header provides the format of the structures.
> > 
> > Ok, let's _just_ review that api please:
> > 
> > > diff --git a/include/uapi/linux/dell-smbios-wmi.h b/include/uapi/linux/dell-
> > smbios-wmi.h
> > > new file mode 100644
> > > index 000000000000..0d0d09b04021
> > > --- /dev/null
> > > +++ b/include/uapi/linux/dell-smbios-wmi.h
> > > @@ -0,0 +1,25 @@
> > > +#ifndef _UAPI_DELL_SMBIOS_WMI_H_
> > > +#define _UAPI_DELL_SMBIOS_WMI_H_
> > > +
> > > +#include <linux/ioctl.h>
> > > +#include <linux/wmi.h>
> > > +
> > > +struct wmi_calling_interface_buffer {
> > > +	u16 class;
> > > +	u16 select;
> > > +	u32 input[4];
> > > +	u32 output[4];
> > > +	u32 argattrib;
> > > +	u32 blength;
> > > +	u8 *data;
> > > +} __packed;
> > 
> > {sigh}
> > 
> > For structures that cross the user/kernel boundry, you _HAVE_ to use the
> > correct types.  For some things, that is easy, u16 needs to be __u16,
> > u32 needs to be __u32, but u8*?  Hah, good luck!  Remember what I
> > mentioned above about 32/64 bit issues?
> > 
> > Why do you need a pointer here at all?  You are providing a huge chunk
> > of memory to the ioctl, what's the use of a pointer?  How are you
> > dereferenceing this pointer (remember, it's a userspace pointer, which
> > you are not saying here, so odds are the kernel code is wrong...)
> 
> So the part that is probably not obvious here is that the size of this buffer
> The BIOS will expect will vary from one machine to another.  The two sizes
> that will be encountered are 4k and 32k.  The last 10 years it's been 4k,
> we just jumped up to 32k.  Maybe some day it will be 64k, who knows.
> 
> This detail of the size is encoded in the MOF, and also available through
> the dell-wmi-descriptor driver call I added to look up buffer size.

Fine, then make it a variable structure size.  Using a pointer is not
how to do it in a portable way (if you tried a 32bit userspace, boom...)

> > > +	struct wmi_calling_interface_buffer *buf;
> > 
> > Another pointer?  2 pointer dereferences in the same ioctl structure?
> > Crazy, you are wanting to make your life harder than it has to be...
> > 
> Well so the way I look at it, if you have to support 4k and 32k, you
> want userspace to at least claim that it allocated the right size.

Again, variable length structures are your friend.

> So I did give this some thought, which is why I ended up with where 
> I am.
> 
> 1) Userspace reads buffer size

>From where?  That's a crazy thing in the first place you know, how does
the kernel "know" this in a way that userspace doesn't ahead of time?

> 2) Userspace allocates a structure to pass buffer size and a pointer

No pointers!

> 3) Userpsace allocates another structure of what buffer size should be and 
> fills in the first structure with the length of the pointer.

Ick ick ick.

> 4) Kernel picks it up, and if it sees that userspace used the wrong length
> complains.

length checking is good, no objection there.

> 5) If it's the right length, kernel unwinds and does stuff.

"unwinding" is hard to do right, on all of the needed combinations, try
it.  I'll be waiting :)

variable length structures are your friend, you can still put the length
it in, no objection there (you need it.)

hope this helps,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
@ 2017-10-05 16:40         ` Greg KH
  0 siblings, 0 replies; 93+ messages in thread
From: Greg KH @ 2017-10-05 16:40 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 04:28:40PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Greg KH [mailto:greg@kroah.com]
> > Sent: Thursday, October 5, 2017 2:23 AM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: dvhart@infradead.org; Andy Shevchenko <andy.shevchenko@gmail.com>;
> > LKML <linux-kernel@vger.kernel.org>; platform-driver-x86@vger.kernel.org;
> > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > userspace interface
> > 
> > On Wed, Oct 04, 2017 at 05:48:39PM -0500, Mario Limonciello wrote:
> > > This userspace character device will be used to perform SMBIOS calls
> > > from any applications.
> > >
> > > It provides an ioctl that will allow passing the 32k WMI calling
> > > interface buffer between userspace and kernel space.
> > 
> > {sigh}  Did you really test this?  It feels like it wasn't, due to the
> > api you are using here.  Did you run it with a 32bit userspace and 64bit
> > kernel?  32bit kernel/userspace?  How well did your userspace developer
> > fall down crying when you tried that?  :)
> 
> I tested 64 bit kernel / 64 bit userspace.

It showed :(

> > > This character device is intended to deprecate the dcdbas kernel module
> > > and the interface that it provides to userspace.
> > 
> > At least that driver has a well-documented api to userspace, you are
> > throwing all of that away here, are you _sure_ you want to do that?
> > Seems like you just made things much harder.
> 
> Being a well-documented API isn't the same as a "good" API.  Have you
> seen how exactly that driver works to userspace?  It's not pretty.
> 
> That BIOS <-> OS interface that we use with it will stop working too on new
> machines at some point soon too.  With no new interface available
> this will just mean no way to get this data from userspace.

Sure it will stop, if you change the BIOS to use a different interface.
I don't understand the comparison here, you will have to do _something_,
right?  Giving a "raw pipe" to userspace doesn't feel like a good
solution given the issues involved (see the other emails in this
thread...)

> > > It's important for the driver to provide a R/W ioctl to ensure that
> > > two competing userspace processes don't race to provide or read each
> > > others data.
> > 
> > The whole goal of this patch is to provide that ioctl, right?  So of
> > course it is "important" :)
> > 
> > > The API for interacting with this interface is defined in documentation
> > > as well as a uapi header provides the format of the structures.
> > 
> > Ok, let's _just_ review that api please:
> > 
> > > diff --git a/include/uapi/linux/dell-smbios-wmi.h b/include/uapi/linux/dell-
> > smbios-wmi.h
> > > new file mode 100644
> > > index 000000000000..0d0d09b04021
> > > --- /dev/null
> > > +++ b/include/uapi/linux/dell-smbios-wmi.h
> > > @@ -0,0 +1,25 @@
> > > +#ifndef _UAPI_DELL_SMBIOS_WMI_H_
> > > +#define _UAPI_DELL_SMBIOS_WMI_H_
> > > +
> > > +#include <linux/ioctl.h>
> > > +#include <linux/wmi.h>
> > > +
> > > +struct wmi_calling_interface_buffer {
> > > +	u16 class;
> > > +	u16 select;
> > > +	u32 input[4];
> > > +	u32 output[4];
> > > +	u32 argattrib;
> > > +	u32 blength;
> > > +	u8 *data;
> > > +} __packed;
> > 
> > {sigh}
> > 
> > For structures that cross the user/kernel boundry, you _HAVE_ to use the
> > correct types.  For some things, that is easy, u16 needs to be __u16,
> > u32 needs to be __u32, but u8*?  Hah, good luck!  Remember what I
> > mentioned above about 32/64 bit issues?
> > 
> > Why do you need a pointer here at all?  You are providing a huge chunk
> > of memory to the ioctl, what's the use of a pointer?  How are you
> > dereferenceing this pointer (remember, it's a userspace pointer, which
> > you are not saying here, so odds are the kernel code is wrong...)
> 
> So the part that is probably not obvious here is that the size of this buffer
> The BIOS will expect will vary from one machine to another.  The two sizes
> that will be encountered are 4k and 32k.  The last 10 years it's been 4k,
> we just jumped up to 32k.  Maybe some day it will be 64k, who knows.
> 
> This detail of the size is encoded in the MOF, and also available through
> the dell-wmi-descriptor driver call I added to look up buffer size.

Fine, then make it a variable structure size.  Using a pointer is not
how to do it in a portable way (if you tried a 32bit userspace, boom...)

> > > +	struct wmi_calling_interface_buffer *buf;
> > 
> > Another pointer?  2 pointer dereferences in the same ioctl structure?
> > Crazy, you are wanting to make your life harder than it has to be...
> > 
> Well so the way I look at it, if you have to support 4k and 32k, you
> want userspace to at least claim that it allocated the right size.

Again, variable length structures are your friend.

> So I did give this some thought, which is why I ended up with where 
> I am.
> 
> 1) Userspace reads buffer size

From where?  That's a crazy thing in the first place you know, how does
the kernel "know" this in a way that userspace doesn't ahead of time?

> 2) Userspace allocates a structure to pass buffer size and a pointer

No pointers!

> 3) Userpsace allocates another structure of what buffer size should be and 
> fills in the first structure with the length of the pointer.

Ick ick ick.

> 4) Kernel picks it up, and if it sees that userspace used the wrong length
> complains.

length checking is good, no objection there.

> 5) If it's the right length, kernel unwinds and does stuff.

"unwinding" is hard to do right, on all of the needed combinations, try
it.  I'll be waiting :)

variable length structures are your friend, you can still put the length
it in, no objection there (you need it.)

hope this helps,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 16:28           ` Greg KH
@ 2017-10-05 16:48               ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 16:48 UTC (permalink / raw)
  To: gregkh, pali.rohar
  Cc: gnomes, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Thursday, October 5, 2017 11:28 AM
> To: Pali Rohár <pali.rohar@gmail.com>
> Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>;
> gnomes@lxorguk.ukuu.org.uk; dvhart@infradead.org;
> andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-driver-
> x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Thu, Oct 05, 2017 at 05:56:19PM +0200, Pali Rohár wrote:
> > On Thursday 05 October 2017 17:44:45 Greg KH wrote:
> > > On Thu, Oct 05, 2017 at 02:22:37PM +0000, Mario.Limonciello@dell.com
> wrote:
> > > > > -----Original Message-----
> > > > > From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> > > > > Sent: Thursday, October 5, 2017 8:59 AM
> > > > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > > > Cc: dvhart@infradead.org; Andy Shevchenko
> <andy.shevchenko@gmail.com>;
> > > > > LKML <linux-kernel@vger.kernel.org>; platform-driver-
> x86@vger.kernel.org;
> > > > > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > > > > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com;
> hch@lst.de; Greg
> > > > > KH <greg@kroah.com>
> > > > > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > > > > userspace interface
> > > > >
> > > > > On Wed,  4 Oct 2017 17:48:39 -0500
> > > > > Mario Limonciello <mario.limonciello@dell.com> wrote:
> > > > >
> > > > > > This userspace character device will be used to perform SMBIOS calls
> > > > > > from any applications.
> > > > > >
> > > > > > It provides an ioctl that will allow passing the 32k WMI calling
> > > > > > interface buffer between userspace and kernel space.
> > > > >
> > > > > What is your security model for firing 32K of random crap at the BIOS ?
> > > >
> > > > Adding new class and select methods requires a review with the security
> > > > team.  They will do STRIDE analysis and threat modeling.
> > > >
> > > > > Do you fuzz test the BIOS interface ?
> > > >
> > > > Yes there has been internal fuzz testing classes and selects used in the
> > > > ACPI interface in the past.  I can't comment on how regularly that is done.
> > > > I do think it's interesting is to use the interface in Linux for further fuzz
> > > > testing though.
> > >
> > > That should be simple, start firing random data at this memory location
> > > and see what happens.  Can you brick the box?  Change the
> > > manufactured-date?  Change the serial number?  Normally these types of
> > > BIOS interfaces allow all sorts of "fun" things like this, which is why
> > > we have the kernel "own" the interface, to protect yourself from
> > > breaking the box.
> >
> > There are also Dell calls to "permanently disable TPM" and similar which
> > are irreversible. So this can be really a problem.
> >
> > > > > How do we know that between now and the end of the universe every
> call is
> > > > > safe to execute as any random user without upsetting other users on the
> > > > > same PC ?
> > > >
> > > > Any random user shouldn't be executing the ioctl.
> > > > Only root should be executing any of these calls.
> > >
> > > "only root" isn't the best protection method, you should know better :)
> > >
> > > You are going to have to do some kind of parsing/whitelisting here,
> > > trust us...
> >
> > That is also why I in past suggested to create fully transparent
> > whitelisting filter for all WMI calls. And properly implement particular
> > filter in kernel...
> >
> > But that is of course hard as you need to know all details of internal
> > structures and data which may be sent via userspace. To prevent e.g.
> > action "permanently disable TPM" in kernel.
> 
> It's not "hard" as userspace would have to know these same things if it
> were to just have an clean "pipe" to the BIOS as it has to create and
> parse the commands to get the BIOS to do anything.
> 
> So I agree with you, whitelisting seems to be the only sane solution,
> unless people don't like their TPMs to be erased by root exploits?  :)
> 
> thanks,
> 
> greg k-h

Permanently disable TPM can't be run from OS through this interface.
Something like that requires a special manufacturing mode (which also
can't be activated through this interface).

There are some "write once" items that for the general purpose user that
won't brick a box, but should probably be blacklisted though.
I'll think this through some more.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
@ 2017-10-05 16:48               ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 16:48 UTC (permalink / raw)
  To: gregkh, pali.rohar
  Cc: gnomes, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:gregkh@linuxfoundation.org]
> Sent: Thursday, October 5, 2017 11:28 AM
> To: Pali Rohár <pali.rohar@gmail.com>
> Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>;
> gnomes@lxorguk.ukuu.org.uk; dvhart@infradead.org;
> andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-driver-
> x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> On Thu, Oct 05, 2017 at 05:56:19PM +0200, Pali Rohár wrote:
> > On Thursday 05 October 2017 17:44:45 Greg KH wrote:
> > > On Thu, Oct 05, 2017 at 02:22:37PM +0000, Mario.Limonciello@dell.com
> wrote:
> > > > > -----Original Message-----
> > > > > From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> > > > > Sent: Thursday, October 5, 2017 8:59 AM
> > > > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > > > Cc: dvhart@infradead.org; Andy Shevchenko
> <andy.shevchenko@gmail.com>;
> > > > > LKML <linux-kernel@vger.kernel.org>; platform-driver-
> x86@vger.kernel.org;
> > > > > Andy Lutomirski <luto@kernel.org>; quasisec@google.com;
> > > > > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com;
> hch@lst.de; Greg
> > > > > KH <greg@kroah.com>
> > > > > Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> > > > > userspace interface
> > > > >
> > > > > On Wed,  4 Oct 2017 17:48:39 -0500
> > > > > Mario Limonciello <mario.limonciello@dell.com> wrote:
> > > > >
> > > > > > This userspace character device will be used to perform SMBIOS calls
> > > > > > from any applications.
> > > > > >
> > > > > > It provides an ioctl that will allow passing the 32k WMI calling
> > > > > > interface buffer between userspace and kernel space.
> > > > >
> > > > > What is your security model for firing 32K of random crap at the BIOS ?
> > > >
> > > > Adding new class and select methods requires a review with the security
> > > > team.  They will do STRIDE analysis and threat modeling.
> > > >
> > > > > Do you fuzz test the BIOS interface ?
> > > >
> > > > Yes there has been internal fuzz testing classes and selects used in the
> > > > ACPI interface in the past.  I can't comment on how regularly that is done.
> > > > I do think it's interesting is to use the interface in Linux for further fuzz
> > > > testing though.
> > >
> > > That should be simple, start firing random data at this memory location
> > > and see what happens.  Can you brick the box?  Change the
> > > manufactured-date?  Change the serial number?  Normally these types of
> > > BIOS interfaces allow all sorts of "fun" things like this, which is why
> > > we have the kernel "own" the interface, to protect yourself from
> > > breaking the box.
> >
> > There are also Dell calls to "permanently disable TPM" and similar which
> > are irreversible. So this can be really a problem.
> >
> > > > > How do we know that between now and the end of the universe every
> call is
> > > > > safe to execute as any random user without upsetting other users on the
> > > > > same PC ?
> > > >
> > > > Any random user shouldn't be executing the ioctl.
> > > > Only root should be executing any of these calls.
> > >
> > > "only root" isn't the best protection method, you should know better :)
> > >
> > > You are going to have to do some kind of parsing/whitelisting here,
> > > trust us...
> >
> > That is also why I in past suggested to create fully transparent
> > whitelisting filter for all WMI calls. And properly implement particular
> > filter in kernel...
> >
> > But that is of course hard as you need to know all details of internal
> > structures and data which may be sent via userspace. To prevent e.g.
> > action "permanently disable TPM" in kernel.
> 
> It's not "hard" as userspace would have to know these same things if it
> were to just have an clean "pipe" to the BIOS as it has to create and
> parse the commands to get the BIOS to do anything.
> 
> So I agree with you, whitelisting seems to be the only sane solution,
> unless people don't like their TPMs to be erased by root exploits?  :)
> 
> thanks,
> 
> greg k-h

Permanently disable TPM can't be run from OS through this interface.
Something like that requires a special manufacturing mode (which also
can't be activated through this interface).

There are some "write once" items that for the general purpose user that
won't brick a box, but should probably be blacklisted though.
I'll think this through some more.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05  5:34   ` Andy Shevchenko
@ 2017-10-05 17:04       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 17:04 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: dvhart, linux-kernel, platform-driver-x86, luto, quasisec,
	pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 12:34 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
> <mario.limonciello@dell.com> wrote:
> > All communication on individual GUIDs should occur in separate drivers.
> > Allowing a driver to communicate with the bus to another GUID is just
> > a hack that discourages drivers to adopt the bus model.
> >
> > The information found from the WMI descriptor driver is now exported
> > for use by other drivers.
> 
> > +       priv = list_first_entry_or_null(&wmi_list,
> > +                                       struct descriptor_priv,
> > +                                       list);
> 
> > +       priv = list_first_entry_or_null(&wmi_list,
> > +                                       struct descriptor_priv,
> > +                                       list);
> 
> static inline ...to_priv(...)
> {
>  return list_first_entry_...();
> }
> 
> > +       list_add_tail(&priv->list, &wmi_list);
> 
> > +       list_del(&priv->list);
> 
> Do these need locking?

Yeah this seems like a good idea.  I'll add it in.

> 
> > +bool dell_wmi_get_interface_version(u32 *version);
> > +bool dell_wmi_get_size(u32 *size);
> 
> This might need stubs when module is not selected (when functionality
> is optional if it would be the case), otherwise all users should
> select it explicitly.

Per Darren's other threads I'm adjusting Kconfig to make sure this module
is selected.  It's realistically not optional when using these others.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
@ 2017-10-05 17:04       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 17:04 UTC (permalink / raw)
  To: andy.shevchenko
  Cc: dvhart, linux-kernel, platform-driver-x86, luto, quasisec,
	pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Andy Shevchenko [mailto:andy.shevchenko@gmail.com]
> Sent: Thursday, October 5, 2017 12:34 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; Platform Driver
> <platform-driver-x86@vger.kernel.org>; Andy Lutomirski <luto@kernel.org>;
> quasisec@google.com; Pali Rohár <pali.rohar@gmail.com>; Rafael J. Wysocki
> <rjw@rjwysocki.net>; mjg59@google.com; Christoph Hellwig <hch@lst.de>;
> Greg KH <greg@kroah.com>
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 5, 2017 at 1:48 AM, Mario Limonciello
> <mario.limonciello@dell.com> wrote:
> > All communication on individual GUIDs should occur in separate drivers.
> > Allowing a driver to communicate with the bus to another GUID is just
> > a hack that discourages drivers to adopt the bus model.
> >
> > The information found from the WMI descriptor driver is now exported
> > for use by other drivers.
> 
> > +       priv = list_first_entry_or_null(&wmi_list,
> > +                                       struct descriptor_priv,
> > +                                       list);
> 
> > +       priv = list_first_entry_or_null(&wmi_list,
> > +                                       struct descriptor_priv,
> > +                                       list);
> 
> static inline ...to_priv(...)
> {
>  return list_first_entry_...();
> }
> 
> > +       list_add_tail(&priv->list, &wmi_list);
> 
> > +       list_del(&priv->list);
> 
> Do these need locking?

Yeah this seems like a good idea.  I'll add it in.

> 
> > +bool dell_wmi_get_interface_version(u32 *version);
> > +bool dell_wmi_get_size(u32 *size);
> 
> This might need stubs when module is not selected (when functionality
> is optional if it would be the case), otherwise all users should
> select it explicitly.

Per Darren's other threads I'm adjusting Kconfig to make sure this module
is selected.  It's realistically not optional when using these others.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05 14:47                 ` Mario.Limonciello
  (?)
@ 2017-10-05 17:22                 ` Darren Hart
  2017-10-05 17:32                     ` Mario.Limonciello
  -1 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05 17:22 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

On Thu, Oct 05, 2017 at 02:47:15PM +0000, Mario.Limonciello@dell.com wrote:
> > >
> > > So I believe it should be a mandatory runtime dependency due to needing
> > > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > > this then no?
> > 
> > This was nagging me all night, and I was thinking the last time I had to
> > use this it was indeed a runtime dependency. Sorry for the noise on
> > this.
> > 
> > The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> > module if the dependent drivers are modules.
> > 
> > --
> > Darren Hart
> > VMware Open Source Technology Center
> 
> Even if the others are modules shouldn't module ordering from depmod still DTRT?
> You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was loaded.
> 

I worded that wrong *facepalm*, let me try again...

The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
module if the dependent drivers are built-in.

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
  2017-10-05 17:22                 ` Darren Hart
@ 2017-10-05 17:32                     ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 17:32 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 12:22 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 05, 2017 at 02:47:15PM +0000, Mario.Limonciello@dell.com wrote:
> > > >
> > > > So I believe it should be a mandatory runtime dependency due to needing
> > > > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > > > this then no?
> > >
> > > This was nagging me all night, and I was thinking the last time I had to
> > > use this it was indeed a runtime dependency. Sorry for the noise on
> > > this.
> > >
> > > The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> > > module if the dependent drivers are modules.
> > >
> > > --
> > > Darren Hart
> > > VMware Open Source Technology Center
> >
> > Even if the others are modules shouldn't module ordering from depmod still
> DTRT?
> > You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was
> loaded.
> >
> 
> I worded that wrong *facepalm*, let me try again...
> 
> The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> module if the dependent drivers are built-in.
> 

OK got it.  I've got Kconfig adjusted for this.  Unlike DELL_SMBIOS, 
DELL_WMI_DESCRIPTOR could still be used on it's own.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
@ 2017-10-05 17:32                     ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 17:32 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 12:22 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI
> descriptor into it's own driver
> 
> On Thu, Oct 05, 2017 at 02:47:15PM +0000, Mario.Limonciello@dell.com wrote:
> > > >
> > > > So I believe it should be a mandatory runtime dependency due to needing
> > > > the symbol dell_wmi_get_interface_version.  Depmod should be handling
> > > > this then no?
> > >
> > > This was nagging me all night, and I was thinking the last time I had to
> > > use this it was indeed a runtime dependency. Sorry for the noise on
> > > this.
> > >
> > > The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> > > module if the dependent drivers are modules.
> > >
> > > --
> > > Darren Hart
> > > VMware Open Source Technology Center
> >
> > Even if the others are modules shouldn't module ordering from depmod still
> DTRT?
> > You still won't be able to load dell-wmi.ko until dell-wmi-descriptor.ko was
> loaded.
> >
> 
> I worded that wrong *facepalm*, let me try again...
> 
> The kconfig needs to be setup such that dell-wmi-descriptor cannot be a
> module if the dependent drivers are built-in.
> 

OK got it.  I've got Kconfig adjusted for this.  Unlike DELL_SMBIOS, 
DELL_WMI_DESCRIPTOR could still be used on it's own.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 16:26           ` Greg KH
@ 2017-10-05 17:39             ` Darren Hart
  2017-10-05 18:47               ` Greg KH
  0 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05 17:39 UTC (permalink / raw)
  To: Greg KH
  Cc: Pali Rohár, Mario.Limonciello, andy.shevchenko,
	linux-kernel, platform-driver-x86, luto, quasisec, rjw, mjg59,
	hch

On Thu, Oct 05, 2017 at 06:26:28PM +0200, Greg KH wrote:
> On Thu, Oct 05, 2017 at 05:51:56PM +0200, Pali Rohár wrote:
> > On Thursday 05 October 2017 17:42:14 Greg KH wrote:
> > > > > > --- /dev/null
> > > > > > +++ b/include/uapi/linux/wmi.h
> > > > > > @@ -0,0 +1,10 @@
> > > > > > +#ifndef _UAPI_LINUX_WMI_H
> > > > > > +#define _UAPI_LINUX_WMI_H
> > > > > > +
> > > > > > +#define WMI_IOC 'W'
> > > > > > +#define WMI_IO(instance)	_IO(WMI_IOC, instance)
> > > > > > +#define WMI_IOR(instance)	_IOR(WMI_IOC, instance, void*)
> > > > > > +#define WMI_IOW(instance)	_IOW(WMI_IOC, instance, void*)
> > > > > > +#define WMI_IOWR(instance)	_IOWR(WMI_IOC, instance, void*)
> > > > > 
> > > > > Ugh, void *, this is going to be "fun"...
> > > > > 
> > > > > My comments on just how fun is left for the actual driver that attempted
> > > > > to implement these...
> > > > > 
> > > > 
> > > > So until in kernel MOF parsing is available you can't predict the format of
> > > > what an individual ACPI method will expect for its input.  Even when the in
> > > > kernel MOF parsing is made available the data types may be complex structures.
> > > 
> > > 
> > > I have no idea what MOF is, what "parsing" is involved, or how in the
> > > world ACPI got involved here...
> > > 
> > > good luck!
> > > 
> > > greg k-h
> > 
> > Hi Greg! Simple description: In ACPI is stored binary MOF buffer which
> > describe format (function name, parameters, sizeof and type of
> > parameters, etc) for all those calls.
> > 
> > Basically it is what should be used for checking if userspace pass
> > correct "buffer" via ioctl to WMI.
> > 
> > But that binary MOF is undocumented, invented by Microsoft... and
> > present in every one ACPI BIOS notebook (which uses WMI). It is
> > de-facto industrial standard, just tools for encoding/decoding it are
> > only for Microsoft Windows systems.
> > 
> > I was able to decipher that format and wrote simple userspace parser:
> > https://github.com/pali/bmfdec
> > 
> > Funny part is that format is not encrypted, but compressed by DMSDOS
> > compatible compression algorithm :-) You probably would remember old
> > FAT16 days with compression...
> > 
> > Hope that it helps you to understand it.
> 
> It does, thanks.  And as we now understand it (I'm guessing it had to be
> semi-understood in the older wmi drivers already), validating it
> properly seems to be the key for creating an interface that we "know" to
> be safe.
> 

We don't use the MOF data in any of the existing wmi drivers, because
they are all oddities which map to kernel managed subsystems (hotkeys,
LED control, RF Kill switches) rather than what WMI (Windows
Manageability Interface) was designed for. The intent of these patches
to enable that management aspect of the platform.

This is the biggest hurdle for WMI support.

WMI was designed to bypass the OS, and is used in consumer devices
intended to run Windows. This leads to an interface that is very vendor
specific and not consistently broken up into nice functional blocks.

Vendors would like to use this interface in Linux as it is being used in
Windows. Specifically, they want to be able to have a generic system in
the kernel which allows the WMI mechanism to be used by userspace,
without the need to patch the kernel for every platform.

This conflicts with the Linux approach, and I've worked with Mario,
Pali, and others to try to bridge this gap with something more
acceptable.

MOF parsing is typically done in userspace, but by doing it in the
kernel, we can do at least some amount of message auditing within the
kernel in a generic way. So long as vendors continue using the same
GUIDs and provide proper MOF data, the kernel wouldn't need to be
changed. New GUIDs require new drivers, which must create the function
ops to get the char device created.

I thought this served as a pragmatic bridge between the two approaches.

This particular driver, doesn't have the benefit of the MOF data. It is
a halfway point intended to eliminate the SMI access to SMBIOS and
replace it with the WMI access, which uses an op region instead of
passing a physical memory pointer to SMM - but doesn't improve on the
message audit of the existing mechanism (but it shouldn't make it any
worse either).

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  2017-10-05 15:12       ` Mario.Limonciello
  (?)
@ 2017-10-05 17:57       ` Darren Hart
  2017-10-05 19:47           ` Mario.Limonciello
  -1 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-05 17:57 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

On Thu, Oct 05, 2017 at 03:12:46PM +0000, Mario.Limonciello@dell.com wrote:

> > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > > index f0b97cb8e449..ef597f440d2e 100644
> > > --- a/drivers/platform/x86/Kconfig
> > > +++ b/drivers/platform/x86/Kconfig
> > > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> > >
> > >  config DELL_SMBIOS
> > >  	tristate "Dell SMBIOS calling interface"
> > > -	depends on DELL_SMBIOS_SMM
> > > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> > >  	---help---
> > >  	This module provides common functions for kernel modules using
> > >  	Dell SMBIOS.
> > 
> > You use select DELL_SMBIOS below, which implies this modules should be
> > invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> > option at all now, they can select DELL_SMBIOS_WMI and or
> > DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> > 
> So when you say make invisible, does that mean that it should never show
> up in make menuconfig and just be implicitly selected?

Right. It shouldn't have a prompt.

> 
> When I was adjusting Kconfig for your other feedback I noticed setting something
> to "select $DRIVER" that invisible driver does show up just can't be turned off.
> Is that what you mean?

No, I mean eliminate the menu entry by eliminating the prompt.

> 
> > > diff --git a/drivers/platform/x86/dell-smbios-wmi.c
> > b/drivers/platform/x86/dell-smbios-wmi.c
> > > +static void __init parse_b1_table(const struct dmi_header *dm)
> > > +{
> > > +	struct misc_bios_flags_structure *flags =
> > > +	container_of(dm, struct misc_bios_flags_structure, header);
> > > +
> > > +	/* 4 bytes header, and one word of flags */
> > 
> > Assuming specifically 8 bytes of flags, independent of arch?
> 
> Well platform/drivers/*x86*...

I was thinking 32b vs 64b x86 which have a different definition of word size.

(and depending on context, even that changes)

So... "8 bytes" ? I presume this is a fixed length independent of word size?

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures
  2017-10-05 15:02       ` Mario.Limonciello
  (?)
@ 2017-10-05 18:22       ` Andy Shevchenko
  -1 siblings, 0 replies; 93+ messages in thread
From: Andy Shevchenko @ 2017-10-05 18:22 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: dvhart, linux-kernel, Platform Driver, Andy Lutomirski, quasisec,
	Pali Rohár, Rafael J. Wysocki, mjg59, Christoph Hellwig,
	Greg KH

On Thu, Oct 5, 2017 at 6:02 PM,  <Mario.Limonciello@dell.com> wrote:

>> > -       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0)
>> > -               dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature
>> (%8ph)\n",
>> > +       if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
>> > +               dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature
>> (%8ph)\n",
>>
>> A nit: ping-pong programming detected.
>> Looks like current patch 2 should go at least after this one.

> I'll re-order them, but either way both patches are touching these lines in some
> way.

Yeah, I noticed as well.

The rule of thumb is to arrange such small and non-so-important clean
ups at the tail of the series (as possible).

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 17:39             ` Darren Hart
@ 2017-10-05 18:47               ` Greg KH
  2017-10-05 19:03                   ` Mario.Limonciello
  0 siblings, 1 reply; 93+ messages in thread
From: Greg KH @ 2017-10-05 18:47 UTC (permalink / raw)
  To: Darren Hart
  Cc: Pali Rohár, Mario.Limonciello, andy.shevchenko,
	linux-kernel, platform-driver-x86, luto, quasisec, rjw, mjg59,
	hch

On Thu, Oct 05, 2017 at 10:39:25AM -0700, Darren Hart wrote:
> > It does, thanks.  And as we now understand it (I'm guessing it had to be
> > semi-understood in the older wmi drivers already), validating it
> > properly seems to be the key for creating an interface that we "know" to
> > be safe.
> > 
> 
> We don't use the MOF data in any of the existing wmi drivers, because
> they are all oddities which map to kernel managed subsystems (hotkeys,
> LED control, RF Kill switches) rather than what WMI (Windows
> Manageability Interface) was designed for. The intent of these patches
> to enable that management aspect of the platform.
> 
> This is the biggest hurdle for WMI support.
> 
> WMI was designed to bypass the OS, and is used in consumer devices
> intended to run Windows. This leads to an interface that is very vendor
> specific and not consistently broken up into nice functional blocks.
> 
> Vendors would like to use this interface in Linux as it is being used in
> Windows. Specifically, they want to be able to have a generic system in
> the kernel which allows the WMI mechanism to be used by userspace,
> without the need to patch the kernel for every platform.

And how _exactly_ is this interface exposed in Windows?  Is it ad-hoc
with custom kernel drivers written by each vendor?  Or does the OS
provide a "sane" interface for it?

> This conflicts with the Linux approach, and I've worked with Mario,
> Pali, and others to try to bridge this gap with something more
> acceptable.
> 
> MOF parsing is typically done in userspace, but by doing it in the
> kernel, we can do at least some amount of message auditing within the
> kernel in a generic way. So long as vendors continue using the same
> GUIDs and provide proper MOF data, the kernel wouldn't need to be
> changed. New GUIDs require new drivers, which must create the function
> ops to get the char device created.
> 
> I thought this served as a pragmatic bridge between the two approaches.

The code as-is isn't a bridge at all, it's a pass-through tunnel with no
tollbooth.  No parsing is being done that I can see here (if it is,
where exactly was it done?)

> This particular driver, doesn't have the benefit of the MOF data. It is
> a halfway point intended to eliminate the SMI access to SMBIOS and
> replace it with the WMI access, which uses an op region instead of
> passing a physical memory pointer to SMM - but doesn't improve on the
> message audit of the existing mechanism (but it shouldn't make it any
> worse either).

Again, it looks just to be a pass-through, no validation happening at
all, with a random "blob" appended that userspace knows all about, and
the BIOS knows about, but the kernel has no clue.  Given that the kernel
is what is there to protect the BIOS from userspace, that feels really
wrong.

Again, I like my TPM to work, and I don't want a random rootkit exploit
to be able to destroy it :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 18:47               ` Greg KH
@ 2017-10-05 19:03                   ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:03 UTC (permalink / raw)
  To: greg, dvhart
  Cc: pali.rohar, andy.shevchenko, linux-kernel, platform-driver-x86,
	luto, quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 1:47 PM
> To: Darren Hart <dvhart@infradead.org>
> Cc: Pali Rohár <pali.rohar@gmail.com>; Limonciello, Mario
> <Mario_Limonciello@Dell.com>; andy.shevchenko@gmail.com; linux-
> kernel@vger.kernel.org; platform-driver-x86@vger.kernel.org; luto@kernel.org;
> quasisec@google.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> On Thu, Oct 05, 2017 at 10:39:25AM -0700, Darren Hart wrote:
> > > It does, thanks.  And as we now understand it (I'm guessing it had to be
> > > semi-understood in the older wmi drivers already), validating it
> > > properly seems to be the key for creating an interface that we "know" to
> > > be safe.
> > >
> >
> > We don't use the MOF data in any of the existing wmi drivers, because
> > they are all oddities which map to kernel managed subsystems (hotkeys,
> > LED control, RF Kill switches) rather than what WMI (Windows
> > Manageability Interface) was designed for. The intent of these patches
> > to enable that management aspect of the platform.
> >
> > This is the biggest hurdle for WMI support.
> >
> > WMI was designed to bypass the OS, and is used in consumer devices
> > intended to run Windows. This leads to an interface that is very vendor
> > specific and not consistently broken up into nice functional blocks.
> >
> > Vendors would like to use this interface in Linux as it is being used in
> > Windows. Specifically, they want to be able to have a generic system in
> > the kernel which allows the WMI mechanism to be used by userspace,
> > without the need to patch the kernel for every platform.
> 
> And how _exactly_ is this interface exposed in Windows?  Is it ad-hoc
> with custom kernel drivers written by each vendor?  Or does the OS
> provide a "sane" interface for it?

On Windows it's a driver-less solution.  Vendors don't do anything other
than provide the MOF (which describes how the data passed to ASL looks).

When Windows boots up, _WDG is parsed, the binary MOF is loaded into
the WMI repository.  The MOF describes how named objects map to GUIDs
which map to ASL.

>From Powershell or from any application that uses WMI as admin you can 
look up the root namespace and see all objects.  You can pass calls back
and forth.  There's all sorts of examples of it here:
https://msdn.microsoft.com/en-us/library/windows/hardware/dn614028(v=vs.85).aspx

Windows doesn't validate the data when it's passed to ASL and back.
It just knows what it looks like, size of the buffer and relays the information.

It's up to firmware to block the crazy stuff that you can put in a buffer.

> 
> > This conflicts with the Linux approach, and I've worked with Mario,
> > Pali, and others to try to bridge this gap with something more
> > acceptable.
> >
> > MOF parsing is typically done in userspace, but by doing it in the
> > kernel, we can do at least some amount of message auditing within the
> > kernel in a generic way. So long as vendors continue using the same
> > GUIDs and provide proper MOF data, the kernel wouldn't need to be
> > changed. New GUIDs require new drivers, which must create the function
> > ops to get the char device created.
> >
> > I thought this served as a pragmatic bridge between the two approaches.
> 
> The code as-is isn't a bridge at all, it's a pass-through tunnel with no
> tollbooth.  No parsing is being done that I can see here (if it is,
> where exactly was it done?)
> 
> > This particular driver, doesn't have the benefit of the MOF data. It is
> > a halfway point intended to eliminate the SMI access to SMBIOS and
> > replace it with the WMI access, which uses an op region instead of
> > passing a physical memory pointer to SMM - but doesn't improve on the
> > message audit of the existing mechanism (but it shouldn't make it any
> > worse either).
> 
> Again, it looks just to be a pass-through, no validation happening at
> all, with a random "blob" appended that userspace knows all about, and
> the BIOS knows about, but the kernel has no clue.  Given that the kernel
> is what is there to protect the BIOS from userspace, that feels really
> wrong.
> 

It's entirely reasonable that Linux can filter more than Windows
can given there ARE vendor specific drivers in the Linux implementation
of WMI.

I'll add some verification of the supported calls on the system being run
on for v5.  Some of the write once only things can be filtered too here.

> Again, I like my TPM to work, and I don't want a random rootkit exploit
> to be able to destroy it :)

I'd like to however point out you can't kill your TPM from this interface.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
@ 2017-10-05 19:03                   ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:03 UTC (permalink / raw)
  To: greg, dvhart
  Cc: pali.rohar, andy.shevchenko, linux-kernel, platform-driver-x86,
	luto, quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 1:47 PM
> To: Darren Hart <dvhart@infradead.org>
> Cc: Pali Rohár <pali.rohar@gmail.com>; Limonciello, Mario
> <Mario_Limonciello@Dell.com>; andy.shevchenko@gmail.com; linux-
> kernel@vger.kernel.org; platform-driver-x86@vger.kernel.org; luto@kernel.org;
> quasisec@google.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> On Thu, Oct 05, 2017 at 10:39:25AM -0700, Darren Hart wrote:
> > > It does, thanks.  And as we now understand it (I'm guessing it had to be
> > > semi-understood in the older wmi drivers already), validating it
> > > properly seems to be the key for creating an interface that we "know" to
> > > be safe.
> > >
> >
> > We don't use the MOF data in any of the existing wmi drivers, because
> > they are all oddities which map to kernel managed subsystems (hotkeys,
> > LED control, RF Kill switches) rather than what WMI (Windows
> > Manageability Interface) was designed for. The intent of these patches
> > to enable that management aspect of the platform.
> >
> > This is the biggest hurdle for WMI support.
> >
> > WMI was designed to bypass the OS, and is used in consumer devices
> > intended to run Windows. This leads to an interface that is very vendor
> > specific and not consistently broken up into nice functional blocks.
> >
> > Vendors would like to use this interface in Linux as it is being used in
> > Windows. Specifically, they want to be able to have a generic system in
> > the kernel which allows the WMI mechanism to be used by userspace,
> > without the need to patch the kernel for every platform.
> 
> And how _exactly_ is this interface exposed in Windows?  Is it ad-hoc
> with custom kernel drivers written by each vendor?  Or does the OS
> provide a "sane" interface for it?

On Windows it's a driver-less solution.  Vendors don't do anything other
than provide the MOF (which describes how the data passed to ASL looks).

When Windows boots up, _WDG is parsed, the binary MOF is loaded into
the WMI repository.  The MOF describes how named objects map to GUIDs
which map to ASL.

From Powershell or from any application that uses WMI as admin you can 
look up the root namespace and see all objects.  You can pass calls back
and forth.  There's all sorts of examples of it here:
https://msdn.microsoft.com/en-us/library/windows/hardware/dn614028(v=vs.85).aspx

Windows doesn't validate the data when it's passed to ASL and back.
It just knows what it looks like, size of the buffer and relays the information.

It's up to firmware to block the crazy stuff that you can put in a buffer.

> 
> > This conflicts with the Linux approach, and I've worked with Mario,
> > Pali, and others to try to bridge this gap with something more
> > acceptable.
> >
> > MOF parsing is typically done in userspace, but by doing it in the
> > kernel, we can do at least some amount of message auditing within the
> > kernel in a generic way. So long as vendors continue using the same
> > GUIDs and provide proper MOF data, the kernel wouldn't need to be
> > changed. New GUIDs require new drivers, which must create the function
> > ops to get the char device created.
> >
> > I thought this served as a pragmatic bridge between the two approaches.
> 
> The code as-is isn't a bridge at all, it's a pass-through tunnel with no
> tollbooth.  No parsing is being done that I can see here (if it is,
> where exactly was it done?)
> 
> > This particular driver, doesn't have the benefit of the MOF data. It is
> > a halfway point intended to eliminate the SMI access to SMBIOS and
> > replace it with the WMI access, which uses an op region instead of
> > passing a physical memory pointer to SMM - but doesn't improve on the
> > message audit of the existing mechanism (but it shouldn't make it any
> > worse either).
> 
> Again, it looks just to be a pass-through, no validation happening at
> all, with a random "blob" appended that userspace knows all about, and
> the BIOS knows about, but the kernel has no clue.  Given that the kernel
> is what is there to protect the BIOS from userspace, that feels really
> wrong.
> 

It's entirely reasonable that Linux can filter more than Windows
can given there ARE vendor specific drivers in the Linux implementation
of WMI.

I'll add some verification of the supported calls on the system being run
on for v5.  Some of the write once only things can be filtered too here.

> Again, I like my TPM to work, and I don't want a random rootkit exploit
> to be able to destroy it :)

I'd like to however point out you can't kill your TPM from this interface.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 19:03                   ` Mario.Limonciello
  (?)
@ 2017-10-05 19:09                   ` Greg KH
  2017-10-05 19:32                     ` Pali Rohár
                                       ` (2 more replies)
  -1 siblings, 3 replies; 93+ messages in thread
From: Greg KH @ 2017-10-05 19:09 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: dvhart, pali.rohar, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Greg KH [mailto:greg@kroah.com]
> > Sent: Thursday, October 5, 2017 1:47 PM
> > To: Darren Hart <dvhart@infradead.org>
> > Cc: Pali Rohár <pali.rohar@gmail.com>; Limonciello, Mario
> > <Mario_Limonciello@Dell.com>; andy.shevchenko@gmail.com; linux-
> > kernel@vger.kernel.org; platform-driver-x86@vger.kernel.org; luto@kernel.org;
> > quasisec@google.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> > Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> > requested by drivers
> > 
> > On Thu, Oct 05, 2017 at 10:39:25AM -0700, Darren Hart wrote:
> > > > It does, thanks.  And as we now understand it (I'm guessing it had to be
> > > > semi-understood in the older wmi drivers already), validating it
> > > > properly seems to be the key for creating an interface that we "know" to
> > > > be safe.
> > > >
> > >
> > > We don't use the MOF data in any of the existing wmi drivers, because
> > > they are all oddities which map to kernel managed subsystems (hotkeys,
> > > LED control, RF Kill switches) rather than what WMI (Windows
> > > Manageability Interface) was designed for. The intent of these patches
> > > to enable that management aspect of the platform.
> > >
> > > This is the biggest hurdle for WMI support.
> > >
> > > WMI was designed to bypass the OS, and is used in consumer devices
> > > intended to run Windows. This leads to an interface that is very vendor
> > > specific and not consistently broken up into nice functional blocks.
> > >
> > > Vendors would like to use this interface in Linux as it is being used in
> > > Windows. Specifically, they want to be able to have a generic system in
> > > the kernel which allows the WMI mechanism to be used by userspace,
> > > without the need to patch the kernel for every platform.
> > 
> > And how _exactly_ is this interface exposed in Windows?  Is it ad-hoc
> > with custom kernel drivers written by each vendor?  Or does the OS
> > provide a "sane" interface for it?
> 
> On Windows it's a driver-less solution.  Vendors don't do anything other
> than provide the MOF (which describes how the data passed to ASL looks).

How do they "provide it"?

> When Windows boots up, _WDG is parsed,

Who parses it, the Windows kernel?

> the binary MOF is loaded into the WMI repository.

Who does the loading?  Where does the "WMI repository" live?

> The MOF describes how named objects map to GUIDs which map to ASL.

So this all lives in kernelspace?

> From Powershell or from any application that uses WMI as admin you can 
> look up the root namespace and see all objects.

And what is the interface that powershell uses to get that information
from the kerenel?

> You can pass calls back
> and forth.  There's all sorts of examples of it here:
> https://msdn.microsoft.com/en-us/library/windows/hardware/dn614028(v=vs.85).aspx
> 
> Windows doesn't validate the data when it's passed to ASL and back.

How do you know?  Who does the "passing"?  The Windows kernel is just a
blind pipe?  If so, then what does the mappings?

> It just knows what it looks like, size of the buffer and relays the information.

relays from/to what?

> It's up to firmware to block the crazy stuff that you can put in a buffer.

So userspace can pass any blob it wants to the firmware through this
interface and the kernel does not parse anything?  How is that
"protected"?

> > Again, I like my TPM to work, and I don't want a random rootkit exploit
> > to be able to destroy it :)
> 
> I'd like to however point out you can't kill your TPM from this interface.

On _your_ platform, can you guarantee it on any other platform?  :)

And I strongly doubt your BIOS would stand up to a good fuzzer, almost
no firmware can.  Heck, the kernel even has issues, we've been fixing
them for years...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 19:09                   ` Greg KH
@ 2017-10-05 19:32                     ` Pali Rohár
  2017-10-05 19:39                         ` Mario.Limonciello
  2017-10-05 19:34                       ` Mario.Limonciello
  2017-10-05 20:58                     ` Darren Hart
  2 siblings, 1 reply; 93+ messages in thread
From: Pali Rohár @ 2017-10-05 19:32 UTC (permalink / raw)
  To: Greg KH
  Cc: Mario.Limonciello, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

Hi Greg! I would answer some of your question...

On Thursday 05 October 2017 21:09:48 Greg KH wrote:
> On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
> > On Windows it's a driver-less solution.  Vendors don't do anything other
> > than provide the MOF (which describes how the data passed to ASL looks).
> 
> How do they "provide it"?

I described it in my email. Binary MOF is in ACPI buffer returned by
well known ACPI function.

Vendor fills into DSDT ACPI table (part of BIOS firmware) at correct
place binary MOF buffer and ACPI interpreter which is part of kernel can
access it.

> > When Windows boots up, _WDG is parsed,
> 
> Who parses it, the Windows kernel?

Yes, some Windows kernel driver parses ACPI's _WDG and also binary MOF
buffer from ACPI.

> > the binary MOF is loaded into the WMI repository.
> 
> Who does the loading?  Where does the "WMI repository" live?

IIRC it can be loaded by both userspace and kernel. No idea about
permissions, but ACPI/WMI kernel driver loads that binary MOF from ACPI
table.

Via some tools user can loads also its own MOF buffer into "WMI
repository".

> > It's up to firmware to block the crazy stuff that you can put in a buffer.
> 
> So userspace can pass any blob it wants to the firmware through this
> interface and the kernel does not parse anything?  How is that
> "protected"?

In that binary MOF is described C++ style object system and mapping from
those class/objects into ACPI methods. With information how are mapped
object method parameters (e.g. integer, strings, structures...) into
ACPI buffer. And in Windows you can IIRC call those class/objects
defined in MOF and something (I bet Windows kernel driver) translate
class method parameters (integers, strings, ...) into kernel ACPI
buffers and call correct ACPI method. So there is just protection that
method is called with correct "signature".

But IIRC Dell describe in its MOF object system, that there is one class
with just one method which has parameter "String" at specified size --
which maps 1:1 to ACPI buffer.

-- 
Pali Rohár
pali.rohar@gmail.com

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 19:09                   ` Greg KH
@ 2017-10-05 19:34                       ` Mario.Limonciello
  2017-10-05 19:34                       ` Mario.Limonciello
  2017-10-05 20:58                     ` Darren Hart
  2 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:34 UTC (permalink / raw)
  To: greg
  Cc: dvhart, pali.rohar, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:10 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; pali.rohar@gmail.com; andy.shevchenko@gmail.com;
> linux-kernel@vger.kernel.org; platform-driver-x86@vger.kernel.org;
> luto@kernel.org; quasisec@google.com; rjw@rjwysocki.net;
> mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Greg KH [mailto:greg@kroah.com]
> > > Sent: Thursday, October 5, 2017 1:47 PM
> > > To: Darren Hart <dvhart@infradead.org>
> > > Cc: Pali Rohár <pali.rohar@gmail.com>; Limonciello, Mario
> > > <Mario_Limonciello@Dell.com>; andy.shevchenko@gmail.com; linux-
> > > kernel@vger.kernel.org; platform-driver-x86@vger.kernel.org;
> luto@kernel.org;
> > > quasisec@google.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> > > Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices
> when
> > > requested by drivers
> > >
> > > On Thu, Oct 05, 2017 at 10:39:25AM -0700, Darren Hart wrote:
> > > > > It does, thanks.  And as we now understand it (I'm guessing it had to be
> > > > > semi-understood in the older wmi drivers already), validating it
> > > > > properly seems to be the key for creating an interface that we "know" to
> > > > > be safe.
> > > > >
> > > >
> > > > We don't use the MOF data in any of the existing wmi drivers, because
> > > > they are all oddities which map to kernel managed subsystems (hotkeys,
> > > > LED control, RF Kill switches) rather than what WMI (Windows
> > > > Manageability Interface) was designed for. The intent of these patches
> > > > to enable that management aspect of the platform.
> > > >
> > > > This is the biggest hurdle for WMI support.
> > > >
> > > > WMI was designed to bypass the OS, and is used in consumer devices
> > > > intended to run Windows. This leads to an interface that is very vendor
> > > > specific and not consistently broken up into nice functional blocks.
> > > >
> > > > Vendors would like to use this interface in Linux as it is being used in
> > > > Windows. Specifically, they want to be able to have a generic system in
> > > > the kernel which allows the WMI mechanism to be used by userspace,
> > > > without the need to patch the kernel for every platform.
> > >
> > > And how _exactly_ is this interface exposed in Windows?  Is it ad-hoc
> > > with custom kernel drivers written by each vendor?  Or does the OS
> > > provide a "sane" interface for it?
> >
> > On Windows it's a driver-less solution.  Vendors don't do anything other
> > than provide the MOF (which describes how the data passed to ASL looks).
> 
> How do they "provide it"?

In that link I shared you can see there is a GUID that maps to the one that
has the binary MOF.  The MOF is compiled when the BIOS is built using
mofcomp.exe on Windows into a binary format.

> 
> > When Windows boots up, _WDG is parsed,
> 
> Who parses it, the Windows kernel?
> 
Presumably?  Wmiacpi.sys.  I believe it to be user side, but I don't know Windows
source code and where they draw the line.

> > the binary MOF is loaded into the WMI repository.
> 
> Who does the loading?  Where does the "WMI repository" live?

Windows OS does this.  Same wmiacpi.sys I believe.  The WMI repository is a
database that's on disk.  It doesn't just do these things, it contains MOF (managed
object format) for a bunch of stuff.  You can tweak way too many knobs with it.

It's store in "%windir%System32\Wbem\Repository"
There's more info about how it works here
https://technet.microsoft.com/en-us/library/cc753534.aspx

I do have a longer term vision for Linux that CIMOM tools will be able to parse
what the kernel shares in sysfs from the WMI bus and know how to work with 
these character devices.

My patch series is the first part of that, and there are still a lot of other steps.

> 
> > The MOF describes how named objects map to GUIDs which map to ASL.
> 
> So this all lives in kernelspace?
> 
> > From Powershell or from any application that uses WMI as admin you can
> > look up the root namespace and see all objects.
> 
> And what is the interface that powershell uses to get that information
> from the kerenel?

You query the WMI repository for available namespaces.  The stuff in the binary
MOF will have registered under a particular namespace.
When you look at that namespace, you can query classes within it.

Some of those classes will enumerate objects that you can read attributes.
If you're calling a method, you need to fill in the arguments as described in the
MOF.  You can query the namespace to tell what those arguments look like.

So going to my patch series, "dell-wmi-descriptor" would map out to a class
In the namespace.  You can query it to see what the size of the buffer looks
like and what the interface is.

The class that in Linux represents "dell-smbios-wmi" would map to another one.  
You can't enumerate it since It's not a data type, but you can look at what arguments
it takes and if you provide the arguments it expects you can call it and the OS
will pass it to the ASL and return the result.

It's not very different than what I proposed in my patch series.

> 
> > You can pass calls back
> > and forth.  There's all sorts of examples of it here:
> > https://msdn.microsoft.com/en-
> us/library/windows/hardware/dn614028(v=vs.85).aspx
> >
> > Windows doesn't validate the data when it's passed to ASL and back.
> 
> How do you know?  Who does the "passing"?  The Windows kernel is just a
> blind pipe?  If so, then what does the mappings?

The application or cmdlet calling the method passes the data as described
in the MOF which can be queried from the namespace.

Windows doesn't know anything about what that data is, it can't.  All it knows
is the format of the data as described in the MOF.  It knows which ASL method
to call by the GUID in the MOF which matches the GUID in _WDG which contains
the ASL method.

I can't confidently know which parts of that are done by Windows kernel and
which are handled by Windows userspace.  All I know is that from a "consumer"
of this the application or cmdlet runs in userspace. 

> 
> > It just knows what it looks like, size of the buffer and relays the information.
> 
> relays from/to what?

The ASL method.

Let me try to explain better.
_WDG contains a bunch of objects.
Each of those objects has a GUID, instance count, data type, and two letters that
correspond to an ASL method.
One of those objects is binary MOF.

Binary MOF contains a description of namespaces, objects, their formats etc.
It also contains classes that map to GUIDs.

Windows boots up, some process parses _WDG.
It looks at binary MOF, decompiles/parses it.
It maps the classes to GUIDs, the GUIDs to ASL methods.

You call an object of a class, that will then call the ASL method.

Make more sense?
> 
> > It's up to firmware to block the crazy stuff that you can put in a buffer.
> 
> So userspace can pass any blob it wants to the firmware through this
> interface and the kernel does not parse anything?  How is that
> "protected"?
> 
> > > Again, I like my TPM to work, and I don't want a random rootkit exploit
> > > to be able to destroy it :)
> >
> > I'd like to however point out you can't kill your TPM from this interface.
> 
> On _your_ platform, can you guarantee it on any other platform?  :)
> 
> And I strongly doubt your BIOS would stand up to a good fuzzer, almost
> no firmware can.  Heck, the kernel even has issues, we've been fixing
> them for years...
> 
Well that's software for you.  It will always have problems, but 

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
@ 2017-10-05 19:34                       ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:34 UTC (permalink / raw)
  To: greg
  Cc: dvhart, pali.rohar, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Greg KH [mailto:greg@kroah.com]
> Sent: Thursday, October 5, 2017 2:10 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; pali.rohar@gmail.com; andy.shevchenko@gmail.com;
> linux-kernel@vger.kernel.org; platform-driver-x86@vger.kernel.org;
> luto@kernel.org; quasisec@google.com; rjw@rjwysocki.net;
> mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Greg KH [mailto:greg@kroah.com]
> > > Sent: Thursday, October 5, 2017 1:47 PM
> > > To: Darren Hart <dvhart@infradead.org>
> > > Cc: Pali Rohár <pali.rohar@gmail.com>; Limonciello, Mario
> > > <Mario_Limonciello@Dell.com>; andy.shevchenko@gmail.com; linux-
> > > kernel@vger.kernel.org; platform-driver-x86@vger.kernel.org;
> luto@kernel.org;
> > > quasisec@google.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> > > Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices
> when
> > > requested by drivers
> > >
> > > On Thu, Oct 05, 2017 at 10:39:25AM -0700, Darren Hart wrote:
> > > > > It does, thanks.  And as we now understand it (I'm guessing it had to be
> > > > > semi-understood in the older wmi drivers already), validating it
> > > > > properly seems to be the key for creating an interface that we "know" to
> > > > > be safe.
> > > > >
> > > >
> > > > We don't use the MOF data in any of the existing wmi drivers, because
> > > > they are all oddities which map to kernel managed subsystems (hotkeys,
> > > > LED control, RF Kill switches) rather than what WMI (Windows
> > > > Manageability Interface) was designed for. The intent of these patches
> > > > to enable that management aspect of the platform.
> > > >
> > > > This is the biggest hurdle for WMI support.
> > > >
> > > > WMI was designed to bypass the OS, and is used in consumer devices
> > > > intended to run Windows. This leads to an interface that is very vendor
> > > > specific and not consistently broken up into nice functional blocks.
> > > >
> > > > Vendors would like to use this interface in Linux as it is being used in
> > > > Windows. Specifically, they want to be able to have a generic system in
> > > > the kernel which allows the WMI mechanism to be used by userspace,
> > > > without the need to patch the kernel for every platform.
> > >
> > > And how _exactly_ is this interface exposed in Windows?  Is it ad-hoc
> > > with custom kernel drivers written by each vendor?  Or does the OS
> > > provide a "sane" interface for it?
> >
> > On Windows it's a driver-less solution.  Vendors don't do anything other
> > than provide the MOF (which describes how the data passed to ASL looks).
> 
> How do they "provide it"?

In that link I shared you can see there is a GUID that maps to the one that
has the binary MOF.  The MOF is compiled when the BIOS is built using
mofcomp.exe on Windows into a binary format.

> 
> > When Windows boots up, _WDG is parsed,
> 
> Who parses it, the Windows kernel?
> 
Presumably?  Wmiacpi.sys.  I believe it to be user side, but I don't know Windows
source code and where they draw the line.

> > the binary MOF is loaded into the WMI repository.
> 
> Who does the loading?  Where does the "WMI repository" live?

Windows OS does this.  Same wmiacpi.sys I believe.  The WMI repository is a
database that's on disk.  It doesn't just do these things, it contains MOF (managed
object format) for a bunch of stuff.  You can tweak way too many knobs with it.

It's store in "%windir%System32\Wbem\Repository"
There's more info about how it works here
https://technet.microsoft.com/en-us/library/cc753534.aspx

I do have a longer term vision for Linux that CIMOM tools will be able to parse
what the kernel shares in sysfs from the WMI bus and know how to work with 
these character devices.

My patch series is the first part of that, and there are still a lot of other steps.

> 
> > The MOF describes how named objects map to GUIDs which map to ASL.
> 
> So this all lives in kernelspace?
> 
> > From Powershell or from any application that uses WMI as admin you can
> > look up the root namespace and see all objects.
> 
> And what is the interface that powershell uses to get that information
> from the kerenel?

You query the WMI repository for available namespaces.  The stuff in the binary
MOF will have registered under a particular namespace.
When you look at that namespace, you can query classes within it.

Some of those classes will enumerate objects that you can read attributes.
If you're calling a method, you need to fill in the arguments as described in the
MOF.  You can query the namespace to tell what those arguments look like.

So going to my patch series, "dell-wmi-descriptor" would map out to a class
In the namespace.  You can query it to see what the size of the buffer looks
like and what the interface is.

The class that in Linux represents "dell-smbios-wmi" would map to another one.  
You can't enumerate it since It's not a data type, but you can look at what arguments
it takes and if you provide the arguments it expects you can call it and the OS
will pass it to the ASL and return the result.

It's not very different than what I proposed in my patch series.

> 
> > You can pass calls back
> > and forth.  There's all sorts of examples of it here:
> > https://msdn.microsoft.com/en-
> us/library/windows/hardware/dn614028(v=vs.85).aspx
> >
> > Windows doesn't validate the data when it's passed to ASL and back.
> 
> How do you know?  Who does the "passing"?  The Windows kernel is just a
> blind pipe?  If so, then what does the mappings?

The application or cmdlet calling the method passes the data as described
in the MOF which can be queried from the namespace.

Windows doesn't know anything about what that data is, it can't.  All it knows
is the format of the data as described in the MOF.  It knows which ASL method
to call by the GUID in the MOF which matches the GUID in _WDG which contains
the ASL method.

I can't confidently know which parts of that are done by Windows kernel and
which are handled by Windows userspace.  All I know is that from a "consumer"
of this the application or cmdlet runs in userspace. 

> 
> > It just knows what it looks like, size of the buffer and relays the information.
> 
> relays from/to what?

The ASL method.

Let me try to explain better.
_WDG contains a bunch of objects.
Each of those objects has a GUID, instance count, data type, and two letters that
correspond to an ASL method.
One of those objects is binary MOF.

Binary MOF contains a description of namespaces, objects, their formats etc.
It also contains classes that map to GUIDs.

Windows boots up, some process parses _WDG.
It looks at binary MOF, decompiles/parses it.
It maps the classes to GUIDs, the GUIDs to ASL methods.

You call an object of a class, that will then call the ASL method.

Make more sense?
> 
> > It's up to firmware to block the crazy stuff that you can put in a buffer.
> 
> So userspace can pass any blob it wants to the firmware through this
> interface and the kernel does not parse anything?  How is that
> "protected"?
> 
> > > Again, I like my TPM to work, and I don't want a random rootkit exploit
> > > to be able to destroy it :)
> >
> > I'd like to however point out you can't kill your TPM from this interface.
> 
> On _your_ platform, can you guarantee it on any other platform?  :)
> 
> And I strongly doubt your BIOS would stand up to a good fuzzer, almost
> no firmware can.  Heck, the kernel even has issues, we've been fixing
> them for years...
> 
Well that's software for you.  It will always have problems, but 

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 19:32                     ` Pali Rohár
@ 2017-10-05 19:39                         ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:39 UTC (permalink / raw)
  To: pali.rohar, greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Pali Rohár [mailto:pali.rohar@gmail.com]
> Sent: Thursday, October 5, 2017 2:33 PM
> To: Greg KH <greg@kroah.com>
> Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; dvhart@infradead.org;
> andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-driver-
> x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> Hi Greg! I would answer some of your question...
> 
> On Thursday 05 October 2017 21:09:48 Greg KH wrote:
> > On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
> > > On Windows it's a driver-less solution.  Vendors don't do anything other
> > > than provide the MOF (which describes how the data passed to ASL looks).
> >
> > How do they "provide it"?
> 
> I described it in my email. Binary MOF is in ACPI buffer returned by
> well known ACPI function.
> 
> Vendor fills into DSDT ACPI table (part of BIOS firmware) at correct
> place binary MOF buffer and ACPI interpreter which is part of kernel can
> access it.
> 
> > > When Windows boots up, _WDG is parsed,
> >
> > Who parses it, the Windows kernel?
> 
> Yes, some Windows kernel driver parses ACPI's _WDG and also binary MOF
> buffer from ACPI.
> 
> > > the binary MOF is loaded into the WMI repository.
> >
> > Who does the loading?  Where does the "WMI repository" live?
> 
> IIRC it can be loaded by both userspace and kernel. No idea about
> permissions, but ACPI/WMI kernel driver loads that binary MOF from ACPI
> table.
> 
> Via some tools user can loads also its own MOF buffer into "WMI
> repository".
> 
> > > It's up to firmware to block the crazy stuff that you can put in a buffer.
> >
> > So userspace can pass any blob it wants to the firmware through this
> > interface and the kernel does not parse anything?  How is that
> > "protected"?
> 
> In that binary MOF is described C++ style object system and mapping from
> those class/objects into ACPI methods. With information how are mapped
> object method parameters (e.g. integer, strings, structures...) into
> ACPI buffer. And in Windows you can IIRC call those class/objects
> defined in MOF and something (I bet Windows kernel driver) translate
> class method parameters (integers, strings, ...) into kernel ACPI
> buffers and call correct ACPI method. So there is just protection that
> method is called with correct "signature".
> 
> But IIRC Dell describe in its MOF object system, that there is one class
> with just one method which has parameter "String" at specified size --
> which maps 1:1 to ACPI buffer.
> 

In the current MOF implementation for Dell SMBIOS calling interface yes similar
to your description.
One class describes data filled with bytes, and then the class for making the 
call will use that as an argument.

class BDat {
    [WmiDataId(1), read, write, Description("data")] uint8 Bytes[WMI_PACKAGE_SIZE];                  };

void DoBFn([in, out, Description("Fn buf")] BDat Data);

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
@ 2017-10-05 19:39                         ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:39 UTC (permalink / raw)
  To: pali.rohar, greg
  Cc: dvhart, andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, rjw, mjg59, hch

> -----Original Message-----
> From: Pali Rohár [mailto:pali.rohar@gmail.com]
> Sent: Thursday, October 5, 2017 2:33 PM
> To: Greg KH <greg@kroah.com>
> Cc: Limonciello, Mario <Mario_Limonciello@Dell.com>; dvhart@infradead.org;
> andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-driver-
> x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when
> requested by drivers
> 
> Hi Greg! I would answer some of your question...
> 
> On Thursday 05 October 2017 21:09:48 Greg KH wrote:
> > On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
> > > On Windows it's a driver-less solution.  Vendors don't do anything other
> > > than provide the MOF (which describes how the data passed to ASL looks).
> >
> > How do they "provide it"?
> 
> I described it in my email. Binary MOF is in ACPI buffer returned by
> well known ACPI function.
> 
> Vendor fills into DSDT ACPI table (part of BIOS firmware) at correct
> place binary MOF buffer and ACPI interpreter which is part of kernel can
> access it.
> 
> > > When Windows boots up, _WDG is parsed,
> >
> > Who parses it, the Windows kernel?
> 
> Yes, some Windows kernel driver parses ACPI's _WDG and also binary MOF
> buffer from ACPI.
> 
> > > the binary MOF is loaded into the WMI repository.
> >
> > Who does the loading?  Where does the "WMI repository" live?
> 
> IIRC it can be loaded by both userspace and kernel. No idea about
> permissions, but ACPI/WMI kernel driver loads that binary MOF from ACPI
> table.
> 
> Via some tools user can loads also its own MOF buffer into "WMI
> repository".
> 
> > > It's up to firmware to block the crazy stuff that you can put in a buffer.
> >
> > So userspace can pass any blob it wants to the firmware through this
> > interface and the kernel does not parse anything?  How is that
> > "protected"?
> 
> In that binary MOF is described C++ style object system and mapping from
> those class/objects into ACPI methods. With information how are mapped
> object method parameters (e.g. integer, strings, structures...) into
> ACPI buffer. And in Windows you can IIRC call those class/objects
> defined in MOF and something (I bet Windows kernel driver) translate
> class method parameters (integers, strings, ...) into kernel ACPI
> buffers and call correct ACPI method. So there is just protection that
> method is called with correct "signature".
> 
> But IIRC Dell describe in its MOF object system, that there is one class
> with just one method which has parameter "String" at specified size --
> which maps 1:1 to ACPI buffer.
> 

In the current MOF implementation for Dell SMBIOS calling interface yes similar
to your description.
One class describes data filled with bytes, and then the class for making the 
call will use that as an argument.

class BDat {
    [WmiDataId(1), read, write, Description("data")] uint8 Bytes[WMI_PACKAGE_SIZE];                  };

void DoBFn([in, out, Description("Fn buf")] BDat Data);


^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  2017-10-05 17:57       ` Darren Hart
@ 2017-10-05 19:47           ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:47 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 12:58 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> dispatcher driver
> 
> On Thu, Oct 05, 2017 at 03:12:46PM +0000, Mario.Limonciello@dell.com wrote:
> 
> > > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > > > index f0b97cb8e449..ef597f440d2e 100644
> > > > --- a/drivers/platform/x86/Kconfig
> > > > +++ b/drivers/platform/x86/Kconfig
> > > > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> > > >
> > > >  config DELL_SMBIOS
> > > >  	tristate "Dell SMBIOS calling interface"
> > > > -	depends on DELL_SMBIOS_SMM
> > > > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> > > >  	---help---
> > > >  	This module provides common functions for kernel modules using
> > > >  	Dell SMBIOS.
> > >
> > > You use select DELL_SMBIOS below, which implies this modules should be
> > > invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> > > option at all now, they can select DELL_SMBIOS_WMI and or
> > > DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> > >
> > So when you say make invisible, does that mean that it should never show
> > up in make menuconfig and just be implicitly selected?
> 
> Right. It shouldn't have a prompt.
> 
> >
> > When I was adjusting Kconfig for your other feedback I noticed setting
> something
> > to "select $DRIVER" that invisible driver does show up just can't be turned off.
> > Is that what you mean?
> 
> No, I mean eliminate the menu entry by eliminating the prompt.
Do you have an example of a driver that does it this way? 
When I tried, CONFIG_DELL_WMI_DESCRIPTOR doesn't get saved to .config
and then doesn't compile into a module anymore.

> 
> >
> > > > diff --git a/drivers/platform/x86/dell-smbios-wmi.c
> > > b/drivers/platform/x86/dell-smbios-wmi.c
> > > > +static void __init parse_b1_table(const struct dmi_header *dm)
> > > > +{
> > > > +	struct misc_bios_flags_structure *flags =
> > > > +	container_of(dm, struct misc_bios_flags_structure, header);
> > > > +
> > > > +	/* 4 bytes header, and one word of flags */
> > >
> > > Assuming specifically 8 bytes of flags, independent of arch?
> >
> > Well platform/drivers/*x86*...
> 
> I was thinking 32b vs 64b x86 which have a different definition of word size.
> 
I'll make this clearer.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
@ 2017-10-05 19:47           ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-05 19:47 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Thursday, October 5, 2017 12:58 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> dispatcher driver
> 
> On Thu, Oct 05, 2017 at 03:12:46PM +0000, Mario.Limonciello@dell.com wrote:
> 
> > > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > > > index f0b97cb8e449..ef597f440d2e 100644
> > > > --- a/drivers/platform/x86/Kconfig
> > > > +++ b/drivers/platform/x86/Kconfig
> > > > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> > > >
> > > >  config DELL_SMBIOS
> > > >  	tristate "Dell SMBIOS calling interface"
> > > > -	depends on DELL_SMBIOS_SMM
> > > > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> > > >  	---help---
> > > >  	This module provides common functions for kernel modules using
> > > >  	Dell SMBIOS.
> > >
> > > You use select DELL_SMBIOS below, which implies this modules should be
> > > invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> > > option at all now, they can select DELL_SMBIOS_WMI and or
> > > DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> > >
> > So when you say make invisible, does that mean that it should never show
> > up in make menuconfig and just be implicitly selected?
> 
> Right. It shouldn't have a prompt.
> 
> >
> > When I was adjusting Kconfig for your other feedback I noticed setting
> something
> > to "select $DRIVER" that invisible driver does show up just can't be turned off.
> > Is that what you mean?
> 
> No, I mean eliminate the menu entry by eliminating the prompt.
Do you have an example of a driver that does it this way? 
When I tried, CONFIG_DELL_WMI_DESCRIPTOR doesn't get saved to .config
and then doesn't compile into a module anymore.

> 
> >
> > > > diff --git a/drivers/platform/x86/dell-smbios-wmi.c
> > > b/drivers/platform/x86/dell-smbios-wmi.c
> > > > +static void __init parse_b1_table(const struct dmi_header *dm)
> > > > +{
> > > > +	struct misc_bios_flags_structure *flags =
> > > > +	container_of(dm, struct misc_bios_flags_structure, header);
> > > > +
> > > > +	/* 4 bytes header, and one word of flags */
> > >
> > > Assuming specifically 8 bytes of flags, independent of arch?
> >
> > Well platform/drivers/*x86*...
> 
> I was thinking 32b vs 64b x86 which have a different definition of word size.
> 
I'll make this clearer.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 19:03                   ` Mario.Limonciello
  (?)
  (?)
@ 2017-10-05 20:51                   ` Darren Hart
  -1 siblings, 0 replies; 93+ messages in thread
From: Darren Hart @ 2017-10-05 20:51 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: greg, pali.rohar, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
> > 
> > And how _exactly_ is this interface exposed in Windows?  Is it ad-hoc
> > with custom kernel drivers written by each vendor?  Or does the OS
> > provide a "sane" interface for it?
> 
> On Windows it's a driver-less solution.  Vendors don't do anything other
> than provide the MOF (which describes how the data passed to ASL looks).
> 
> When Windows boots up, _WDG is parsed, the binary MOF is loaded into
> the WMI repository.  The MOF describes how named objects map to GUIDs
> which map to ASL.
> 
> >From Powershell or from any application that uses WMI as admin you can 
> look up the root namespace and see all objects.  You can pass calls back
> and forth.  There's all sorts of examples of it here:
> https://msdn.microsoft.com/en-us/library/windows/hardware/dn614028(v=vs.85).aspx
> 

A couple snippets from this link which I believe I've shared previously
that clarify the design intent of the WMI mechanism:

"
ACPI-to-WMI Mapper Goals for Windows Instrumentation:

...

* Allow OEMs to include OEM-specific data blocks, user-mode-callable
  ACPI control methods, and events without requiring any changes to the
  ACPI-to-WMI mapper.

* Allow general-purpose data consumer applications--those written
  without any special knowledge of the data blocks exposed by a
  particular machine--to be able to access and understand the data
  blocks, user-mode-callable ACPI control methods, and events being
  mapped--including those that are OEM specific.

...

The following are not goals for the ACPI-to-WMI mapper:

* To have specific knowledge about any data block that passes through
  the mapper.

* To provide interfaces specifically for SMBIOS data and functions. The
  mapper is an open architecture that is not restricted to SMBIOS data
  and functionality.
"

This model is not consistent with Linux design principles, and Mario's
changes attempt to allow for more kernel oversight by:

* Requiring a driver to be written to bind to any GUID which will expose
  WMI methods to userspace. The goal here is to provide an effective
  whitelist, and to promote vendor participation (they need to send the
  patch, have it reviewed, respond to challenges on the security
  implications, etc.)

* In the future, provide for the MOF parsing within the kernel so Linux
  will have more ability to audit messaging.

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers
  2017-10-05 19:09                   ` Greg KH
  2017-10-05 19:32                     ` Pali Rohár
  2017-10-05 19:34                       ` Mario.Limonciello
@ 2017-10-05 20:58                     ` Darren Hart
  2 siblings, 0 replies; 93+ messages in thread
From: Darren Hart @ 2017-10-05 20:58 UTC (permalink / raw)
  To: Greg KH
  Cc: Mario.Limonciello, pali.rohar, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

On Thu, Oct 05, 2017 at 09:09:48PM +0200, Greg KH wrote:
> On Thu, Oct 05, 2017 at 07:03:24PM +0000, Mario.Limonciello@dell.com wrote:
...
> > It's up to firmware to block the crazy stuff that you can put in a buffer.
> 
> So userspace can pass any blob it wants to the firmware through this
> interface and the kernel does not parse anything?  How is that
> "protected"?
> 
> > > Again, I like my TPM to work, and I don't want a random rootkit exploit
> > > to be able to destroy it :)
> > 
> > I'd like to however point out you can't kill your TPM from this interface.
> 
> On _your_ platform, can you guarantee it on any other platform?  :)

The dell-smbios-wmi driver won't load on any other platform. No
character device is created for any other platform. When drivers are
written for those other platforms for different WMI GUIDs, we need to
review them.

This driver not having MOF data should be the exception. We'll have more
ability to inspect others. If drivers are submitted that don't look at
the MOF data even through it is present, we should reject them.

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  2017-10-05 19:47           ` Mario.Limonciello
  (?)
@ 2017-10-06 16:44           ` Darren Hart
  2017-10-06 16:47               ` Mario.Limonciello
  -1 siblings, 1 reply; 93+ messages in thread
From: Darren Hart @ 2017-10-06 16:44 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

On Thu, Oct 05, 2017 at 07:47:38PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Darren Hart [mailto:dvhart@infradead.org]
> > Sent: Thursday, October 5, 2017 12:58 PM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> > driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> > greg@kroah.com
> > Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> > dispatcher driver
> > 
> > On Thu, Oct 05, 2017 at 03:12:46PM +0000, Mario.Limonciello@dell.com wrote:
> > 
> > > > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > > > > index f0b97cb8e449..ef597f440d2e 100644
> > > > > --- a/drivers/platform/x86/Kconfig
> > > > > +++ b/drivers/platform/x86/Kconfig
> > > > > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> > > > >
> > > > >  config DELL_SMBIOS
> > > > >  	tristate "Dell SMBIOS calling interface"
> > > > > -	depends on DELL_SMBIOS_SMM
> > > > > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> > > > >  	---help---
> > > > >  	This module provides common functions for kernel modules using
> > > > >  	Dell SMBIOS.
> > > >
> > > > You use select DELL_SMBIOS below, which implies this modules should be
> > > > invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> > > > option at all now, they can select DELL_SMBIOS_WMI and or
> > > > DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> > > >
> > > So when you say make invisible, does that mean that it should never show
> > > up in make menuconfig and just be implicitly selected?
> > 
> > Right. It shouldn't have a prompt.
> > 
> > >
> > > When I was adjusting Kconfig for your other feedback I noticed setting
> > something
> > > to "select $DRIVER" that invisible driver does show up just can't be turned off.
> > > Is that what you mean?
> > 
> > No, I mean eliminate the menu entry by eliminating the prompt.
> Do you have an example of a driver that does it this way? 
> When I tried, CONFIG_DELL_WMI_DESCRIPTOR doesn't get saved to .config
> and then doesn't compile into a module anymore.

Just eliminating the prompt will hide DELL_SMBIOS from menuconfig:

config DELL_SMBIOS
	tristate
	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM

-- 
Darren Hart
VMware Open Source Technology Center

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
  2017-10-06 16:44           ` Darren Hart
@ 2017-10-06 16:47               ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-06 16:47 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Friday, October 6, 2017 11:45 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> dispatcher driver
> 
> On Thu, Oct 05, 2017 at 07:47:38PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Darren Hart [mailto:dvhart@infradead.org]
> > > Sent: Thursday, October 5, 2017 12:58 PM
> > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> > > driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> > > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> > > greg@kroah.com
> > > Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> > > dispatcher driver
> > >
> > > On Thu, Oct 05, 2017 at 03:12:46PM +0000, Mario.Limonciello@dell.com
> wrote:
> > >
> > > > > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > > > > > index f0b97cb8e449..ef597f440d2e 100644
> > > > > > --- a/drivers/platform/x86/Kconfig
> > > > > > +++ b/drivers/platform/x86/Kconfig
> > > > > > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> > > > > >
> > > > > >  config DELL_SMBIOS
> > > > > >  	tristate "Dell SMBIOS calling interface"
> > > > > > -	depends on DELL_SMBIOS_SMM
> > > > > > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> > > > > >  	---help---
> > > > > >  	This module provides common functions for kernel modules
> using
> > > > > >  	Dell SMBIOS.
> > > > >
> > > > > You use select DELL_SMBIOS below, which implies this modules should be
> > > > > invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> > > > > option at all now, they can select DELL_SMBIOS_WMI and or
> > > > > DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> > > > >
> > > > So when you say make invisible, does that mean that it should never show
> > > > up in make menuconfig and just be implicitly selected?
> > >
> > > Right. It shouldn't have a prompt.
> > >
> > > >
> > > > When I was adjusting Kconfig for your other feedback I noticed setting
> > > something
> > > > to "select $DRIVER" that invisible driver does show up just can't be turned
> off.
> > > > Is that what you mean?
> > >
> > > No, I mean eliminate the menu entry by eliminating the prompt.
> > Do you have an example of a driver that does it this way?
> > When I tried, CONFIG_DELL_WMI_DESCRIPTOR doesn't get saved to .config
> > and then doesn't compile into a module anymore.
> 
> Just eliminating the prompt will hide DELL_SMBIOS from menuconfig:
> 
> config DELL_SMBIOS
> 	tristate
> 	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> 
> --
> Darren Hart
> VMware Open Source Technology Center

Ohhh.  I didn't know that's what you meant by prompt.  Thanks for
clarifying.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver
@ 2017-10-06 16:47               ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-06 16:47 UTC (permalink / raw)
  To: dvhart
  Cc: andy.shevchenko, linux-kernel, platform-driver-x86, luto,
	quasisec, pali.rohar, rjw, mjg59, hch, greg

> -----Original Message-----
> From: Darren Hart [mailto:dvhart@infradead.org]
> Sent: Friday, October 6, 2017 11:45 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> greg@kroah.com
> Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> dispatcher driver
> 
> On Thu, Oct 05, 2017 at 07:47:38PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Darren Hart [mailto:dvhart@infradead.org]
> > > Sent: Thursday, October 5, 2017 12:58 PM
> > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > Cc: andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-
> > > driver-x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> > > pali.rohar@gmail.com; rjw@rjwysocki.net; mjg59@google.com; hch@lst.de;
> > > greg@kroah.com
> > > Subject: Re: [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI
> > > dispatcher driver
> > >
> > > On Thu, Oct 05, 2017 at 03:12:46PM +0000, Mario.Limonciello@dell.com
> wrote:
> > >
> > > > > > diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
> > > > > > index f0b97cb8e449..ef597f440d2e 100644
> > > > > > --- a/drivers/platform/x86/Kconfig
> > > > > > +++ b/drivers/platform/x86/Kconfig
> > > > > > @@ -93,13 +93,27 @@ config ASUS_LAPTOP
> > > > > >
> > > > > >  config DELL_SMBIOS
> > > > > >  	tristate "Dell SMBIOS calling interface"
> > > > > > -	depends on DELL_SMBIOS_SMM
> > > > > > +	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> > > > > >  	---help---
> > > > > >  	This module provides common functions for kernel modules
> using
> > > > > >  	Dell SMBIOS.
> > > > >
> > > > > You use select DELL_SMBIOS below, which implies this modules should be
> > > > > invisible. Indeed, there is no need for the user to see the DELL_SMBIOS
> > > > > option at all now, they can select DELL_SMBIOS_WMI and or
> > > > > DELL_SMBIOS_SMM, no need to keep the DELL_SMBIOS option.
> > > > >
> > > > So when you say make invisible, does that mean that it should never show
> > > > up in make menuconfig and just be implicitly selected?
> > >
> > > Right. It shouldn't have a prompt.
> > >
> > > >
> > > > When I was adjusting Kconfig for your other feedback I noticed setting
> > > something
> > > > to "select $DRIVER" that invisible driver does show up just can't be turned
> off.
> > > > Is that what you mean?
> > >
> > > No, I mean eliminate the menu entry by eliminating the prompt.
> > Do you have an example of a driver that does it this way?
> > When I tried, CONFIG_DELL_WMI_DESCRIPTOR doesn't get saved to .config
> > and then doesn't compile into a module anymore.
> 
> Just eliminating the prompt will hide DELL_SMBIOS from menuconfig:
> 
> config DELL_SMBIOS
> 	tristate
> 	depends on DELL_SMBIOS_WMI || DELL_SMBIOS_SMM
> 
> --
> Darren Hart
> VMware Open Source Technology Center

Ohhh.  I didn't know that's what you meant by prompt.  Thanks for
clarifying.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-05 16:48               ` Mario.Limonciello
@ 2017-10-10 19:40                 ` Alan Cox
  -1 siblings, 0 replies; 93+ messages in thread
From: Alan Cox @ 2017-10-10 19:40 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: gregkh, pali.rohar, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

> There are some "write once" items that for the general purpose user that
> won't brick a box, but should probably be blacklisted though.
> I'll think this through some more.

I would strongly urge you to do whitelisting as it's good security. If
you can divide the calls into something like this it fits the Linxu
desktop model well:

Safe -> anyone can do it
Console -> only console owner
Superuser -> administrator level (things that can be irritating but
don't persist a reboot)

Beyond that it's trickier - if you are an enterprise business then you
don't for example want to allow someone with root on the system to
subvert BIOS level settings they can't access.

You need a minimum of CAP_SYS_RAWIO for anything that can (through bugs
or design) subvert secure boot type stuff. It's also probably an
appropriate check for 'anything goes' if you decide to have that
category. CAP_SYS_RAWIO implies total power over the machine although
with secureboot it's less clear.

Alan

^ permalink raw reply	[flat|nested] 93+ messages in thread

* Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
@ 2017-10-10 19:40                 ` Alan Cox
  0 siblings, 0 replies; 93+ messages in thread
From: Alan Cox @ 2017-10-10 19:40 UTC (permalink / raw)
  To: Mario.Limonciello
  Cc: gregkh, pali.rohar, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

> There are some "write once" items that for the general purpose user that
> won't brick a box, but should probably be blacklisted though.
> I'll think this through some more.

I would strongly urge you to do whitelisting as it's good security. If
you can divide the calls into something like this it fits the Linxu
desktop model well:

Safe -> anyone can do it
Console -> only console owner
Superuser -> administrator level (things that can be irritating but
don't persist a reboot)

Beyond that it's trickier - if you are an enterprise business then you
don't for example want to allow someone with root on the system to
subvert BIOS level settings they can't access.

You need a minimum of CAP_SYS_RAWIO for anything that can (through bugs
or design) subvert secure boot type stuff. It's also probably an
appropriate check for 'anything goes' if you decide to have that
category. CAP_SYS_RAWIO implies total power over the machine although
with secureboot it's less clear.

Alan

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
  2017-10-10 19:40                 ` Alan Cox
@ 2017-10-10 19:51                   ` Mario.Limonciello
  -1 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-10 19:51 UTC (permalink / raw)
  To: gnomes
  Cc: gregkh, pali.rohar, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

Alan,

> -----Original Message-----
> From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> Sent: Tuesday, October 10, 2017 2:41 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: gregkh@linuxfoundation.org; pali.rohar@gmail.com; dvhart@infradead.org;
> andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-driver-
> x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> > There are some "write once" items that for the general purpose user that
> > won't brick a box, but should probably be blacklisted though.
> > I'll think this through some more.
> 
> I would strongly urge you to do whitelisting as it's good security. If
> you can divide the calls into something like this it fits the Linxu
> desktop model well:
> 
> Safe -> anyone can do it
> Console -> only console owner
> Superuser -> administrator level (things that can be irritating but
> don't persist a reboot)

I've added filtering in my most recent submission (v6).

I don't feel that any single one of these calls or pieces of data should
be accessible without root.  Furthermore discussion on the merits of different
levels is stepping into bikeshedding territory. 
If someone wants to bubble up things that they feel are safe to read or write 
as user, that can be the job of a daemon or other service to decide not the kernel.

> 
> Beyond that it's trickier - if you are an enterprise business then you
> don't for example want to allow someone with root on the system to
> subvert BIOS level settings they can't access.

This level of split is actually comprehended already by the BIOS itself.  When you
enable an administrative password on the BIOS, you aren't able to access (read
or write) a variety of settings without a security key (which requires some handshaking).

> 
> You need a minimum of CAP_SYS_RAWIO for anything that can (through bugs
> or design) subvert secure boot type stuff. It's also probably an
> appropriate check for 'anything goes' if you decide to have that
> category. CAP_SYS_RAWIO implies total power over the machine although
> with secureboot it's less clear.
> 
Secure boot can't programmatically be disabled from within OS.

^ permalink raw reply	[flat|nested] 93+ messages in thread

* RE: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface
@ 2017-10-10 19:51                   ` Mario.Limonciello
  0 siblings, 0 replies; 93+ messages in thread
From: Mario.Limonciello @ 2017-10-10 19:51 UTC (permalink / raw)
  To: gnomes
  Cc: gregkh, pali.rohar, dvhart, andy.shevchenko, linux-kernel,
	platform-driver-x86, luto, quasisec, rjw, mjg59, hch

Alan,

> -----Original Message-----
> From: Alan Cox [mailto:gnomes@lxorguk.ukuu.org.uk]
> Sent: Tuesday, October 10, 2017 2:41 PM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: gregkh@linuxfoundation.org; pali.rohar@gmail.com; dvhart@infradead.org;
> andy.shevchenko@gmail.com; linux-kernel@vger.kernel.org; platform-driver-
> x86@vger.kernel.org; luto@kernel.org; quasisec@google.com;
> rjw@rjwysocki.net; mjg59@google.com; hch@lst.de
> Subject: Re: [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce
> userspace interface
> 
> > There are some "write once" items that for the general purpose user that
> > won't brick a box, but should probably be blacklisted though.
> > I'll think this through some more.
> 
> I would strongly urge you to do whitelisting as it's good security. If
> you can divide the calls into something like this it fits the Linxu
> desktop model well:
> 
> Safe -> anyone can do it
> Console -> only console owner
> Superuser -> administrator level (things that can be irritating but
> don't persist a reboot)

I've added filtering in my most recent submission (v6).

I don't feel that any single one of these calls or pieces of data should
be accessible without root.  Furthermore discussion on the merits of different
levels is stepping into bikeshedding territory. 
If someone wants to bubble up things that they feel are safe to read or write 
as user, that can be the job of a daemon or other service to decide not the kernel.

> 
> Beyond that it's trickier - if you are an enterprise business then you
> don't for example want to allow someone with root on the system to
> subvert BIOS level settings they can't access.

This level of split is actually comprehended already by the BIOS itself.  When you
enable an administrative password on the BIOS, you aren't able to access (read
or write) a variety of settings without a security key (which requires some handshaking).

> 
> You need a minimum of CAP_SYS_RAWIO for anything that can (through bugs
> or design) subvert secure boot type stuff. It's also probably an
> appropriate check for 'anything goes' if you decide to have that
> category. CAP_SYS_RAWIO implies total power over the machine although
> with secureboot it's less clear.
> 
Secure boot can't programmatically be disabled from within OS.

^ permalink raw reply	[flat|nested] 93+ messages in thread

end of thread, other threads:[~2017-10-10 19:52 UTC | newest]

Thread overview: 93+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-04 22:48 [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Mario Limonciello
2017-10-04 22:48 ` [PATCH v4 01/14] platform/x86: wmi: Add new method wmidev_evaluate_method Mario Limonciello
2017-10-04 22:48 ` [PATCH v4 02/14] platform/x86: dell-wmi: clean up wmi descriptor check Mario Limonciello
2017-10-04 22:48 ` [PATCH v4 03/14] platform/x86: dell-wmi: allow 32k return size in the descriptor Mario Limonciello
2017-10-04 22:48 ` [PATCH v4 04/14] platform/x86: dell-wmi: increase severity of some failures Mario Limonciello
2017-10-05  5:20   ` Andy Shevchenko
2017-10-05 15:02     ` Mario.Limonciello
2017-10-05 15:02       ` Mario.Limonciello
2017-10-05 18:22       ` Andy Shevchenko
2017-10-04 22:48 ` [PATCH v4 05/14] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver Mario Limonciello
2017-10-05  1:09   ` Darren Hart
2017-10-05  5:29     ` Andy Shevchenko
2017-10-05  7:11       ` Darren Hart
2017-10-05  8:47         ` Andy Shevchenko
2017-10-05 13:59           ` Mario.Limonciello
2017-10-05 13:59             ` Mario.Limonciello
2017-10-05 14:14             ` Darren Hart
2017-10-05 14:47               ` Mario.Limonciello
2017-10-05 14:47                 ` Mario.Limonciello
2017-10-05 17:22                 ` Darren Hart
2017-10-05 17:32                   ` Mario.Limonciello
2017-10-05 17:32                     ` Mario.Limonciello
2017-10-05  5:34   ` Andy Shevchenko
2017-10-05 17:04     ` Mario.Limonciello
2017-10-05 17:04       ` Mario.Limonciello
2017-10-04 22:48 ` [PATCH v4 06/14] platform/x86: wmi: Don't allow drivers to get each other's GUIDs Mario Limonciello
2017-10-04 22:48 ` [PATCH v4 07/14] platform/x86: dell-smbios: only run if proper oem string is detected Mario Limonciello
2017-10-04 22:48 ` [PATCH v4 08/14] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens Mario Limonciello
2017-10-05  8:49   ` Andy Shevchenko
2017-10-05 13:58     ` Mario.Limonciello
2017-10-05 13:58       ` Mario.Limonciello
2017-10-05 14:22       ` Andy Shevchenko
2017-10-04 22:48 ` [PATCH v4 09/14] platform/x86: dell-smbios: Introduce dispatcher for SMM calls Mario Limonciello
2017-10-05  1:57   ` Darren Hart
2017-10-05 15:04     ` Mario.Limonciello
2017-10-05 15:04       ` Mario.Limonciello
2017-10-04 22:48 ` [PATCH v4 10/14] platform/x86: dell-smbios-smm: test for WSMT Mario Limonciello
2017-10-05  1:59   ` Darren Hart
2017-10-04 22:48 ` [PATCH v4 11/14] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver Mario Limonciello
2017-10-05  2:14   ` Darren Hart
2017-10-05 15:12     ` Mario.Limonciello
2017-10-05 15:12       ` Mario.Limonciello
2017-10-05 17:57       ` Darren Hart
2017-10-05 19:47         ` Mario.Limonciello
2017-10-05 19:47           ` Mario.Limonciello
2017-10-06 16:44           ` Darren Hart
2017-10-06 16:47             ` Mario.Limonciello
2017-10-06 16:47               ` Mario.Limonciello
2017-10-04 22:48 ` [PATCH v4 12/14] platform/x86: wmi: create character devices when requested by drivers Mario Limonciello
2017-10-05  2:33   ` Darren Hart
2017-10-05  7:16   ` Greg KH
2017-10-05 14:35     ` Mario.Limonciello
2017-10-05 14:35       ` Mario.Limonciello
2017-10-05 15:42       ` Greg KH
2017-10-05 15:51         ` Pali Rohár
2017-10-05 16:26           ` Greg KH
2017-10-05 17:39             ` Darren Hart
2017-10-05 18:47               ` Greg KH
2017-10-05 19:03                 ` Mario.Limonciello
2017-10-05 19:03                   ` Mario.Limonciello
2017-10-05 19:09                   ` Greg KH
2017-10-05 19:32                     ` Pali Rohár
2017-10-05 19:39                       ` Mario.Limonciello
2017-10-05 19:39                         ` Mario.Limonciello
2017-10-05 19:34                     ` Mario.Limonciello
2017-10-05 19:34                       ` Mario.Limonciello
2017-10-05 20:58                     ` Darren Hart
2017-10-05 20:51                   ` Darren Hart
2017-10-04 22:48 ` [PATCH v4 13/14] platform/x86: dell-smbios-wmi: introduce userspace interface Mario Limonciello
2017-10-05  7:23   ` Greg KH
2017-10-05 16:28     ` Mario.Limonciello
2017-10-05 16:28       ` Mario.Limonciello
2017-10-05 16:34       ` Pali Rohár
2017-10-05 16:40       ` Greg KH
2017-10-05 16:40         ` Greg KH
2017-10-05  7:33   ` Greg KH
2017-10-05 16:37     ` Mario.Limonciello
2017-10-05 16:37       ` Mario.Limonciello
2017-10-05 13:59   ` Alan Cox
2017-10-05 14:22     ` Mario.Limonciello
2017-10-05 14:22       ` Mario.Limonciello
2017-10-05 15:44       ` Greg KH
2017-10-05 15:56         ` Pali Rohár
2017-10-05 16:28           ` Greg KH
2017-10-05 16:48             ` Mario.Limonciello
2017-10-05 16:48               ` Mario.Limonciello
2017-10-10 19:40               ` Alan Cox
2017-10-10 19:40                 ` Alan Cox
2017-10-10 19:51                 ` Mario.Limonciello
2017-10-10 19:51                   ` Mario.Limonciello
2017-10-04 22:48 ` [PATCH v4 14/14] platform/x86: Kconfig: Set default for dell-smbios to ACPI_WMI Mario Limonciello
2017-10-05  0:09 ` [PATCH v4 00/14] Introduce support for Dell SMBIOS over WMI Darren Hart
2017-10-05  9:00   ` Andy Shevchenko

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.