lkml.org 
[lkml]   [2020]   [May]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 95/99] NFS: Fix memory leaks and corruption in readdir
    3.16.84-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Trond Myklebust <trondmy@gmail.com>

    commit 4b310319c6a8ce708f1033d57145e2aa027a883c upstream.

    nfs_readdir_xdr_to_array() must not exit without having initialised
    the array, so that the page cache deletion routines can safely
    call nfs_readdir_clear_array().
    Furthermore, we should ensure that if we exit nfs_readdir_filler()
    with an error, we free up any page contents to prevent a leak
    if we try to fill the page again.

    Fixes: 11de3b11e08c ("NFS: Fix a memory leak in nfs_readdir")
    Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
    Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
    Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    fs/nfs/dir.c | 17 +++++++++++++++--
    1 file changed, 15 insertions(+), 2 deletions(-)

    --- a/fs/nfs/dir.c
    +++ b/fs/nfs/dir.c
    @@ -169,6 +169,17 @@ typedef struct {
    unsigned int eof:1;
    } nfs_readdir_descriptor_t;

    +static
    +void nfs_readdir_init_array(struct page *page)
    +{
    + struct nfs_cache_array *array;
    +
    + array = kmap_atomic(page);
    + memset(array, 0, sizeof(struct nfs_cache_array));
    + array->eof_index = -1;
    + kunmap_atomic(array);
    +}
    +
    /*
    * we are freeing strings created by nfs_add_to_readdir_array()
    */
    @@ -181,6 +192,7 @@ void nfs_readdir_clear_array(struct page
    array = kmap_atomic(page);
    for (i = 0; i < array->size; i++)
    kfree(array->array[i].string.name);
    + array->size = 0;
    kunmap_atomic(array);
    }

    @@ -580,6 +592,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir
    int status = -ENOMEM;
    unsigned int array_size = ARRAY_SIZE(pages);

    + nfs_readdir_init_array(page);
    +
    entry.prev_cookie = 0;
    entry.cookie = desc->last_cookie;
    entry.eof = 0;
    @@ -596,8 +610,6 @@ int nfs_readdir_xdr_to_array(nfs_readdir
    }

    array = kmap(page);
    - memset(array, 0, sizeof(struct nfs_cache_array));
    - array->eof_index = -1;

    status = nfs_readdir_large_page(pages, array_size);
    if (status < 0)
    @@ -651,6 +663,7 @@ int nfs_readdir_filler(nfs_readdir_descr
    unlock_page(page);
    return 0;
    error:
    + nfs_readdir_clear_array(page);
    unlock_page(page);
    return ret;
    }
    \
     
     \ /
      Last update: 2020-05-20 16:25    [W:4.131 / U:0.136 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site