diff options
author | Benjamin Coddington <bcodding@redhat.com> | 2015-04-21 20:17:35 +0200 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-04-23 21:16:15 +0200 |
commit | ce85cfbed6fe3dbc01bd1976b23ac3e97878cde6 (patch) | |
tree | cdc5d556a35eb0b1c5566d17ffa6a4a1767b8a50 | |
parent | Revert "nfs: replace nfs_add_stats with nfs_inc_stats when add one" (diff) | |
download | linux-ce85cfbed6fe3dbc01bd1976b23ac3e97878cde6.tar.xz linux-ce85cfbed6fe3dbc01bd1976b23ac3e97878cde6.zip |
NFS: Don't attempt to decode missing directory entries
If a READDIR reply comes back without any page data, avoid a NULL pointer
dereference in xdr_copy_to_scratch().
BUG: unable to handle kernel NULL pointer dereference at 0000000000000001
IP: [<ffffffff813a378d>] memcpy+0xd/0x110
...
Call Trace:
? xdr_inline_decode+0x7a/0xb0 [sunrpc]
nfs3_decode_dirent+0x73/0x320 [nfsv3]
nfs_readdir_page_filler+0xd5/0x4e0 [nfs]
? nfs3_rpc_wrapper.constprop.9+0x42/0xc0 [nfsv3]
nfs_readdir_xdr_to_array+0x1fa/0x330 [nfs]
? mem_cgroup_commit_charge+0xac/0x160
? nfs_readdir_xdr_to_array+0x330/0x330 [nfs]
nfs_readdir_filler+0x22/0x90 [nfs]
do_read_cache_page+0x7e/0x1a0
read_cache_page+0x1c/0x20
nfs_readdir+0x18e/0x660 [nfs]
? nfs3_xdr_dec_getattr3res+0x80/0x80 [nfsv3]
iterate_dir+0x97/0x130
SyS_getdents+0x94/0x120
? fillonedir+0xd0/0xd0
system_call_fastpath+0x12/0x17
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
-rw-r--r-- | fs/nfs/dir.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index c19e16f0b2d0..a00ba92acccc 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -544,6 +544,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en if (scratch == NULL) return -ENOMEM; + if (buflen == 0) + goto out_nopages; + xdr_init_decode_pages(&stream, &buf, xdr_pages, buflen); xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); @@ -565,6 +568,7 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en break; } while (!entry->eof); +out_nopages: if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) { array = nfs_readdir_get_array(page); if (!IS_ERR(array)) { |