From: Greg Kroah-Hartman Date: Sun, 16 Jul 2023 15:18:00 +0000 (+0200) Subject: 6.4-stable patches X-Git-Tag: v6.1.39~51 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2c179737accec3abe5bee1cd13d690aa3a1af60e;p=thirdparty%2Fkernel%2Fstable-queue.git 6.4-stable patches added patches: ovl-fix-null-pointer-dereference-in-ovl_get_acl_rcu.patch ovl-fix-null-pointer-dereference-in-ovl_permission.patch ovl-let-helper-ovl_i_path_real-return-the-realinode.patch --- diff --git a/queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_get_acl_rcu.patch b/queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_get_acl_rcu.patch new file mode 100644 index 00000000000..9ce8df36ed0 --- /dev/null +++ b/queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_get_acl_rcu.patch @@ -0,0 +1,98 @@ +From f4e19e595cc2e76a8a58413eb19d3d9c51328b53 Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Tue, 16 May 2023 22:16:19 +0800 +Subject: ovl: fix null pointer dereference in ovl_get_acl_rcu() + +From: Zhihao Cheng + +commit f4e19e595cc2e76a8a58413eb19d3d9c51328b53 upstream. + +Following process: + P1 P2 + path_openat + link_path_walk + may_lookup + inode_permission(rcu) + ovl_permission + acl_permission_check + check_acl + get_cached_acl_rcu + ovl_get_inode_acl + realinode = ovl_inode_real(ovl_inode) + drop_cache + __dentry_kill(ovl_dentry) + iput(ovl_inode) + ovl_destroy_inode(ovl_inode) + dput(oi->__upperdentry) + dentry_kill(upperdentry) + dentry_unlink_inode + upperdentry->d_inode = NULL + ovl_inode_upper + upperdentry = ovl_i_dentry_upper(ovl_inode) + d_inode(upperdentry) // returns NULL + IS_POSIXACL(realinode) // NULL pointer dereference +, will trigger an null pointer dereference at realinode: + [ 205.472797] BUG: kernel NULL pointer dereference, address: + 0000000000000028 + [ 205.476701] CPU: 2 PID: 2713 Comm: ls Not tainted + 6.3.0-12064-g2edfa098e750-dirty #1216 + [ 205.478754] RIP: 0010:do_ovl_get_acl+0x5d/0x300 + [ 205.489584] Call Trace: + [ 205.489812] + [ 205.490014] ovl_get_inode_acl+0x26/0x30 + [ 205.490466] get_cached_acl_rcu+0x61/0xa0 + [ 205.490908] generic_permission+0x1bf/0x4e0 + [ 205.491447] ovl_permission+0x79/0x1b0 + [ 205.491917] inode_permission+0x15e/0x2c0 + [ 205.492425] link_path_walk+0x115/0x550 + [ 205.493311] path_lookupat.isra.0+0xb2/0x200 + [ 205.493803] filename_lookup+0xda/0x240 + [ 205.495747] vfs_fstatat+0x7b/0xb0 + +Fetch a reproducer in [Link]. + +Use the helper ovl_i_path_realinode() to get realinode and then do +non-nullptr checking. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217404 +Fixes: 332f606b32b6 ("ovl: enable RCU'd ->get_acl()") +Cc: # v5.15 +Signed-off-by: Zhihao Cheng +Suggested-by: Christian Brauner +Suggested-by: Amir Goldstein +Signed-off-by: Amir Goldstein +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/inode.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -558,20 +558,20 @@ struct posix_acl *do_ovl_get_acl(struct + struct inode *inode, int type, + bool rcu, bool noperm) + { +- struct inode *realinode = ovl_inode_real(inode); ++ struct inode *realinode; + struct posix_acl *acl; + struct path realpath; + +- if (!IS_POSIXACL(realinode)) +- return NULL; +- + /* Careful in RCU walk mode */ +- ovl_i_path_real(inode, &realpath); +- if (!realpath.dentry) { ++ realinode = ovl_i_path_real(inode, &realpath); ++ if (!realinode) { + WARN_ON(!rcu); + return ERR_PTR(-ECHILD); + } + ++ if (!IS_POSIXACL(realinode)) ++ return NULL; ++ + if (rcu) { + /* + * If the layer is idmapped drop out of RCU path walk diff --git a/queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_permission.patch b/queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_permission.patch new file mode 100644 index 00000000000..31275be4eb6 --- /dev/null +++ b/queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_permission.patch @@ -0,0 +1,82 @@ +From 1a73f5b8f079fd42a544c1600beface50c63af7c Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Tue, 16 May 2023 22:16:18 +0800 +Subject: ovl: fix null pointer dereference in ovl_permission() + +From: Zhihao Cheng + +commit 1a73f5b8f079fd42a544c1600beface50c63af7c upstream. + +Following process: + P1 P2 + path_lookupat + link_path_walk + inode_permission + ovl_permission + ovl_i_path_real(inode, &realpath) + path->dentry = ovl_i_dentry_upper(inode) + drop_cache + __dentry_kill(ovl_dentry) + iput(ovl_inode) + ovl_destroy_inode(ovl_inode) + dput(oi->__upperdentry) + dentry_kill(upperdentry) + dentry_unlink_inode + upperdentry->d_inode = NULL + realinode = d_inode(realpath.dentry) // return NULL + inode_permission(realinode) + inode->i_sb // NULL pointer dereference +, will trigger an null pointer dereference at realinode: + [ 335.664979] BUG: kernel NULL pointer dereference, + address: 0000000000000002 + [ 335.668032] CPU: 0 PID: 2592 Comm: ls Not tainted 6.3.0 + [ 335.669956] RIP: 0010:inode_permission+0x33/0x2c0 + [ 335.678939] Call Trace: + [ 335.679165] + [ 335.679371] ovl_permission+0xde/0x320 + [ 335.679723] inode_permission+0x15e/0x2c0 + [ 335.680090] link_path_walk+0x115/0x550 + [ 335.680771] path_lookupat.isra.0+0xb2/0x200 + [ 335.681170] filename_lookup+0xda/0x240 + [ 335.681922] vfs_statx+0xa6/0x1f0 + [ 335.682233] vfs_fstatat+0x7b/0xb0 + +Fetch a reproducer in [Link]. + +Use the helper ovl_i_path_realinode() to get realinode and then do +non-nullptr checking. + +Link: https://bugzilla.kernel.org/show_bug.cgi?id=217405 +Fixes: 4b7791b2e958 ("ovl: handle idmappings in ovl_permission()") +Cc: # v5.19 +Signed-off-by: Zhihao Cheng +Suggested-by: Christian Brauner +Suggested-by: Amir Goldstein +Signed-off-by: Amir Goldstein +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/inode.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/fs/overlayfs/inode.c ++++ b/fs/overlayfs/inode.c +@@ -288,8 +288,8 @@ int ovl_permission(struct mnt_idmap *idm + int err; + + /* Careful in RCU walk mode */ +- ovl_i_path_real(inode, &realpath); +- if (!realpath.dentry) { ++ realinode = ovl_i_path_real(inode, &realpath); ++ if (!realinode) { + WARN_ON(!(mask & MAY_NOT_BLOCK)); + return -ECHILD; + } +@@ -302,7 +302,6 @@ int ovl_permission(struct mnt_idmap *idm + if (err) + return err; + +- realinode = d_inode(realpath.dentry); + old_cred = ovl_override_creds(inode->i_sb); + if (!upperinode && + !special_file(realinode->i_mode) && mask & MAY_WRITE) { diff --git a/queue-6.4/ovl-let-helper-ovl_i_path_real-return-the-realinode.patch b/queue-6.4/ovl-let-helper-ovl_i_path_real-return-the-realinode.patch new file mode 100644 index 00000000000..6d4736913ca --- /dev/null +++ b/queue-6.4/ovl-let-helper-ovl_i_path_real-return-the-realinode.patch @@ -0,0 +1,67 @@ +From b2dd05f107b11966e26fe52a313b418364cf497b Mon Sep 17 00:00:00 2001 +From: Zhihao Cheng +Date: Tue, 16 May 2023 22:16:17 +0800 +Subject: ovl: let helper ovl_i_path_real() return the realinode + +From: Zhihao Cheng + +commit b2dd05f107b11966e26fe52a313b418364cf497b upstream. + +Let helper ovl_i_path_real() return the realinode to prepare for +checking non-null realinode in RCU walking path. + +[msz] Use d_inode_rcu() since we are depending on the consitency +between dentry and inode being non-NULL in an RCU setting. + +Signed-off-by: Zhihao Cheng +Signed-off-by: Amir Goldstein +Fixes: ffa5723c6d25 ("ovl: store lower path in ovl_inode") +Cc: # v5.19 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman +--- + fs/overlayfs/overlayfs.h | 2 +- + fs/overlayfs/util.c | 7 ++++--- + 2 files changed, 5 insertions(+), 4 deletions(-) + +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -384,7 +384,7 @@ enum ovl_path_type ovl_path_type(struct + void ovl_path_upper(struct dentry *dentry, struct path *path); + void ovl_path_lower(struct dentry *dentry, struct path *path); + void ovl_path_lowerdata(struct dentry *dentry, struct path *path); +-void ovl_i_path_real(struct inode *inode, struct path *path); ++struct inode *ovl_i_path_real(struct inode *inode, struct path *path); + enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path); + enum ovl_path_type ovl_path_realdata(struct dentry *dentry, struct path *path); + struct dentry *ovl_dentry_upper(struct dentry *dentry); +--- a/fs/overlayfs/util.c ++++ b/fs/overlayfs/util.c +@@ -266,7 +266,7 @@ struct dentry *ovl_i_dentry_upper(struct + return ovl_upperdentry_dereference(OVL_I(inode)); + } + +-void ovl_i_path_real(struct inode *inode, struct path *path) ++struct inode *ovl_i_path_real(struct inode *inode, struct path *path) + { + path->dentry = ovl_i_dentry_upper(inode); + if (!path->dentry) { +@@ -275,6 +275,8 @@ void ovl_i_path_real(struct inode *inode + } else { + path->mnt = ovl_upper_mnt(OVL_FS(inode->i_sb)); + } ++ ++ return path->dentry ? d_inode_rcu(path->dentry) : NULL; + } + + struct inode *ovl_inode_upper(struct inode *inode) +@@ -1121,8 +1123,7 @@ void ovl_copyattr(struct inode *inode) + vfsuid_t vfsuid; + vfsgid_t vfsgid; + +- ovl_i_path_real(inode, &realpath); +- realinode = d_inode(realpath.dentry); ++ realinode = ovl_i_path_real(inode, &realpath); + real_idmap = mnt_idmap(realpath.mnt); + + vfsuid = i_uid_into_vfsuid(real_idmap, realinode); diff --git a/queue-6.4/series b/queue-6.4/series index 4df4cce3a71..42b7eb95eb1 100644 --- a/queue-6.4/series +++ b/queue-6.4/series @@ -781,3 +781,6 @@ powerpc-vdso-include-clang_flags-explicitly-in-ldflags-y.patch kbuild-add-clang_flags-to-as-instr.patch kbuild-add-kbuild_cppflags-to-as-option-invocation.patch kbuild-add-clang_flags-to-kbuild_cppflags.patch +ovl-fix-null-pointer-dereference-in-ovl_permission.patch +ovl-let-helper-ovl_i_path_real-return-the-realinode.patch +ovl-fix-null-pointer-dereference-in-ovl_get_acl_rcu.patch