From: Greg Kroah-Hartman Date: Wed, 14 Aug 2019 14:51:11 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v5.2.9~10 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bb0b5ff808b129a7cfc8e86b2caf98f7039044c5;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: hid-sony-fix-race-condition-between-rumble-and-device-remove.patch --- diff --git a/queue-4.14/hid-sony-fix-race-condition-between-rumble-and-device-remove.patch b/queue-4.14/hid-sony-fix-race-condition-between-rumble-and-device-remove.patch new file mode 100644 index 00000000000..ead50891a1e --- /dev/null +++ b/queue-4.14/hid-sony-fix-race-condition-between-rumble-and-device-remove.patch @@ -0,0 +1,79 @@ +From e0f6974a54d3f7f1b5fdf5a593bd43ce9206ec04 Mon Sep 17 00:00:00 2001 +From: Roderick Colenbrander +Date: Fri, 2 Aug 2019 15:50:19 -0700 +Subject: HID: sony: Fix race condition between rumble and device remove. + +From: Roderick Colenbrander + +commit e0f6974a54d3f7f1b5fdf5a593bd43ce9206ec04 upstream. + +Valve reported a kernel crash on Ubuntu 18.04 when disconnecting a DS4 +gamepad while rumble is enabled. This issue is reproducible with a +frequency of 1 in 3 times in the game Borderlands 2 when using an +automatic weapon, which triggers many rumble operations. + +We found the issue to be a race condition between sony_remove and the +final device destruction by the HID / input system. The problem was +that sony_remove didn't clean some of its work_item state in +"struct sony_sc". After sony_remove work, the corresponding evdev +node was around for sufficient time for applications to still queue +rumble work after "sony_remove". + +On pre-4.19 kernels the race condition caused a kernel crash due to a +NULL-pointer dereference as "sc->output_report_dmabuf" got freed during +sony_remove. On newer kernels this crash doesn't happen due the buffer +now being allocated using devm_kzalloc. However we can still queue work, +while the driver is an undefined state. + +This patch fixes the described problem, by guarding the work_item +"state_worker" with an initialized variable, which we are setting back +to 0 on cleanup. + +Signed-off-by: Roderick Colenbrander +CC: stable@vger.kernel.org +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/hid/hid-sony.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -578,10 +578,14 @@ static void sony_set_leds(struct sony_sc + static inline void sony_schedule_work(struct sony_sc *sc, + enum sony_worker which) + { ++ unsigned long flags; ++ + switch (which) { + case SONY_WORKER_STATE: +- if (!sc->defer_initialization) ++ spin_lock_irqsave(&sc->lock, flags); ++ if (!sc->defer_initialization && sc->state_worker_initialized) + schedule_work(&sc->state_worker); ++ spin_unlock_irqrestore(&sc->lock, flags); + break; + case SONY_WORKER_HOTPLUG: + if (sc->hotplug_worker_initialized) +@@ -2488,13 +2492,18 @@ static inline void sony_init_output_repo + + static inline void sony_cancel_work_sync(struct sony_sc *sc) + { ++ unsigned long flags; ++ + if (sc->hotplug_worker_initialized) + cancel_work_sync(&sc->hotplug_worker); +- if (sc->state_worker_initialized) ++ if (sc->state_worker_initialized) { ++ spin_lock_irqsave(&sc->lock, flags); ++ sc->state_worker_initialized = 0; ++ spin_unlock_irqrestore(&sc->lock, flags); + cancel_work_sync(&sc->state_worker); ++ } + } + +- + static int sony_input_configured(struct hid_device *hdev, + struct hid_input *hidinput) + { diff --git a/queue-4.14/series b/queue-4.14/series index ce95e48012d..1548714f634 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -48,3 +48,4 @@ scsi-scsi_dh_alua-always-use-a-2-second-delay-before.patch test_firmware-fix-a-memory-leak-bug.patch tty-ldsem-locking-rwsem-add-missing-acquire-to-read_.patch perf-core-fix-creating-kernel-counters-for-pmus-that.patch +hid-sony-fix-race-condition-between-rumble-and-device-remove.patch