Takashi Iwai 67938a
From bce9332220bd677d83b19d21502776ad555a0e73 Mon Sep 17 00:00:00 2001
Takashi Iwai 67938a
From: Linus Torvalds <torvalds@linux-foundation.org>
Takashi Iwai 67938a
Date: Mon, 5 Dec 2022 12:09:06 -0800
Takashi Iwai 67938a
Subject: [PATCH] proc: proc_skip_spaces() shouldn't think it is working on C strings
Takashi Iwai 67938a
Git-commit: bce9332220bd677d83b19d21502776ad555a0e73
Takashi Iwai 67938a
Patch-mainline: v6.1
Takashi Iwai cab6fa
References: CVE-2022-4378 bsc#1206207
Takashi Iwai 67938a
Takashi Iwai 67938a
proc_skip_spaces() seems to think it is working on C strings, and ends
Takashi Iwai 67938a
up being just a wrapper around skip_spaces() with a really odd calling
Takashi Iwai 67938a
convention.
Takashi Iwai 67938a
Takashi Iwai 67938a
Instead of basing it on skip_spaces(), it should have looked more like
Takashi Iwai 67938a
proc_skip_char(), which really is the exact same function (except it
Takashi Iwai 67938a
skips a particular character, rather than whitespace).  So use that as
Takashi Iwai 67938a
inspiration, odd coding and all.
Takashi Iwai 67938a
Takashi Iwai 67938a
Now the calling convention actually makes sense and works for the
Takashi Iwai 67938a
intended purpose.
Takashi Iwai 67938a
Takashi Iwai 67938a
Reported-and-tested-by: Kyle Zeng <zengyhkyle@gmail.com>
Takashi Iwai 67938a
Acked-by: Eric Dumazet <edumazet@google.com>
Takashi Iwai 67938a
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Takashi Iwai 67938a
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 67938a
Takashi Iwai 67938a
---
Takashi Iwai 67938a
 kernel/sysctl.c | 25 +++++++++++++------------
Takashi Iwai 67938a
 1 file changed, 13 insertions(+), 12 deletions(-)
Takashi Iwai 67938a
Takashi Iwai 67938a
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
Takashi Iwai 67938a
index 8898ddeaaf75..c6d9dec11b74 100644
Takashi Iwai 67938a
--- a/kernel/sysctl.c
Takashi Iwai 67938a
+++ b/kernel/sysctl.c
Takashi Iwai 67938a
@@ -267,13 +267,14 @@ int proc_dostring(struct ctl_table *table, int write,
Takashi Iwai 67938a
 			ppos);
Takashi Iwai 67938a
 }
Takashi Iwai 67938a
 
Takashi Iwai 67938a
-static size_t proc_skip_spaces(char **buf)
Takashi Iwai 67938a
+static void proc_skip_spaces(char **buf, size_t *size)
Takashi Iwai 67938a
 {
Takashi Iwai 67938a
-	size_t ret;
Takashi Iwai 67938a
-	char *tmp = skip_spaces(*buf);
Takashi Iwai 67938a
-	ret = tmp - *buf;
Takashi Iwai 67938a
-	*buf = tmp;
Takashi Iwai 67938a
-	return ret;
Takashi Iwai 67938a
+	while (*size) {
Takashi Iwai 67938a
+		if (!isspace(**buf))
Takashi Iwai 67938a
+			break;
Takashi Iwai 67938a
+		(*size)--;
Takashi Iwai 67938a
+		(*buf)++;
Takashi Iwai 67938a
+	}
Takashi Iwai 67938a
 }
Takashi Iwai 67938a
 
Takashi Iwai 67938a
 static void proc_skip_char(char **buf, size_t *size, const char v)
Takashi Iwai 67938a
@@ -520,7 +521,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
Takashi Iwai 67938a
 		bool neg;
Takashi Iwai 67938a
 
Takashi Iwai 67938a
 		if (write) {
Takashi Iwai 67938a
-			left -= proc_skip_spaces(&p);
Takashi Iwai 67938a
+			proc_skip_spaces(&p, &left);
Takashi Iwai 67938a
 
Takashi Iwai 67938a
 			if (!left)
Takashi Iwai 67938a
 				break;
Takashi Iwai 67938a
@@ -547,7 +548,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
Takashi Iwai 67938a
 	if (!write && !first && left && !err)
Takashi Iwai 67938a
 		proc_put_char(&buffer, &left, '\n');
Takashi Iwai 67938a
 	if (write && !err && left)
Takashi Iwai 67938a
-		left -= proc_skip_spaces(&p);
Takashi Iwai 67938a
+		proc_skip_spaces(&p, &left);
Takashi Iwai 67938a
 	if (write && first)
Takashi Iwai 67938a
 		return err ? : -EINVAL;
Takashi Iwai 67938a
 	*lenp -= left;
Takashi Iwai 67938a
@@ -589,7 +590,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data,
Takashi Iwai 67938a
 	if (left > PAGE_SIZE - 1)
Takashi Iwai 67938a
 		left = PAGE_SIZE - 1;
Takashi Iwai 67938a
 
Takashi Iwai 67938a
-	left -= proc_skip_spaces(&p);
Takashi Iwai 67938a
+	proc_skip_spaces(&p, &left);
Takashi Iwai 67938a
 	if (!left) {
Takashi Iwai 67938a
 		err = -EINVAL;
Takashi Iwai 67938a
 		goto out_free;
Takashi Iwai 67938a
@@ -609,7 +610,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data,
Takashi Iwai 67938a
 	}
Takashi Iwai 67938a
 
Takashi Iwai 67938a
 	if (!err && left)
Takashi Iwai 67938a
-		left -= proc_skip_spaces(&p);
Takashi Iwai 67938a
+		proc_skip_spaces(&p, &left);
Takashi Iwai 67938a
 
Takashi Iwai 67938a
 out_free:
Takashi Iwai 67938a
 	if (err)
Takashi Iwai 67938a
@@ -1074,7 +1075,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
Takashi Iwai 67938a
 		if (write) {
Takashi Iwai 67938a
 			bool neg;
Takashi Iwai 67938a
 
Takashi Iwai 67938a
-			left -= proc_skip_spaces(&p);
Takashi Iwai 67938a
+			proc_skip_spaces(&p, &left);
Takashi Iwai 67938a
 			if (!left)
Takashi Iwai 67938a
 				break;
Takashi Iwai 67938a
 
Takashi Iwai 67938a
@@ -1103,7 +1104,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table,
Takashi Iwai 67938a
 	if (!write && !first && left && !err)
Takashi Iwai 67938a
 		proc_put_char(&buffer, &left, '\n');
Takashi Iwai 67938a
 	if (write && !err)
Takashi Iwai 67938a
-		left -= proc_skip_spaces(&p);
Takashi Iwai 67938a
+		proc_skip_spaces(&p, &left);
Takashi Iwai 67938a
 	if (write && first)
Takashi Iwai 67938a
 		return err ? : -EINVAL;
Takashi Iwai 67938a
 	*lenp -= left;
Takashi Iwai 67938a
-- 
Takashi Iwai 67938a
2.35.3
Takashi Iwai 67938a