From: Erez Zadok Date: Sun, 8 May 2022 01:14:41 +0000 (-0400) Subject: update bug-fixes/andrew-bugfix.log bug-fixes/andrew-bugfix.patch X-Git-Url: https://git.fsl.cs.sunysb.edu/?a=commitdiff_plain;h=68d8162dcf926cc8032b81afc8a5801b1460327e;p=wrapfs-mgmt.git update bug-fixes/andrew-bugfix.log bug-fixes/andrew-bugfix.patch --- diff --git a/bug-fixes/andrew-bugfix.log b/bug-fixes/andrew-bugfix.log new file mode 100644 index 0000000..5dd6701 --- /dev/null +++ b/bug-fixes/andrew-bugfix.log @@ -0,0 +1,9 @@ +Wrapfs: fix NULL ptr deref in ->d_release and ->read_super + +It is possible that the dentry private data is NULL in case we ran out of +memory while initializing it in new_dentry_private_data. So check for NULL +before attempting to release resources. Similarly, in ->read_super, only +cleanu resources actually needed (the VFS cleans up the rest indirectly). + +Signed-off-by: Andrew Burford +Signed-off-by: Erez Zadok diff --git a/bug-fixes/andrew-bugfix.patch b/bug-fixes/andrew-bugfix.patch new file mode 100644 index 0000000..1eee2b2 --- /dev/null +++ b/bug-fixes/andrew-bugfix.patch @@ -0,0 +1,90 @@ +diff --git a/fs/wrapfs/dentry.c b/fs/wrapfs/dentry.c +index 08110aceb05b..45498e4a4804 100644 +--- a/fs/wrapfs/dentry.c ++++ b/fs/wrapfs/dentry.c +@@ -34,9 +34,17 @@ static int wrapfs_d_revalidate(struct dentry *dentry, unsigned int flags) + + static void wrapfs_d_release(struct dentry *dentry) + { +- /* release and reset the lower paths */ +- wrapfs_put_reset_lower_path(dentry); +- free_dentry_private_data(dentry); ++ /* ++ * It is possible that the dentry private data is NULL in case we ++ * ran out of memory while initializing it in ++ * new_dentry_private_data. So check for NULL before attempting to ++ * release resources. ++ */ ++ if (WRAPFS_D(dentry)) { ++ /* release and reset the lower paths */ ++ wrapfs_put_reset_lower_path(dentry); ++ free_dentry_private_data(dentry); ++ } + return; + } + +diff --git a/fs/wrapfs/main.c b/fs/wrapfs/main.c +index b73a7d86084b..3df02cc778b3 100644 +--- a/fs/wrapfs/main.c ++++ b/fs/wrapfs/main.c +@@ -42,7 +42,7 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) + if (!WRAPFS_SB(sb)) { + printk(KERN_CRIT "wrapfs: read_super: out of memory\n"); + err = -ENOMEM; +- goto out_free; ++ goto out_pput; + } + + /* set the lower superblock field of upper superblock */ +@@ -68,12 +68,12 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) + inode = wrapfs_iget(sb, d_inode(lower_path.dentry)); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); +- goto out_sput; ++ goto out_pput; + } + sb->s_root = d_make_root(inode); + if (!sb->s_root) { + err = -ENOMEM; +- goto out_iput; ++ goto out_pput; + } + d_set_d_op(sb->s_root, &wrapfs_dops); + +@@ -81,7 +81,7 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) + sb->s_root->d_fsdata = NULL; + err = new_dentry_private_data(sb->s_root); + if (err) +- goto out_freeroot; ++ goto out_pput; + + /* if get here: cannot have error */ + +@@ -100,19 +100,15 @@ static int wrapfs_read_super(struct super_block *sb, void *raw_data, int silent) + dev_name, lower_sb->s_type->name); + goto out; /* all is well */ + +- /* no longer needed: free_dentry_private_data(sb->s_root); */ +-out_freeroot: +- dput(sb->s_root); +-out_iput: +- iput(inode); +-out_sput: +- /* drop refs we took earlier */ +- atomic_dec(&lower_sb->s_active); +- kfree(WRAPFS_SB(sb)); +- sb->s_fs_info = NULL; +-out_free: ++ /* ++ * path_put is the only resource we need to free if an error occurred ++ * because returning an error from this function will cause ++ * generic_shutdown_super to be called, which will call ++ * wrapfs_put_super, and that function will release any other ++ * resources we took. ++ */ ++out_pput: + path_put(&lower_path); +- + out: + return err; + }