diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index f9821ce6658a..b01f6e100ee8 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -2657,6 +2657,7 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, | |||
2657 | struct xdr_stream *xdr = cd->xdr; | 2657 | struct xdr_stream *xdr = cd->xdr; |
2658 | int start_offset = xdr->buf->len; | 2658 | int start_offset = xdr->buf->len; |
2659 | int cookie_offset; | 2659 | int cookie_offset; |
2660 | u32 name_and_cookie; | ||
2660 | int entry_bytes; | 2661 | int entry_bytes; |
2661 | __be32 nfserr = nfserr_toosmall; | 2662 | __be32 nfserr = nfserr_toosmall; |
2662 | __be64 wire_offset; | 2663 | __be64 wire_offset; |
@@ -2718,7 +2719,14 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, | |||
2718 | cd->rd_maxcount -= entry_bytes; | 2719 | cd->rd_maxcount -= entry_bytes; |
2719 | if (!cd->rd_dircount) | 2720 | if (!cd->rd_dircount) |
2720 | goto fail; | 2721 | goto fail; |
2721 | cd->rd_dircount--; | 2722 | /* |
2723 | * RFC 3530 14.2.24 describes rd_dircount as only a "hint", so | ||
2724 | * let's always let through the first entry, at least: | ||
2725 | */ | ||
2726 | name_and_cookie = 4 * XDR_QUADLEN(namlen) + 8; | ||
2727 | if (name_and_cookie > cd->rd_dircount && cd->cookie_offset) | ||
2728 | goto fail; | ||
2729 | cd->rd_dircount -= min(cd->rd_dircount, name_and_cookie); | ||
2722 | cd->cookie_offset = cookie_offset; | 2730 | cd->cookie_offset = cookie_offset; |
2723 | skip_entry: | 2731 | skip_entry: |
2724 | cd->common.err = nfs_ok; | 2732 | cd->common.err = nfs_ok; |
@@ -3096,7 +3104,8 @@ static __be32 nfsd4_encode_splice_read( | |||
3096 | 3104 | ||
3097 | buf->page_len = maxcount; | 3105 | buf->page_len = maxcount; |
3098 | buf->len += maxcount; | 3106 | buf->len += maxcount; |
3099 | xdr->page_ptr += (maxcount + PAGE_SIZE - 1) / PAGE_SIZE; | 3107 | xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1) |
3108 | / PAGE_SIZE; | ||
3100 | 3109 | ||
3101 | /* Use rest of head for padding and remaining ops: */ | 3110 | /* Use rest of head for padding and remaining ops: */ |
3102 | buf->tail[0].iov_base = xdr->p; | 3111 | buf->tail[0].iov_base = xdr->p; |
@@ -3321,6 +3330,10 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 | |||
3321 | } | 3330 | } |
3322 | maxcount = min_t(int, maxcount-16, bytes_left); | 3331 | maxcount = min_t(int, maxcount-16, bytes_left); |
3323 | 3332 | ||
3333 | /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */ | ||
3334 | if (!readdir->rd_dircount) | ||
3335 | readdir->rd_dircount = INT_MAX; | ||
3336 | |||
3324 | readdir->xdr = xdr; | 3337 | readdir->xdr = xdr; |
3325 | readdir->rd_maxcount = maxcount; | 3338 | readdir->rd_maxcount = maxcount; |
3326 | readdir->common.err = 0; | 3339 | readdir->common.err = 0; |