All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path
@ 2023-07-17  3:09 Zhihao Cheng
  2023-07-17  3:09 ` [PATCH 6.1 1/2] ovl: let helper ovl_i_path_real() return the realinode Zhihao Cheng
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Zhihao Cheng @ 2023-07-17  3:09 UTC (permalink / raw)
  To: amir73il, gregkh, miklos; +Cc: linux-unionfs, stable, sashal

Zhihao Cheng (2):
  ovl: let helper ovl_i_path_real() return the realinode
  ovl: fix null pointer dereference in ovl_get_acl_rcu()

 fs/overlayfs/inode.c     | 12 ++++++------
 fs/overlayfs/overlayfs.h |  2 +-
 fs/overlayfs/util.c      |  7 ++++---
 3 files changed, 11 insertions(+), 10 deletions(-)

-- 
2.39.2


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 6.1 1/2] ovl: let helper ovl_i_path_real() return the realinode
  2023-07-17  3:09 [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path Zhihao Cheng
@ 2023-07-17  3:09 ` Zhihao Cheng
  2023-07-17  3:09 ` [PATCH 6.1 2/2] ovl: fix null pointer dereference in ovl_get_acl_rcu() Zhihao Cheng
  2023-07-20 17:59 ` [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path Greg KH
  2 siblings, 0 replies; 4+ messages in thread
From: Zhihao Cheng @ 2023-07-17  3:09 UTC (permalink / raw)
  To: amir73il, gregkh, miklos; +Cc: linux-unionfs, stable, sashal

[ Upstream commit b2dd05f107b11966e26fe52a313b418364cf497b ]

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.

There are some changes from upstream commit:
1. Context conflicts caused by 73db6a063c785bc ("ovl: port to
   vfs{g,u}id_t and associated helpers") is handled.

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Fixes: ffa5723c6d25 ("ovl: store lower path in ovl_inode")
Cc: <stable@vger.kernel.org> # v5.19
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
 fs/overlayfs/overlayfs.h | 2 +-
 fs/overlayfs/util.c      | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index e74a610a117e..6fb65df09a79 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -367,7 +367,7 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry);
 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);
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index 81a57a8d80d9..c9984785999c 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -250,7 +250,7 @@ struct dentry *ovl_i_dentry_upper(struct inode *inode)
 	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) {
@@ -259,6 +259,8 @@ void ovl_i_path_real(struct inode *inode, struct path *path)
 	} 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)
@@ -1105,8 +1107,7 @@ void ovl_copyattr(struct inode *inode)
 	struct inode *realinode;
 	struct user_namespace *real_mnt_userns;
 
-	ovl_i_path_real(inode, &realpath);
-	realinode = d_inode(realpath.dentry);
+	realinode = ovl_i_path_real(inode, &realpath);
 	real_mnt_userns = mnt_user_ns(realpath.mnt);
 
 	inode->i_uid = i_uid_into_mnt(real_mnt_userns, realinode);
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 6.1 2/2] ovl: fix null pointer dereference in ovl_get_acl_rcu()
  2023-07-17  3:09 [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path Zhihao Cheng
  2023-07-17  3:09 ` [PATCH 6.1 1/2] ovl: let helper ovl_i_path_real() return the realinode Zhihao Cheng
@ 2023-07-17  3:09 ` Zhihao Cheng
  2023-07-20 17:59 ` [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path Greg KH
  2 siblings, 0 replies; 4+ messages in thread
From: Zhihao Cheng @ 2023-07-17  3:09 UTC (permalink / raw)
  To: amir73il, gregkh, miklos; +Cc: linux-unionfs, stable, sashal

[ Upstream commit f4e19e595cc2e76a8a58413eb19d3d9c51328b53 ]

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]  <TASK>
  [  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.

There are some changes from upstream commit:
1. Corrusponds to do_ovl_get_acl() in 6.1 is ovl_get_acl()
2. Context conflicts caused by 6c0a8bfb84af8f3 ("ovl: implement get acl
   method") is handled.

Link: https://bugzilla.kernel.org/show_bug.cgi?id=217404
Fixes: 332f606b32b6 ("ovl: enable RCU'd ->get_acl()")
Cc: <stable@vger.kernel.org> # v5.15
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Suggested-by: Christian Brauner <brauner@kernel.org>
Suggested-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
---
 fs/overlayfs/inode.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 9e61511de7a7..677649b34965 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -497,20 +497,20 @@ static void ovl_idmap_posix_acl(struct inode *realinode,
  */
 struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu)
 {
-	struct inode *realinode = ovl_inode_real(inode);
+	struct inode *realinode;
 	struct posix_acl *acl, *clone;
 	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) {
 		acl = get_cached_acl_rcu(realinode, type);
 	} else {
-- 
2.39.2


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path
  2023-07-17  3:09 [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path Zhihao Cheng
  2023-07-17  3:09 ` [PATCH 6.1 1/2] ovl: let helper ovl_i_path_real() return the realinode Zhihao Cheng
  2023-07-17  3:09 ` [PATCH 6.1 2/2] ovl: fix null pointer dereference in ovl_get_acl_rcu() Zhihao Cheng
@ 2023-07-20 17:59 ` Greg KH
  2 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2023-07-20 17:59 UTC (permalink / raw)
  To: Zhihao Cheng; +Cc: amir73il, miklos, linux-unionfs, stable, sashal

On Mon, Jul 17, 2023 at 11:09:02AM +0800, Zhihao Cheng wrote:
> Zhihao Cheng (2):
>   ovl: let helper ovl_i_path_real() return the realinode
>   ovl: fix null pointer dereference in ovl_get_acl_rcu()
> 
>  fs/overlayfs/inode.c     | 12 ++++++------
>  fs/overlayfs/overlayfs.h |  2 +-
>  fs/overlayfs/util.c      |  7 ++++---
>  3 files changed, 11 insertions(+), 10 deletions(-)
> 
> -- 
> 2.39.2
> 

Now queued up, thanks.

greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2023-07-20 17:59 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-17  3:09 [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path Zhihao Cheng
2023-07-17  3:09 ` [PATCH 6.1 1/2] ovl: let helper ovl_i_path_real() return the realinode Zhihao Cheng
2023-07-17  3:09 ` [PATCH 6.1 2/2] ovl: fix null pointer dereference in ovl_get_acl_rcu() Zhihao Cheng
2023-07-20 17:59 ` [PATCH 6.1 0/2] ovl: fix null pointer dereference in ovl_get_acl rcu path Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.