]> www.infradead.org Git - users/hch/misc.git/commitdiff
platform/x86: lenovo-yoga-tab2-pro-1380-fastcharger: fix serdev race
authorChenyuan Yang <chenyuan0y@gmail.com>
Sat, 11 Jan 2025 18:09:51 +0000 (12:09 -0600)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Tue, 14 Jan 2025 16:30:33 +0000 (18:30 +0200)
The yt2_1380_fc_serdev_probe() function calls devm_serdev_device_open()
before setting the client ops via serdev_device_set_client_ops(). This
ordering can trigger a NULL pointer dereference in the serdev controller's
receive_buf handler, as it assumes serdev->ops is valid when
SERPORT_ACTIVE is set.

This is similar to the issue fixed in commit 5e700b384ec1
("platform/chrome: cros_ec_uart: properly fix race condition") where
devm_serdev_device_open() was called before fully initializing the
device.

Fix the race by ensuring client ops are set before enabling the port via
devm_serdev_device_open().

Note, serdev_device_set_baudrate() and serdev_device_set_flow_control()
calls should be after the devm_serdev_device_open() call.

Fixes: b2ed33e8d486 ("platform/x86: Add lenovo-yoga-tab2-pro-1380-fastcharger driver")
Signed-off-by: Chenyuan Yang <chenyuan0y@gmail.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20250111180951.2277757-1-chenyuan0y@gmail.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/lenovo-yoga-tab2-pro-1380-fastcharger.c

index d2699ca24f340d06128b3ec8bf4170cb153d5a68..a96b215cd2c5ea2edb860cdc4bf661a45fe353ba 100644 (file)
@@ -199,14 +199,15 @@ static int yt2_1380_fc_serdev_probe(struct serdev_device *serdev)
        if (ret)
                return ret;
 
+       serdev_device_set_drvdata(serdev, fc);
+       serdev_device_set_client_ops(serdev, &yt2_1380_fc_serdev_ops);
+
        ret = devm_serdev_device_open(dev, serdev);
        if (ret)
                return dev_err_probe(dev, ret, "opening UART device\n");
 
        serdev_device_set_baudrate(serdev, 600);
        serdev_device_set_flow_control(serdev, false);
-       serdev_device_set_drvdata(serdev, fc);
-       serdev_device_set_client_ops(serdev, &yt2_1380_fc_serdev_ops);
 
        ret = devm_extcon_register_notifier_all(dev, fc->extcon, &fc->nb);
        if (ret)