ovl: fix warning in ovl_create_real()
authorMiklos Szeredi <mszeredi@redhat.com>
Thu, 4 Nov 2021 09:55:34 +0000 (10:55 +0100)
committerMiklos Szeredi <mszeredi@redhat.com>
Thu, 4 Nov 2021 09:55:34 +0000 (10:55 +0100)
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>
fs/overlayfs/dir.c
fs/overlayfs/overlayfs.h
fs/overlayfs/super.c

index 93c7c267de934de9b10040151d1646887b3596bf..f18490813170af41375c24360ba6e136a841b30a 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 3894f3347955215f74a075bd9dfb55dd440eb637..2cd5741c873b60592a139273017b669075bac72f 100644 (file)
@@ -570,6 +570,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 178daa5e82c9ddac45f0a972976ba90afeab4af8..265181c110ae2978ce802824c3091cfe45c93e20 100644 (file)
@@ -787,10 +787,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: