summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
authorJ. Bruce Fields2016-06-10 22:56:05 +0200
committerJ. Bruce Fields2016-11-01 20:47:52 +0100
commite864c189e1d63f2f6a052e296f0da0616d88b625 (patch)
tree9b88ed7ea2af0d4bde7b58dabf8bcba748e345ba /fs/nfsd/nfs4xdr.c
parentnfsd: clean up supported attribute handling (diff)
downloadkernel-qcow2-linux-e864c189e1d63f2f6a052e296f0da0616d88b625.tar.gz
kernel-qcow2-linux-e864c189e1d63f2f6a052e296f0da0616d88b625.tar.xz
kernel-qcow2-linux-e864c189e1d63f2f6a052e296f0da0616d88b625.zip
nfsd: catch errors in decode_fattr earlier
3c8e03166ae2 "NFSv4: do exact check about attribute specified" fixed some handling of unsupported-attribute errors, but it also delayed checking for unwriteable attributes till after we decode them. This could lead to odd behavior in the case a client attemps to set an attribute we don't know about followed by one we try to parse. In that case the parser for the known attribute will attempt to parse the unknown attribute. It should fail in some safe way, but the error might at least be incorrect (probably bad_xdr instead of inval). So, it's better to do that check at the start. As far as I know this doesn't cause any problems with current clients but it might be a minor issue e.g. if we encounter a future client that supports a new attribute that we currently don't. Cc: Yu Zhiguo <yuzg@cn.fujitsu.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r--fs/nfsd/nfs4xdr.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index a99bbb88c6e1..281739e1d477 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -310,6 +310,14 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
if ((status = nfsd4_decode_bitmap(argp, bmval)))
return status;
+ if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
+ || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
+ || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) {
+ if (nfsd_attrs_supported(argp->minorversion, bmval))
+ return nfserr_inval;
+ return nfserr_attrnotsupp;
+ }
+
READ_BUF(4);
expected_len = be32_to_cpup(p++);
@@ -449,12 +457,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
return nfserr_jukebox;
}
#endif
-
- if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
- || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
- || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
- READ_BUF(expected_len - len);
- else if (len != expected_len)
+ if (len != expected_len)
goto xdr_error;
DECODE_TAIL;