Commit ac396128 authored by Trond Myklebust's avatar Trond Myklebust

NFS: readdir shouldn't read beyond the reply returned by the server

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 8cd51a0c
...@@ -573,11 +573,13 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, ...@@ -573,11 +573,13 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
if (!pages_ptr) if (!pages_ptr)
goto out_release_array; goto out_release_array;
do { do {
unsigned int pglen;
status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode);
if (status < 0) if (status < 0)
break; break;
status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, array_size * PAGE_SIZE); pglen = status;
status = nfs_readdir_page_filler(desc, &entry, pages_ptr, page, pglen);
if (status < 0) { if (status < 0) {
if (status == -ENOSPC) if (status == -ENOSPC)
status = 0; status = 0;
......
...@@ -423,7 +423,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) ...@@ -423,7 +423,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
struct page **page; struct page **page;
size_t hdrlen; size_t hdrlen;
unsigned int pglen, recvd; unsigned int pglen, recvd;
int status, nr = 0; int status;
if ((status = ntohl(*p++))) if ((status = ntohl(*p++)))
return nfs_stat_to_errno(status); return nfs_stat_to_errno(status);
...@@ -443,7 +443,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy) ...@@ -443,7 +443,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
if (pglen > recvd) if (pglen > recvd)
pglen = recvd; pglen = recvd;
page = rcvbuf->pages; page = rcvbuf->pages;
return nr; return pglen;
} }
static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
......
...@@ -555,7 +555,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res ...@@ -555,7 +555,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
struct page **page; struct page **page;
size_t hdrlen; size_t hdrlen;
u32 recvd, pglen; u32 recvd, pglen;
int status, nr = 0; int status;
status = ntohl(*p++); status = ntohl(*p++);
/* Decode post_op_attrs */ /* Decode post_op_attrs */
...@@ -586,7 +586,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res ...@@ -586,7 +586,7 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
pglen = recvd; pglen = recvd;
page = rcvbuf->pages; page = rcvbuf->pages;
return nr; return pglen;
} }
__be32 * __be32 *
......
...@@ -2852,8 +2852,10 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, ...@@ -2852,8 +2852,10 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
res.pgbase = args.pgbase; res.pgbase = args.pgbase;
status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0); status = nfs4_call_sync(NFS_SERVER(dir), &msg, &args, &res, 0);
if (status == 0) if (status >= 0) {
memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
status += args.pgbase;
}
nfs_invalidate_atime(dir); nfs_invalidate_atime(dir);
......
...@@ -4518,7 +4518,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n ...@@ -4518,7 +4518,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
xdr_read_pages(xdr, pglen); xdr_read_pages(xdr, pglen);
return 0; return pglen;
} }
static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req) static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment