aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-30 15:43:56 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-31 19:28:23 -0500
commit8b7e3f49ddda0d43c5bc8de404c1dc7e7a13cc80 (patch)
tree984c2ad953660725d30340bd657c85a33e592658 /fs/nfs/nfs4xdr.c
parentc15c928f36a2710746c2b945067215f436f45544 (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.c23
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
4296static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, 4300static 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
4410static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4413static 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:
4440static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, 4444static 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);
6585out: 6590out:
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;