summaryrefslogtreecommitdiff
path: root/fs/nfs/dir.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-11-20 23:18:22 +0300
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-11-22 21:24:47 +0300
commit3020093f578fb6c9acc6914dfd887a1ebd1db659 (patch)
tree473af4f139dcb3975b20bcd9d2e04fb1cadc97b3 /fs/nfs/dir.c
parentece0b4233b6b915d1f63add2bd9f2733aec6317a (diff)
downloadlinux-3020093f578fb6c9acc6914dfd887a1ebd1db659.tar.xz
NFS: Correct the array bound calculation in nfs_readdir_add_to_array
It looks as if the array size calculation in MAX_READDIR_ARRAY does not take the alignment of struct nfs_cache_array_entry into account. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/dir.c')
-rw-r--r--fs/nfs/dir.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ddc2e439702b..ced7291cc5f8 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -171,8 +171,6 @@ struct nfs_cache_array {
struct nfs_cache_array_entry array[0];
};
-#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
-
typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
typedef struct {
struct file *file;
@@ -257,11 +255,14 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
if (IS_ERR(array))
return PTR_ERR(array);
+
+ cache_entry = &array->array[array->size];
+
+ /* Check that this entry lies within the page bounds */
ret = -ENOSPC;
- if (array->size >= MAX_READDIR_ARRAY)
+ if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE)
goto out;
- cache_entry = &array->array[array->size];
cache_entry->cookie = entry->prev_cookie;
cache_entry->ino = entry->ino;
ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);