Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b96fba8d authored by Samuel Thibault's avatar Samuel Thibault Committed by Greg Kroah-Hartman
Browse files

staging: speakup: fix wraparound in uaccess length check



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")
Cc: stable@vger.kernel.org
Signed-off-by: default avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
Signed-off-by: default avatarJann Horn <jannh@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent eb37430d
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -198,11 +198,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;
	DEFINE_WAIT(wait);

	if (count < bytes_per_ch)
		return -EINVAL;

	spin_lock_irqsave(&speakup_info.spinlock, flags);
	while (1) {
		prepare_to_wait(&speakup_event, &wait, TASK_INTERRUPTIBLE);
@@ -228,7 +232,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';