aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2016-06-10 16:56:05 -0400
committerJ. Bruce Fields <bfields@redhat.com>2016-11-01 15:47:52 -0400
commite864c189e1d63f2f6a052e296f0da0616d88b625 (patch)
tree9b88ed7ea2af0d4bde7b58dabf8bcba748e345ba
parent916d2d844afd09dc8cf144e0e9dc98daa9dfc34a (diff)
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>
-rw-r--r--fs/nfsd/nfs4xdr.c15
-rw-r--r--fs/nfsd/nfsd.h6
2 files changed, 14 insertions, 7 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,
310 if ((status = nfsd4_decode_bitmap(argp, bmval))) 310 if ((status = nfsd4_decode_bitmap(argp, bmval)))
311 return status; 311 return status;
312 312
313 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
314 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
315 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) {
316 if (nfsd_attrs_supported(argp->minorversion, bmval))
317 return nfserr_inval;
318 return nfserr_attrnotsupp;
319 }
320
313 READ_BUF(4); 321 READ_BUF(4);
314 expected_len = be32_to_cpup(p++); 322 expected_len = be32_to_cpup(p++);
315 323
@@ -449,12 +457,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
449 return nfserr_jukebox; 457 return nfserr_jukebox;
450 } 458 }
451#endif 459#endif
452 460 if (len != expected_len)
453 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
454 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
455 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
456 READ_BUF(expected_len - len);
457 else if (len != expected_len)
458 goto xdr_error; 461 goto xdr_error;
459 462
460 DECODE_TAIL; 463 DECODE_TAIL;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index a72d4163273a..7155239b2908 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -379,7 +379,11 @@ static inline bool nfsd_attrs_supported(u32 minorversion, u32 *bmval)
379#define NFSD_WRITEONLY_ATTRS_WORD1 \ 379#define NFSD_WRITEONLY_ATTRS_WORD1 \
380 (FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) 380 (FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET)
381 381
382/* These are the only attrs allowed in CREATE/OPEN/SETATTR. */ 382/*
383 * These are the only attrs allowed in CREATE/OPEN/SETATTR. Don't add
384 * a writeable attribute here without also adding code to parse it to
385 * nfsd4_decode_fattr().
386 */
383#define NFSD_WRITEABLE_ATTRS_WORD0 \ 387#define NFSD_WRITEABLE_ATTRS_WORD0 \
384 (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL) 388 (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL)
385#define NFSD_WRITEABLE_ATTRS_WORD1 \ 389#define NFSD_WRITEABLE_ATTRS_WORD1 \