commit 77324db5ec3fdd371461566f043309acd83e8c29
Author: Erez_Zadok <[EMAIL PROTECTED]>
Date:   Wed May 23 21:27:58 2007 -0400

    bugfix: prevent a NULL ptr deref if branch is nfs and using mmap writes
    
    By some strange condition, the VFS can pass our unionfs_writepage a
    writeback_control structure which, if passed as is to the lower ->writepage
    -- here nfs_writepage, triggers a NULL ptr deref in NFS.  This fix works
    around this issue, and results in a successfully written mmaped file.
    
    Signed-off-by: Erez Zadok <[EMAIL PROTECTED]>

diff --git a/fs/unionfs/mmap.c b/fs/unionfs/mmap.c
index ccad33f..105cc20 100644
--- a/fs/unionfs/mmap.c
+++ b/fs/unionfs/mmap.c
@@ -26,6 +26,7 @@ int unionfs_writepage(struct page *page, struct 
writeback_control *wbc)
        struct inode *lower_inode;
        struct page *lower_page;
        char *kaddr, *lower_kaddr;
+       struct writeback_control lower_wbc;
 
        inode = page->mapping->host;
        lower_inode = unionfs_lower_inode(inode);
@@ -44,8 +45,21 @@ int unionfs_writepage(struct page *page, struct 
writeback_control *wbc)
        kunmap(page);
        kunmap(lower_page);
 
+       BUG_ON(!lower_inode->i_mapping->a_ops->writepage);
+       memcpy(&lower_wbc, wbc, sizeof(struct writeback_control));
+       /*
+        * This condition should never occur, but if it does, it causes NFS
+        * (if used a s lower branch) to deference wbc->fs_private,
+        * resulting in a NULL deref oops.
+        * XXX: Maybe it's an NFS/VFS bug?
+        */
+       if (lower_wbc.for_writepages && !lower_wbc.fs_private) {
+               printk("unionfs: setting wbc.for_writepages to 0\n");
+               lower_wbc.for_writepages = 0;
+       }
+
        /* call lower writepage (expects locked page) */
-       err = lower_inode->i_mapping->a_ops->writepage(lower_page, wbc);
+       err = lower_inode->i_mapping->a_ops->writepage(lower_page, &lower_wbc);
 
        /*
         * update mtime and ctime of lower level file system
@@ -298,7 +312,6 @@ void unionfs_sync_page(struct page *page)
        page_cache_release(lower_page); /* b/c grab_cache_page increased refcnt 
*/
 
 out:
-
        return;
 }
 
_______________________________________________
unionfs-cvs mailing list: http://unionfs.filesystems.org/
[email protected]
http://www.fsl.cs.sunysb.edu/mailman/listinfo/unionfs-cvs

Reply via email to