linux-acpi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] Hans's generic serial bus fix
@ 2021-02-18 23:17 Erik Kaneda
  2021-02-18 23:17 ` [PATCH 1/2] ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling Erik Kaneda
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Erik Kaneda @ 2021-02-18 23:17 UTC (permalink / raw)
  To: Rafael J . Wysocki, ACPI Devel Maling List, Hans de Goede; +Cc: Erik Kaneda

Hi Hans and Rafael,

Sorry about the late responses. I've accidentally dropped the ball on
the comunication of this pull request. Bob has merged it now and here
are the linux-ized versions of them.

Rafael, if you haven't merged the patches, please consider taking
these as it will keep things easier to maintain on my end..

Thanks and apologies,
Erik Kaneda


Hans de Goede (2):
  ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region
    parameter handling
  ACPICA: Remove some code duplication from
    acpi_ev_address_space_dispatch

 drivers/acpi/acpica/acobject.h  |  1 +
 drivers/acpi/acpica/evhandler.c |  7 ++++
 drivers/acpi/acpica/evregion.c  | 69 ++++++++++++++++++++-------------
 drivers/acpi/acpica/evxfregn.c  |  2 +
 4 files changed, 53 insertions(+), 26 deletions(-)

-- 
2.29.2


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

* [PATCH 1/2] ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling
  2021-02-18 23:17 [PATCH 0/2] Hans's generic serial bus fix Erik Kaneda
@ 2021-02-18 23:17 ` Erik Kaneda
  2021-02-18 23:17 ` [PATCH 2/2] ACPICA: Remove some code duplication from acpi_ev_address_space_dispatch Erik Kaneda
  2021-02-19 15:08 ` [PATCH 0/2] Hans's generic serial bus fix Rafael J. Wysocki
  2 siblings, 0 replies; 4+ messages in thread
From: Erik Kaneda @ 2021-02-18 23:17 UTC (permalink / raw)
  To: Rafael J . Wysocki, ACPI Devel Maling List, Hans de Goede
  Cc: Bob Moore, Erik Kaneda

From: Hans de Goede <hdegoede@redhat.com>

ACPICA commit c9e0116952363b0fa815143dca7e9a2eb4fefa61

The handling of the generic_serial_bus (I2C) and GPIO op_regions in
acpi_ev_address_space_dispatch() passes a number of extra parameters to
the address-space handler through the address-space Context pointer
(instead of using more function parameters).

The Context is shared between threads, so if multiple threads try to call
the handler for the same address-space at the same time, then
a second thread could change the parameters of a first thread while the
handler is running for the first thread.

An example of this race hitting is the Lenovo Yoga Tablet2 1015L, where
there are both attrib_bytes accesses and attrib_byte accesses to the same
address-space. The attrib_bytes access stores the number of bytes to
transfer in Context->access_length. Where as for the attrib_byte access the
number of bytes to transfer is always 1 and field_obj->Field.access_length
is unused (so 0). Both types of accesses racing from different threads
leads to the following problem:

1. Thread a. starts an attrib_bytes access, stores a non 0 value
from field_obj->Field.access_length in Context->access_length
2. Thread b. starts an attrib_byte access, stores 0 in
Context->access_length
3. Thread a. calls i2c_acpi_space_handler() (under Linux). Which
sees that the access-type is ACPI_GSB_ACCESS_ATTRIB_MULTIBYTE and
calls acpi_gsb_i2c_read_bytes(..., Context->access_length)
4. At this point Context->access_length is 0 (set by thread b.)
rather then the field_obj->Field.access_length value from thread a.
This 0 length reads leads to the following errors being logged:

 i2c i2c-0: adapter quirk: no zero length (addr 0x0078, size 0, read)
 i2c i2c-0: i2c read 0 bytes from client@0x78 starting at reg 0x0 failed, error: -95

Note this is just an example of the problems which this race can cause.
There are likely many more (sporadic) problems caused by this race.

This commit adds a new context_mutex to struct acpi_object_addr_handler
and makes acpi_ev_address_space_dispatch() take that mutex when
using the shared Context to pass extra parameters to an address-space
handler, fixing this race.

Note the new mutex must be taken *after* exiting the interpreter,
therefor the existing acpi_ex_exit_interpreter() call is moved to above
the code which stores the extra parameters in the Context.

Link: https://github.com/acpica/acpica/commit/c9e01169
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Erik Kaneda <erik.kaneda@intel.com>
---
 drivers/acpi/acpica/acobject.h  |  1 +
 drivers/acpi/acpica/evhandler.c |  7 ++++
 drivers/acpi/acpica/evregion.c  | 64 ++++++++++++++++++++++++---------
 drivers/acpi/acpica/evxfregn.c  |  2 ++
 4 files changed, 57 insertions(+), 17 deletions(-)

diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index af47a3ffd2a4..9db5ae0f79ea 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -284,6 +284,7 @@ struct acpi_object_addr_handler {
 	acpi_adr_space_handler handler;
 	struct acpi_namespace_node *node;	/* Parent device */
 	void *context;
+	acpi_mutex context_mutex;
 	acpi_adr_space_setup setup;
 	union acpi_operand_object *region_list;	/* Regions using this handler */
 	union acpi_operand_object *next;
diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c
index ea9485e6a475..c0cd7147a5a3 100644
--- a/drivers/acpi/acpica/evhandler.c
+++ b/drivers/acpi/acpica/evhandler.c
@@ -489,6 +489,13 @@ acpi_ev_install_space_handler(struct acpi_namespace_node *node,
 
 	/* Init handler obj */
 
+	status =
+	    acpi_os_create_mutex(&handler_obj->address_space.context_mutex);
+	if (ACPI_FAILURE(status)) {
+		acpi_ut_remove_reference(handler_obj);
+		goto unlock_and_exit;
+	}
+
 	handler_obj->address_space.space_id = (u8)space_id;
 	handler_obj->address_space.handler_flags = flags;
 	handler_obj->address_space.region_list = NULL;
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 3ed7d9ae95cf..2a3c13e97555 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -112,6 +112,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 	union acpi_operand_object *region_obj2;
 	void *region_context = NULL;
 	struct acpi_connection_info *context;
+	acpi_mutex context_mutex;
+	u8 context_locked;
 	acpi_physical_address address;
 
 	ACPI_FUNCTION_TRACE(ev_address_space_dispatch);
@@ -136,6 +138,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 	}
 
 	context = handler_desc->address_space.context;
+	context_mutex = handler_desc->address_space.context_mutex;
+	context_locked = FALSE;
 
 	/*
 	 * It may be the case that the region has never been initialized.
@@ -204,6 +208,23 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 	handler = handler_desc->address_space.handler;
 	address = (region_obj->region.address + region_offset);
 
+	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
+			  &region_obj->region.handler->address_space, handler,
+			  ACPI_FORMAT_UINT64(address),
+			  acpi_ut_get_region_name(region_obj->region.
+						  space_id)));
+
+	if (!(handler_desc->address_space.handler_flags &
+	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
+		/*
+		 * For handlers other than the default (supplied) handlers, we must
+		 * exit the interpreter because the handler *might* block -- we don't
+		 * know what it will do, so we can't hold the lock on the interpreter.
+		 */
+		acpi_ex_exit_interpreter();
+	}
+
 	/*
 	 * Special handling for generic_serial_bus and general_purpose_io:
 	 * There are three extra parameters that must be passed to the
@@ -212,6 +233,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 	 *   2) Length of the above buffer
 	 *   3) Actual access length from the access_as() op
 	 *
+	 * Since we pass these extra parameters via the context, which is
+	 * shared between threads, we must lock the context to avoid these
+	 * parameters being changed from another thread before the handler
+	 * has completed running.
+	 *
 	 * In addition, for general_purpose_io, the Address and bit_width fields
 	 * are defined as follows:
 	 *   1) Address is the pin number index of the field (bit offset from
@@ -221,6 +247,14 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
 	    context && field_obj) {
 
+		status =
+		    acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER);
+		if (ACPI_FAILURE(status)) {
+			goto re_enter_interpreter;
+		}
+
+		context_locked = TRUE;
+
 		/* Get the Connection (resource_template) buffer */
 
 		context->connection = field_obj->field.resource_buffer;
@@ -230,6 +264,14 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
 	    context && field_obj) {
 
+		status =
+		    acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER);
+		if (ACPI_FAILURE(status)) {
+			goto re_enter_interpreter;
+		}
+
+		context_locked = TRUE;
+
 		/* Get the Connection (resource_template) buffer */
 
 		context->connection = field_obj->field.resource_buffer;
@@ -239,28 +281,15 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 		bit_width = field_obj->field.bit_length;
 	}
 
-	ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
-			  "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
-			  &region_obj->region.handler->address_space, handler,
-			  ACPI_FORMAT_UINT64(address),
-			  acpi_ut_get_region_name(region_obj->region.
-						  space_id)));
-
-	if (!(handler_desc->address_space.handler_flags &
-	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
-		/*
-		 * For handlers other than the default (supplied) handlers, we must
-		 * exit the interpreter because the handler *might* block -- we don't
-		 * know what it will do, so we can't hold the lock on the interpreter.
-		 */
-		acpi_ex_exit_interpreter();
-	}
-
 	/* Call the handler */
 
 	status = handler(function, address, bit_width, value, context,
 			 region_obj2->extra.region_context);
 
+	if (context_locked) {
+		acpi_os_release_mutex(context_mutex);
+	}
+
 	if (ACPI_FAILURE(status)) {
 		ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",
 				acpi_ut_get_region_name(region_obj->region.
@@ -277,6 +306,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 		}
 	}
 
+re_enter_interpreter:
 	if (!(handler_desc->address_space.handler_flags &
 	      ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {
 		/*
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index 7672d70da850..b1ff0a8f9c14 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -201,6 +201,8 @@ acpi_remove_address_space_handler(acpi_handle device,
 
 			/* Now we can delete the handler object */
 
+			acpi_os_release_mutex(handler_obj->address_space.
+					      context_mutex);
 			acpi_ut_remove_reference(handler_obj);
 			goto unlock_and_exit;
 		}
-- 
2.29.2


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

* [PATCH 2/2] ACPICA: Remove some code duplication from acpi_ev_address_space_dispatch
  2021-02-18 23:17 [PATCH 0/2] Hans's generic serial bus fix Erik Kaneda
  2021-02-18 23:17 ` [PATCH 1/2] ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling Erik Kaneda
@ 2021-02-18 23:17 ` Erik Kaneda
  2021-02-19 15:08 ` [PATCH 0/2] Hans's generic serial bus fix Rafael J. Wysocki
  2 siblings, 0 replies; 4+ messages in thread
From: Erik Kaneda @ 2021-02-18 23:17 UTC (permalink / raw)
  To: Rafael J . Wysocki, ACPI Devel Maling List, Hans de Goede
  Cc: Bob Moore, Erik Kaneda

From: Hans de Goede <hdegoede@redhat.com>

ACPICA commit 383f50ff8cb7424ca16a6c0234f103b41d4a783e

The handling of the space_id == ACPI_ADR_SPACE_GSBUS and
space_id == ACPI_ADR_SPACE_GPIO cases is almost identical,
fold the 2 cases into 1 to remove some code duplication.

Link: https://github.com/acpica/acpica/commit/383f50ff
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Erik Kaneda <erik.kaneda@intel.com>
---
 drivers/acpi/acpica/evregion.c | 23 +++++------------------
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 2a3c13e97555..4ef43c8ef5e7 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -244,7 +244,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 	 *      the previous Connection)
 	 *   2) bit_width is the actual bit length of the field (number of pins)
 	 */
-	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) &&
+	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS ||
+	     region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
 	    context && field_obj) {
 
 		status =
@@ -260,25 +261,11 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
 		context->connection = field_obj->field.resource_buffer;
 		context->length = field_obj->field.resource_length;
 		context->access_length = field_obj->field.access_length;
-	}
-	if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&
-	    context && field_obj) {
 
-		status =
-		    acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER);
-		if (ACPI_FAILURE(status)) {
-			goto re_enter_interpreter;
+		if (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) {
+			address = field_obj->field.pin_number_index;
+			bit_width = field_obj->field.bit_length;
 		}
-
-		context_locked = TRUE;
-
-		/* Get the Connection (resource_template) buffer */
-
-		context->connection = field_obj->field.resource_buffer;
-		context->length = field_obj->field.resource_length;
-		context->access_length = field_obj->field.access_length;
-		address = field_obj->field.pin_number_index;
-		bit_width = field_obj->field.bit_length;
 	}
 
 	/* Call the handler */
-- 
2.29.2


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

* Re: [PATCH 0/2] Hans's generic serial bus fix
  2021-02-18 23:17 [PATCH 0/2] Hans's generic serial bus fix Erik Kaneda
  2021-02-18 23:17 ` [PATCH 1/2] ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling Erik Kaneda
  2021-02-18 23:17 ` [PATCH 2/2] ACPICA: Remove some code duplication from acpi_ev_address_space_dispatch Erik Kaneda
@ 2021-02-19 15:08 ` Rafael J. Wysocki
  2 siblings, 0 replies; 4+ messages in thread
From: Rafael J. Wysocki @ 2021-02-19 15:08 UTC (permalink / raw)
  To: Erik Kaneda; +Cc: Rafael J . Wysocki, ACPI Devel Maling List, Hans de Goede

On Fri, Feb 19, 2021 at 12:49 AM Erik Kaneda <erik.kaneda@intel.com> wrote:
>
> Hi Hans and Rafael,
>
> Sorry about the late responses. I've accidentally dropped the ball on
> the comunication of this pull request. Bob has merged it now and here
> are the linux-ized versions of them.
>
> Rafael, if you haven't merged the patches, please consider taking
> these as it will keep things easier to maintain on my end..
>
> Thanks and apologies,
> Erik Kaneda
>
>
> Hans de Goede (2):
>   ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region
>     parameter handling
>   ACPICA: Remove some code duplication from
>     acpi_ev_address_space_dispatch
>
>  drivers/acpi/acpica/acobject.h  |  1 +
>  drivers/acpi/acpica/evhandler.c |  7 ++++
>  drivers/acpi/acpica/evregion.c  | 69 ++++++++++++++++++++-------------
>  drivers/acpi/acpica/evxfregn.c  |  2 +
>  4 files changed, 53 insertions(+), 26 deletions(-)
>
> --

Both applied, thanks!

Note that I will send a pull request containing them only after the
previous ACPI pull request has been processed, though.

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

end of thread, other threads:[~2021-02-19 15:09 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-02-18 23:17 [PATCH 0/2] Hans's generic serial bus fix Erik Kaneda
2021-02-18 23:17 ` [PATCH 1/2] ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling Erik Kaneda
2021-02-18 23:17 ` [PATCH 2/2] ACPICA: Remove some code duplication from acpi_ev_address_space_dispatch Erik Kaneda
2021-02-19 15:08 ` [PATCH 0/2] Hans's generic serial bus fix Rafael J. Wysocki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).