From: Greg Kroah-Hartman Date: Thu, 27 Oct 2022 08:36:20 +0000 (+0200) Subject: drop large nfsd series. X-Git-Tag: v5.10.151~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=07050d1b0860e83c0b822e5d003b32a046a47ce6;p=thirdparty%2Fkernel%2Fstable-queue.git drop large nfsd series. Should be reviewed on the list. --- diff --git a/queue-5.10/dmaengine-mxs-dma-remove-the-unused-.id_table.patch b/queue-5.10/dmaengine-mxs-dma-remove-the-unused-.id_table.patch index 454df88aeb2..f1442f7dc05 100644 --- a/queue-5.10/dmaengine-mxs-dma-remove-the-unused-.id_table.patch +++ b/queue-5.10/dmaengine-mxs-dma-remove-the-unused-.id_table.patch @@ -18,14 +18,12 @@ Signed-off-by: Vinod Koul Stable-dep-of: 26696d465716 ("dmaengine: mxs: use platform_driver_register") Signed-off-by: Sasha Levin --- - drivers/dma/mxs-dma.c | 37 +++++-------------------------------- + drivers/dma/mxs-dma.c | 37 +++++-------------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) -diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c -index 65f816b40c32..994fc4d2aca4 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c -@@ -167,29 +167,11 @@ static struct mxs_dma_type mxs_dma_types[] = { +@@ -167,29 +167,11 @@ static struct mxs_dma_type mxs_dma_types } }; @@ -59,7 +57,7 @@ index 65f816b40c32..994fc4d2aca4 100644 { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mxs_dma_dt_ids); -@@ -762,8 +744,6 @@ static struct dma_chan *mxs_dma_xlate(struct of_phandle_args *dma_spec, +@@ -762,8 +744,6 @@ static struct dma_chan *mxs_dma_xlate(st static int __init mxs_dma_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -68,7 +66,7 @@ index 65f816b40c32..994fc4d2aca4 100644 const struct mxs_dma_type *dma_type; struct mxs_dma_engine *mxs_dma; struct resource *iores; -@@ -779,13 +759,7 @@ static int __init mxs_dma_probe(struct platform_device *pdev) +@@ -779,13 +759,7 @@ static int __init mxs_dma_probe(struct p return ret; } @@ -83,7 +81,7 @@ index 65f816b40c32..994fc4d2aca4 100644 mxs_dma->type = dma_type->type; mxs_dma->dev_id = dma_type->id; -@@ -865,7 +839,6 @@ static struct platform_driver mxs_dma_driver = { +@@ -865,7 +839,6 @@ static struct platform_driver mxs_dma_dr .name = "mxs-dma", .of_match_table = mxs_dma_dt_ids, }, @@ -91,6 +89,3 @@ index 65f816b40c32..994fc4d2aca4 100644 }; static int __init mxs_dma_module_init(void) --- -2.35.1 - diff --git a/queue-5.10/nfsd-add-common-helpers-to-decode-void-args-and-enco.patch b/queue-5.10/nfsd-add-common-helpers-to-decode-void-args-and-enco.patch deleted file mode 100644 index 2f9b17abdce..00000000000 --- a/queue-5.10/nfsd-add-common-helpers-to-decode-void-args-and-enco.patch +++ /dev/null @@ -1,407 +0,0 @@ -From 34e09e5c9a1611aa6be5e62844ff84e408ee3701 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 5 Nov 2020 14:48:29 -0500 -Subject: NFSD: Add common helpers to decode void args and encode void results - -From: Chuck Lever - -[ Upstream commit 788f7183fba86b46074c16e7d57ea09302badff4 ] - -Start off the conversion to xdr_stream by de-duplicating the functions -that decode void arguments and encode void results. - -Signed-off-by: Chuck Lever -Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs2acl.c | 21 ++++----------------- - fs/nfsd/nfs3acl.c | 8 ++++---- - fs/nfsd/nfs3proc.c | 10 ++++------ - fs/nfsd/nfs3xdr.c | 11 ----------- - fs/nfsd/nfs4proc.c | 11 ++++------- - fs/nfsd/nfs4xdr.c | 12 ------------ - fs/nfsd/nfsd.h | 8 ++++++++ - fs/nfsd/nfsproc.c | 25 ++++++++++++------------- - fs/nfsd/nfssvc.c | 28 ++++++++++++++++++++++++++++ - fs/nfsd/nfsxdr.c | 10 ---------- - fs/nfsd/xdr.h | 2 -- - fs/nfsd/xdr3.h | 2 -- - fs/nfsd/xdr4.h | 2 -- - 13 files changed, 64 insertions(+), 86 deletions(-) - -diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c -index 6a900f770dd2..b0f66604532a 100644 ---- a/fs/nfsd/nfs2acl.c -+++ b/fs/nfsd/nfs2acl.c -@@ -185,10 +185,6 @@ static __be32 nfsacld_proc_access(struct svc_rqst *rqstp) - /* - * XDR decode functions - */ --static int nfsaclsvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) --{ -- return 1; --} - - static int nfsaclsvc_decode_getaclargs(struct svc_rqst *rqstp, __be32 *p) - { -@@ -255,15 +251,6 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p) - * XDR encode functions - */ - --/* -- * There must be an encoding function for void results so svc_process -- * will work properly. -- */ --static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) --{ -- return xdr_ressize_check(rqstp, p); --} -- - /* GETACL */ - static int nfsaclsvc_encode_getaclres(struct svc_rqst *rqstp, __be32 *p) - { -@@ -378,10 +365,10 @@ struct nfsd3_voidargs { int dummy; }; - static const struct svc_procedure nfsd_acl_procedures2[5] = { - [ACLPROC2_NULL] = { - .pc_func = nfsacld_proc_null, -- .pc_decode = nfsaclsvc_decode_voidarg, -- .pc_encode = nfsaclsvc_encode_voidres, -- .pc_argsize = sizeof(struct nfsd3_voidargs), -- .pc_ressize = sizeof(struct nfsd3_voidargs), -+ .pc_decode = nfssvc_decode_voidarg, -+ .pc_encode = nfssvc_encode_voidres, -+ .pc_argsize = sizeof(struct nfsd_voidargs), -+ .pc_ressize = sizeof(struct nfsd_voidres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = ST, - }, -diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c -index 34a394e50e1d..7c30876a31a1 100644 ---- a/fs/nfsd/nfs3acl.c -+++ b/fs/nfsd/nfs3acl.c -@@ -245,10 +245,10 @@ struct nfsd3_voidargs { int dummy; }; - static const struct svc_procedure nfsd_acl_procedures3[3] = { - [ACLPROC3_NULL] = { - .pc_func = nfsd3_proc_null, -- .pc_decode = nfs3svc_decode_voidarg, -- .pc_encode = nfs3svc_encode_voidres, -- .pc_argsize = sizeof(struct nfsd3_voidargs), -- .pc_ressize = sizeof(struct nfsd3_voidargs), -+ .pc_decode = nfssvc_decode_voidarg, -+ .pc_encode = nfssvc_encode_voidres, -+ .pc_argsize = sizeof(struct nfsd_voidargs), -+ .pc_ressize = sizeof(struct nfsd_voidres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = ST, - }, -diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c -index 981a4e4c9a3c..a4dfe8160d55 100644 ---- a/fs/nfsd/nfs3proc.c -+++ b/fs/nfsd/nfs3proc.c -@@ -698,8 +698,6 @@ nfsd3_proc_commit(struct svc_rqst *rqstp) - #define nfsd3_attrstatres nfsd3_attrstat - #define nfsd3_wccstatres nfsd3_attrstat - #define nfsd3_createres nfsd3_diropres --#define nfsd3_voidres nfsd3_voidargs --struct nfsd3_voidargs { int dummy; }; - - #define ST 1 /* status*/ - #define FH 17 /* filehandle with length */ -@@ -710,10 +708,10 @@ struct nfsd3_voidargs { int dummy; }; - static const struct svc_procedure nfsd_procedures3[22] = { - [NFS3PROC_NULL] = { - .pc_func = nfsd3_proc_null, -- .pc_decode = nfs3svc_decode_voidarg, -- .pc_encode = nfs3svc_encode_voidres, -- .pc_argsize = sizeof(struct nfsd3_voidargs), -- .pc_ressize = sizeof(struct nfsd3_voidres), -+ .pc_decode = nfssvc_decode_voidarg, -+ .pc_encode = nfssvc_encode_voidres, -+ .pc_argsize = sizeof(struct nfsd_voidargs), -+ .pc_ressize = sizeof(struct nfsd_voidres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = ST, - }, -diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c -index 716566da400e..9dc22d917bd2 100644 ---- a/fs/nfsd/nfs3xdr.c -+++ b/fs/nfsd/nfs3xdr.c -@@ -304,11 +304,6 @@ void fill_post_wcc(struct svc_fh *fhp) - /* - * XDR decode functions - */ --int --nfs3svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) --{ -- return 1; --} - - int - nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) -@@ -642,12 +637,6 @@ nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p) - * XDR encode functions - */ - --int --nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) --{ -- return xdr_ressize_check(rqstp, p); --} -- - /* GETATTR */ - int - nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p) -diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c -index 9aeeb51e8c61..1acafc39f008 100644 ---- a/fs/nfsd/nfs4proc.c -+++ b/fs/nfsd/nfs4proc.c -@@ -3293,16 +3293,13 @@ static const char *nfsd4_op_name(unsigned opnum) - return "unknown_operation"; - } - --#define nfsd4_voidres nfsd4_voidargs --struct nfsd4_voidargs { int dummy; }; -- - static const struct svc_procedure nfsd_procedures4[2] = { - [NFSPROC4_NULL] = { - .pc_func = nfsd4_proc_null, -- .pc_decode = nfs4svc_decode_voidarg, -- .pc_encode = nfs4svc_encode_voidres, -- .pc_argsize = sizeof(struct nfsd4_voidargs), -- .pc_ressize = sizeof(struct nfsd4_voidres), -+ .pc_decode = nfssvc_decode_voidarg, -+ .pc_encode = nfssvc_encode_voidres, -+ .pc_argsize = sizeof(struct nfsd_voidargs), -+ .pc_ressize = sizeof(struct nfsd_voidres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = 1, - }, -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index cc605ee0b2fa..e7b891a19bf8 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -5263,12 +5263,6 @@ nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op) - p = xdr_encode_opaque_fixed(p, rp->rp_buf, rp->rp_buflen); - } - --int --nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) --{ -- return xdr_ressize_check(rqstp, p); --} -- - void nfsd4_release_compoundargs(struct svc_rqst *rqstp) - { - struct nfsd4_compoundargs *args = rqstp->rq_argp; -@@ -5286,12 +5280,6 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp) - } - } - --int --nfs4svc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) --{ -- return 1; --} -- - int - nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p) - { -diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h -index cb742e17e04a..7907de3f2ee6 100644 ---- a/fs/nfsd/nfsd.h -+++ b/fs/nfsd/nfsd.h -@@ -73,6 +73,14 @@ extern unsigned long nfsd_drc_mem_used; - - extern const struct seq_operations nfs_exports_op; - -+/* -+ * Common void argument and result helpers -+ */ -+struct nfsd_voidargs { }; -+struct nfsd_voidres { }; -+int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p); -+int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p); -+ - /* - * Function prototypes. - */ -diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c -index bbd01e8397f6..dbd8d3604653 100644 ---- a/fs/nfsd/nfsproc.c -+++ b/fs/nfsd/nfsproc.c -@@ -609,7 +609,6 @@ nfsd_proc_statfs(struct svc_rqst *rqstp) - * NFSv2 Server procedures. - * Only the results of non-idempotent operations are cached. - */ --struct nfsd_void { int dummy; }; - - #define ST 1 /* status */ - #define FH 8 /* filehandle */ -@@ -618,10 +617,10 @@ struct nfsd_void { int dummy; }; - static const struct svc_procedure nfsd_procedures2[18] = { - [NFSPROC_NULL] = { - .pc_func = nfsd_proc_null, -- .pc_decode = nfssvc_decode_void, -- .pc_encode = nfssvc_encode_void, -- .pc_argsize = sizeof(struct nfsd_void), -- .pc_ressize = sizeof(struct nfsd_void), -+ .pc_decode = nfssvc_decode_voidarg, -+ .pc_encode = nfssvc_encode_voidres, -+ .pc_argsize = sizeof(struct nfsd_voidargs), -+ .pc_ressize = sizeof(struct nfsd_voidres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = 0, - }, -@@ -647,10 +646,10 @@ static const struct svc_procedure nfsd_procedures2[18] = { - }, - [NFSPROC_ROOT] = { - .pc_func = nfsd_proc_root, -- .pc_decode = nfssvc_decode_void, -- .pc_encode = nfssvc_encode_void, -- .pc_argsize = sizeof(struct nfsd_void), -- .pc_ressize = sizeof(struct nfsd_void), -+ .pc_decode = nfssvc_decode_voidarg, -+ .pc_encode = nfssvc_encode_voidres, -+ .pc_argsize = sizeof(struct nfsd_voidargs), -+ .pc_ressize = sizeof(struct nfsd_voidres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = 0, - }, -@@ -685,10 +684,10 @@ static const struct svc_procedure nfsd_procedures2[18] = { - }, - [NFSPROC_WRITECACHE] = { - .pc_func = nfsd_proc_writecache, -- .pc_decode = nfssvc_decode_void, -- .pc_encode = nfssvc_encode_void, -- .pc_argsize = sizeof(struct nfsd_void), -- .pc_ressize = sizeof(struct nfsd_void), -+ .pc_decode = nfssvc_decode_voidarg, -+ .pc_encode = nfssvc_encode_voidres, -+ .pc_argsize = sizeof(struct nfsd_voidargs), -+ .pc_ressize = sizeof(struct nfsd_voidres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = 0, - }, -diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c -index ad6fedf37a40..8b675e8e6a6e 100644 ---- a/fs/nfsd/nfssvc.c -+++ b/fs/nfsd/nfssvc.c -@@ -1074,6 +1074,34 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) - return 1; - } - -+/** -+ * nfssvc_decode_voidarg - Decode void arguments -+ * @rqstp: Server RPC transaction context -+ * @p: buffer containing arguments to decode -+ * -+ * Return values: -+ * %0: Arguments were not valid -+ * %1: Decoding was successful -+ */ -+int nfssvc_decode_voidarg(struct svc_rqst *rqstp, __be32 *p) -+{ -+ return 1; -+} -+ -+/** -+ * nfssvc_encode_voidres - Encode void results -+ * @rqstp: Server RPC transaction context -+ * @p: buffer in which to encode results -+ * -+ * Return values: -+ * %0: Local error while encoding -+ * %1: Encoding was successful -+ */ -+int nfssvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p) -+{ -+ return xdr_ressize_check(rqstp, p); -+} -+ - int nfsd_pool_stats_open(struct inode *inode, struct file *file) - { - int ret; -diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c -index 8a288c8fcd57..13df5464a087 100644 ---- a/fs/nfsd/nfsxdr.c -+++ b/fs/nfsd/nfsxdr.c -@@ -192,11 +192,6 @@ __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *f - /* - * XDR decode functions - */ --int --nfssvc_decode_void(struct svc_rqst *rqstp, __be32 *p) --{ -- return xdr_argsize_check(rqstp, p); --} - - int - nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) -@@ -423,11 +418,6 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) - /* - * XDR encode functions - */ --int --nfssvc_encode_void(struct svc_rqst *rqstp, __be32 *p) --{ -- return xdr_ressize_check(rqstp, p); --} - - int - nfssvc_encode_stat(struct svc_rqst *rqstp, __be32 *p) -diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h -index b8cc6a4b2e0e..edd87688ff86 100644 ---- a/fs/nfsd/xdr.h -+++ b/fs/nfsd/xdr.h -@@ -144,7 +144,6 @@ union nfsd_xdrstore { - #define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore) - - --int nfssvc_decode_void(struct svc_rqst *, __be32 *); - int nfssvc_decode_fhandle(struct svc_rqst *, __be32 *); - int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *); - int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *); -@@ -156,7 +155,6 @@ int nfssvc_decode_readlinkargs(struct svc_rqst *, __be32 *); - int nfssvc_decode_linkargs(struct svc_rqst *, __be32 *); - int nfssvc_decode_symlinkargs(struct svc_rqst *, __be32 *); - int nfssvc_decode_readdirargs(struct svc_rqst *, __be32 *); --int nfssvc_encode_void(struct svc_rqst *, __be32 *); - int nfssvc_encode_stat(struct svc_rqst *, __be32 *); - int nfssvc_encode_attrstat(struct svc_rqst *, __be32 *); - int nfssvc_encode_diropres(struct svc_rqst *, __be32 *); -diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h -index ae6fa6c9cb46..456fcd7a1038 100644 ---- a/fs/nfsd/xdr3.h -+++ b/fs/nfsd/xdr3.h -@@ -273,7 +273,6 @@ union nfsd3_xdrstore { - - #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) - --int nfs3svc_decode_voidarg(struct svc_rqst *, __be32 *); - int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *); - int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *); - int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *); -@@ -290,7 +289,6 @@ int nfs3svc_decode_symlinkargs(struct svc_rqst *, __be32 *); - int nfs3svc_decode_readdirargs(struct svc_rqst *, __be32 *); - int nfs3svc_decode_readdirplusargs(struct svc_rqst *, __be32 *); - int nfs3svc_decode_commitargs(struct svc_rqst *, __be32 *); --int nfs3svc_encode_voidres(struct svc_rqst *, __be32 *); - int nfs3svc_encode_attrstat(struct svc_rqst *, __be32 *); - int nfs3svc_encode_wccstat(struct svc_rqst *, __be32 *); - int nfs3svc_encode_diropres(struct svc_rqst *, __be32 *); -diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h -index 679d40af1bbb..37f89ad5e992 100644 ---- a/fs/nfsd/xdr4.h -+++ b/fs/nfsd/xdr4.h -@@ -781,8 +781,6 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) - - - bool nfsd4_mach_creds_match(struct nfs4_client *cl, struct svc_rqst *rqstp); --int nfs4svc_decode_voidarg(struct svc_rqst *, __be32 *); --int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *); - int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *); - int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *); - __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32); --- -2.35.1 - diff --git a/queue-5.10/nfsd-fix-the-behavior-of-read-near-offset_max.patch b/queue-5.10/nfsd-fix-the-behavior-of-read-near-offset_max.patch deleted file mode 100644 index ef6f1b05d3d..00000000000 --- a/queue-5.10/nfsd-fix-the-behavior-of-read-near-offset_max.patch +++ /dev/null @@ -1,123 +0,0 @@ -From 3d69c488be74d18b9be2d42a67f4f2326a499362 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Fri, 4 Feb 2022 15:19:34 -0500 -Subject: NFSD: Fix the behavior of READ near OFFSET_MAX - -From: Chuck Lever - -[ Upstream commit 0cb4d23ae08c48f6bf3c29a8e5c4a74b8388b960 ] - -Dan Aloni reports: -> Due to commit 8cfb9015280d ("NFS: Always provide aligned buffers to -> the RPC read layers") on the client, a read of 0xfff is aligned up -> to server rsize of 0x1000. -> -> As a result, in a test where the server has a file of size -> 0x7fffffffffffffff, and the client tries to read from the offset -> 0x7ffffffffffff000, the read causes loff_t overflow in the server -> and it returns an NFS code of EINVAL to the client. The client as -> a result indefinitely retries the request. - -The Linux NFS client does not handle NFS?ERR_INVAL, even though all -NFS specifications permit servers to return that status code for a -READ. - -Instead of NFS?ERR_INVAL, have out-of-range READ requests succeed -and return a short result. Set the EOF flag in the result to prevent -the client from retrying the READ request. This behavior appears to -be consistent with Solaris NFS servers. - -Note that NFSv3 and NFSv4 use u64 offset values on the wire. These -must be converted to loff_t internally before use -- an implicit -type cast is not adequate for this purpose. Otherwise VFS checks -against sb->s_maxbytes do not work properly. - -Reported-by: Dan Aloni -Cc: stable@vger.kernel.org -Signed-off-by: Chuck Lever -Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs3proc.c | 8 ++++++-- - fs/nfsd/nfs4proc.c | 8 ++++++-- - fs/nfsd/nfs4xdr.c | 8 ++------ - 3 files changed, 14 insertions(+), 10 deletions(-) - -diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c -index 104e7d705ea8..60faa5b8eccf 100644 ---- a/fs/nfsd/nfs3proc.c -+++ b/fs/nfsd/nfs3proc.c -@@ -148,13 +148,17 @@ nfsd3_proc_read(struct svc_rqst *rqstp) - unsigned int len; - int v; - -- argp->count = min_t(u32, argp->count, max_blocksize); -- - dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n", - SVCFH_fmt(&argp->fh), - (unsigned long) argp->count, - (unsigned long long) argp->offset); - -+ argp->count = min_t(u32, argp->count, max_blocksize); -+ if (argp->offset > (u64)OFFSET_MAX) -+ argp->offset = (u64)OFFSET_MAX; -+ if (argp->offset + argp->count > (u64)OFFSET_MAX) -+ argp->count = (u64)OFFSET_MAX - argp->offset; -+ - v = 0; - len = argp->count; - while (len > 0) { -diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c -index 5054dc66cbf9..363df0a795bc 100644 ---- a/fs/nfsd/nfs4proc.c -+++ b/fs/nfsd/nfs4proc.c -@@ -772,12 +772,16 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - __be32 status; - - read->rd_nf = NULL; -- if (read->rd_offset >= OFFSET_MAX) -- return nfserr_inval; - - trace_nfsd_read_start(rqstp, &cstate->current_fh, - read->rd_offset, read->rd_length); - -+ read->rd_length = min_t(u32, read->rd_length, svc_max_payload(rqstp)); -+ if (read->rd_offset > (u64)OFFSET_MAX) -+ read->rd_offset = (u64)OFFSET_MAX; -+ if (read->rd_offset + read->rd_length > (u64)OFFSET_MAX) -+ read->rd_length = (u64)OFFSET_MAX - read->rd_offset; -+ - /* - * If we do a zero copy read, then a client will see read data - * that reflects the state of the file *after* performing the -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index d0af93a0558f..930bed3e40a4 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -3754,10 +3754,8 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, - } - xdr_commit_encode(xdr); - -- maxcount = svc_max_payload(resp->rqstp); -- maxcount = min_t(unsigned long, maxcount, -+ maxcount = min_t(unsigned long, read->rd_length, - (xdr->buf->buflen - xdr->buf->len)); -- maxcount = min_t(unsigned long, maxcount, read->rd_length); - - if (file->f_op->splice_read && - test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) -@@ -4585,10 +4583,8 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr, - return nfserr_resource; - xdr_commit_encode(xdr); - -- maxcount = svc_max_payload(resp->rqstp); -- maxcount = min_t(unsigned long, maxcount, -+ maxcount = min_t(unsigned long, read->rd_length, - (xdr->buf->buflen - xdr->buf->len)); -- maxcount = min_t(unsigned long, maxcount, read->rd_length); - count = maxcount; - - eof = read->rd_offset >= i_size_read(file_inode(file)); --- -2.35.1 - diff --git a/queue-5.10/nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch b/queue-5.10/nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch deleted file mode 100644 index e167699ef91..00000000000 --- a/queue-5.10/nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 371805ae7d57acb15b4ae15945abde5c27336ac4 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 1 Sep 2022 15:10:18 -0400 -Subject: NFSD: Protect against send buffer overflow in NFSv2 READ - -From: Chuck Lever - -[ Upstream commit 401bc1f90874280a80b93f23be33a0e7e2d1f912 ] - -Since before the git era, NFSD has conserved the number of pages -held by each nfsd thread by combining the RPC receive and send -buffers into a single array of pages. This works because there are -no cases where an operation needs a large RPC Call message and a -large RPC Reply at the same time. - -Once an RPC Call has been received, svc_process() updates -svc_rqst::rq_res to describe the part of rq_pages that can be -used for constructing the Reply. This means that the send buffer -(rq_res) shrinks when the received RPC record containing the RPC -Call is large. - -A client can force this shrinkage on TCP by sending a correctly- -formed RPC Call header contained in an RPC record that is -excessively large. The full maximum payload size cannot be -constructed in that case. - -Cc: -Signed-off-by: Chuck Lever -Reviewed-by: Jeff Layton -Signed-off-by: Chuck Lever -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfsproc.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c -index deaa34b89251..c540326c8e00 100644 ---- a/fs/nfsd/nfsproc.c -+++ b/fs/nfsd/nfsproc.c -@@ -180,6 +180,7 @@ nfsd_proc_read(struct svc_rqst *rqstp) - argp->count, argp->offset); - - argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2); -+ argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen); - - v = 0; - len = argp->count; --- -2.35.1 - diff --git a/queue-5.10/nfsd-protect-against-send-buffer-overflow-in-nfsv3-r.patch b/queue-5.10/nfsd-protect-against-send-buffer-overflow-in-nfsv3-r.patch deleted file mode 100644 index b5803398a5e..00000000000 --- a/queue-5.10/nfsd-protect-against-send-buffer-overflow-in-nfsv3-r.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 4d327c12bb49db2ecc125a939bbc32a273a6607a Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 1 Sep 2022 15:10:24 -0400 -Subject: NFSD: Protect against send buffer overflow in NFSv3 READ - -From: Chuck Lever - -[ Upstream commit fa6be9cc6e80ec79892ddf08a8c10cabab9baf38 ] - -Since before the git era, NFSD has conserved the number of pages -held by each nfsd thread by combining the RPC receive and send -buffers into a single array of pages. This works because there are -no cases where an operation needs a large RPC Call message and a -large RPC Reply at the same time. - -Once an RPC Call has been received, svc_process() updates -svc_rqst::rq_res to describe the part of rq_pages that can be -used for constructing the Reply. This means that the send buffer -(rq_res) shrinks when the received RPC record containing the RPC -Call is large. - -A client can force this shrinkage on TCP by sending a correctly- -formed RPC Call header contained in an RPC record that is -excessively large. The full maximum payload size cannot be -constructed in that case. - -Cc: -Signed-off-by: Chuck Lever -Reviewed-by: Jeff Layton -Signed-off-by: Chuck Lever -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs3proc.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c -index 60faa5b8eccf..84e700a54d01 100644 ---- a/fs/nfsd/nfs3proc.c -+++ b/fs/nfsd/nfs3proc.c -@@ -144,7 +144,6 @@ nfsd3_proc_read(struct svc_rqst *rqstp) - { - struct nfsd3_readargs *argp = rqstp->rq_argp; - struct nfsd3_readres *resp = rqstp->rq_resp; -- u32 max_blocksize = svc_max_payload(rqstp); - unsigned int len; - int v; - -@@ -153,7 +152,8 @@ nfsd3_proc_read(struct svc_rqst *rqstp) - (unsigned long) argp->count, - (unsigned long long) argp->offset); - -- argp->count = min_t(u32, argp->count, max_blocksize); -+ argp->count = min_t(u32, argp->count, svc_max_payload(rqstp)); -+ argp->count = min_t(u32, argp->count, rqstp->rq_res.buflen); - if (argp->offset > (u64)OFFSET_MAX) - argp->offset = (u64)OFFSET_MAX; - if (argp->offset + argp->count > (u64)OFFSET_MAX) --- -2.35.1 - diff --git a/queue-5.10/nfsd-replace-read-macros-in-nfsd4_decode_commit.patch b/queue-5.10/nfsd-replace-read-macros-in-nfsd4_decode_commit.patch deleted file mode 100644 index 5db7821c37d..00000000000 --- a/queue-5.10/nfsd-replace-read-macros-in-nfsd4_decode_commit.patch +++ /dev/null @@ -1,75 +0,0 @@ -From add4e4ab8734bc7519f9c446cb6b5a4aa1bb5b63 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 3 Nov 2020 13:19:51 -0500 -Subject: NFSD: Replace READ* macros in nfsd4_decode_commit() - -From: Chuck Lever - -[ Upstream commit cbd9abb3706e96563b36af67595707a7054ab693 ] - -Signed-off-by: Chuck Lever -Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs4xdr.c | 12 +++++------- - include/linux/sunrpc/xdr.h | 21 +++++++++++++++++++++ - 2 files changed, 26 insertions(+), 7 deletions(-) - -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index 69233350b061..d0af93a0558f 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -568,13 +568,11 @@ nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) - static __be32 - nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit) - { -- DECODE_HEAD; -- -- READ_BUF(12); -- p = xdr_decode_hyper(p, &commit->co_offset); -- commit->co_count = be32_to_cpup(p++); -- -- DECODE_TAIL; -+ if (xdr_stream_decode_u64(argp->xdr, &commit->co_offset) < 0) -+ return nfserr_bad_xdr; -+ if (xdr_stream_decode_u32(argp->xdr, &commit->co_count) < 0) -+ return nfserr_bad_xdr; -+ return nfs_ok; - } - - static __be32 -diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h -index c03f7bf585c9..6b1757543747 100644 ---- a/include/linux/sunrpc/xdr.h -+++ b/include/linux/sunrpc/xdr.h -@@ -569,6 +569,27 @@ xdr_stream_decode_u32(struct xdr_stream *xdr, __u32 *ptr) - return 0; - } - -+/** -+ * xdr_stream_decode_u64 - Decode a 64-bit integer -+ * @xdr: pointer to xdr_stream -+ * @ptr: location to store 64-bit integer -+ * -+ * Return values: -+ * %0 on success -+ * %-EBADMSG on XDR buffer overflow -+ */ -+static inline ssize_t -+xdr_stream_decode_u64(struct xdr_stream *xdr, __u64 *ptr) -+{ -+ const size_t count = sizeof(*ptr); -+ __be32 *p = xdr_inline_decode(xdr, count); -+ -+ if (unlikely(!p)) -+ return -EBADMSG; -+ xdr_decode_hyper(p, ptr); -+ return 0; -+} -+ - /** - * xdr_stream_decode_opaque_fixed - Decode fixed length opaque xdr data - * @xdr: pointer to xdr_stream --- -2.35.1 - diff --git a/queue-5.10/nfsd-replace-the-internals-of-the-read_buf-macro.patch b/queue-5.10/nfsd-replace-the-internals-of-the-read_buf-macro.patch deleted file mode 100644 index b51d22a0d6e..00000000000 --- a/queue-5.10/nfsd-replace-the-internals-of-the-read_buf-macro.patch +++ /dev/null @@ -1,412 +0,0 @@ -From fbbbdfeb61de7dfbaa5e5498af2254b49f0cb417 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 3 Nov 2020 11:54:23 -0500 -Subject: NFSD: Replace the internals of the READ_BUF() macro - -From: Chuck Lever - -[ Upstream commit c1346a1216ab5cb04a265380ac9035d91b16b6d5 ] - -Convert the READ_BUF macro in nfs4xdr.c from open code to instead -use the new xdr_stream-style decoders already in use by the encode -side (and by the in-kernel NFS client implementation). Once this -conversion is done, each individual NFSv4 argument decoder can be -independently cleaned up to replace these macros with C code. - -Signed-off-by: Chuck Lever -Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs4proc.c | 4 +- - fs/nfsd/nfs4xdr.c | 181 ++++++------------------------------- - fs/nfsd/xdr4.h | 10 +- - include/linux/sunrpc/xdr.h | 2 + - net/sunrpc/xdr.c | 45 +++++++++ - 5 files changed, 77 insertions(+), 165 deletions(-) - -diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c -index 1acafc39f008..5054dc66cbf9 100644 ---- a/fs/nfsd/nfs4proc.c -+++ b/fs/nfsd/nfs4proc.c -@@ -1024,8 +1024,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, - - write->wr_how_written = write->wr_stable_how; - -- nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist, -- &write->wr_head, write->wr_buflen); -+ nvecs = svc_fill_write_vector(rqstp, write->wr_payload.pages, -+ write->wr_payload.head, write->wr_buflen); - WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec)); - - status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf, -diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c -index e7b891a19bf8..69233350b061 100644 ---- a/fs/nfsd/nfs4xdr.c -+++ b/fs/nfsd/nfs4xdr.c -@@ -129,90 +129,13 @@ xdr_error: \ - memcpy((x), p, nbytes); \ - p += XDR_QUADLEN(nbytes); \ - } while (0) -- --/* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */ --#define READ_BUF(nbytes) do { \ -- if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \ -- p = argp->p; \ -- argp->p += XDR_QUADLEN(nbytes); \ -- } else if (!(p = read_buf(argp, nbytes))) { \ -- dprintk("NFSD: xdr error (%s:%d)\n", \ -- __FILE__, __LINE__); \ -- goto xdr_error; \ -- } \ --} while (0) -- --static void next_decode_page(struct nfsd4_compoundargs *argp) --{ -- argp->p = page_address(argp->pagelist[0]); -- argp->pagelist++; -- if (argp->pagelen < PAGE_SIZE) { -- argp->end = argp->p + XDR_QUADLEN(argp->pagelen); -- argp->pagelen = 0; -- } else { -- argp->end = argp->p + (PAGE_SIZE>>2); -- argp->pagelen -= PAGE_SIZE; -- } --} -- --static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) --{ -- /* We want more bytes than seem to be available. -- * Maybe we need a new page, maybe we have just run out -- */ -- unsigned int avail = (char *)argp->end - (char *)argp->p; -- __be32 *p; -- -- if (argp->pagelen == 0) { -- struct kvec *vec = &argp->rqstp->rq_arg.tail[0]; -- -- if (!argp->tail) { -- argp->tail = true; -- avail = vec->iov_len; -- argp->p = vec->iov_base; -- argp->end = vec->iov_base + avail; -- } -- -- if (avail < nbytes) -- return NULL; -- -- p = argp->p; -- argp->p += XDR_QUADLEN(nbytes); -- return p; -- } -- -- if (avail + argp->pagelen < nbytes) -- return NULL; -- if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */ -- return NULL; -- /* ok, we can do it with the current plus the next page */ -- if (nbytes <= sizeof(argp->tmp)) -- p = argp->tmp; -- else { -- kfree(argp->tmpp); -- p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); -- if (!p) -- return NULL; -- -- } -- /* -- * The following memcpy is safe because read_buf is always -- * called with nbytes > avail, and the two cases above both -- * guarantee p points to at least nbytes bytes. -- */ -- memcpy(p, argp->p, avail); -- next_decode_page(argp); -- memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); -- argp->p += XDR_QUADLEN(nbytes - avail); -- return p; --} -- --static unsigned int compoundargs_bytes_left(struct nfsd4_compoundargs *argp) --{ -- unsigned int this = (char *)argp->end - (char *)argp->p; -- -- return this + argp->pagelen; --} -+#define READ_BUF(nbytes) \ -+ do { \ -+ p = xdr_inline_decode(argp->xdr,\ -+ nbytes); \ -+ if (!p) \ -+ goto xdr_error; \ -+ } while (0) - - static int zero_clientid(clientid_t *clid) - { -@@ -259,44 +182,6 @@ svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len) - return p; - } - --static __be32 --svcxdr_construct_vector(struct nfsd4_compoundargs *argp, struct kvec *head, -- struct page ***pagelist, u32 buflen) --{ -- int avail; -- int len; -- int pages; -- -- /* Sorry .. no magic macros for this.. * -- * READ_BUF(write->wr_buflen); -- * SAVEMEM(write->wr_buf, write->wr_buflen); -- */ -- avail = (char *)argp->end - (char *)argp->p; -- if (avail + argp->pagelen < buflen) { -- dprintk("NFSD: xdr error (%s:%d)\n", -- __FILE__, __LINE__); -- return nfserr_bad_xdr; -- } -- head->iov_base = argp->p; -- head->iov_len = avail; -- *pagelist = argp->pagelist; -- -- len = XDR_QUADLEN(buflen) << 2; -- if (len >= avail) { -- len -= avail; -- -- pages = len >> PAGE_SHIFT; -- argp->pagelist += pages; -- argp->pagelen -= pages * PAGE_SIZE; -- len -= pages * PAGE_SIZE; -- -- next_decode_page(argp); -- } -- argp->p += XDR_QUADLEN(len); -- -- return 0; --} -- - /** - * savemem - duplicate a chunk of memory for later processing - * @argp: NFSv4 compound argument structure to be freed with -@@ -396,7 +281,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, - READ_BUF(4); len += 4; - nace = be32_to_cpup(p++); - -- if (nace > compoundargs_bytes_left(argp)/20) -+ if (nace > xdr_stream_remaining(argp->xdr) / sizeof(struct nfs4_ace)) - /* - * Even with 4-byte names there wouldn't be - * space for that many aces; something fishy is -@@ -927,7 +812,7 @@ static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x) - - static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o) - { -- __be32 *p; -+ DECODE_HEAD; - - READ_BUF(4); - o->len = be32_to_cpup(p++); -@@ -937,9 +822,8 @@ static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_ne - - READ_BUF(o->len); - SAVEMEM(o->data, o->len); -- return nfs_ok; --xdr_error: -- return nfserr_bad_xdr; -+ -+ DECODE_TAIL; - } - - static __be32 -@@ -1317,10 +1201,8 @@ nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) - goto xdr_error; - write->wr_buflen = be32_to_cpup(p++); - -- status = svcxdr_construct_vector(argp, &write->wr_head, -- &write->wr_pagelist, write->wr_buflen); -- if (status) -- return status; -+ if (!xdr_stream_subsegment(argp->xdr, &write->wr_payload, write->wr_buflen)) -+ goto xdr_error; - - DECODE_TAIL; - } -@@ -1889,13 +1771,14 @@ nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek) - */ - - /* -- * Decode data into buffer. Uses head and pages constructed by -- * svcxdr_construct_vector. -+ * Decode data into buffer. - */ - static __be32 --nfsd4_vbuf_from_vector(struct nfsd4_compoundargs *argp, struct kvec *head, -- struct page **pages, char **bufp, u32 buflen) -+nfsd4_vbuf_from_vector(struct nfsd4_compoundargs *argp, struct xdr_buf *xdr, -+ char **bufp, u32 buflen) - { -+ struct page **pages = xdr->pages; -+ struct kvec *head = xdr->head; - char *tmp, *dp; - u32 len; - -@@ -2010,8 +1893,6 @@ nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp, - { - DECODE_HEAD; - u32 flags, maxcount, size; -- struct kvec head; -- struct page **pagelist; - - READ_BUF(4); - flags = be32_to_cpup(p++); -@@ -2034,12 +1915,12 @@ nfsd4_decode_setxattr(struct nfsd4_compoundargs *argp, - - setxattr->setxa_len = size; - if (size > 0) { -- status = svcxdr_construct_vector(argp, &head, &pagelist, size); -- if (status) -- return status; -+ struct xdr_buf payload; - -- status = nfsd4_vbuf_from_vector(argp, &head, pagelist, -- &setxattr->setxa_buf, size); -+ if (!xdr_stream_subsegment(argp->xdr, &payload, size)) -+ goto xdr_error; -+ status = nfsd4_vbuf_from_vector(argp, &payload, -+ &setxattr->setxa_buf, size); - } - - DECODE_TAIL; -@@ -5271,8 +5152,6 @@ void nfsd4_release_compoundargs(struct svc_rqst *rqstp) - kfree(args->ops); - args->ops = args->iops; - } -- kfree(args->tmpp); -- args->tmpp = NULL; - while (args->to_free) { - struct svcxdr_tmpbuf *tb = args->to_free; - args->to_free = tb->next; -@@ -5285,19 +5164,11 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p) - { - struct nfsd4_compoundargs *args = rqstp->rq_argp; - -- if (rqstp->rq_arg.head[0].iov_len % 4) { -- /* client is nuts */ -- dprintk("%s: compound not properly padded! (peeraddr=%pISc xid=0x%x)", -- __func__, svc_addr(rqstp), be32_to_cpu(rqstp->rq_xid)); -- return 0; -- } -- args->p = p; -- args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; -- args->pagelist = rqstp->rq_arg.pages; -- args->pagelen = rqstp->rq_arg.page_len; -- args->tail = false; -+ /* svcxdr_tmp_alloc */ - args->tmpp = NULL; - args->to_free = NULL; -+ -+ args->xdr = &rqstp->rq_arg_stream; - args->ops = args->iops; - args->rqstp = rqstp; - -diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h -index 37f89ad5e992..0eb13bd603ea 100644 ---- a/fs/nfsd/xdr4.h -+++ b/fs/nfsd/xdr4.h -@@ -419,8 +419,7 @@ struct nfsd4_write { - u64 wr_offset; /* request */ - u32 wr_stable_how; /* request */ - u32 wr_buflen; /* request */ -- struct kvec wr_head; -- struct page ** wr_pagelist; /* request */ -+ struct xdr_buf wr_payload; /* request */ - - u32 wr_bytes_written; /* response */ - u32 wr_how_written; /* response */ -@@ -696,15 +695,10 @@ struct svcxdr_tmpbuf { - - struct nfsd4_compoundargs { - /* scratch variables for XDR decode */ -- __be32 * p; -- __be32 * end; -- struct page ** pagelist; -- int pagelen; -- bool tail; - __be32 tmp[8]; - __be32 * tmpp; -+ struct xdr_stream *xdr; - struct svcxdr_tmpbuf *to_free; -- - struct svc_rqst *rqstp; - - u32 taglen; -diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h -index 0c8cab6210b3..c03f7bf585c9 100644 ---- a/include/linux/sunrpc/xdr.h -+++ b/include/linux/sunrpc/xdr.h -@@ -252,6 +252,8 @@ extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len); - extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned int len, int (*actor)(struct scatterlist *, void *), void *data); - extern uint64_t xdr_align_data(struct xdr_stream *, uint64_t, uint32_t); - extern uint64_t xdr_expand_hole(struct xdr_stream *, uint64_t, uint64_t); -+extern bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf, -+ unsigned int len); - - /** - * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data. -diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c -index 02adc5c7f034..722586696fad 100644 ---- a/net/sunrpc/xdr.c -+++ b/net/sunrpc/xdr.c -@@ -1412,6 +1412,51 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, - } - EXPORT_SYMBOL_GPL(xdr_buf_subsegment); - -+/** -+ * xdr_stream_subsegment - set @subbuf to a portion of @xdr -+ * @xdr: an xdr_stream set up for decoding -+ * @subbuf: the result buffer -+ * @nbytes: length of @xdr to extract, in bytes -+ * -+ * Sets up @subbuf to represent a portion of @xdr. The portion -+ * starts at the current offset in @xdr, and extends for a length -+ * of @nbytes. If this is successful, @xdr is advanced to the next -+ * position following that portion. -+ * -+ * Return values: -+ * %true: @subbuf has been initialized, and @xdr has been advanced. -+ * %false: a bounds error has occurred -+ */ -+bool xdr_stream_subsegment(struct xdr_stream *xdr, struct xdr_buf *subbuf, -+ unsigned int nbytes) -+{ -+ unsigned int remaining, offset, len; -+ -+ if (xdr_buf_subsegment(xdr->buf, subbuf, xdr_stream_pos(xdr), nbytes)) -+ return false; -+ -+ if (subbuf->head[0].iov_len) -+ if (!__xdr_inline_decode(xdr, subbuf->head[0].iov_len)) -+ return false; -+ -+ remaining = subbuf->page_len; -+ offset = subbuf->page_base; -+ while (remaining) { -+ len = min_t(unsigned int, remaining, PAGE_SIZE) - offset; -+ -+ if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr)) -+ return false; -+ if (!__xdr_inline_decode(xdr, len)) -+ return false; -+ -+ remaining -= len; -+ offset = 0; -+ } -+ -+ return true; -+} -+EXPORT_SYMBOL_GPL(xdr_stream_subsegment); -+ - /** - * xdr_buf_trim - lop at most "len" bytes off the end of "buf" - * @buf: buf to be trimmed --- -2.35.1 - diff --git a/queue-5.10/nfsd-update-getattr3args-decoder-to-use-struct-xdr_s.patch b/queue-5.10/nfsd-update-getattr3args-decoder-to-use-struct-xdr_s.patch deleted file mode 100644 index 390213d6ab5..00000000000 --- a/queue-5.10/nfsd-update-getattr3args-decoder-to-use-struct-xdr_s.patch +++ /dev/null @@ -1,115 +0,0 @@ -From f846eda22099bbc03b9706b9a0e4318b753d8077 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 20 Oct 2020 14:30:02 -0400 -Subject: NFSD: Update GETATTR3args decoder to use struct xdr_stream - -From: Chuck Lever - -[ Upstream commit 9575363a9e4c8d7e2f9ba5e79884d623fff0be6f ] - -Signed-off-by: Chuck Lever -Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs3proc.c | 3 +-- - fs/nfsd/nfs3xdr.c | 31 +++++++++++++++++++++++++------ - fs/nfsd/xdr3.h | 2 +- - 3 files changed, 27 insertions(+), 9 deletions(-) - -diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c -index a4dfe8160d55..3d741ea482f4 100644 ---- a/fs/nfsd/nfs3proc.c -+++ b/fs/nfsd/nfs3proc.c -@@ -688,7 +688,6 @@ nfsd3_proc_commit(struct svc_rqst *rqstp) - * NFSv3 Server procedures. - * Only the results of non-idempotent operations are cached. - */ --#define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle - #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat - #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat - #define nfsd3_mkdirargs nfsd3_createargs -@@ -720,7 +719,7 @@ static const struct svc_procedure nfsd_procedures3[22] = { - .pc_decode = nfs3svc_decode_fhandleargs, - .pc_encode = nfs3svc_encode_attrstatres, - .pc_release = nfs3svc_release_fhandle, -- .pc_argsize = sizeof(struct nfsd3_fhandleargs), -+ .pc_argsize = sizeof(struct nfsd_fhandle), - .pc_ressize = sizeof(struct nfsd3_attrstatres), - .pc_cachetype = RC_NOCACHE, - .pc_xdrressize = ST+AT, -diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c -index 9dc22d917bd2..ed500f254337 100644 ---- a/fs/nfsd/nfs3xdr.c -+++ b/fs/nfsd/nfs3xdr.c -@@ -29,8 +29,9 @@ static u32 nfs3_ftypes[] = { - - - /* -- * XDR functions for basic NFS types -+ * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6) - */ -+ - static __be32 * - encode_time3(__be32 *p, struct timespec64 *time) - { -@@ -46,6 +47,26 @@ decode_time3(__be32 *p, struct timespec64 *time) - return p; - } - -+static bool -+svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp) -+{ -+ __be32 *p; -+ u32 size; -+ -+ if (xdr_stream_decode_u32(xdr, &size) < 0) -+ return false; -+ if (size == 0 || size > NFS3_FHSIZE) -+ return false; -+ p = xdr_inline_decode(xdr, size); -+ if (!p) -+ return false; -+ fh_init(fhp, NFS3_FHSIZE); -+ fhp->fh_handle.fh_size = size; -+ memcpy(&fhp->fh_handle.fh_base, p, size); -+ -+ return true; -+} -+ - static __be32 * - decode_fh(__be32 *p, struct svc_fh *fhp) - { -@@ -306,14 +327,12 @@ void fill_post_wcc(struct svc_fh *fhp) - */ - - int --nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) -+nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p) - { -+ struct xdr_stream *xdr = &rqstp->rq_arg_stream; - struct nfsd_fhandle *args = rqstp->rq_argp; - -- p = decode_fh(p, &args->fh); -- if (!p) -- return 0; -- return xdr_argsize_check(rqstp, p); -+ return svcxdr_decode_nfs_fh3(xdr, &args->fh); - } - - int -diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h -index 456fcd7a1038..62ea669768cf 100644 ---- a/fs/nfsd/xdr3.h -+++ b/fs/nfsd/xdr3.h -@@ -273,7 +273,7 @@ union nfsd3_xdrstore { - - #define NFS3_SVC_XDRSIZE sizeof(union nfsd3_xdrstore) - --int nfs3svc_decode_fhandle(struct svc_rqst *, __be32 *); -+int nfs3svc_decode_fhandleargs(struct svc_rqst *, __be32 *); - int nfs3svc_decode_sattrargs(struct svc_rqst *, __be32 *); - int nfs3svc_decode_diropargs(struct svc_rqst *, __be32 *); - int nfs3svc_decode_accessargs(struct svc_rqst *, __be32 *); --- -2.35.1 - diff --git a/queue-5.10/nfsd-update-read3arg-decoder-to-use-struct-xdr_strea.patch b/queue-5.10/nfsd-update-read3arg-decoder-to-use-struct-xdr_strea.patch deleted file mode 100644 index 2f66e4b812a..00000000000 --- a/queue-5.10/nfsd-update-read3arg-decoder-to-use-struct-xdr_strea.patch +++ /dev/null @@ -1,127 +0,0 @@ -From ec8c3337fcceb6bc1f0cbbd1ae44d5e419cbf171 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Tue, 20 Oct 2020 14:34:40 -0400 -Subject: NFSD: Update READ3arg decoder to use struct xdr_stream - -From: Chuck Lever - -[ Upstream commit be63bd2ac6bbf8c065a0ef6dfbea76934326c352 ] - -The code that sets up rq_vec is refactored so that it is now -adjacent to the nfsd_read() call site where it is used. - -Signed-off-by: Chuck Lever -Stable-dep-of: fa6be9cc6e80 ("NFSD: Protect against send buffer overflow in NFSv3 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfs3proc.c | 23 ++++++++++++++++++----- - fs/nfsd/nfs3xdr.c | 28 +++++++--------------------- - fs/nfsd/xdr3.h | 1 - - 3 files changed, 25 insertions(+), 27 deletions(-) - -diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c -index 3d741ea482f4..104e7d705ea8 100644 ---- a/fs/nfsd/nfs3proc.c -+++ b/fs/nfsd/nfs3proc.c -@@ -144,25 +144,38 @@ nfsd3_proc_read(struct svc_rqst *rqstp) - { - struct nfsd3_readargs *argp = rqstp->rq_argp; - struct nfsd3_readres *resp = rqstp->rq_resp; -- u32 max_blocksize = svc_max_payload(rqstp); -- unsigned long cnt = min(argp->count, max_blocksize); -+ u32 max_blocksize = svc_max_payload(rqstp); -+ unsigned int len; -+ int v; -+ -+ argp->count = min_t(u32, argp->count, max_blocksize); - - dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n", - SVCFH_fmt(&argp->fh), - (unsigned long) argp->count, - (unsigned long long) argp->offset); - -+ v = 0; -+ len = argp->count; -+ while (len > 0) { -+ struct page *page = *(rqstp->rq_next_page++); -+ -+ rqstp->rq_vec[v].iov_base = page_address(page); -+ rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE); -+ len -= rqstp->rq_vec[v].iov_len; -+ v++; -+ } -+ - /* Obtain buffer pointer for payload. - * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof) - * + 1 (xdr opaque byte count) = 26 - */ -- resp->count = cnt; -+ resp->count = argp->count; - svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); - - fh_copy(&resp->fh, &argp->fh); - resp->status = nfsd_read(rqstp, &resp->fh, argp->offset, -- rqstp->rq_vec, argp->vlen, &resp->count, -- &resp->eof); -+ rqstp->rq_vec, v, &resp->count, &resp->eof); - return rpc_success; - } - -diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c -index ed500f254337..0c51f241c047 100644 ---- a/fs/nfsd/nfs3xdr.c -+++ b/fs/nfsd/nfs3xdr.c -@@ -382,31 +382,17 @@ nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p) - int - nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p) - { -+ struct xdr_stream *xdr = &rqstp->rq_arg_stream; - struct nfsd3_readargs *args = rqstp->rq_argp; -- unsigned int len; -- int v; -- u32 max_blocksize = svc_max_payload(rqstp); - -- p = decode_fh(p, &args->fh); -- if (!p) -+ if (!svcxdr_decode_nfs_fh3(xdr, &args->fh)) -+ return 0; -+ if (xdr_stream_decode_u64(xdr, &args->offset) < 0) -+ return 0; -+ if (xdr_stream_decode_u32(xdr, &args->count) < 0) - return 0; -- p = xdr_decode_hyper(p, &args->offset); -- -- args->count = ntohl(*p++); -- len = min(args->count, max_blocksize); -- -- /* set up the kvec */ -- v=0; -- while (len > 0) { -- struct page *p = *(rqstp->rq_next_page++); - -- rqstp->rq_vec[v].iov_base = page_address(p); -- rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE); -- len -= rqstp->rq_vec[v].iov_len; -- v++; -- } -- args->vlen = v; -- return xdr_argsize_check(rqstp, p); -+ return 1; - } - - int -diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h -index 62ea669768cf..68cbb9e24afa 100644 ---- a/fs/nfsd/xdr3.h -+++ b/fs/nfsd/xdr3.h -@@ -32,7 +32,6 @@ struct nfsd3_readargs { - struct svc_fh fh; - __u64 offset; - __u32 count; -- int vlen; - }; - - struct nfsd3_writeargs { --- -2.35.1 - diff --git a/queue-5.10/nfsd-update-the-nfsv2-getattr-argument-decoder-to-us.patch b/queue-5.10/nfsd-update-the-nfsv2-getattr-argument-decoder-to-us.patch deleted file mode 100644 index c92e58ae550..00000000000 --- a/queue-5.10/nfsd-update-the-nfsv2-getattr-argument-decoder-to-us.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 1e265741e8e5554e2fd1e4a42aa49e827a518da2 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 21 Oct 2020 12:14:23 -0400 -Subject: NFSD: Update the NFSv2 GETATTR argument decoder to use struct - xdr_stream - -From: Chuck Lever - -[ Upstream commit ebcd8e8b28535b643a4c06685bd363b3b73a96af ] - -Signed-off-by: Chuck Lever -Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfsproc.c | 4 ++-- - fs/nfsd/nfsxdr.c | 26 ++++++++++++++++++++------ - fs/nfsd/xdr.h | 2 +- - 3 files changed, 23 insertions(+), 9 deletions(-) - -diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c -index dbd8d3604653..5c187d3bcb57 100644 ---- a/fs/nfsd/nfsproc.c -+++ b/fs/nfsd/nfsproc.c -@@ -626,7 +626,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { - }, - [NFSPROC_GETATTR] = { - .pc_func = nfsd_proc_getattr, -- .pc_decode = nfssvc_decode_fhandle, -+ .pc_decode = nfssvc_decode_fhandleargs, - .pc_encode = nfssvc_encode_attrstat, - .pc_release = nfssvc_release_attrstat, - .pc_argsize = sizeof(struct nfsd_fhandle), -@@ -776,7 +776,7 @@ static const struct svc_procedure nfsd_procedures2[18] = { - }, - [NFSPROC_STATFS] = { - .pc_func = nfsd_proc_statfs, -- .pc_decode = nfssvc_decode_fhandle, -+ .pc_decode = nfssvc_decode_fhandleargs, - .pc_encode = nfssvc_encode_statfsres, - .pc_argsize = sizeof(struct nfsd_fhandle), - .pc_ressize = sizeof(struct nfsd_statfsres), -diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c -index 13df5464a087..45d980d624f4 100644 ---- a/fs/nfsd/nfsxdr.c -+++ b/fs/nfsd/nfsxdr.c -@@ -23,8 +23,9 @@ static u32 nfs_ftypes[] = { - - - /* -- * XDR functions for basic NFS types -+ * Basic NFSv2 data types (RFC 1094 Section 2.3) - */ -+ - static __be32 * - decode_fh(__be32 *p, struct svc_fh *fhp) - { -@@ -37,6 +38,21 @@ decode_fh(__be32 *p, struct svc_fh *fhp) - return p + (NFS_FHSIZE >> 2); - } - -+static bool -+svcxdr_decode_fhandle(struct xdr_stream *xdr, struct svc_fh *fhp) -+{ -+ __be32 *p; -+ -+ p = xdr_inline_decode(xdr, NFS_FHSIZE); -+ if (!p) -+ return false; -+ fh_init(fhp, NFS_FHSIZE); -+ memcpy(&fhp->fh_handle.fh_base, p, NFS_FHSIZE); -+ fhp->fh_handle.fh_size = NFS_FHSIZE; -+ -+ return true; -+} -+ - /* Helper function for NFSv2 ACL code */ - __be32 *nfs2svc_decode_fh(__be32 *p, struct svc_fh *fhp) - { -@@ -194,14 +210,12 @@ __be32 *nfs2svc_encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *f - */ - - int --nfssvc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p) -+nfssvc_decode_fhandleargs(struct svc_rqst *rqstp, __be32 *p) - { -+ struct xdr_stream *xdr = &rqstp->rq_arg_stream; - struct nfsd_fhandle *args = rqstp->rq_argp; - -- p = decode_fh(p, &args->fh); -- if (!p) -- return 0; -- return xdr_argsize_check(rqstp, p); -+ return svcxdr_decode_fhandle(xdr, &args->fh); - } - - int -diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h -index edd87688ff86..50466ac6200c 100644 ---- a/fs/nfsd/xdr.h -+++ b/fs/nfsd/xdr.h -@@ -144,7 +144,7 @@ union nfsd_xdrstore { - #define NFS2_SVC_XDRSIZE sizeof(union nfsd_xdrstore) - - --int nfssvc_decode_fhandle(struct svc_rqst *, __be32 *); -+int nfssvc_decode_fhandleargs(struct svc_rqst *, __be32 *); - int nfssvc_decode_sattrargs(struct svc_rqst *, __be32 *); - int nfssvc_decode_diropargs(struct svc_rqst *, __be32 *); - int nfssvc_decode_readargs(struct svc_rqst *, __be32 *); --- -2.35.1 - diff --git a/queue-5.10/nfsd-update-the-nfsv2-read-argument-decoder-to-use-s.patch b/queue-5.10/nfsd-update-the-nfsv2-read-argument-decoder-to-use-s.patch deleted file mode 100644 index 6ea6a861816..00000000000 --- a/queue-5.10/nfsd-update-the-nfsv2-read-argument-decoder-to-use-s.patch +++ /dev/null @@ -1,141 +0,0 @@ -From 8085ba35427e0fa7b6378cddbd1d5cc0e89c8b09 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 21 Oct 2020 12:15:51 -0400 -Subject: NFSD: Update the NFSv2 READ argument decoder to use struct xdr_stream - -From: Chuck Lever - -[ Upstream commit 8c293ef993c8df0b1bea9ecb0de6eb96dec3ac9d ] - -The code that sets up rq_vec is refactored so that it is now -adjacent to the nfsd_read() call site where it is used. - -Signed-off-by: Chuck Lever -Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfsproc.c | 32 ++++++++++++++++++-------------- - fs/nfsd/nfsxdr.c | 36 ++++++++++++------------------------ - fs/nfsd/xdr.h | 1 - - 3 files changed, 30 insertions(+), 39 deletions(-) - -diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c -index 5c187d3bcb57..deaa34b89251 100644 ---- a/fs/nfsd/nfsproc.c -+++ b/fs/nfsd/nfsproc.c -@@ -171,32 +171,36 @@ nfsd_proc_read(struct svc_rqst *rqstp) - { - struct nfsd_readargs *argp = rqstp->rq_argp; - struct nfsd_readres *resp = rqstp->rq_resp; -+ unsigned int len; - u32 eof; -+ int v; - - dprintk("nfsd: READ %s %d bytes at %d\n", - SVCFH_fmt(&argp->fh), - argp->count, argp->offset); - -+ argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2); -+ -+ v = 0; -+ len = argp->count; -+ while (len > 0) { -+ struct page *page = *(rqstp->rq_next_page++); -+ -+ rqstp->rq_vec[v].iov_base = page_address(page); -+ rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE); -+ len -= rqstp->rq_vec[v].iov_len; -+ v++; -+ } -+ - /* Obtain buffer pointer for payload. 19 is 1 word for - * status, 17 words for fattr, and 1 word for the byte count. - */ -- -- if (NFSSVC_MAXBLKSIZE_V2 < argp->count) { -- char buf[RPC_MAX_ADDRBUFLEN]; -- printk(KERN_NOTICE -- "oversized read request from %s (%d bytes)\n", -- svc_print_addr(rqstp, buf, sizeof(buf)), -- argp->count); -- argp->count = NFSSVC_MAXBLKSIZE_V2; -- } - svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); - - resp->count = argp->count; -- resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), -- argp->offset, -- rqstp->rq_vec, argp->vlen, -- &resp->count, -- &eof); -+ fh_copy(&resp->fh, &argp->fh); -+ resp->status = nfsd_read(rqstp, &resp->fh, argp->offset, -+ rqstp->rq_vec, v, &resp->count, &eof); - if (resp->status == nfs_ok) - resp->status = fh_getattr(&resp->fh, &resp->stat); - else if (resp->status == nfserr_jukebox) -diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c -index 45d980d624f4..a44c42d35351 100644 ---- a/fs/nfsd/nfsxdr.c -+++ b/fs/nfsd/nfsxdr.c -@@ -246,33 +246,21 @@ nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p) - int - nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p) - { -+ struct xdr_stream *xdr = &rqstp->rq_arg_stream; - struct nfsd_readargs *args = rqstp->rq_argp; -- unsigned int len; -- int v; -- p = decode_fh(p, &args->fh); -- if (!p) -- return 0; -+ u32 totalcount; - -- args->offset = ntohl(*p++); -- len = args->count = ntohl(*p++); -- p++; /* totalcount - unused */ -- -- len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2); -+ if (!svcxdr_decode_fhandle(xdr, &args->fh)) -+ return 0; -+ if (xdr_stream_decode_u32(xdr, &args->offset) < 0) -+ return 0; -+ if (xdr_stream_decode_u32(xdr, &args->count) < 0) -+ return 0; -+ /* totalcount is ignored */ -+ if (xdr_stream_decode_u32(xdr, &totalcount) < 0) -+ return 0; - -- /* set up somewhere to store response. -- * We take pages, put them on reslist and include in iovec -- */ -- v=0; -- while (len > 0) { -- struct page *p = *(rqstp->rq_next_page++); -- -- rqstp->rq_vec[v].iov_base = page_address(p); -- rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE); -- len -= rqstp->rq_vec[v].iov_len; -- v++; -- } -- args->vlen = v; -- return xdr_argsize_check(rqstp, p); -+ return 1; - } - - int -diff --git a/fs/nfsd/xdr.h b/fs/nfsd/xdr.h -index 50466ac6200c..7c704fa3215e 100644 ---- a/fs/nfsd/xdr.h -+++ b/fs/nfsd/xdr.h -@@ -27,7 +27,6 @@ struct nfsd_readargs { - struct svc_fh fh; - __u32 offset; - __u32 count; -- int vlen; - }; - - struct nfsd_writeargs { --- -2.35.1 - diff --git a/queue-5.10/series b/queue-5.10/series index 51c080fd640..0b3c9308434 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -53,18 +53,6 @@ net-phy-dp83822-disable-mdi-crossover-status-change-.patch iommu-vt-d-allow-nvs-regions-in-arch_rmrr_sanity_che.patch iommu-vt-d-clean-up-si_domain-in-the-init_dmars-erro.patch drm-virtio-use-appropriate-atomic-state-in-virtio_gp.patch -sunrpc-add-xdr_set_scratch_page-and-xdr_reset_scratc.patch -sunrpc-prepare-for-xdr_stream-style-decoding-on-the-.patch -nfsd-add-common-helpers-to-decode-void-args-and-enco.patch -nfsd-update-the-nfsv2-getattr-argument-decoder-to-us.patch -nfsd-update-the-nfsv2-read-argument-decoder-to-use-s.patch -nfsd-protect-against-send-buffer-overflow-in-nfsv2-r.patch -nfsd-replace-the-internals-of-the-read_buf-macro.patch -nfsd-replace-read-macros-in-nfsd4_decode_commit.patch -nfsd-update-getattr3args-decoder-to-use-struct-xdr_s.patch -nfsd-update-read3arg-decoder-to-use-struct-xdr_strea.patch -nfsd-fix-the-behavior-of-read-near-offset_max.patch -nfsd-protect-against-send-buffer-overflow-in-nfsv3-r.patch dmaengine-mxs-dma-remove-the-unused-.id_table.patch dmaengine-mxs-use-platform_driver_register.patch writeback-don-t-warn-on-an-unregistered-bdi-in-__mar.patch diff --git a/queue-5.10/sunrpc-add-xdr_set_scratch_page-and-xdr_reset_scratc.patch b/queue-5.10/sunrpc-add-xdr_set_scratch_page-and-xdr_reset_scratc.patch deleted file mode 100644 index d7503513116..00000000000 --- a/queue-5.10/sunrpc-add-xdr_set_scratch_page-and-xdr_reset_scratc.patch +++ /dev/null @@ -1,309 +0,0 @@ -From 520c12fe7527e8c6fa85982c46d0d079fa704a08 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Wed, 11 Nov 2020 15:52:47 -0500 -Subject: SUNRPC: Add xdr_set_scratch_page() and xdr_reset_scratch_buffer() - -From: Chuck Lever - -[ Upstream commit 0ae4c3e8a64ace1b8d7de033b0751afe43024416 ] - -Clean up: De-duplicate some frequently-used code. - -Signed-off-by: Chuck Lever -Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ") -Signed-off-by: Sasha Levin ---- - fs/nfs/blocklayout/blocklayout.c | 2 +- - fs/nfs/blocklayout/dev.c | 2 +- - fs/nfs/dir.c | 2 +- - fs/nfs/filelayout/filelayout.c | 2 +- - fs/nfs/filelayout/filelayoutdev.c | 2 +- - fs/nfs/flexfilelayout/flexfilelayout.c | 2 +- - fs/nfs/flexfilelayout/flexfilelayoutdev.c | 2 +- - fs/nfs/nfs42xdr.c | 2 +- - fs/nfs/nfs4xdr.c | 6 ++-- - fs/nfsd/nfs4proc.c | 2 +- - include/linux/sunrpc/xdr.h | 44 ++++++++++++++++++++++- - net/sunrpc/auth_gss/gss_rpc_xdr.c | 2 +- - net/sunrpc/xdr.c | 28 +++------------ - 13 files changed, 59 insertions(+), 39 deletions(-) - -diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c -index 08108b6d2fa1..3be6836074ae 100644 ---- a/fs/nfs/blocklayout/blocklayout.c -+++ b/fs/nfs/blocklayout/blocklayout.c -@@ -697,7 +697,7 @@ bl_alloc_lseg(struct pnfs_layout_hdr *lo, struct nfs4_layoutget_res *lgr, - - xdr_init_decode_pages(&xdr, &buf, - lgr->layoutp->pages, lgr->layoutp->len); -- xdr_set_scratch_buffer(&xdr, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(&xdr, scratch); - - status = -EIO; - p = xdr_inline_decode(&xdr, 4); -diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c -index dec5880ac6de..acb1d22907da 100644 ---- a/fs/nfs/blocklayout/dev.c -+++ b/fs/nfs/blocklayout/dev.c -@@ -510,7 +510,7 @@ bl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, - goto out; - - xdr_init_decode_pages(&xdr, &buf, pdev->pages, pdev->pglen); -- xdr_set_scratch_buffer(&xdr, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(&xdr, scratch); - - p = xdr_inline_decode(&xdr, sizeof(__be32)); - if (!p) -diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c -index 9f88ca7b2001..935029632d5f 100644 ---- a/fs/nfs/dir.c -+++ b/fs/nfs/dir.c -@@ -576,7 +576,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en - goto out_nopages; - - xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen); -- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(&stream, scratch); - - do { - if (entry->label) -diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c -index ae5ed3a07494..d2103852475f 100644 ---- a/fs/nfs/filelayout/filelayout.c -+++ b/fs/nfs/filelayout/filelayout.c -@@ -666,7 +666,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, - return -ENOMEM; - - xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, lgr->layoutp->len); -- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(&stream, scratch); - - /* 20 = ufl_util (4), first_stripe_index (4), pattern_offset (8), - * num_fh (4) */ -diff --git a/fs/nfs/filelayout/filelayoutdev.c b/fs/nfs/filelayout/filelayoutdev.c -index d913e818858f..86c3f7e69ec4 100644 ---- a/fs/nfs/filelayout/filelayoutdev.c -+++ b/fs/nfs/filelayout/filelayoutdev.c -@@ -82,7 +82,7 @@ nfs4_fl_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, - goto out_err; - - xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen); -- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(&stream, scratch); - - /* Get the stripe count (number of stripe index) */ - p = xdr_inline_decode(&stream, 4); -diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c -index a8a02081942d..0200d96b8d5b 100644 ---- a/fs/nfs/flexfilelayout/flexfilelayout.c -+++ b/fs/nfs/flexfilelayout/flexfilelayout.c -@@ -378,7 +378,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh, - - xdr_init_decode_pages(&stream, &buf, lgr->layoutp->pages, - lgr->layoutp->len); -- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(&stream, scratch); - - /* stripe unit and mirror_array_cnt */ - rc = -EIO; -diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c -index 1f12297109b4..bfa7202ca7be 100644 ---- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c -+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c -@@ -69,7 +69,7 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev, - INIT_LIST_HEAD(&dsaddrs); - - xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen); -- xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(&stream, scratch); - - /* multipath count */ - p = xdr_inline_decode(&stream, 4); -diff --git a/fs/nfs/nfs42xdr.c b/fs/nfs/nfs42xdr.c -index f2248d9d4db5..df5bee2f505c 100644 ---- a/fs/nfs/nfs42xdr.c -+++ b/fs/nfs/nfs42xdr.c -@@ -1536,7 +1536,7 @@ static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp, - struct compound_hdr hdr; - int status; - -- xdr_set_scratch_buffer(xdr, page_address(res->scratch), PAGE_SIZE); -+ xdr_set_scratch_page(xdr, res->scratch); - - status = decode_compound_hdr(xdr, &hdr); - if (status) -diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c -index e2f0e3446e22..f21dc4284468 100644 ---- a/fs/nfs/nfs4xdr.c -+++ b/fs/nfs/nfs4xdr.c -@@ -6406,10 +6406,8 @@ nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr, - struct compound_hdr hdr; - int status; - -- if (res->acl_scratch != NULL) { -- void *p = page_address(res->acl_scratch); -- xdr_set_scratch_buffer(xdr, p, PAGE_SIZE); -- } -+ if (res->acl_scratch != NULL) -+ xdr_set_scratch_page(xdr, res->acl_scratch); - status = decode_compound_hdr(xdr, &hdr); - if (status) - goto out; -diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c -index 735ee8a79870..9aeeb51e8c61 100644 ---- a/fs/nfsd/nfs4proc.c -+++ b/fs/nfsd/nfs4proc.c -@@ -2274,7 +2274,7 @@ static void svcxdr_init_encode(struct svc_rqst *rqstp, - xdr->end = head->iov_base + PAGE_SIZE - rqstp->rq_auth_slack; - /* Tail and page_len should be zero at this point: */ - buf->len = buf->head[0].iov_len; -- xdr->scratch.iov_len = 0; -+ xdr_reset_scratch_buffer(xdr); - xdr->page_ptr = buf->pages - 1; - buf->buflen = PAGE_SIZE * (1 + rqstp->rq_page_end - buf->pages) - - rqstp->rq_auth_slack; -diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h -index 6d9d1520612b..0c8cab6210b3 100644 ---- a/include/linux/sunrpc/xdr.h -+++ b/include/linux/sunrpc/xdr.h -@@ -246,7 +246,6 @@ extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, - __be32 *p, struct rpc_rqst *rqst); - extern void xdr_init_decode_pages(struct xdr_stream *xdr, struct xdr_buf *buf, - struct page **pages, unsigned int len); --extern void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen); - extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes); - extern unsigned int xdr_read_pages(struct xdr_stream *xdr, unsigned int len); - extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len); -@@ -254,6 +253,49 @@ extern int xdr_process_buf(struct xdr_buf *buf, unsigned int offset, unsigned in - extern uint64_t xdr_align_data(struct xdr_stream *, uint64_t, uint32_t); - extern uint64_t xdr_expand_hole(struct xdr_stream *, uint64_t, uint64_t); - -+/** -+ * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data. -+ * @xdr: pointer to xdr_stream struct -+ * @buf: pointer to an empty buffer -+ * @buflen: size of 'buf' -+ * -+ * The scratch buffer is used when decoding from an array of pages. -+ * If an xdr_inline_decode() call spans across page boundaries, then -+ * we copy the data into the scratch buffer in order to allow linear -+ * access. -+ */ -+static inline void -+xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen) -+{ -+ xdr->scratch.iov_base = buf; -+ xdr->scratch.iov_len = buflen; -+} -+ -+/** -+ * xdr_set_scratch_page - Attach a scratch buffer for decoding data -+ * @xdr: pointer to xdr_stream struct -+ * @page: an anonymous page -+ * -+ * See xdr_set_scratch_buffer(). -+ */ -+static inline void -+xdr_set_scratch_page(struct xdr_stream *xdr, struct page *page) -+{ -+ xdr_set_scratch_buffer(xdr, page_address(page), PAGE_SIZE); -+} -+ -+/** -+ * xdr_reset_scratch_buffer - Clear scratch buffer information -+ * @xdr: pointer to xdr_stream struct -+ * -+ * See xdr_set_scratch_buffer(). -+ */ -+static inline void -+xdr_reset_scratch_buffer(struct xdr_stream *xdr) -+{ -+ xdr_set_scratch_buffer(xdr, NULL, 0); -+} -+ - /** - * xdr_stream_remaining - Return the number of bytes remaining in the stream - * @xdr: pointer to struct xdr_stream -diff --git a/net/sunrpc/auth_gss/gss_rpc_xdr.c b/net/sunrpc/auth_gss/gss_rpc_xdr.c -index 2ff7b7083eba..c636c648849b 100644 ---- a/net/sunrpc/auth_gss/gss_rpc_xdr.c -+++ b/net/sunrpc/auth_gss/gss_rpc_xdr.c -@@ -789,7 +789,7 @@ int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp, - scratch = alloc_page(GFP_KERNEL); - if (!scratch) - return -ENOMEM; -- xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE); -+ xdr_set_scratch_page(xdr, scratch); - - /* res->status */ - err = gssx_dec_status(xdr, &res->status); -diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c -index d84bb5037bb5..02adc5c7f034 100644 ---- a/net/sunrpc/xdr.c -+++ b/net/sunrpc/xdr.c -@@ -669,7 +669,7 @@ void xdr_init_encode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, - struct kvec *iov = buf->head; - int scratch_len = buf->buflen - buf->page_len - buf->tail[0].iov_len; - -- xdr_set_scratch_buffer(xdr, NULL, 0); -+ xdr_reset_scratch_buffer(xdr); - BUG_ON(scratch_len < 0); - xdr->buf = buf; - xdr->iov = iov; -@@ -713,7 +713,7 @@ inline void xdr_commit_encode(struct xdr_stream *xdr) - page = page_address(*xdr->page_ptr); - memcpy(xdr->scratch.iov_base, page, shift); - memmove(page, page + shift, (void *)xdr->p - page); -- xdr->scratch.iov_len = 0; -+ xdr_reset_scratch_buffer(xdr); - } - EXPORT_SYMBOL_GPL(xdr_commit_encode); - -@@ -743,8 +743,7 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, - * the "scratch" iov to track any temporarily unused fragment of - * space at the end of the previous buffer: - */ -- xdr->scratch.iov_base = xdr->p; -- xdr->scratch.iov_len = frag1bytes; -+ xdr_set_scratch_buffer(xdr, xdr->p, frag1bytes); - p = page_address(*xdr->page_ptr); - /* - * Note this is where the next encode will start after we've -@@ -1056,8 +1055,7 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p, - struct rpc_rqst *rqst) - { - xdr->buf = buf; -- xdr->scratch.iov_base = NULL; -- xdr->scratch.iov_len = 0; -+ xdr_reset_scratch_buffer(xdr); - xdr->nwords = XDR_QUADLEN(buf->len); - if (buf->head[0].iov_len != 0) - xdr_set_iov(xdr, buf->head, buf->len); -@@ -1105,24 +1103,6 @@ static __be32 * __xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes) - return p; - } - --/** -- * xdr_set_scratch_buffer - Attach a scratch buffer for decoding data. -- * @xdr: pointer to xdr_stream struct -- * @buf: pointer to an empty buffer -- * @buflen: size of 'buf' -- * -- * The scratch buffer is used when decoding from an array of pages. -- * If an xdr_inline_decode() call spans across page boundaries, then -- * we copy the data into the scratch buffer in order to allow linear -- * access. -- */ --void xdr_set_scratch_buffer(struct xdr_stream *xdr, void *buf, size_t buflen) --{ -- xdr->scratch.iov_base = buf; -- xdr->scratch.iov_len = buflen; --} --EXPORT_SYMBOL_GPL(xdr_set_scratch_buffer); -- - static __be32 *xdr_copy_to_scratch(struct xdr_stream *xdr, size_t nbytes) - { - __be32 *p; --- -2.35.1 - diff --git a/queue-5.10/sunrpc-prepare-for-xdr_stream-style-decoding-on-the-.patch b/queue-5.10/sunrpc-prepare-for-xdr_stream-style-decoding-on-the-.patch deleted file mode 100644 index 70895e879fa..00000000000 --- a/queue-5.10/sunrpc-prepare-for-xdr_stream-style-decoding-on-the-.patch +++ /dev/null @@ -1,103 +0,0 @@ -From ba564cda1b99d035764257f9c3fc615b81efb780 Mon Sep 17 00:00:00 2001 -From: Sasha Levin -Date: Thu, 5 Nov 2020 11:19:42 -0500 -Subject: SUNRPC: Prepare for xdr_stream-style decoding on the server-side - -From: Chuck Lever - -[ Upstream commit 5191955d6fc65e6d4efe8f4f10a6028298f57281 ] - -A "permanent" struct xdr_stream is allocated in struct svc_rqst so -that it is usable by all server-side decoders. A per-rqst scratch -buffer is also allocated to handle decoding XDR data items that -cross page boundaries. - -To demonstrate how it will be used, add the first call site for the -new svcxdr_init_decode() API. - -As an additional part of the overall conversion, add symbolic -constants for successful and failed XDR operations. Returning "0" is -overloaded. Sometimes it means something failed, but sometimes it -means success. To make it more clear when XDR decoding functions -succeed or fail, introduce symbolic constants. - -Signed-off-by: Chuck Lever -Stable-dep-of: 401bc1f90874 ("NFSD: Protect against send buffer overflow in NFSv2 READ") -Signed-off-by: Sasha Levin ---- - fs/nfsd/nfssvc.c | 2 ++ - include/linux/sunrpc/svc.h | 16 ++++++++++++++++ - net/sunrpc/svc.c | 5 +++++ - 3 files changed, 23 insertions(+) - -diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c -index 9323e30a7eaf..ad6fedf37a40 100644 ---- a/fs/nfsd/nfssvc.c -+++ b/fs/nfsd/nfssvc.c -@@ -1019,6 +1019,8 @@ int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) - * (necessary in the NFSv4.0 compound case) - */ - rqstp->rq_cachetype = proc->pc_cachetype; -+ -+ svcxdr_init_decode(rqstp); - if (!proc->pc_decode(rqstp, argv->iov_base)) - goto out_decode_err; - -diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h -index 386628b36bc7..6ce2e12589cb 100644 ---- a/include/linux/sunrpc/svc.h -+++ b/include/linux/sunrpc/svc.h -@@ -247,6 +247,8 @@ struct svc_rqst { - - size_t rq_xprt_hlen; /* xprt header len */ - struct xdr_buf rq_arg; -+ struct xdr_stream rq_arg_stream; -+ struct page *rq_scratch_page; - struct xdr_buf rq_res; - struct page *rq_pages[RPCSVC_MAXPAGES + 1]; - struct page * *rq_respages; /* points into rq_pages */ -@@ -557,4 +559,18 @@ static inline void svc_reserve_auth(struct svc_rqst *rqstp, int space) - svc_reserve(rqstp, space + rqstp->rq_auth_slack); - } - -+/** -+ * svcxdr_init_decode - Prepare an xdr_stream for svc Call decoding -+ * @rqstp: controlling server RPC transaction context -+ * -+ */ -+static inline void svcxdr_init_decode(struct svc_rqst *rqstp) -+{ -+ struct xdr_stream *xdr = &rqstp->rq_arg_stream; -+ struct kvec *argv = rqstp->rq_arg.head; -+ -+ xdr_init_decode(xdr, &rqstp->rq_arg, argv->iov_base, NULL); -+ xdr_set_scratch_page(xdr, rqstp->rq_scratch_page); -+} -+ - #endif /* SUNRPC_SVC_H */ -diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c -index d38788cd9433..bb55f124b62e 100644 ---- a/net/sunrpc/svc.c -+++ b/net/sunrpc/svc.c -@@ -614,6 +614,10 @@ svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) - rqstp->rq_server = serv; - rqstp->rq_pool = pool; - -+ rqstp->rq_scratch_page = alloc_pages_node(node, GFP_KERNEL, 0); -+ if (!rqstp->rq_scratch_page) -+ goto out_enomem; -+ - rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); - if (!rqstp->rq_argp) - goto out_enomem; -@@ -842,6 +846,7 @@ void - svc_rqst_free(struct svc_rqst *rqstp) - { - svc_release_buffer(rqstp); -+ put_page(rqstp->rq_scratch_page); - kfree(rqstp->rq_resp); - kfree(rqstp->rq_argp); - kfree(rqstp->rq_auth_data); --- -2.35.1 -