Blame SOURCES/CVE-2022-43945.patch

b58b33
From 9b4bc5423447796134efeabaf76fbd669428a028 Mon Sep 17 00:00:00 2001
b58b33
From: Yannick Cote <ycote@redhat.com>
b58b33
Date: Fri, 2 Dec 2022 12:58:38 -0500
b58b33
Subject: [KPATCH CVE-2022-43945] kpatch fixes for CVE-2022-43945
b58b33
b58b33
Kernels:
b58b33
4.18.0-425.3.1.el8
b58b33
4.18.0-425.10.1.el8_7
b58b33
b58b33
b58b33
Kpatch-MR: https://gitlab.com/redhat/prdsc/rhel/src/kpatch/rhel-8/-/merge_requests/76
b58b33
Approved-by: Joe Lawrence (@joe.lawrence)
b58b33
Changes since last build:
b58b33
arches: x86_64 ppc64le
b58b33
callback_xdr.o: changed function: nfs_callback_dispatch
b58b33
mremap.o: changed function: move_page_tables
b58b33
nfs3proc.o: changed function: nfsd3_init_dirlist_pages
b58b33
nfs3proc.o: changed function: nfsd3_proc_read
b58b33
nfsproc.o: changed function: nfsd_proc_read
b58b33
nfsproc.o: changed function: nfsd_proc_readdir
b58b33
nfssvc.o: changed function: nfsd_dispatch
b58b33
svc.o: changed function: nlmsvc_dispatch
b58b33
---------------------------
b58b33
b58b33
Modifications:
b58b33
- Take out modifications to header routines and roll new kpatch versions
b58b33
  of them to be included at all call sites.
b58b33
- Wrapped new routines: svcxdr_init_decode(), svcxdr_init_encode()
b58b33
b58b33
commit e608b2dbbb132ebed6b63967b0915159cdf52ce4
b58b33
Author: Scott Mayhew <smayhew@redhat.com>
b58b33
Date:   Thu Nov 10 13:46:47 2022 -0500
b58b33
b58b33
    SUNRPC: Fix svcxdr_init_decode's end-of-buffer calculation
b58b33
b58b33
    Bugzilla: https://bugzilla.redhat.com/2143172
b58b33
    CVE: CVE-2022-43945
b58b33
    Y-Commit: 804daece339d51a00b7b466cc648139009b1c0fb
b58b33
b58b33
    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141774
b58b33
    O-CVE: CVE-2022-43945
b58b33
b58b33
    commit 90bfc37b5ab91c1a6165e3e5cfc49bf04571b762
b58b33
    Author: Chuck Lever <chuck.lever@oracle.com>
b58b33
    Date:   Thu Sep 1 15:09:53 2022 -0400
b58b33
b58b33
        SUNRPC: Fix svcxdr_init_decode's end-of-buffer calculation
b58b33
b58b33
        Ensure that stream-based argument decoding can't go past the actual
b58b33
        end of the receive buffer. xdr_init_decode's calculation of the
b58b33
        value of xdr->end over-estimates the end of the buffer because the
b58b33
        Linux kernel RPC server code does not remove the size of the RPC
b58b33
        header from rqstp->rq_arg before calling the upper layer's
b58b33
        dispatcher.
b58b33
b58b33
        The server-side still uses the svc_getnl() macros to decode the
b58b33
        RPC call header. These macros reduce the length of the head iov
b58b33
        but do not update the total length of the message in the buffer
b58b33
        (buf->len).
b58b33
b58b33
        A proper fix for this would be to replace the use of svc_getnl() and
b58b33
        friends in the RPC header decoder, but that would be a large and
b58b33
        invasive change that would be difficult to backport.
b58b33
b58b33
        Fixes: 5191955d6fc6 ("SUNRPC: Prepare for xdr_stream-style decoding on the server-side")
b58b33
        Reviewed-by: Jeff Layton <jlayton@kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
b58b33
    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
b58b33
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
b58b33
b58b33
commit c43d2ebcf1b3893e044ee76490cbc225212dcd09
b58b33
Author: Scott Mayhew <smayhew@redhat.com>
b58b33
Date:   Thu Nov 10 13:46:47 2022 -0500
b58b33
b58b33
    SUNRPC: Fix svcxdr_init_encode's buflen calculation
b58b33
b58b33
    Bugzilla: https://bugzilla.redhat.com/2143172
b58b33
    CVE: CVE-2022-43945
b58b33
    Y-Commit: 0dfe425436b4e11f1cd68ed8cbf4a8c4276d47c6
b58b33
b58b33
    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141774
b58b33
    O-CVE: CVE-2022-43945
b58b33
b58b33
    commit 1242a87da0d8cd2a428e96ca68e7ea899b0f4624
b58b33
    Author: Chuck Lever <chuck.lever@oracle.com>
b58b33
    Date:   Thu Sep 1 15:09:59 2022 -0400
b58b33
b58b33
        SUNRPC: Fix svcxdr_init_encode's buflen calculation
b58b33
b58b33
        Commit 2825a7f90753 ("nfsd4: allow encoding across page boundaries")
b58b33
        added an explicit computation of the remaining length in the rq_res
b58b33
        XDR buffer.
b58b33
b58b33
        The computation appears to suffer from an "off-by-one" bug. Because
b58b33
        buflen is too large by one page, XDR encoding can run off the end of
b58b33
        the send buffer by eventually trying to use the struct page address
b58b33
        in rq_page_end, which always contains NULL.
b58b33
b58b33
        Fixes: bddfdbcddbe2 ("NFSD: Extract the svcxdr_init_encode() helper")
b58b33
        Reviewed-by: Jeff Layton <jlayton@kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
b58b33
    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
b58b33
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
b58b33
b58b33
commit 2c36509ef08d24a538bca8369ec0e88420813c3b
b58b33
Author: Scott Mayhew <smayhew@redhat.com>
b58b33
Date:   Thu Nov 10 13:46:47 2022 -0500
b58b33
b58b33
    NFSD: Protect against send buffer overflow in NFSv2 READDIR
b58b33
b58b33
    Bugzilla: https://bugzilla.redhat.com/2143172
b58b33
    CVE: CVE-2022-43945
b58b33
    Y-Commit: f4e8bb36f1ddd7d2111db324154793c7c6d3cad1
b58b33
b58b33
    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141774
b58b33
    O-CVE: CVE-2022-43945
b58b33
b58b33
    commit 00b4492686e0497fdb924a9d4c8f6f99377e176c
b58b33
    Author: Chuck Lever <chuck.lever@oracle.com>
b58b33
    Date:   Thu Sep 1 15:10:05 2022 -0400
b58b33
b58b33
        NFSD: Protect against send buffer overflow in NFSv2 READDIR
b58b33
b58b33
        Restore the previous limit on the @count argument to prevent a
b58b33
        buffer overflow attack.
b58b33
b58b33
        Fixes: 53b1119a6e50 ("NFSD: Fix READDIR buffer overflow")
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
        Reviewed-by: Jeff Layton <jlayton@kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
b58b33
    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
b58b33
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
b58b33
b58b33
commit e7f5ff9960dd6667538bf642a42168473e1d987d
b58b33
Author: Scott Mayhew <smayhew@redhat.com>
b58b33
Date:   Thu Nov 10 13:46:47 2022 -0500
b58b33
b58b33
    NFSD: Protect against send buffer overflow in NFSv3 READDIR
b58b33
b58b33
    Bugzilla: https://bugzilla.redhat.com/2143172
b58b33
    CVE: CVE-2022-43945
b58b33
    Y-Commit: c33579e1e26c423888888482a0e1ca9a0980f292
b58b33
b58b33
    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141774
b58b33
    O-CVE: CVE-2022-43945
b58b33
b58b33
    commit 640f87c190e0d1b2a0fcb2ecf6d2cd53b1c41991
b58b33
    Author: Chuck Lever <chuck.lever@oracle.com>
b58b33
    Date:   Thu Sep 1 15:10:12 2022 -0400
b58b33
b58b33
        NFSD: Protect against send buffer overflow in NFSv3 READDIR
b58b33
b58b33
        Since before the git era, NFSD has conserved the number of pages
b58b33
        held by each nfsd thread by combining the RPC receive and send
b58b33
        buffers into a single array of pages. This works because there are
b58b33
        no cases where an operation needs a large RPC Call message and a
b58b33
        large RPC Reply message at the same time.
b58b33
b58b33
        Once an RPC Call has been received, svc_process() updates
b58b33
        svc_rqst::rq_res to describe the part of rq_pages that can be
b58b33
        used for constructing the Reply. This means that the send buffer
b58b33
        (rq_res) shrinks when the received RPC record containing the RPC
b58b33
        Call is large.
b58b33
b58b33
        A client can force this shrinkage on TCP by sending a correctly-
b58b33
        formed RPC Call header contained in an RPC record that is
b58b33
        excessively large. The full maximum payload size cannot be
b58b33
        constructed in that case.
b58b33
b58b33
        Thanks to Aleksi Illikainen and Kari Hulkko for uncovering this
b58b33
        issue.
b58b33
b58b33
        Reported-by: Ben Ronallo <Benjamin.Ronallo@synopsys.com>
b58b33
        Cc: <stable@vger.kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
        Reviewed-by: Jeff Layton <jlayton@kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
b58b33
    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
b58b33
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
b58b33
b58b33
commit be58a0f8fe047e3cbc9891133b34cd323d01f8e3
b58b33
Author: Scott Mayhew <smayhew@redhat.com>
b58b33
Date:   Thu Nov 10 13:46:47 2022 -0500
b58b33
b58b33
    NFSD: Protect against send buffer overflow in NFSv2 READ
b58b33
b58b33
    Bugzilla: https://bugzilla.redhat.com/2143172
b58b33
    CVE: CVE-2022-43945
b58b33
    Y-Commit: 436325d0734d253f50a547b842a95ed4bb752ae3
b58b33
b58b33
    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141774
b58b33
    O-CVE: CVE-2022-43945
b58b33
b58b33
    commit 401bc1f90874280a80b93f23be33a0e7e2d1f912
b58b33
    Author: Chuck Lever <chuck.lever@oracle.com>
b58b33
    Date:   Thu Sep 1 15:10:18 2022 -0400
b58b33
b58b33
        NFSD: Protect against send buffer overflow in NFSv2 READ
b58b33
b58b33
        Since before the git era, NFSD has conserved the number of pages
b58b33
        held by each nfsd thread by combining the RPC receive and send
b58b33
        buffers into a single array of pages. This works because there are
b58b33
        no cases where an operation needs a large RPC Call message and a
b58b33
        large RPC Reply at the same time.
b58b33
b58b33
        Once an RPC Call has been received, svc_process() updates
b58b33
        svc_rqst::rq_res to describe the part of rq_pages that can be
b58b33
        used for constructing the Reply. This means that the send buffer
b58b33
        (rq_res) shrinks when the received RPC record containing the RPC
b58b33
        Call is large.
b58b33
b58b33
        A client can force this shrinkage on TCP by sending a correctly-
b58b33
        formed RPC Call header contained in an RPC record that is
b58b33
        excessively large. The full maximum payload size cannot be
b58b33
        constructed in that case.
b58b33
b58b33
        Cc: <stable@vger.kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
        Reviewed-by: Jeff Layton <jlayton@kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
b58b33
    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
b58b33
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
b58b33
b58b33
commit b0be04c547fb3f2c98bda81f9f93e68dfdcad398
b58b33
Author: Scott Mayhew <smayhew@redhat.com>
b58b33
Date:   Thu Nov 10 13:46:46 2022 -0500
b58b33
b58b33
    NFSD: Protect against send buffer overflow in NFSv3 READ
b58b33
b58b33
    Bugzilla: https://bugzilla.redhat.com/2143172
b58b33
    CVE: CVE-2022-43945
b58b33
    Y-Commit: cc970cde839098c5dd3d1dd013620ca972d4c9db
b58b33
b58b33
    O-Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2141774
b58b33
    O-CVE: CVE-2022-43945
b58b33
b58b33
    commit fa6be9cc6e80ec79892ddf08a8c10cabab9baf38
b58b33
    Author: Chuck Lever <chuck.lever@oracle.com>
b58b33
    Date:   Thu Sep 1 15:10:24 2022 -0400
b58b33
b58b33
        NFSD: Protect against send buffer overflow in NFSv3 READ
b58b33
b58b33
        Since before the git era, NFSD has conserved the number of pages
b58b33
        held by each nfsd thread by combining the RPC receive and send
b58b33
        buffers into a single array of pages. This works because there are
b58b33
        no cases where an operation needs a large RPC Call message and a
b58b33
        large RPC Reply at the same time.
b58b33
b58b33
        Once an RPC Call has been received, svc_process() updates
b58b33
        svc_rqst::rq_res to describe the part of rq_pages that can be
b58b33
        used for constructing the Reply. This means that the send buffer
b58b33
        (rq_res) shrinks when the received RPC record containing the RPC
b58b33
        Call is large.
b58b33
b58b33
        A client can force this shrinkage on TCP by sending a correctly-
b58b33
        formed RPC Call header contained in an RPC record that is
b58b33
        excessively large. The full maximum payload size cannot be
b58b33
        constructed in that case.
b58b33
b58b33
        Cc: <stable@vger.kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
        Reviewed-by: Jeff Layton <jlayton@kernel.org>
b58b33
        Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
b58b33
b58b33
    Signed-off-by: Scott Mayhew <smayhew@redhat.com>
b58b33
    Signed-off-by: Jarod Wilson <jarod@redhat.com>
b58b33
b58b33
Signed-off-by: Yannick Cote <ycote@redhat.com>
b58b33
---
b58b33
 fs/lockd/svc.c                        |  6 ++-
b58b33
 fs/nfs/callback_xdr.c                 |  6 ++-
b58b33
 fs/nfsd/nfs3proc.c                    | 11 +++---
b58b33
 fs/nfsd/nfsproc.c                     |  6 +--
b58b33
 fs/nfsd/nfssvc.c                      |  6 ++-
b58b33
 include/linux/kpatch_cve_2022_43945.h | 53 +++++++++++++++++++++++++++
b58b33
 6 files changed, 74 insertions(+), 14 deletions(-)
b58b33
 create mode 100644 include/linux/kpatch_cve_2022_43945.h
b58b33
b58b33
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
b58b33
index 31fd841010c2..13f3813b38a8 100644
b58b33
--- a/fs/lockd/svc.c
b58b33
+++ b/fs/lockd/svc.c
b58b33
@@ -767,6 +767,8 @@ static void __exit exit_nlm(void)
b58b33
 module_init(init_nlm);
b58b33
 module_exit(exit_nlm);
b58b33
 
b58b33
+#include <linux/kpatch_cve_2022_43945.h>
b58b33
+
b58b33
 /**
b58b33
  * nlmsvc_dispatch - Process an NLM Request
b58b33
  * @rqstp: incoming request
b58b33
@@ -780,7 +782,7 @@ static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp)
b58b33
 {
b58b33
 	const struct svc_procedure *procp = rqstp->rq_procinfo;
b58b33
 
b58b33
-	svcxdr_init_decode(rqstp);
b58b33
+	kpatch_cve_2022_43945_svcxdr_init_decode(rqstp);
b58b33
 	if (!procp->pc_decode(rqstp, &rqstp->rq_arg_stream))
b58b33
 		goto out_decode_err;
b58b33
 
b58b33
@@ -790,7 +792,7 @@ static int nlmsvc_dispatch(struct svc_rqst *rqstp, __be32 *statp)
b58b33
 	if (*statp != rpc_success)
b58b33
 		return 1;
b58b33
 
b58b33
-	svcxdr_init_encode(rqstp);
b58b33
+	kpatch_cve_2022_43945_svcxdr_init_encode(rqstp);
b58b33
 	if (!procp->pc_encode(rqstp, &rqstp->rq_res_stream))
b58b33
 		goto out_encode_err;
b58b33
 
b58b33
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
b58b33
index a67c41ec545f..9438f91b9c2d 100644
b58b33
--- a/fs/nfs/callback_xdr.c
b58b33
+++ b/fs/nfs/callback_xdr.c
b58b33
@@ -983,13 +983,15 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp)
b58b33
 	return rpc_success;
b58b33
 }
b58b33
 
b58b33
+#include <linux/kpatch_cve_2022_43945.h>
b58b33
+
b58b33
 static int
b58b33
 nfs_callback_dispatch(struct svc_rqst *rqstp, __be32 *statp)
b58b33
 {
b58b33
 	const struct svc_procedure *procp = rqstp->rq_procinfo;
b58b33
 
b58b33
-	svcxdr_init_decode(rqstp);
b58b33
-	svcxdr_init_encode(rqstp);
b58b33
+	kpatch_cve_2022_43945_svcxdr_init_decode(rqstp);
b58b33
+	kpatch_cve_2022_43945_svcxdr_init_encode(rqstp);
b58b33
 
b58b33
 	*statp = procp->pc_func(rqstp);
b58b33
 	return 1;
b58b33
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
b58b33
index f1d81704d5bd..233f07958b09 100644
b58b33
--- a/fs/nfsd/nfs3proc.c
b58b33
+++ b/fs/nfsd/nfs3proc.c
b58b33
@@ -146,7 +146,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
b58b33
 {
b58b33
 	struct nfsd3_readargs *argp = rqstp->rq_argp;
b58b33
 	struct nfsd3_readres *resp = rqstp->rq_resp;
b58b33
-	u32 max_blocksize = svc_max_payload(rqstp);
b58b33
 	unsigned int len;
b58b33
 	int v;
b58b33
 
b58b33
@@ -155,7 +154,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp)
b58b33
 				(unsigned long) argp->count,
b58b33
 				(unsigned long long) argp->offset);
b58b33
 
b58b33
-	argp->count = min_t(u32, argp->count, max_blocksize);
b58b33
+	argp->count = min_t(u32, argp->count, svc_max_payload(rqstp));
b58b33
+	argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
b58b33
 	if (argp->offset > (u64)OFFSET_MAX)
b58b33
 		argp->offset = (u64)OFFSET_MAX;
b58b33
 	if (argp->offset + argp->count > (u64)OFFSET_MAX)
b58b33
@@ -451,13 +451,14 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
b58b33
 {
b58b33
 	struct xdr_buf *buf = &resp->dirlist;
b58b33
 	struct xdr_stream *xdr = &resp->xdr;
b58b33
-
b58b33
-	count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp));
b58b33
+	unsigned int sendbuf = min_t(unsigned int, rqstp->rq_res.buflen,
b58b33
+				     svc_max_payload(rqstp));
b58b33
 
b58b33
 	memset(buf, 0, sizeof(*buf));
b58b33
 
b58b33
 	/* Reserve room for the NULL ptr & eof flag (-2 words) */
b58b33
-	buf->buflen = count - XDR_UNIT * 2;
b58b33
+	buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), sendbuf);
b58b33
+	buf->buflen -= XDR_UNIT * 2;
b58b33
 	buf->pages = rqstp->rq_next_page;
b58b33
 	rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
b58b33
 
b58b33
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
b58b33
index e4b0e0e6d1bc..87d0c443767c 100644
b58b33
--- a/fs/nfsd/nfsproc.c
b58b33
+++ b/fs/nfsd/nfsproc.c
b58b33
@@ -182,6 +182,7 @@ nfsd_proc_read(struct svc_rqst *rqstp)
b58b33
 		argp->count, argp->offset);
b58b33
 
b58b33
 	argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2);
b58b33
+	argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen);
b58b33
 
b58b33
 	v = 0;
b58b33
 	len = argp->count;
b58b33
@@ -561,12 +562,11 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,
b58b33
 	struct xdr_buf *buf = &resp->dirlist;
b58b33
 	struct xdr_stream *xdr = &resp->xdr;
b58b33
 
b58b33
-	count = clamp(count, (u32)(XDR_UNIT * 2), svc_max_payload(rqstp));
b58b33
-
b58b33
 	memset(buf, 0, sizeof(*buf));
b58b33
 
b58b33
 	/* Reserve room for the NULL ptr & eof flag (-2 words) */
b58b33
-	buf->buflen = count - XDR_UNIT * 2;
b58b33
+	buf->buflen = clamp(count, (u32)(XDR_UNIT * 2), (u32)PAGE_SIZE);
b58b33
+	buf->buflen -= XDR_UNIT * 2;
b58b33
 	buf->pages = rqstp->rq_next_page;
b58b33
 	rqstp->rq_next_page++;
b58b33
 
b58b33
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
b58b33
index c3c5613c29a8..b9aaf205ec0f 100644
b58b33
--- a/fs/nfsd/nfssvc.c
b58b33
+++ b/fs/nfsd/nfssvc.c
b58b33
@@ -985,6 +985,8 @@ nfsd(void *vrqstp)
b58b33
 	return 0;
b58b33
 }
b58b33
 
b58b33
+#include <linux/kpatch_cve_2022_43945.h>
b58b33
+
b58b33
 /**
b58b33
  * nfsd_dispatch - Process an NFS or NFSACL Request
b58b33
  * @rqstp: incoming request
b58b33
@@ -1006,7 +1008,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
b58b33
 	 */
b58b33
 	rqstp->rq_cachetype = proc->pc_cachetype;
b58b33
 
b58b33
-	svcxdr_init_decode(rqstp);
b58b33
+	kpatch_cve_2022_43945_svcxdr_init_decode(rqstp);
b58b33
 	if (!proc->pc_decode(rqstp, &rqstp->rq_arg_stream))
b58b33
 		goto out_decode_err;
b58b33
 
b58b33
@@ -1023,7 +1025,7 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
b58b33
 	 * Need to grab the location to store the status, as
b58b33
 	 * NFSv4 does some encoding while processing
b58b33
 	 */
b58b33
-	svcxdr_init_encode(rqstp);
b58b33
+	kpatch_cve_2022_43945_svcxdr_init_encode(rqstp);
b58b33
 
b58b33
 	*statp = proc->pc_func(rqstp);
b58b33
 	if (*statp == rpc_drop_reply || test_bit(RQ_DROPME, &rqstp->rq_flags))
b58b33
diff --git a/include/linux/kpatch_cve_2022_43945.h b/include/linux/kpatch_cve_2022_43945.h
b58b33
new file mode 100644
b58b33
index 000000000000..d52392485a57
b58b33
--- /dev/null
b58b33
+++ b/include/linux/kpatch_cve_2022_43945.h
b58b33
@@ -0,0 +1,53 @@
b58b33
+#ifndef _KPATCH_CVE_2022_43945_H
b58b33
+#define _KPATCH_CVE_2022_43945_H
b58b33
+
b58b33
+/*
b58b33
+ * svcxdr_init_decode - Prepare an xdr_stream for Call decoding
b58b33
+ * @rqstp: controlling server RPC transaction context
b58b33
+ *
b58b33
+ * This function currently assumes the RPC header in rq_arg has
b58b33
+ * already been decoded. Upon return, xdr->p points to the
b58b33
+ * location of the upper layer header.
b58b33
+ */
b58b33
+static inline void kpatch_cve_2022_43945_svcxdr_init_decode(struct svc_rqst *rqstp)
b58b33
+{
b58b33
+	struct xdr_stream *xdr = &rqstp->rq_arg_stream;
b58b33
+	struct xdr_buf *buf = &rqstp->rq_arg;
b58b33
+	struct kvec *argv = buf->head;
b58b33
+
b58b33
+	/*
b58b33
+	 * svc_getnl() and friends do not keep the xdr_buf's ::len
b58b33
+	 * field up to date. Refresh that field before initializing
b58b33
+	 * the argument decoding stream.
b58b33
+	 */
b58b33
+	buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len;
b58b33
+
b58b33
+	xdr_init_decode(xdr, buf, argv->iov_base, NULL);
b58b33
+	xdr_set_scratch_page(xdr, rqstp->rq_scratch_page);
b58b33
+}
b58b33
+
b58b33
+/*
b58b33
+ * svcxdr_init_encode - Prepare an xdr_stream for svc Reply encoding
b58b33
+ * @rqstp: controlling server RPC transaction context
b58b33
+ *
b58b33
+ */
b58b33
+static inline void kpatch_cve_2022_43945_svcxdr_init_encode(struct svc_rqst *rqstp)
b58b33
+{
b58b33
+	struct xdr_stream *xdr = &rqstp->rq_res_stream;
b58b33
+	struct xdr_buf *buf = &rqstp->rq_res;
b58b33
+	struct kvec *resv = buf->head;
b58b33
+
b58b33
+	xdr_reset_scratch_buffer(xdr);
b58b33
+
b58b33
+	xdr->buf = buf;
b58b33
+	xdr->iov = resv;
b58b33
+	xdr->p   = resv->iov_base + resv->iov_len;
b58b33
+	xdr->end = resv->iov_base + PAGE_SIZE - rqstp->rq_auth_slack;
b58b33
+	buf->len = resv->iov_len;
b58b33
+	xdr->page_ptr = buf->pages - 1;
b58b33
+	buf->buflen = PAGE_SIZE * (rqstp->rq_page_end - buf->pages);
b58b33
+	buf->buflen -= rqstp->rq_auth_slack;
b58b33
+	xdr->rqst = NULL;
b58b33
+}
b58b33
+
b58b33
+#endif /* _KPATCH_CVE_2022_43945_H */
b58b33
-- 
b58b33
2.39.1
b58b33
b58b33