Commit Graph

5 Commits

Author SHA1 Message Date
Mark Langsdorf 56c36e3e98 platform/chrome: cros_ec_uart: properly fix race condition
JIRA: https://issues.redhat.com/browse/RHEL-33550

commit 5e700b384ec13f5bcac9855cb28fcc674f1d3593
Author: Noah Loomans <noah@noahloomans.com>
Date:   Wed Apr 10 20:26:19 2024 +0200

The cros_ec_uart_probe() function calls devm_serdev_device_open() before
it calls serdev_device_set_client_ops(). This can trigger a NULL pointer
dereference:

    BUG: kernel NULL pointer dereference, address: 0000000000000000
    ...
    Call Trace:
     <TASK>
     ...
     ? ttyport_receive_buf

A simplified version of crashing code is as follows:

    static inline size_t serdev_controller_receive_buf(struct serdev_controller *ctrl,
                                                      const u8 *data,
                                                      size_t count)
    {
            struct serdev_device *serdev = ctrl->serdev;

            if (!serdev || !serdev->ops->receive_buf) // CRASH!
                return 0;

            return serdev->ops->receive_buf(serdev, data, count);
    }

It assumes that if SERPORT_ACTIVE is set and serdev exists, serdev->ops
will also exist. This conflicts with the existing cros_ec_uart_probe()
logic, as it first calls devm_serdev_device_open() (which sets
SERPORT_ACTIVE), and only later sets serdev->ops via
serdev_device_set_client_ops().

Commit 01f95d42b8f4 ("platform/chrome: cros_ec_uart: fix race
condition") attempted to fix a similar race condition, but while doing
so, made the window of error for this race condition to happen much
wider.

Attempt to fix the race condition again, making sure we fully setup
before calling devm_serdev_device_open().

Fixes: 01f95d42b8f4 ("platform/chrome: cros_ec_uart: fix race condition")
Cc: stable@vger.kernel.org
Signed-off-by: Noah Loomans <noah@noahloomans.com>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Link: https://lore.kernel.org/r/20240410182618.169042-2-noah@noahloomans.com
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
2024-05-22 11:40:01 -04:00
Mark Langsdorf 73f696cb40 platform/chrome: cros_ec_uart: fix negative type promoted to high
JIRA: https://issues.redhat.com/browse/RHEL-33550

commit 8bb233b27fb7c11deefbe2318e75490b22cf3d1a
Author: Tzung-Bi Shih <tzungbi@kernel.org>
Date: Wed, 18 Jan 2023 10:57:51 +0000

serdev_device_write_buf() returns negative numbers on errors.  When
the return value compares to unsigned integer `len`, it promotes to
quite large positive number.

Fix it.

Fixes: 04a8bdd135cc ("platform/chrome: cros_ec_uart: Add transport layer")
Reported-by: Dan Carpenter <error27@gmail.com>
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Benson Leung <bleung@chromium.org>
Link: https://lore.kernel.org/r/20230109081554.3792547-1-tzungbi@kernel.org
Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
2024-05-22 11:39:36 -04:00
Mark Langsdorf 533c9a69c0 platform/chrome: cros_ec_uart: fix race condition
JIRA: https://issues.redhat.com/browse/RHEL-33550

commit 01f95d42b8f4e88f20d68791b0a85dbb9e3d1ac9
Author: Robert Zieba <robertzieba@google.com>
Date: Thu, 05 Jan 2023 23:27:14 +0000

serdev_device_set_client_ops() is called before `ec_dev` is fully
initialized.  This can result in cros_ec_uart_rx_bytes() being called
while `ec_dev` is still not initialized, resulting in a kernel panic.

Call serdev_device_set_client_ops() after `ec_dev` is initialized.

Fixes: 04a8bdd135cc ("platform/chrome: cros_ec_uart: Add transport layer")
Signed-off-by: Robert Zieba <robertzieba@google.com>
[tzungbi: modified commit message and fixed context conflict.]
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
Link: https://lore.kernel.org/r/20221229094738.2304044-1-tzungbi@kernel.org
Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
2024-05-22 11:39:34 -04:00
Mark Langsdorf 772bf192ca platform/chrome: cros_ec_uart: Add DT enumeration support
JIRA: https://issues.redhat.com/browse/RHEL-33550

commit f9bce00f78ed9ff9c38130388c13a2b2b72b857e
Author: Bhanu Prakash Maiya <bhanumaiya@chromium.org>
Date: Thu, 05 Jan 2023 23:27:14 +0000

Existing firmware uses the "PRP0001" _HID and an associated compatible
string to enumerate the cros_ec_uart.

Add DT enumeration support for already shipped firmware.

Signed-off-by: Bhanu Prakash Maiya <bhanumaiya@chromium.org>
Co-developed-by: Mark Hasemeyer <markhas@chromium.org>
Signed-off-by: Mark Hasemeyer <markhas@chromium.org>
Reviewed-by: Prashant Malani <pmalani@chromium.org>
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Link: https://lore.kernel.org/r/20221227123212.v13.3.Ie23c217d69ff25d7354db942613f143bbc8ef891@changeid
Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
2024-05-22 11:39:34 -04:00
Mark Langsdorf e2510c4bbe platform/chrome: cros_ec_uart: Add transport layer
JIRA: https://issues.redhat.com/browse/RHEL-33550

commit 04a8bdd135cc05b10b665cedb360c7353312602d
Author: Bhanu Prakash Maiya <bhanumaiya@chromium.org>
Date: Wed, 28 Dec 2022 11:41:48 +0000

This patch does following:
1. Adds a new cros-ec-uart driver. This driver can send EC requests on
   UART and process response packets received on UART transport.
2. Once probed, this driver will initialize the serdev device based on
   the underlying information in the ACPI resource. After serdev device
   properties are set, this driver will register itself cros-ec.
3. High level driver can use this implementation to talk to ChromeOS
   Embedded Controller device in case it supports UART as transport.
4. When cros-ec driver initiates a request packet, outgoing message is
   processed in buffer and sent via serdev. Once bytes are sent, driver
   enables a wait_queue.
5. Since ChromeOS EC device sends response asynchronously, AP's TTY
   driver accumulates response bytes and calls the registered callback.
   TTY driver can send multiple callback for bytes ranging from 1 to MAX
   bytes supported by EC device.
6. Driver waits for EC_MSG_DEADLINE_MS to collect and process received
   bytes. It wakes wait_queue if expected bytes are received or else
   wait_queue timeout. Based on the error condition, driver returns
   data_len or error to cros_ec.

Signed-off-by: Bhanu Prakash Maiya <bhanumaiya@chromium.org>
Co-developed-by: Mark Hasemeyer <markhas@chromium.org>
Signed-off-by: Mark Hasemeyer <markhas@chromium.org>
Reviewed-by: Prashant Malani <pmalani@chromium.org>
Signed-off-by: Tzung-Bi Shih <tzungbi@kernel.org>
Link: https://lore.kernel.org/r/20221227123212.v13.1.If7926fcbad397bc6990dd725690229bed403948c@changeid
Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
2024-05-22 11:39:33 -04:00