summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2017-07-18 21:07:43 +0300
committerMiklos Szeredi <mszeredi@redhat.com>2017-07-20 11:08:21 +0200
commit0e082555cec9510d276965fe391f709acb32c0f4 (patch)
tree437e67241b032c2a0e3f009f9ae940839b077008
parent61b674710cd9afa2a8b17bdd1ac80670c9b79f1d (diff)
ovl: check for bad and whiteout index on lookup
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>
-rw-r--r--fs/overlayfs/namei.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 229a88ff335c..8aef2b304b2d 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -513,6 +513,7 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
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",
@@ -522,11 +523,22 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
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;
}