Some devices, particularly the 3DConnexion Spacemouse wireless 3D
controllers, return more than just the battery capacity in the battery
report. The Spacemouse devices return an additional byte with a device
specific field. However, hidinput_query_battery_capacity() only
requests a 2 byte transfer.
When a spacemouse is connected via USB (direct wire, no wireless dongle)
and it returns a 3 byte report instead of the assumed 2 byte battery
report the larger transfer confuses and frightens the USB subsystem
which chooses to ignore the transfer. Then after 2 seconds assume the
device has stopped responding and reset it. This can be reproduced
easily by using a wired connection with a wireless spacemouse. The
Spacemouse will enter a loop of resetting every 2 seconds which can be
observed in dmesg.
This patch solves the problem by increasing the transfer request to 4
bytes instead of 2. The fix isn't particularly elegant, but it is simple
and safe to backport to stable kernels. A further patch will follow to
more elegantly handle battery reports that contain additional data.
Signed-off-by: Grant Likely <grant.likely(a)secretlab.ca>
Cc: Darren Hart <darren(a)dvhart.com>
Cc: Jiri Kosina <jikos(a)kernel.org>
Cc: Benjamin Tissoires <benjamin.tissoires(a)redhat.com>
Cc: stable(a)vger.kernel.org
---
drivers/hid/hid-input.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index dea9cc65bf80..e8641ce677e4 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -350,13 +350,13 @@ static int hidinput_query_battery_capacity(struct hid_device *dev)
u8 *buf;
int ret;
- buf = kmalloc(2, GFP_KERNEL);
+ buf = kmalloc(4, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2,
+ ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 4,
dev->battery_report_type, HID_REQ_GET_REPORT);
- if (ret != 2) {
+ if (ret < 2) {
kfree(buf);
return -ENODATA;
}
--
2.20.1
Although we zero the upper bits of x0 on entry to the kernel from an
AArch32 task, we do not clear them on the exception return path and can
therefore expose 64-bit sign extended syscall return values to userspace
via interfaces such as the 'perf_regs' ABI, which deal exclusively with
64-bit registers.
Explicitly clear the upper 32 bits of x0 on return from a compat system
call.
Cc: <stable(a)vger.kernel.org>
Cc: Mark Rutland <mark.rutland(a)arm.com>
Cc: Keno Fischer <keno(a)juliacomputing.com>
Cc: Luis Machado <luis.machado(a)linaro.org>
Signed-off-by: Will Deacon <will(a)kernel.org>
---
arch/arm64/include/asm/syscall.h | 12 +++++++++++-
arch/arm64/kernel/syscall.c | 3 +++
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/include/asm/syscall.h b/arch/arm64/include/asm/syscall.h
index 65299a2dcf9c..cfc0672013f6 100644
--- a/arch/arm64/include/asm/syscall.h
+++ b/arch/arm64/include/asm/syscall.h
@@ -34,6 +34,10 @@ static inline long syscall_get_error(struct task_struct *task,
struct pt_regs *regs)
{
unsigned long error = regs->regs[0];
+
+ if (is_compat_thread(task_thread_info(task)))
+ error = sign_extend64(error, 31);
+
return IS_ERR_VALUE(error) ? error : 0;
}
@@ -47,7 +51,13 @@ static inline void syscall_set_return_value(struct task_struct *task,
struct pt_regs *regs,
int error, long val)
{
- regs->regs[0] = (long) error ? error : val;
+ if (error)
+ val = error;
+
+ if (is_compat_thread(task_thread_info(task)))
+ val = lower_32_bits(val);
+
+ regs->regs[0] = val;
}
#define SYSCALL_MAX_ARGS 6
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index 7c14466a12af..98a26d4e7b0c 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -50,6 +50,9 @@ static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
ret = do_ni_syscall(regs, scno);
}
+ if (is_compat_task())
+ ret = lower_32_bits(ret);
+
regs->regs[0] = ret;
}
--
2.27.0.383.g050319c2ae-goog
Hi
[This is an automated email]
This commit has been processed because it contains a "Fixes:" tag
fixing commit: 711419e504eb ("irqdomain: Add the missing assignment of domain->fwnode for named fwnode").
The bot has tested the following trees: v5.7.8, v5.4.51, v4.19.132, v4.14.188.
v5.7.8: Failed to apply! Possible dependencies:
Unable to calculate
v5.4.51: Failed to apply! Possible dependencies:
051a07ec7a3de ("net: sgi: ioc3-eth: simplify setting the DMA mask")
0ce5ebd24d25f ("mfd: ioc3: Add driver for SGI IOC3 chip")
10cf8300ecada ("MIPS: SGI-IP27: fix readb/writeb addressing")
4dd147471dae0 ("net: sgi: ioc3-eth: don't abuse dma_direct_* calls")
v4.19.132: Failed to apply! Possible dependencies:
437f2b8c20858 ("MIPS: remove the HT_PCI config option")
69a07a41d908f ("MIPS: SGI-IP27: rework HUB interrupts")
a15687ca7b927 ("powerpc: PCI_MSI needs PCI")
e6308b6d35ea7 ("MIPS: SGI-IP27: abstract chipset irq from bridge")
eb01d42a77785 ("PCI: consolidate PCI config entry in drivers/pci")
v4.14.188: Failed to apply! Possible dependencies:
3369ddb62a42e ("MIPS: make the default mips dma implementation optional")
4a2e130cce1f6 ("m68k: allow ColdFire PCI bus on MMU and non-MMU configuration")
4c301f9b6a94b ("ARM: Convert to GENERIC_IRQ_MULTI_HANDLER")
69a07a41d908f ("MIPS: SGI-IP27: rework HUB interrupts")
76053854f7d10 ("ARC: [plat-hsdk] Add PCIe support")
b6e05477c10c1 ("dma/direct: Handle the memory encryption bit in common code")
d1f2564a5639b ("MIPS: ath25: use generic dma noncoherent ops")
e6308b6d35ea7 ("MIPS: SGI-IP27: abstract chipset irq from bridge")
ea8c64ace8664 ("dma-mapping: move swiotlb arch helpers to a new header")
eb01d42a77785 ("PCI: consolidate PCI config entry in drivers/pci")
f6d302e33d68d ("MIPS: consolidate the swiotlb implementations")
NOTE: The patch will not be queued to stable trees until it is upstream.
How should we proceed with this patch?
--
Thanks
Sasha
When an expiration delta falls into the last level of the wheel, we want
to compare that delta against the maximum possible delay and reduce our
delta to fit in if necessary.
However instead of comparing the delta against the maximum, we are
comparing the actual expiry against the maximum. Then instead of fixing
the delta to fit in, we set the maximum delta as the expiry value.
This can result in various undesired outcomes, the worst possible one
being a timer expiring 15 days ahead to fire immediately.
Fixes: 500462a9de65 ("timers: Switch to a non-cascading wheel")
Signed-off-by: Frederic Weisbecker <frederic(a)kernel.org>
Cc: Peter Zijlstra <peterz(a)infradead.org>
Cc: Anna-Maria Behnsen <anna-maria(a)linutronix.de>
Cc: Juri Lelli <juri.lelli(a)redhat.com>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: stable(a)vger.kernel.org
---
kernel/time/timer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 9a838d38dbe6..df1ff803acc4 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -521,8 +521,8 @@ static int calc_wheel_index(unsigned long expires, unsigned long clk)
* Force expire obscene large timeouts to expire at the
* capacity limit of the wheel.
*/
- if (expires >= WHEEL_TIMEOUT_CUTOFF)
- expires = WHEEL_TIMEOUT_MAX;
+ if (delta >= WHEEL_TIMEOUT_CUTOFF)
+ expires = clk + WHEEL_TIMEOUT_MAX;
idx = calc_index(expires, LVL_DEPTH - 1);
}
--
2.26.2