summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs/namei.c
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2018-01-11 03:47:03 -0500
committerMiklos Szeredi <mszeredi@redhat.com>2018-01-24 05:25:52 -0500
commitad1d615cec1c973aa222c065997a77e7cd5a0d17 (patch)
tree193a26aafc3b595f3a0ebb4dcad6e4c7c9e353d7 /fs/overlayfs/namei.c
parent86eaa13046d5e814484c89f635a95b0342b765ad (diff)
ovl: use directory index entries for consistency verification
A directory index is a directory type entry in index dir with a "trusted.overlay.upper" xattr containing an encoded ovl_fh of the merge directory upper dir inode. On lookup of non-dir files, lower file is followed by origin file handle. On lookup of dir entries, lower dir is found by name and then compared to origin file handle. We only trust dir index if we verified that lower dir matches origin file handle, otherwise index may be inconsistent and we ignore it. If we find an indexed non-upper dir or an indexed merged dir, whose index 'upper' xattr points to a different upper dir, that means that the lower directory may be also referenced by another upper dir via redirect, so we fail the lookup on inconsistency error. To be consistent with directory index entries format, the association of index dir to upper root dir, that was stored by older kernels in "trusted.overlay.origin" xattr is now stored in "trusted.overlay.upper" xattr. This also serves as an indication that overlay was mounted with a kernel that support index directory entries. For backward compatibility, if an 'origin' xattr exists on the index dir we also verify it on mount. Directory index entries are going to be used for NFS export. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs/namei.c')
-rw-r--r--fs/overlayfs/namei.c42
1 files changed, 35 insertions, 7 deletions
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 69ca8eb07519..b00d909e7326 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -538,6 +538,7 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
538 struct dentry *index; 538 struct dentry *index;
539 struct inode *inode; 539 struct inode *inode;
540 struct qstr name; 540 struct qstr name;
541 bool is_dir = d_is_dir(origin);
541 int err; 542 int err;
542 543
543 err = ovl_get_index_name(origin, &name); 544 err = ovl_get_index_name(origin, &name);
@@ -561,8 +562,6 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
561 inode = d_inode(index); 562 inode = d_inode(index);
562 if (d_is_negative(index)) { 563 if (d_is_negative(index)) {
563 goto out_dput; 564 goto out_dput;
564 } else if (upper && d_inode(upper) != inode) {
565 goto out_dput;
566 } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || 565 } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) ||
567 ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { 566 ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) {
568 /* 567 /*
@@ -576,8 +575,25 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
576 index, d_inode(index)->i_mode & S_IFMT, 575 index, d_inode(index)->i_mode & S_IFMT,
577 d_inode(origin)->i_mode & S_IFMT); 576 d_inode(origin)->i_mode & S_IFMT);
578 goto fail; 577 goto fail;
579 } 578 } else if (is_dir) {
579 if (!upper) {
580 pr_warn_ratelimited("overlayfs: suspected uncovered redirected dir found (origin=%pd2, index=%pd2).\n",
581 origin, index);
582 goto fail;
583 }
580 584
585 /* Verify that dir index 'upper' xattr points to upper dir */
586 err = ovl_verify_upper(index, upper, false);
587 if (err) {
588 if (err == -ESTALE) {
589 pr_warn_ratelimited("overlayfs: suspected multiply redirected dir found (upper=%pd2, origin=%pd2, index=%pd2).\n",
590 upper, origin, index);
591 }
592 goto fail;
593 }
594 } else if (upper && d_inode(upper) != inode) {
595 goto out_dput;
596 }
581out: 597out:
582 kfree(name.name); 598 kfree(name.name);
583 return index; 599 return index;
@@ -646,6 +662,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
646 struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata; 662 struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata;
647 struct ovl_path *stack = NULL; 663 struct ovl_path *stack = NULL;
648 struct dentry *upperdir, *upperdentry = NULL; 664 struct dentry *upperdir, *upperdentry = NULL;
665 struct dentry *origin = NULL;
649 struct dentry *index = NULL; 666 struct dentry *index = NULL;
650 unsigned int ctr = 0; 667 unsigned int ctr = 0;
651 struct inode *inode = NULL; 668 struct inode *inode = NULL;
@@ -739,7 +756,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
739 756
740 /* 757 /*
741 * When "verify_lower" feature is enabled, do not merge with a 758 * When "verify_lower" feature is enabled, do not merge with a
742 * lower dir that does not match a stored origin xattr. 759 * lower dir that does not match a stored origin xattr. In any
760 * case, only verified origin is used for index lookup.
743 */ 761 */
744 if (upperdentry && !ctr && ovl_verify_lower(dentry->d_sb)) { 762 if (upperdentry && !ctr && ovl_verify_lower(dentry->d_sb)) {
745 err = ovl_verify_origin(upperdentry, this, false); 763 err = ovl_verify_origin(upperdentry, this, false);
@@ -747,6 +765,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
747 dput(this); 765 dput(this);
748 break; 766 break;
749 } 767 }
768
769 /* Bless lower dir as verified origin */
770 origin = this;
750 } 771 }
751 772
752 stack[ctr].dentry = this; 773 stack[ctr].dentry = this;
@@ -780,10 +801,17 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
780 } 801 }
781 } 802 }
782 803
783 /* Lookup index by lower inode and verify it matches upper inode */ 804 /*
784 if (ctr && !d.is_dir && ovl_indexdir(dentry->d_sb)) { 805 * Lookup index by lower inode and verify it matches upper inode.
785 struct dentry *origin = stack[0].dentry; 806 * We only trust dir index if we verified that lower dir matches
807 * origin, otherwise dir index entries may be inconsistent and we
808 * ignore them. Always lookup index of non-dir and non-upper.
809 */
810 if (ctr && (!upperdentry || !d.is_dir))
811 origin = stack[0].dentry;
786 812
813 if (origin && ovl_indexdir(dentry->d_sb) &&
814 (!d.is_dir || ovl_index_all(dentry->d_sb))) {
787 index = ovl_lookup_index(dentry, upperdentry, origin); 815 index = ovl_lookup_index(dentry, upperdentry, origin);
788 if (IS_ERR(index)) { 816 if (IS_ERR(index)) {
789 err = PTR_ERR(index); 817 err = PTR_ERR(index);