Blob Blame History Raw
From daf9de90e88ffb2e303145733167327f92b869c2 Mon Sep 17 00:00:00 2001
From: Ryan Sullivan <rysulliv@redhat.com>
Date: Tue, 7 Feb 2023 12:08:05 -0500
Subject: [KPATCH CVE-2022-4378] kpatch fixes for CVE-2022-4378

Kernels:
4.18.0-425.3.1.el8
4.18.0-425.10.1.el8_7


Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-8/-/merge_requests/82
Approved-by: Joe Lawrence (@joe.lawrence)
Approved-by: Yannick Cote (@ycote1)
Changes since last build:
[x86_64]:
control.o: changed function: snd_ctl_elem_read
control.o: changed function: snd_ctl_ioctl
sysctl.o: changed function: __do_proc_dointvec
sysctl.o: changed function: __do_proc_douintvec
sysctl.o: changed function: __do_proc_doulongvec_minmax
sysctl.o: changed function: proc_get_long.constprop.14

[ppc64le]:
control.o: changed function: snd_ctl_elem_read
control.o: changed function: snd_ctl_ioctl
sysctl.o: changed function: __do_proc_dointvec
sysctl.o: changed function: __do_proc_doulongvec_minmax
sysctl.o: changed function: proc_dopipe_max_size
sysctl.o: changed function: proc_douintvec
sysctl.o: changed function: proc_douintvec_minmax
sysctl.o: changed function: proc_get_long.constprop.14

---------------------------

Modifications: none

commit 8c873c04cfd546b8b29ae86dc35414cf4167d163
Author: Wander Lairson Costa <wander@redhat.com>
Date:   Mon Dec 12 15:43:15 2022 -0300

    proc: avoid integer type confusion in get_proc_long

    Bugzilla: https://bugzilla.redhat.com/2152571
    CVE: CVE-2022-4378
    Y-Commit: bbda4302821f46972d5139f9af87993a7a07306e

    O-Bugzilla: https://bugzilla.redhat.com/2152572
    O-CVE: CVE-2022-4378

    commit e6cfaf34be9fcd1a8285a294e18986bfc41a409c
    Author: Linus Torvalds <torvalds@linux-foundation.org>
    Date:   Mon Dec 5 11:33:40 2022 -0800

        proc: avoid integer type confusion in get_proc_long

        proc_get_long() is passed a size_t, but then assigns it to an 'int'
        variable for the length.  Let's not do that, even if our IO paths are
        limited to MAX_RW_COUNT (exactly because of these kinds of type errors).

        So do the proper test in the rigth type.

        Reported-by: Kyle Zeng <zengyhkyle@gmail.com>
        Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

    Signed-off-by: Wander Lairson Costa <wander@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

commit 2347e6da850ca59e4730578b53d0e9339a1bb1e6
Author: Wander Lairson Costa <wander@redhat.com>
Date:   Mon Dec 12 15:47:25 2022 -0300

    proc: proc_skip_spaces() shouldn't think it is working on C strings

    Bugzilla: https://bugzilla.redhat.com/2152571
    CVE: CVE-2022-4378
    Y-Commit: ec2f9f80ba44b533578349a97fb2fe9894142221

    O-Bugzilla: https://bugzilla.redhat.com/2152572
    O-CVE: CVE-2022-4378

    Conflicts: context hunks because out version is much older than
               upstream.

    commit bce9332220bd677d83b19d21502776ad555a0e73
    Author: Linus Torvalds <torvalds@linux-foundation.org>
    Date:   Mon Dec 5 12:09:06 2022 -0800

        proc: proc_skip_spaces() shouldn't think it is working on C strings

        proc_skip_spaces() seems to think it is working on C strings, and ends
        up being just a wrapper around skip_spaces() with a really odd calling
        convention.

        Instead of basing it on skip_spaces(), it should have looked more like
        proc_skip_char(), which really is the exact same function (except it
        skips a particular character, rather than whitespace).  So use that as
        inspiration, odd coding and all.

        Now the calling convention actually makes sense and works for the
        intended purpose.

        Reported-and-tested-by: Kyle Zeng <zengyhkyle@gmail.com>
        Acked-by: Eric Dumazet <edumazet@google.com>
        Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

    Signed-off-by: Wander Lairson Costa <wander@redhat.com>
    Signed-off-by: Jarod Wilson <jarod@redhat.com>

Signed-off-by: Ryan Sullivan <rysulliv@redhat.com>
---
 kernel/sysctl.c | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b4c8a670e9e0..3c8a3a787528 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2194,13 +2194,14 @@ int proc_dostring(struct ctl_table *table, int write,
 			       (char __user *)buffer, lenp, ppos);
 }
 
-static size_t proc_skip_spaces(char **buf)
+static void proc_skip_spaces(char **buf, size_t *size)
 {
-	size_t ret;
-	char *tmp = skip_spaces(*buf);
-	ret = tmp - *buf;
-	*buf = tmp;
-	return ret;
+	while (*size) {
+		if (!isspace(**buf))
+			break;
+		(*size)--;
+		(*buf)++;
+	}
 }
 
 static void proc_skip_char(char **buf, size_t *size, const char v)
@@ -2269,13 +2270,12 @@ static int proc_get_long(char **buf, size_t *size,
 			  unsigned long *val, bool *neg,
 			  const char *perm_tr, unsigned perm_tr_len, char *tr)
 {
-	int len;
 	char *p, tmp[TMPBUFLEN];
+	ssize_t len = *size;
 
-	if (!*size)
+	if (len <= 0)
 		return -EINVAL;
 
-	len = *size;
 	if (len > TMPBUFLEN - 1)
 		len = TMPBUFLEN - 1;
 
@@ -2438,7 +2438,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
 		bool neg;
 
 		if (write) {
-			left -= proc_skip_spaces(&p);
+			proc_skip_spaces(&p, &left);
 
 			if (!left)
 				break;
@@ -2469,7 +2469,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
 	if (!write && !first && left && !err)
 		err = proc_put_char(&buffer, &left, '\n');
 	if (write && !err && left)
-		left -= proc_skip_spaces(&p);
+		proc_skip_spaces(&p, &left);
 	if (write) {
 		kfree(kbuf);
 		if (first)
@@ -2518,7 +2518,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data,
 	if (IS_ERR(kbuf))
 		return -EINVAL;
 
-	left -= proc_skip_spaces(&p);
+	proc_skip_spaces(&p, &left);
 	if (!left) {
 		err = -EINVAL;
 		goto out_free;
@@ -2538,7 +2538,7 @@ static int do_proc_douintvec_w(unsigned int *tbl_data,
 	}
 
 	if (!err && left)
-		left -= proc_skip_spaces(&p);
+		proc_skip_spaces(&p, &left);
 
 out_free:
 	kfree(kbuf);
@@ -2982,7 +2982,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
 		if (write) {
 			bool neg;
 
-			left -= proc_skip_spaces(&p);
+			proc_skip_spaces(&p, &left);
 
 			err = proc_get_long(&p, &left, &val, &neg,
 					     proc_wspace_sep,
@@ -3013,7 +3013,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
 	if (!write && !first && left && !err)
 		err = proc_put_char(&buffer, &left, '\n');
 	if (write && !err)
-		left -= proc_skip_spaces(&p);
+		proc_skip_spaces(&p, &left);
 	if (write) {
 		kfree(kbuf);
 		if (first)
-- 
2.39.2