GIT: unionfs2-2.6.27.y: bugfix: prevent a NULL ptr deref if branch is nfs and using mmap writes
Erez Zadok
ezk at fsl.cs.sunysb.edu
Thu Aug 12 23:16:26 EDT 2010
commit 16979aa1f8538b784cebf715063a0b3947802a27
Author: Erez_Zadok <ezk at cs.sunysb.edu>
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 <ezk at cs.sunysb.edu>
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;
}
More information about the unionfs-cvs
mailing list