ovl: fix warning in ovl_create_real()
authorMiklos Szeredi <mszeredi@redhat.com>
Thu, 4 Nov 2021 09:55:34 +0000 (10:55 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Dec 2021 08:30:58 +0000 (09:30 +0100)
commit 1f5573cfe7a7056e80a92c7a037a3e69f3a13d1c upstream.

Syzbot triggered the following warning in ovl_workdir_create() ->
ovl_create_real():

if (!err && WARN_ON(!newdentry->d_inode)) {

The reason is that the cgroup2 filesystem returns from mkdir without
instantiating the new dentry.

Weird filesystems such as this will be rejected by overlayfs at a later
stage during setup, but to prevent such a warning, call ovl_mkdir_real()
directly from ovl_workdir_create() and reject this case early.

Reported-and-tested-by: syzbot+75eab84fd0af9e8bf66b@syzkaller.appspotmail.com
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/overlayfs/dir.c
fs/overlayfs/overlayfs.h
fs/overlayfs/super.c

index 16955a307dcd9edb18389c181835a9a418dca3ef..d0e5cde27702224466905eea473709abf3e31525 100644 (file)
@@ -137,8 +137,7 @@ kill_whiteout:
        goto out;
 }
 
-static int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry,
-                         umode_t mode)
+int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode)
 {
        int err;
        struct dentry *d, *dentry = *newdentry;
index e43dc68bd1b54e69352a44dc40a3965e7803162e..898de3bf884e468fedc9408e697d1eebfb8ffa49 100644 (file)
@@ -519,6 +519,7 @@ struct ovl_cattr {
 
 #define OVL_CATTR(m) (&(struct ovl_cattr) { .mode = (m) })
 
+int ovl_mkdir_real(struct inode *dir, struct dentry **newdentry, umode_t mode);
 struct dentry *ovl_create_real(struct inode *dir, struct dentry *newdentry,
                               struct ovl_cattr *attr);
 int ovl_cleanup(struct inode *dir, struct dentry *dentry);
index 77f08ac04d1f3cedab8204c7643df422354e9d01..45c596dfe3a360b5ac3abc8ee3ae3ecf29a70343 100644 (file)
@@ -743,10 +743,14 @@ retry:
                        goto retry;
                }
 
-               work = ovl_create_real(dir, work, OVL_CATTR(attr.ia_mode));
-               err = PTR_ERR(work);
-               if (IS_ERR(work))
-                       goto out_err;
+               err = ovl_mkdir_real(dir, &work, attr.ia_mode);
+               if (err)
+                       goto out_dput;
+
+               /* Weird filesystem returning with hashed negative (kernfs)? */
+               err = -EINVAL;
+               if (d_really_is_negative(work))
+                       goto out_dput;
 
                /*
                 * Try to remove POSIX ACL xattrs from workdir.  We are good if: