Skip to content

Commit e075c3b

Browse files
jwrdegoedeij-intel
authored andcommitted
platform/x86: intel-vbtn: Protect ACPI notify handler against recursion
Since commit e2ffcda ("ACPI: OSL: Allow Notify () handlers to run on all CPUs") ACPI notify handlers like the intel-vbtn notify_handler() may run on multiple CPU cores racing with themselves. This race gets hit on Dell Venue 7140 tablets when undocking from the keyboard, causing the handler to try and register priv->switches_dev twice, as can be seen from the dev_info() message getting logged twice: [ 83.861800] intel-vbtn INT33D6:00: Registering Intel Virtual Switches input-dev after receiving a switch event [ 83.861858] input: Intel Virtual Switches as /devices/pci0000:00/0000:00:1f.0/PNP0C09:00/INT33D6:00/input/input17 [ 83.861865] intel-vbtn INT33D6:00: Registering Intel Virtual Switches input-dev after receiving a switch event After which things go seriously wrong: [ 83.861872] sysfs: cannot create duplicate filename '/devices/pci0000:00/0000:00:1f.0/PNP0C09:00/INT33D6:00/input/input17' ... [ 83.861967] kobject: kobject_add_internal failed for input17 with -EEXIST, don't try to register things with the same name in the same directory. [ 83.877338] BUG: kernel NULL pointer dereference, address: 0000000000000018 ... Protect intel-vbtn notify_handler() from racing with itself with a mutex to fix this. Fixes: e2ffcda ("ACPI: OSL: Allow Notify () handlers to run on all CPUs") Reported-by: En-Wei Wu <[email protected]> Closes: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/2073001 Tested-by: Kostadin Stoilov <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Ilpo Järvinen <[email protected]> Signed-off-by: Ilpo Järvinen <[email protected]>
1 parent 8400291 commit e075c3b

File tree

1 file changed

+9
-0
lines changed
  • drivers/platform/x86/intel

1 file changed

+9
-0
lines changed

drivers/platform/x86/intel/vbtn.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
*/
88

99
#include <linux/acpi.h>
10+
#include <linux/cleanup.h>
1011
#include <linux/dmi.h>
1112
#include <linux/input.h>
1213
#include <linux/input/sparse-keymap.h>
1314
#include <linux/kernel.h>
1415
#include <linux/module.h>
16+
#include <linux/mutex.h>
1517
#include <linux/platform_device.h>
1618
#include <linux/suspend.h>
1719
#include "../dual_accel_detect.h"
@@ -66,6 +68,7 @@ static const struct key_entry intel_vbtn_switchmap[] = {
6668
};
6769

6870
struct intel_vbtn_priv {
71+
struct mutex mutex; /* Avoid notify_handler() racing with itself */
6972
struct input_dev *buttons_dev;
7073
struct input_dev *switches_dev;
7174
bool dual_accel;
@@ -155,6 +158,8 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
155158
bool autorelease;
156159
int ret;
157160

161+
guard(mutex)(&priv->mutex);
162+
158163
if ((ke = sparse_keymap_entry_from_scancode(priv->buttons_dev, event))) {
159164
if (!priv->has_buttons) {
160165
dev_warn(&device->dev, "Warning: received 0x%02x button event on a device without buttons, please report this.\n",
@@ -290,6 +295,10 @@ static int intel_vbtn_probe(struct platform_device *device)
290295
return -ENOMEM;
291296
dev_set_drvdata(&device->dev, priv);
292297

298+
err = devm_mutex_init(&device->dev, &priv->mutex);
299+
if (err)
300+
return err;
301+
293302
priv->dual_accel = dual_accel;
294303
priv->has_buttons = has_buttons;
295304
priv->has_switches = has_switches;

0 commit comments

Comments
 (0)