diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-03-09 12:46:14 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-03-09 12:46:14 -0500 |
commit | 719ea86151f31f9d30dc854e028d05dc4afb3224 (patch) | |
tree | af46f4307cc5c730baabfe25b8939011ee2dfd3d /fs | |
parent | 2d9b1d69c3e2f1cc82029e58f36c4f0fa19984ef (diff) | |
parent | 36cd95dfa1ed76b59e2dcaafaa89c5479cec32b5 (diff) |
Merge branch 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
Pull overlayfs fixes from Miklos Szeredi:
"This fixes a corner case for NFS exporting (introduced in this cycle)
as well as fixing miscellaneous bugs"
* 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: update Kconfig texts
ovl: redirect_dir=nofollow should not follow redirect for opaque lower
ovl: fix ptr_ret.cocci warnings
ovl: check ERR_PTR() return value from ovl_lookup_real()
ovl: check lower ancestry on encode of lower dir file handle
ovl: hash non-dir by lower inode for fsnotify
Diffstat (limited to 'fs')
-rw-r--r-- | fs/overlayfs/Kconfig | 14 | ||||
-rw-r--r-- | fs/overlayfs/export.c | 216 | ||||
-rw-r--r-- | fs/overlayfs/inode.c | 58 | ||||
-rw-r--r-- | fs/overlayfs/namei.c | 6 | ||||
-rw-r--r-- | fs/overlayfs/overlayfs.h | 1 | ||||
-rw-r--r-- | fs/overlayfs/super.c | 1 |
6 files changed, 228 insertions, 68 deletions
diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig index 406e72de88f6..ce6ff5a0a6e4 100644 --- a/fs/overlayfs/Kconfig +++ b/fs/overlayfs/Kconfig | |||
@@ -24,6 +24,8 @@ config OVERLAY_FS_REDIRECT_DIR | |||
24 | an overlay which has redirects on a kernel that doesn't support this | 24 | an overlay which has redirects on a kernel that doesn't support this |
25 | feature will have unexpected results. | 25 | feature will have unexpected results. |
26 | 26 | ||
27 | If unsure, say N. | ||
28 | |||
27 | config OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW | 29 | config OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW |
28 | bool "Overlayfs: follow redirects even if redirects are turned off" | 30 | bool "Overlayfs: follow redirects even if redirects are turned off" |
29 | default y | 31 | default y |
@@ -32,8 +34,13 @@ config OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW | |||
32 | Disable this to get a possibly more secure configuration, but that | 34 | Disable this to get a possibly more secure configuration, but that |
33 | might not be backward compatible with previous kernels. | 35 | might not be backward compatible with previous kernels. |
34 | 36 | ||
37 | If backward compatibility is not an issue, then it is safe and | ||
38 | recommended to say N here. | ||
39 | |||
35 | For more information, see Documentation/filesystems/overlayfs.txt | 40 | For more information, see Documentation/filesystems/overlayfs.txt |
36 | 41 | ||
42 | If unsure, say Y. | ||
43 | |||
37 | config OVERLAY_FS_INDEX | 44 | config OVERLAY_FS_INDEX |
38 | bool "Overlayfs: turn on inodes index feature by default" | 45 | bool "Overlayfs: turn on inodes index feature by default" |
39 | depends on OVERLAY_FS | 46 | depends on OVERLAY_FS |
@@ -51,6 +58,8 @@ config OVERLAY_FS_INDEX | |||
51 | That is, mounting an overlay which has an inodes index on a kernel | 58 | That is, mounting an overlay which has an inodes index on a kernel |
52 | that doesn't support this feature will have unexpected results. | 59 | that doesn't support this feature will have unexpected results. |
53 | 60 | ||
61 | If unsure, say N. | ||
62 | |||
54 | config OVERLAY_FS_NFS_EXPORT | 63 | config OVERLAY_FS_NFS_EXPORT |
55 | bool "Overlayfs: turn on NFS export feature by default" | 64 | bool "Overlayfs: turn on NFS export feature by default" |
56 | depends on OVERLAY_FS | 65 | depends on OVERLAY_FS |
@@ -72,3 +81,8 @@ config OVERLAY_FS_NFS_EXPORT | |||
72 | Note, that the NFS export feature is not backward compatible. | 81 | Note, that the NFS export feature is not backward compatible. |
73 | That is, mounting an overlay which has a full index on a kernel | 82 | That is, mounting an overlay which has a full index on a kernel |
74 | that doesn't support this feature will have unexpected results. | 83 | that doesn't support this feature will have unexpected results. |
84 | |||
85 | Most users should say N here and enable this feature on a case-by- | ||
86 | case basis with the "nfs_export=on" mount option. | ||
87 | |||
88 | Say N unless you fully understand the consequences. | ||
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c index bb94ce9da5c8..87bd4148f4fb 100644 --- a/fs/overlayfs/export.c +++ b/fs/overlayfs/export.c | |||
@@ -19,6 +19,142 @@ | |||
19 | #include <linux/ratelimit.h> | 19 | #include <linux/ratelimit.h> |
20 | #include "overlayfs.h" | 20 | #include "overlayfs.h" |
21 | 21 | ||
22 | static int ovl_encode_maybe_copy_up(struct dentry *dentry) | ||
23 | { | ||
24 | int err; | ||
25 | |||
26 | if (ovl_dentry_upper(dentry)) | ||
27 | return 0; | ||
28 | |||
29 | err = ovl_want_write(dentry); | ||
30 | if (!err) { | ||
31 | err = ovl_copy_up(dentry); | ||
32 | ovl_drop_write(dentry); | ||
33 | } | ||
34 | |||
35 | if (err) { | ||
36 | pr_warn_ratelimited("overlayfs: failed to copy up on encode (%pd2, err=%i)\n", | ||
37 | dentry, err); | ||
38 | } | ||
39 | |||
40 | return err; | ||
41 | } | ||
42 | |||
43 | /* | ||
44 | * Before encoding a non-upper directory file handle from real layer N, we need | ||
45 | * to check if it will be possible to reconnect an overlay dentry from the real | ||
46 | * lower decoded dentry. This is done by following the overlay ancestry up to a | ||
47 | * "layer N connected" ancestor and verifying that all parents along the way are | ||
48 | * "layer N connectable". If an ancestor that is NOT "layer N connectable" is | ||
49 | * found, we need to copy up an ancestor, which is "layer N connectable", thus | ||
50 | * making that ancestor "layer N connected". For example: | ||
51 | * | ||
52 | * layer 1: /a | ||
53 | * layer 2: /a/b/c | ||
54 | * | ||
55 | * The overlay dentry /a is NOT "layer 2 connectable", because if dir /a is | ||
56 | * copied up and renamed, upper dir /a will be indexed by lower dir /a from | ||
57 | * layer 1. The dir /a from layer 2 will never be indexed, so the algorithm (*) | ||
58 | * in ovl_lookup_real_ancestor() will not be able to lookup a connected overlay | ||
59 | * dentry from the connected lower dentry /a/b/c. | ||
60 | * | ||
61 | * To avoid this problem on decode time, we need to copy up an ancestor of | ||
62 | * /a/b/c, which is "layer 2 connectable", on encode time. That ancestor is | ||
63 | * /a/b. After copy up (and index) of /a/b, it will become "layer 2 connected" | ||
64 | * and when the time comes to decode the file handle from lower dentry /a/b/c, | ||
65 | * ovl_lookup_real_ancestor() will find the indexed ancestor /a/b and decoding | ||
66 | * a connected overlay dentry will be accomplished. | ||
67 | * | ||
68 | * (*) the algorithm in ovl_lookup_real_ancestor() can be improved to lookup an | ||
69 | * entry /a in the lower layers above layer N and find the indexed dir /a from | ||
70 | * layer 1. If that improvement is made, then the check for "layer N connected" | ||
71 | * will need to verify there are no redirects in lower layers above N. In the | ||
72 | * example above, /a will be "layer 2 connectable". However, if layer 2 dir /a | ||
73 | * is a target of a layer 1 redirect, then /a will NOT be "layer 2 connectable": | ||
74 | * | ||
75 | * layer 1: /A (redirect = /a) | ||
76 | * layer 2: /a/b/c | ||
77 | */ | ||
78 | |||
79 | /* Return the lowest layer for encoding a connectable file handle */ | ||
80 | static int ovl_connectable_layer(struct dentry *dentry) | ||
81 | { | ||
82 | struct ovl_entry *oe = OVL_E(dentry); | ||
83 | |||
84 | /* We can get overlay root from root of any layer */ | ||
85 | if (dentry == dentry->d_sb->s_root) | ||
86 | return oe->numlower; | ||
87 | |||
88 | /* | ||
89 | * If it's an unindexed merge dir, then it's not connectable with any | ||
90 | * lower layer | ||
91 | */ | ||
92 | if (ovl_dentry_upper(dentry) && | ||
93 | !ovl_test_flag(OVL_INDEX, d_inode(dentry))) | ||
94 | return 0; | ||
95 | |||
96 | /* We can get upper/overlay path from indexed/lower dentry */ | ||
97 | return oe->lowerstack[0].layer->idx; | ||
98 | } | ||
99 | |||
100 | /* | ||
101 | * @dentry is "connected" if all ancestors up to root or a "connected" ancestor | ||
102 | * have the same uppermost lower layer as the origin's layer. We may need to | ||
103 | * copy up a "connectable" ancestor to make it "connected". A "connected" dentry | ||
104 | * cannot become non "connected", so cache positive result in dentry flags. | ||
105 | * | ||
106 | * Return the connected origin layer or < 0 on error. | ||
107 | */ | ||
108 | static int ovl_connect_layer(struct dentry *dentry) | ||
109 | { | ||
110 | struct dentry *next, *parent = NULL; | ||
111 | int origin_layer; | ||
112 | int err = 0; | ||
113 | |||
114 | if (WARN_ON(dentry == dentry->d_sb->s_root) || | ||
115 | WARN_ON(!ovl_dentry_lower(dentry))) | ||
116 | return -EIO; | ||
117 | |||
118 | origin_layer = OVL_E(dentry)->lowerstack[0].layer->idx; | ||
119 | if (ovl_dentry_test_flag(OVL_E_CONNECTED, dentry)) | ||
120 | return origin_layer; | ||
121 | |||
122 | /* Find the topmost origin layer connectable ancestor of @dentry */ | ||
123 | next = dget(dentry); | ||
124 | for (;;) { | ||
125 | parent = dget_parent(next); | ||
126 | if (WARN_ON(parent == next)) { | ||
127 | err = -EIO; | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * If @parent is not origin layer connectable, then copy up | ||
133 | * @next which is origin layer connectable and we are done. | ||
134 | */ | ||
135 | if (ovl_connectable_layer(parent) < origin_layer) { | ||
136 | err = ovl_encode_maybe_copy_up(next); | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | /* If @parent is connected or indexed we are done */ | ||
141 | if (ovl_dentry_test_flag(OVL_E_CONNECTED, parent) || | ||
142 | ovl_test_flag(OVL_INDEX, d_inode(parent))) | ||
143 | break; | ||
144 | |||
145 | dput(next); | ||
146 | next = parent; | ||
147 | } | ||
148 | |||
149 | dput(parent); | ||
150 | dput(next); | ||
151 | |||
152 | if (!err) | ||
153 | ovl_dentry_set_flag(OVL_E_CONNECTED, dentry); | ||
154 | |||
155 | return err ?: origin_layer; | ||
156 | } | ||
157 | |||
22 | /* | 158 | /* |
23 | * We only need to encode origin if there is a chance that the same object was | 159 | * We only need to encode origin if there is a chance that the same object was |
24 | * encoded pre copy up and then we need to stay consistent with the same | 160 | * encoded pre copy up and then we need to stay consistent with the same |
@@ -41,73 +177,59 @@ | |||
41 | * L = lower file handle | 177 | * L = lower file handle |
42 | * | 178 | * |
43 | * (*) Connecting an overlay dir from real lower dentry is not always | 179 | * (*) Connecting an overlay dir from real lower dentry is not always |
44 | * possible when there are redirects in lower layers. To mitigate this case, | 180 | * possible when there are redirects in lower layers and non-indexed merge dirs. |
45 | * we copy up the lower dir first and then encode an upper dir file handle. | 181 | * To mitigate those case, we may copy up the lower dir ancestor before encode |
182 | * a lower dir file handle. | ||
183 | * | ||
184 | * Return 0 for upper file handle, > 0 for lower file handle or < 0 on error. | ||
46 | */ | 185 | */ |
47 | static bool ovl_should_encode_origin(struct dentry *dentry) | 186 | static int ovl_check_encode_origin(struct dentry *dentry) |
48 | { | 187 | { |
49 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; | 188 | struct ovl_fs *ofs = dentry->d_sb->s_fs_info; |
50 | 189 | ||
190 | /* Upper file handle for pure upper */ | ||
51 | if (!ovl_dentry_lower(dentry)) | 191 | if (!ovl_dentry_lower(dentry)) |
52 | return false; | 192 | return 0; |
53 | 193 | ||
54 | /* | 194 | /* |
55 | * Decoding a merge dir, whose origin's parent is under a redirected | 195 | * Upper file handle for non-indexed upper. |
56 | * lower dir is not always possible. As a simple aproximation, we do | ||
57 | * not encode lower dir file handles when overlay has multiple lower | ||
58 | * layers and origin is below the topmost lower layer. | ||
59 | * | 196 | * |
60 | * TODO: copy up only the parent that is under redirected lower. | 197 | * Root is never indexed, so if there's an upper layer, encode upper for |
198 | * root. | ||
61 | */ | 199 | */ |
62 | if (d_is_dir(dentry) && ofs->upper_mnt && | ||
63 | OVL_E(dentry)->lowerstack[0].layer->idx > 1) | ||
64 | return false; | ||
65 | |||
66 | /* Decoding a non-indexed upper from origin is not implemented */ | ||
67 | if (ovl_dentry_upper(dentry) && | 200 | if (ovl_dentry_upper(dentry) && |
68 | !ovl_test_flag(OVL_INDEX, d_inode(dentry))) | 201 | !ovl_test_flag(OVL_INDEX, d_inode(dentry))) |
69 | return false; | ||
70 | |||
71 | return true; | ||
72 | } | ||
73 | |||
74 | static int ovl_encode_maybe_copy_up(struct dentry *dentry) | ||
75 | { | ||
76 | int err; | ||
77 | |||
78 | if (ovl_dentry_upper(dentry)) | ||
79 | return 0; | 202 | return 0; |
80 | 203 | ||
81 | err = ovl_want_write(dentry); | 204 | /* |
82 | if (err) | 205 | * Decoding a merge dir, whose origin's ancestor is under a redirected |
83 | return err; | 206 | * lower dir or under a non-indexed upper is not always possible. |
84 | 207 | * ovl_connect_layer() will try to make origin's layer "connected" by | |
85 | err = ovl_copy_up(dentry); | 208 | * copying up a "connectable" ancestor. |
209 | */ | ||
210 | if (d_is_dir(dentry) && ofs->upper_mnt) | ||
211 | return ovl_connect_layer(dentry); | ||
86 | 212 | ||
87 | ovl_drop_write(dentry); | 213 | /* Lower file handle for indexed and non-upper dir/non-dir */ |
88 | return err; | 214 | return 1; |
89 | } | 215 | } |
90 | 216 | ||
91 | static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen) | 217 | static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen) |
92 | { | 218 | { |
93 | struct dentry *origin = ovl_dentry_lower(dentry); | ||
94 | struct ovl_fh *fh = NULL; | 219 | struct ovl_fh *fh = NULL; |
95 | int err; | 220 | int err, enc_lower; |
96 | 221 | ||
97 | /* | 222 | /* |
98 | * If we should not encode a lower dir file handle, copy up and encode | 223 | * Check if we should encode a lower or upper file handle and maybe |
99 | * an upper dir file handle. | 224 | * copy up an ancestor to make lower file handle connectable. |
100 | */ | 225 | */ |
101 | if (!ovl_should_encode_origin(dentry)) { | 226 | err = enc_lower = ovl_check_encode_origin(dentry); |
102 | err = ovl_encode_maybe_copy_up(dentry); | 227 | if (enc_lower < 0) |
103 | if (err) | 228 | goto fail; |
104 | goto fail; | ||
105 | |||
106 | origin = NULL; | ||
107 | } | ||
108 | 229 | ||
109 | /* Encode an upper or origin file handle */ | 230 | /* Encode an upper or lower file handle */ |
110 | fh = ovl_encode_fh(origin ?: ovl_dentry_upper(dentry), !origin); | 231 | fh = ovl_encode_fh(enc_lower ? ovl_dentry_lower(dentry) : |
232 | ovl_dentry_upper(dentry), !enc_lower); | ||
111 | err = PTR_ERR(fh); | 233 | err = PTR_ERR(fh); |
112 | if (IS_ERR(fh)) | 234 | if (IS_ERR(fh)) |
113 | goto fail; | 235 | goto fail; |
@@ -355,8 +477,8 @@ static struct dentry *ovl_lookup_real_inode(struct super_block *sb, | |||
355 | dput(upper); | 477 | dput(upper); |
356 | } | 478 | } |
357 | 479 | ||
358 | if (!this) | 480 | if (IS_ERR_OR_NULL(this)) |
359 | return NULL; | 481 | return this; |
360 | 482 | ||
361 | if (WARN_ON(ovl_dentry_real_at(this, layer->idx) != real)) { | 483 | if (WARN_ON(ovl_dentry_real_at(this, layer->idx) != real)) { |
362 | dput(this); | 484 | dput(this); |
@@ -498,7 +620,7 @@ static struct dentry *ovl_lookup_real(struct super_block *sb, | |||
498 | if (err == -ECHILD) { | 620 | if (err == -ECHILD) { |
499 | this = ovl_lookup_real_ancestor(sb, real, | 621 | this = ovl_lookup_real_ancestor(sb, real, |
500 | layer); | 622 | layer); |
501 | err = IS_ERR(this) ? PTR_ERR(this) : 0; | 623 | err = PTR_ERR_OR_ZERO(this); |
502 | } | 624 | } |
503 | if (!err) { | 625 | if (!err) { |
504 | dput(connected); | 626 | dput(connected); |
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index fcd97b783fa1..3b1bd469accd 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c | |||
@@ -669,38 +669,59 @@ struct inode *ovl_lookup_inode(struct super_block *sb, struct dentry *real, | |||
669 | return inode; | 669 | return inode; |
670 | } | 670 | } |
671 | 671 | ||
672 | /* | ||
673 | * Does overlay inode need to be hashed by lower inode? | ||
674 | */ | ||
675 | static bool ovl_hash_bylower(struct super_block *sb, struct dentry *upper, | ||
676 | struct dentry *lower, struct dentry *index) | ||
677 | { | ||
678 | struct ovl_fs *ofs = sb->s_fs_info; | ||
679 | |||
680 | /* No, if pure upper */ | ||
681 | if (!lower) | ||
682 | return false; | ||
683 | |||
684 | /* Yes, if already indexed */ | ||
685 | if (index) | ||
686 | return true; | ||
687 | |||
688 | /* Yes, if won't be copied up */ | ||
689 | if (!ofs->upper_mnt) | ||
690 | return true; | ||
691 | |||
692 | /* No, if lower hardlink is or will be broken on copy up */ | ||
693 | if ((upper || !ovl_indexdir(sb)) && | ||
694 | !d_is_dir(lower) && d_inode(lower)->i_nlink > 1) | ||
695 | return false; | ||
696 | |||
697 | /* No, if non-indexed upper with NFS export */ | ||
698 | if (sb->s_export_op && upper) | ||
699 | return false; | ||
700 | |||
701 | /* Otherwise, hash by lower inode for fsnotify */ | ||
702 | return true; | ||
703 | } | ||
704 | |||
672 | struct inode *ovl_get_inode(struct super_block *sb, struct dentry *upperdentry, | 705 | struct inode *ovl_get_inode(struct super_block *sb, struct dentry *upperdentry, |
673 | struct dentry *lowerdentry, struct dentry *index, | 706 | struct dentry *lowerdentry, struct dentry *index, |
674 | unsigned int numlower) | 707 | unsigned int numlower) |
675 | { | 708 | { |
676 | struct ovl_fs *ofs = sb->s_fs_info; | ||
677 | struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; | 709 | struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; |
678 | struct inode *inode; | 710 | struct inode *inode; |
679 | /* Already indexed or could be indexed on copy up? */ | 711 | bool bylower = ovl_hash_bylower(sb, upperdentry, lowerdentry, index); |
680 | bool indexed = (index || (ovl_indexdir(sb) && !upperdentry)); | ||
681 | struct dentry *origin = indexed ? lowerdentry : NULL; | ||
682 | bool is_dir; | 712 | bool is_dir; |
683 | 713 | ||
684 | if (WARN_ON(upperdentry && indexed && !lowerdentry)) | ||
685 | return ERR_PTR(-EIO); | ||
686 | |||
687 | if (!realinode) | 714 | if (!realinode) |
688 | realinode = d_inode(lowerdentry); | 715 | realinode = d_inode(lowerdentry); |
689 | 716 | ||
690 | /* | 717 | /* |
691 | * Copy up origin (lower) may exist for non-indexed non-dir upper, but | 718 | * Copy up origin (lower) may exist for non-indexed upper, but we must |
692 | * we must not use lower as hash key in that case. | 719 | * not use lower as hash key if this is a broken hardlink. |
693 | * Hash non-dir that is or could be indexed by origin inode. | ||
694 | * Hash dir that is or could be merged by origin inode. | ||
695 | * Hash pure upper and non-indexed non-dir by upper inode. | ||
696 | * Hash non-indexed dir by upper inode for NFS export. | ||
697 | */ | 720 | */ |
698 | is_dir = S_ISDIR(realinode->i_mode); | 721 | is_dir = S_ISDIR(realinode->i_mode); |
699 | if (is_dir && (indexed || !sb->s_export_op || !ofs->upper_mnt)) | 722 | if (upperdentry || bylower) { |
700 | origin = lowerdentry; | 723 | struct inode *key = d_inode(bylower ? lowerdentry : |
701 | 724 | upperdentry); | |
702 | if (upperdentry || origin) { | ||
703 | struct inode *key = d_inode(origin ?: upperdentry); | ||
704 | unsigned int nlink = is_dir ? 1 : realinode->i_nlink; | 725 | unsigned int nlink = is_dir ? 1 : realinode->i_nlink; |
705 | 726 | ||
706 | inode = iget5_locked(sb, (unsigned long) key, | 727 | inode = iget5_locked(sb, (unsigned long) key, |
@@ -728,6 +749,7 @@ struct inode *ovl_get_inode(struct super_block *sb, struct dentry *upperdentry, | |||
728 | nlink = ovl_get_nlink(lowerdentry, upperdentry, nlink); | 749 | nlink = ovl_get_nlink(lowerdentry, upperdentry, nlink); |
729 | set_nlink(inode, nlink); | 750 | set_nlink(inode, nlink); |
730 | } else { | 751 | } else { |
752 | /* Lower hardlink that will be broken on copy up */ | ||
731 | inode = new_inode(sb); | 753 | inode = new_inode(sb); |
732 | if (!inode) | 754 | if (!inode) |
733 | goto out_nomem; | 755 | goto out_nomem; |
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index de3e6da1d5a5..70fcfcc684cc 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c | |||
@@ -913,9 +913,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
913 | stack[ctr].layer = lower.layer; | 913 | stack[ctr].layer = lower.layer; |
914 | ctr++; | 914 | ctr++; |
915 | 915 | ||
916 | if (d.stop) | ||
917 | break; | ||
918 | |||
919 | /* | 916 | /* |
920 | * Following redirects can have security consequences: it's like | 917 | * Following redirects can have security consequences: it's like |
921 | * a symlink into the lower layer without the permission checks. | 918 | * a symlink into the lower layer without the permission checks. |
@@ -933,6 +930,9 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, | |||
933 | goto out_put; | 930 | goto out_put; |
934 | } | 931 | } |
935 | 932 | ||
933 | if (d.stop) | ||
934 | break; | ||
935 | |||
936 | if (d.redirect && d.redirect[0] == '/' && poe != roe) { | 936 | if (d.redirect && d.redirect[0] == '/' && poe != roe) { |
937 | poe = roe; | 937 | poe = roe; |
938 | /* Find the current layer on the root dentry */ | 938 | /* Find the current layer on the root dentry */ |
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 0df25a9c94bd..225ff1171147 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h | |||
@@ -40,6 +40,7 @@ enum ovl_inode_flag { | |||
40 | enum ovl_entry_flag { | 40 | enum ovl_entry_flag { |
41 | OVL_E_UPPER_ALIAS, | 41 | OVL_E_UPPER_ALIAS, |
42 | OVL_E_OPAQUE, | 42 | OVL_E_OPAQUE, |
43 | OVL_E_CONNECTED, | ||
43 | }; | 44 | }; |
44 | 45 | ||
45 | /* | 46 | /* |
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 9ee37c76091d..7c24619ae7fc 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c | |||
@@ -1359,6 +1359,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) | |||
1359 | 1359 | ||
1360 | /* Root is always merge -> can have whiteouts */ | 1360 | /* Root is always merge -> can have whiteouts */ |
1361 | ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry)); | 1361 | ovl_set_flag(OVL_WHITEOUTS, d_inode(root_dentry)); |
1362 | ovl_dentry_set_flag(OVL_E_CONNECTED, root_dentry); | ||
1362 | ovl_inode_init(d_inode(root_dentry), upperpath.dentry, | 1363 | ovl_inode_init(d_inode(root_dentry), upperpath.dentry, |
1363 | ovl_dentry_lower(root_dentry)); | 1364 | ovl_dentry_lower(root_dentry)); |
1364 | 1365 | ||