Commit ab9489c4 authored by Samuel Thibault's avatar Samuel Thibault Committed by Greg Kroah-Hartman

staging: speakup: fix wraparound in uaccess length check

commit b96fba8d upstream.

If softsynthx_read() is called with `count < 3`, `count - 3` wraps, causing
the loop to copy as much data as available to the provided buffer. If
softsynthx_read() is invoked through sys_splice(), this causes an
unbounded kernel write; but even when userspace just reads from it
normally, a small size could cause userspace crashes.

Fixes: 425e586c ("speakup: add unicode variant of /dev/softsynth")
Signed-off-by: default avatarSamuel Thibault <>
Signed-off-by: default avatarJann Horn <>
Signed-off-by: default avatarGreg Kroah-Hartman <>
parent 22e3d317
......@@ -207,11 +207,15 @@ static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count,
int chars_sent = 0;
char __user *cp;
char *init;
size_t bytes_per_ch = unicode ? 3 : 1;
u16 ch;
int empty;
unsigned long flags;
if (count < bytes_per_ch)
return -EINVAL;
spin_lock_irqsave(&speakup_info.spinlock, flags);
while (1) {
prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
......@@ -237,7 +241,7 @@ static ssize_t softsynthx_read(struct file *fp, char __user *buf, size_t count,
init = get_initstring();
/* Keep 3 bytes available for a 16bit UTF-8-encoded character */
while (chars_sent <= count - 3) {
while (chars_sent <= count - bytes_per_ch) {
if (speakup_info.flushing) {
speakup_info.flushing = 0;
ch = '\x18';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment