Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8b7e3f49 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent c15c928f
Loading
Loading
Loading
Loading
+14 −9
Original line number Diff line number Diff line
@@ -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))
@@ -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;
@@ -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;
@@ -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,
@@ -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;

@@ -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);
}

/*
@@ -6580,7 +6584,8 @@ 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,
	status = decode_getfattr_generic(xdr, &res->fs_locations->fattr,
					 NULL, res->fs_locations,
					 res->fs_locations->server);
out:
	return status;
@@ -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;