diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-30 15:43:56 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-01-31 19:28:23 -0500 |
commit | 8b7e3f49ddda0d43c5bc8de404c1dc7e7a13cc80 (patch) | |
tree | 984c2ad953660725d30340bd657c85a33e592658 /fs/nfs/nfs4xdr.c | |
parent | c15c928f36a2710746c2b945067215f436f45544 (diff) |
NFSv4: Don't decode fs_locations if we didn't ask for them...
Currently, the server can potentially cause us to Oops by returning an
fs_locations request that we didn't actually request.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r-- | fs/nfs/nfs4xdr.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 4633d405a94c..ca288d115b54 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3561,6 +3561,10 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st | |||
3561 | status = 0; | 3561 | status = 0; |
3562 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) | 3562 | if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) |
3563 | goto out; | 3563 | goto out; |
3564 | status = -EIO; | ||
3565 | /* Ignore borken servers that return unrequested attrs */ | ||
3566 | if (unlikely(res == NULL)) | ||
3567 | goto out; | ||
3564 | dprintk("%s: fsroot ", __func__); | 3568 | dprintk("%s: fsroot ", __func__); |
3565 | status = decode_pathname(xdr, &res->fs_path); | 3569 | status = decode_pathname(xdr, &res->fs_path); |
3566 | if (unlikely(status != 0)) | 3570 | if (unlikely(status != 0)) |
@@ -4295,6 +4299,7 @@ xdr_error: | |||
4295 | 4299 | ||
4296 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4300 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
4297 | struct nfs_fattr *fattr, struct nfs_fh *fh, | 4301 | struct nfs_fattr *fattr, struct nfs_fh *fh, |
4302 | struct nfs4_fs_locations *fs_loc, | ||
4298 | const struct nfs_server *server) | 4303 | const struct nfs_server *server) |
4299 | { | 4304 | { |
4300 | int status; | 4305 | int status; |
@@ -4342,9 +4347,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4342 | goto xdr_error; | 4347 | goto xdr_error; |
4343 | fattr->valid |= status; | 4348 | fattr->valid |= status; |
4344 | 4349 | ||
4345 | status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, | 4350 | status = decode_attr_fs_locations(xdr, bitmap, fs_loc); |
4346 | struct nfs4_fs_locations, | ||
4347 | fattr)); | ||
4348 | if (status < 0) | 4351 | if (status < 0) |
4349 | goto xdr_error; | 4352 | goto xdr_error; |
4350 | fattr->valid |= status; | 4353 | fattr->valid |= status; |
@@ -4408,7 +4411,8 @@ xdr_error: | |||
4408 | } | 4411 | } |
4409 | 4412 | ||
4410 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4413 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4411 | struct nfs_fh *fh, const struct nfs_server *server) | 4414 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, |
4415 | const struct nfs_server *server) | ||
4412 | { | 4416 | { |
4413 | __be32 *savep; | 4417 | __be32 *savep; |
4414 | uint32_t attrlen, | 4418 | uint32_t attrlen, |
@@ -4427,7 +4431,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat | |||
4427 | if (status < 0) | 4431 | if (status < 0) |
4428 | goto xdr_error; | 4432 | goto xdr_error; |
4429 | 4433 | ||
4430 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server); | 4434 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server); |
4431 | if (status < 0) | 4435 | if (status < 0) |
4432 | goto xdr_error; | 4436 | goto xdr_error; |
4433 | 4437 | ||
@@ -4440,7 +4444,7 @@ xdr_error: | |||
4440 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4444 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4441 | const struct nfs_server *server) | 4445 | const struct nfs_server *server) |
4442 | { | 4446 | { |
4443 | return decode_getfattr_generic(xdr, fattr, NULL, server); | 4447 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, server); |
4444 | } | 4448 | } |
4445 | 4449 | ||
4446 | /* | 4450 | /* |
@@ -6580,8 +6584,9 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, | |||
6580 | if (status) | 6584 | if (status) |
6581 | goto out; | 6585 | goto out; |
6582 | xdr_enter_page(xdr, PAGE_SIZE); | 6586 | xdr_enter_page(xdr, PAGE_SIZE); |
6583 | status = decode_getfattr(xdr, &res->fs_locations->fattr, | 6587 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, |
6584 | res->fs_locations->server); | 6588 | NULL, res->fs_locations, |
6589 | res->fs_locations->server); | ||
6585 | out: | 6590 | out: |
6586 | return status; | 6591 | return status; |
6587 | } | 6592 | } |
@@ -6961,7 +6966,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
6961 | goto out_overflow; | 6966 | goto out_overflow; |
6962 | 6967 | ||
6963 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 6968 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
6964 | entry->server) < 0) | 6969 | NULL, entry->server) < 0) |
6965 | goto out_overflow; | 6970 | goto out_overflow; |
6966 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | 6971 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
6967 | entry->ino = entry->fattr->mounted_on_fileid; | 6972 | entry->ino = entry->fattr->mounted_on_fileid; |