• Hans de Goede's avatar
    ACPICA: Fix race in generic_serial_bus (I2C) and GPIO op_region parameter handling · c27f3d01
    Hans de Goede authored
    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/c9e01169Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
    Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
    Signed-off-by: default avatarErik Kaneda <erik.kaneda@intel.com>
    Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
    c27f3d01
evhandler.c 14.2 KB