[PATCH AUTOSEL for 3.18 100/101] nfsd: return RESOURCE not GARBAGE_ARGS on too many ops

2018-04-08 Thread Sasha Levin
From: "J. Bruce Fields" 

[ Upstream commit 0078117c6d9160031b866cfa1853514d4f6865d2 ]

A client that sends more than a hundred ops in a single compound
currently gets an rpc-level GARBAGE_ARGS error.

It would be more helpful to return NFS4ERR_RESOURCE, since that gives
the client a better idea how to recover (for example by splitting up the
compound into smaller compounds).

This is all a bit academic since we've never actually seen a reason for
clients to send such long compounds, but we may as well fix it.

While we're there, just use NFSD4_MAX_OPS_PER_COMPOUND == 16, the
constant we already use in the 4.1 case, instead of hard-coding 100.
Chances anyone actually uses even 16 ops per compound are small enough
that I think there's a neglible risk or any regression.

This fixes pynfs test COMP6.

Reported-by: "Lu, Xinyu" 
Signed-off-by: J. Bruce Fields 
Signed-off-by: Sasha Levin 
---
 fs/nfsd/nfs4proc.c | 3 +++
 fs/nfsd/nfs4xdr.c  | 9 +++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index f6429b3d89e2..a976c87eae49 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1342,6 +1342,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
status = nfserr_minor_vers_mismatch;
if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
goto out;
+   status = nfserr_resource;
+   if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
+   goto out;
 
status = nfs41_check_op_ordering(args);
if (status) {
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 660c813467e2..c8ebd89f0f2d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1655,8 +1655,13 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 
if (argp->taglen > NFSD4_MAX_TAGLEN)
goto xdr_error;
-   if (argp->opcnt > 100)
-   goto xdr_error;
+   /*
+* NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
+* here, so we return success at the xdr level so that
+* nfsd4_proc can handle this is an NFS-level error.
+*/
+   if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
+   return 0;
 
if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), 
GFP_KERNEL);
-- 
2.15.1


[PATCH AUTOSEL for 3.18 100/101] nfsd: return RESOURCE not GARBAGE_ARGS on too many ops

2018-04-08 Thread Sasha Levin
From: "J. Bruce Fields" 

[ Upstream commit 0078117c6d9160031b866cfa1853514d4f6865d2 ]

A client that sends more than a hundred ops in a single compound
currently gets an rpc-level GARBAGE_ARGS error.

It would be more helpful to return NFS4ERR_RESOURCE, since that gives
the client a better idea how to recover (for example by splitting up the
compound into smaller compounds).

This is all a bit academic since we've never actually seen a reason for
clients to send such long compounds, but we may as well fix it.

While we're there, just use NFSD4_MAX_OPS_PER_COMPOUND == 16, the
constant we already use in the 4.1 case, instead of hard-coding 100.
Chances anyone actually uses even 16 ops per compound are small enough
that I think there's a neglible risk or any regression.

This fixes pynfs test COMP6.

Reported-by: "Lu, Xinyu" 
Signed-off-by: J. Bruce Fields 
Signed-off-by: Sasha Levin 
---
 fs/nfsd/nfs4proc.c | 3 +++
 fs/nfsd/nfs4xdr.c  | 9 +++--
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index f6429b3d89e2..a976c87eae49 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1342,6 +1342,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
status = nfserr_minor_vers_mismatch;
if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
goto out;
+   status = nfserr_resource;
+   if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
+   goto out;
 
status = nfs41_check_op_ordering(args);
if (status) {
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 660c813467e2..c8ebd89f0f2d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1655,8 +1655,13 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
 
if (argp->taglen > NFSD4_MAX_TAGLEN)
goto xdr_error;
-   if (argp->opcnt > 100)
-   goto xdr_error;
+   /*
+* NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
+* here, so we return success at the xdr level so that
+* nfsd4_proc can handle this is an NFS-level error.
+*/
+   if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
+   return 0;
 
if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), 
GFP_KERNEL);
-- 
2.15.1