summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2017-11-21 12:55:51 +0100
committerMiklos Szeredi <mszeredi@redhat.com>2018-01-24 11:25:52 +0100
commit86eaa13046d5e814484c89f635a95b0342b765ad (patch)
tree189e380030e95f8267ea015c1c9b3698828ef696
parentovl: verify stored origin fh matches lower dir (diff)
downloadlinux-86eaa13046d5e814484c89f635a95b0342b765ad.tar.xz
linux-86eaa13046d5e814484c89f635a95b0342b765ad.zip
ovl: unbless lower st_ino of unverified origin
On a malformed overlay, several redirected dirs can point to the same dir on a lower layer. This presents a similar challenge as broken hardlinks, because different objects in the overlay can return the same st_ino/st_dev pair from stat(2). For broken hardlinks, we do not provide constant st_ino on copy up to avoid this inconsistency. When NFS export feature is enabled, apply the same logic to files and directories with unverified lower origin. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/overlayfs/inode.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 94d2f8a8b779..96587075db11 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -105,12 +105,20 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
* Lower hardlinks may be broken on copy up to different
* upper files, so we cannot use the lower origin st_ino
* for those different files, even for the same fs case.
+ *
+ * Similarly, several redirected dirs can point to the
+ * same dir on a lower layer. With the "verify_lower"
+ * feature, we do not use the lower origin st_ino, if
+ * we haven't verified that this redirect is unique.
+ *
* With inodes index enabled, it is safe to use st_ino
- * of an indexed hardlinked origin. The index validates
- * that the upper hardlink is not broken.
+ * of an indexed origin. The index validates that the
+ * upper hardlink is not broken and that a redirected
+ * dir is the only redirect to that origin.
*/
- if (is_dir || lowerstat.nlink == 1 ||
- ovl_test_flag(OVL_INDEX, d_inode(dentry)))
+ if (ovl_test_flag(OVL_INDEX, d_inode(dentry)) ||
+ (!ovl_verify_lower(dentry->d_sb) &&
+ (is_dir || lowerstat.nlink == 1)))
stat->ino = lowerstat.ino;
if (samefs)