NFS: Correct the array bound calculation in nfs_readdir_add_to_array
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Sat, 20 Nov 2010 20:18:22 +0000 (15:18 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Mon, 22 Nov 2010 18:24:47 +0000 (13:24 -0500)
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>
fs/nfs/dir.c

index ddc2e439702be90c408e2cb54e8b39767af84def..ced7291cc5f8d851956308661ed076ed5f2b2461 100644 (file)
@@ -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);