* [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk
@ 2023-05-05 12:24 Zhihao Cheng
2023-05-05 12:24 ` [PATCH 1/2] ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk mode Zhihao Cheng
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Zhihao Cheng @ 2023-05-05 12:24 UTC (permalink / raw)
To: miklos, amir73il, brauner; +Cc: linux-unionfs, linux-kernel
Zhihao Cheng (2):
ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk
mode
ovl: ovl_permission: Fix null pointer dereference at realinode in
rcu-walk mode
fs/overlayfs/inode.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
--
2.31.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk mode
2023-05-05 12:24 [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk Zhihao Cheng
@ 2023-05-05 12:24 ` Zhihao Cheng
2023-05-15 11:08 ` Christian Brauner
2023-05-05 12:24 ` [PATCH 2/2] ovl: ovl_permission: " Zhihao Cheng
2023-05-15 11:04 ` [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk Christian Brauner
2 siblings, 1 reply; 5+ messages in thread
From: Zhihao Cheng @ 2023-05-05 12:24 UTC (permalink / raw)
To: miklos, amir73il, brauner; +Cc: linux-unionfs, linux-kernel
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].
Fix it by checking realinode whether to be NULL before accessing it.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=217404
Fixes: 332f606b32b6 ("ovl: enable RCU'd ->get_acl()")
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
fs/overlayfs/inode.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 541cf3717fc2..38cfdf9e2b44 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -563,16 +563,16 @@ struct posix_acl *do_ovl_get_acl(struct mnt_idmap *idmap,
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) {
+ if (!realpath.dentry || !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
--
2.31.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] ovl: ovl_permission: Fix null pointer dereference at realinode in rcu-walk mode
2023-05-05 12:24 [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk Zhihao Cheng
2023-05-05 12:24 ` [PATCH 1/2] ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk mode Zhihao Cheng
@ 2023-05-05 12:24 ` Zhihao Cheng
2023-05-15 11:04 ` [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk Christian Brauner
2 siblings, 0 replies; 5+ messages in thread
From: Zhihao Cheng @ 2023-05-05 12:24 UTC (permalink / raw)
To: miklos, amir73il, brauner; +Cc: linux-unionfs, linux-kernel
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].
Fix it by checking realinode whether to be NULL before accessing it.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=217405
Fixes: 4b7791b2e958 ("ovl: handle idmappings in ovl_permission()")
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
fs/overlayfs/inode.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 38cfdf9e2b44..a4c56584b8c2 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -293,6 +293,11 @@ int ovl_permission(struct mnt_idmap *idmap,
WARN_ON(!(mask & MAY_NOT_BLOCK));
return -ECHILD;
}
+ realinode = d_inode(realpath.dentry);
+ if (!realinode) {
+ WARN_ON(!(mask & MAY_NOT_BLOCK));
+ return -ECHILD;
+ }
/*
* Check overlay inode with the creds of task and underlying inode
@@ -302,7 +307,6 @@ int ovl_permission(struct mnt_idmap *idmap,
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) {
--
2.31.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk
2023-05-05 12:24 [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk Zhihao Cheng
2023-05-05 12:24 ` [PATCH 1/2] ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk mode Zhihao Cheng
2023-05-05 12:24 ` [PATCH 2/2] ovl: ovl_permission: " Zhihao Cheng
@ 2023-05-15 11:04 ` Christian Brauner
2 siblings, 0 replies; 5+ messages in thread
From: Christian Brauner @ 2023-05-15 11:04 UTC (permalink / raw)
To: Zhihao Cheng; +Cc: miklos, amir73il, linux-unionfs, linux-kernel
On Fri, May 05, 2023 at 08:24:50PM +0800, Zhihao Cheng wrote:
> Zhihao Cheng (2):
> ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk
> mode
> ovl: ovl_permission: Fix null pointer dereference at realinode in
> rcu-walk mode
>
> fs/overlayfs/inode.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
Seems fine to me. Thanks for fixing this,
Reviewed-by: Christian Brauner <brauner@kernel.org>
(One thing that might be possible is to move this into a tiny static
inline helper but might not be worth it.)
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk mode
2023-05-05 12:24 ` [PATCH 1/2] ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk mode Zhihao Cheng
@ 2023-05-15 11:08 ` Christian Brauner
0 siblings, 0 replies; 5+ messages in thread
From: Christian Brauner @ 2023-05-15 11:08 UTC (permalink / raw)
To: Zhihao Cheng; +Cc: miklos, amir73il, linux-unionfs, linux-kernel
On Fri, May 05, 2023 at 08:24:51PM +0800, Zhihao Cheng wrote:
> 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].
>
> Fix it by checking realinode whether to be NULL before accessing it.
>
> Link: https://bugzilla.kernel.org/show_bug.cgi?id=217404
> Fixes: 332f606b32b6 ("ovl: enable RCU'd ->get_acl()")
> Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
> ---
> fs/overlayfs/inode.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
> index 541cf3717fc2..38cfdf9e2b44 100644
> --- a/fs/overlayfs/inode.c
> +++ b/fs/overlayfs/inode.c
> @@ -563,16 +563,16 @@ struct posix_acl *do_ovl_get_acl(struct mnt_idmap *idmap,
> 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) {
> + if (!realpath.dentry || !realinode) {
> WARN_ON(!rcu);
> return ERR_PTR(-ECHILD);
> }
I think the logic here is now a bit strange. I would just not bother
calling ovl_inode_real() anymore and simply use the same logic as in
ovl_permission() (Thus my comment about using a tiny helper.).
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-05-15 11:08 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-05 12:24 [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk Zhihao Cheng
2023-05-05 12:24 ` [PATCH 1/2] ovl: get_acl: Fix null pointer dereference at realinode in rcu-walk mode Zhihao Cheng
2023-05-15 11:08 ` Christian Brauner
2023-05-05 12:24 ` [PATCH 2/2] ovl: ovl_permission: " Zhihao Cheng
2023-05-15 11:04 ` [PATCH 0/2] ovl: Fix null ptr dereference at realinode in rcu-walk Christian Brauner
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.