Skip to content

Commit

Permalink
NFSv4: Don't decode fs_locations if we didn't ask for them...
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Trond Myklebust authored and Trond Myklebust committed Feb 1, 2012
1 parent c15c928 commit 8b7e3f4
Showing 1 changed file with 14 additions and 9 deletions.
23 changes: 14 additions & 9 deletions fs/nfs/nfs4xdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -3561,6 +3561,10 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st
status = 0;
if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
goto out;
status = -EIO;
/* Ignore borken servers that return unrequested attrs */
if (unlikely(res == NULL))
goto out;
dprintk("%s: fsroot ", __func__);
status = decode_pathname(xdr, &res->fs_path);
if (unlikely(status != 0))
Expand Down Expand Up @@ -4295,6 +4299,7 @@ static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf

static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
struct nfs_fattr *fattr, struct nfs_fh *fh,
struct nfs4_fs_locations *fs_loc,
const struct nfs_server *server)
{
int status;
Expand Down Expand Up @@ -4342,9 +4347,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
goto xdr_error;
fattr->valid |= status;

status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr,
struct nfs4_fs_locations,
fattr));
status = decode_attr_fs_locations(xdr, bitmap, fs_loc);
if (status < 0)
goto xdr_error;
fattr->valid |= status;
Expand Down Expand Up @@ -4408,7 +4411,8 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
}

static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
struct nfs_fh *fh, const struct nfs_server *server)
struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc,
const struct nfs_server *server)
{
__be32 *savep;
uint32_t attrlen,
Expand All @@ -4427,7 +4431,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat
if (status < 0)
goto xdr_error;

status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server);
status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server);
if (status < 0)
goto xdr_error;

Expand All @@ -4440,7 +4444,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat
static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
const struct nfs_server *server)
{
return decode_getfattr_generic(xdr, fattr, NULL, server);
return decode_getfattr_generic(xdr, fattr, NULL, NULL, server);
}

/*
Expand Down Expand Up @@ -6580,8 +6584,9 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req,
if (status)
goto out;
xdr_enter_page(xdr, PAGE_SIZE);
status = decode_getfattr(xdr, &res->fs_locations->fattr,
res->fs_locations->server);
status = decode_getfattr_generic(xdr, &res->fs_locations->fattr,
NULL, res->fs_locations,
res->fs_locations->server);
out:
return status;
}
Expand Down Expand Up @@ -6961,7 +6966,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
goto out_overflow;

if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
entry->server) < 0)
NULL, entry->server) < 0)
goto out_overflow;
if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
entry->ino = entry->fattr->mounted_on_fileid;
Expand Down

0 comments on commit 8b7e3f4

Please sign in to comment.