]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jul 2023 15:18:00 +0000 (17:18 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Jul 2023 15:18:00 +0000 (17:18 +0200)
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

queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_get_acl_rcu.patch [new file with mode: 0644]
queue-6.4/ovl-fix-null-pointer-dereference-in-ovl_permission.patch [new file with mode: 0644]
queue-6.4/ovl-let-helper-ovl_i_path_real-return-the-realinode.patch [new file with mode: 0644]
queue-6.4/series

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 (file)
index 0000000..9ce8df3
--- /dev/null
@@ -0,0 +1,98 @@
+From f4e19e595cc2e76a8a58413eb19d3d9c51328b53 Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Tue, 16 May 2023 22:16:19 +0800
+Subject: ovl: fix null pointer dereference in ovl_get_acl_rcu()
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+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]  <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.
+
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..31275be
--- /dev/null
@@ -0,0 +1,82 @@
+From 1a73f5b8f079fd42a544c1600beface50c63af7c Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Tue, 16 May 2023 22:16:18 +0800
+Subject: ovl: fix null pointer dereference in ovl_permission()
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+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]  <TASK>
+  [  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: <stable@vger.kernel.org> # v5.19
+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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..6d47369
--- /dev/null
@@ -0,0 +1,67 @@
+From b2dd05f107b11966e26fe52a313b418364cf497b Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Tue, 16 May 2023 22:16:17 +0800
+Subject: ovl: let helper ovl_i_path_real() return the realinode
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+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 <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>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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);
index 4df4cce3a71eaa1bb97c5624344759ab20586552..42b7eb95eb119dae06a8e194a6d685e4c037f0c3 100644 (file)
@@ -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