ovl: check for bad and whiteout index on lookup
authorAmir Goldstein <amir73il@gmail.com>
Tue, 18 Jul 2017 18:07:43 +0000 (21:07 +0300)
committerMiklos Szeredi <mszeredi@redhat.com>
Thu, 20 Jul 2017 09:08:21 +0000 (11:08 +0200)
Index should always be of the same file type as origin, except for
the case of a whiteout index.  A whiteout index should only exist
if all lower aliases have been unlinked, which means that finding
a lower origin on lookup whose index is a whiteout should be treated
as a lookup error.

Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/overlayfs/namei.c

index 229a88ff335c4bde56772bae2346c5a495b5d41b..8aef2b304b2d2bd2ad0c26942765e4bca0362835 100644 (file)
@@ -513,6 +513,7 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
                goto out;
        }
 
                goto out;
        }
 
+       inode = d_inode(index);
        if (d_is_negative(index)) {
                if (upper && d_inode(origin)->i_nlink > 1) {
                        pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n",
        if (d_is_negative(index)) {
                if (upper && d_inode(origin)->i_nlink > 1) {
                        pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n",
@@ -522,11 +523,22 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
 
                dput(index);
                index = NULL;
 
                dput(index);
                index = NULL;
-       } else if (upper && d_inode(index) != d_inode(upper)) {
-               inode = d_inode(index);
-               pr_warn_ratelimited("overlayfs: wrong index found (index ino: %lu, upper ino: %lu).\n",
-                                   d_inode(index)->i_ino,
-                                   d_inode(upper)->i_ino);
+       } else if (upper && d_inode(upper) != inode) {
+               pr_warn_ratelimited("overlayfs: wrong index found (index=%pd2, ino=%lu, upper ino=%lu).\n",
+                                   index, inode->i_ino, d_inode(upper)->i_ino);
+               goto fail;
+       } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) ||
+                  ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) {
+               /*
+                * Index should always be of the same file type as origin
+                * except for the case of a whiteout index. A whiteout
+                * index should only exist if all lower aliases have been
+                * unlinked, which means that finding a lower origin on lookup
+                * whose index is a whiteout should be treated as an error.
+                */
+               pr_warn_ratelimited("overlayfs: bad index found (index=%pd2, ftype=%x, origin ftype=%x).\n",
+                                   index, d_inode(index)->i_mode & S_IFMT,
+                                   d_inode(origin)->i_mode & S_IFMT);
                goto fail;
        }
 
                goto fail;
        }