summaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorAmir Goldstein <amir73il@gmail.com>2017-06-21 08:28:38 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2017-07-04 16:03:17 -0400
commit54fb347e836faadaed2a5617fb4dd4a4597d0490 (patch)
tree776d77e3848edf181ebeeda5bea8169c8937c6bc /fs/overlayfs
parent8b88a2e6403638b56556ed5b1c60d9318eefea9c (diff)
ovl: verify index dir matches upper dir
An index dir contains persistent hardlinks to files in upper dir. Therefore, we must never mount an existing index dir with a differnt upper dir. Store the upper root dir file handle in index dir inode when index dir is created and verify the file handle before using an existing index dir on mount. Add an 'is_upper' flag to the overlay file handle encoding and set it when encoding the upper root file handle. This is not critical for index dir verification, but it is good practice towards a standard overlayfs file handle format for NFS export. Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r--fs/overlayfs/copy_up.c12
-rw-r--r--fs/overlayfs/namei.c4
-rw-r--r--fs/overlayfs/overlayfs.h6
-rw-r--r--fs/overlayfs/super.c13
4 files changed, 27 insertions, 8 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 42807cb57da0..5e8fd99557e1 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -233,7 +233,7 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
233 return err; 233 return err;
234} 234}
235 235
236struct ovl_fh *ovl_encode_fh(struct dentry *lower) 236struct ovl_fh *ovl_encode_fh(struct dentry *lower, bool is_upper)
237{ 237{
238 struct ovl_fh *fh; 238 struct ovl_fh *fh;
239 int fh_type, fh_len, dwords; 239 int fh_type, fh_len, dwords;
@@ -272,6 +272,14 @@ struct ovl_fh *ovl_encode_fh(struct dentry *lower)
272 fh->magic = OVL_FH_MAGIC; 272 fh->magic = OVL_FH_MAGIC;
273 fh->type = fh_type; 273 fh->type = fh_type;
274 fh->flags = OVL_FH_FLAG_CPU_ENDIAN; 274 fh->flags = OVL_FH_FLAG_CPU_ENDIAN;
275 /*
276 * When we will want to decode an overlay dentry from this handle
277 * and all layers are on the same fs, if we get a disconncted real
278 * dentry when we decode fid, the only way to tell if we should assign
279 * it to upperdentry or to lowerstack is by checking this flag.
280 */
281 if (is_upper)
282 fh->flags |= OVL_FH_FLAG_PATH_UPPER;
275 fh->len = fh_len; 283 fh->len = fh_len;
276 fh->uuid = *uuid; 284 fh->uuid = *uuid;
277 memcpy(fh->fid, buf, buflen); 285 memcpy(fh->fid, buf, buflen);
@@ -293,7 +301,7 @@ static int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
293 * up and a pure upper inode. 301 * up and a pure upper inode.
294 */ 302 */
295 if (ovl_can_decode_fh(lower->d_sb)) { 303 if (ovl_can_decode_fh(lower->d_sb)) {
296 fh = ovl_encode_fh(lower); 304 fh = ovl_encode_fh(lower, false);
297 if (IS_ERR(fh)) 305 if (IS_ERR(fh))
298 return PTR_ERR(fh); 306 return PTR_ERR(fh);
299 } 307 }
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 197b53d34861..0c816e9aa50c 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -350,13 +350,13 @@ static int ovl_verify_origin_fh(struct dentry *dentry, const struct ovl_fh *fh)
350 * Return 0 on match, -ESTALE on mismatch, < 0 on error. 350 * Return 0 on match, -ESTALE on mismatch, < 0 on error.
351 */ 351 */
352int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt, 352int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt,
353 struct dentry *origin, bool set) 353 struct dentry *origin, bool is_upper, bool set)
354{ 354{
355 struct inode *inode; 355 struct inode *inode;
356 struct ovl_fh *fh; 356 struct ovl_fh *fh;
357 int err; 357 int err;
358 358
359 fh = ovl_encode_fh(origin); 359 fh = ovl_encode_fh(origin, is_upper);
360 err = PTR_ERR(fh); 360 err = PTR_ERR(fh);
361 if (IS_ERR(fh)) 361 if (IS_ERR(fh))
362 goto fail; 362 goto fail;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 38ac84cba6ea..58bbd135a7b3 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -42,6 +42,8 @@ enum ovl_flag {
42/* CPU byte order required for fid decoding: */ 42/* CPU byte order required for fid decoding: */
43#define OVL_FH_FLAG_BIG_ENDIAN (1 << 0) 43#define OVL_FH_FLAG_BIG_ENDIAN (1 << 0)
44#define OVL_FH_FLAG_ANY_ENDIAN (1 << 1) 44#define OVL_FH_FLAG_ANY_ENDIAN (1 << 1)
45/* Is the real inode encoded in fid an upper inode? */
46#define OVL_FH_FLAG_PATH_UPPER (1 << 2)
45 47
46#define OVL_FH_FLAG_ALL (OVL_FH_FLAG_BIG_ENDIAN | OVL_FH_FLAG_ANY_ENDIAN) 48#define OVL_FH_FLAG_ALL (OVL_FH_FLAG_BIG_ENDIAN | OVL_FH_FLAG_ANY_ENDIAN)
47 49
@@ -233,7 +235,7 @@ static inline bool ovl_is_impuredir(struct dentry *dentry)
233 235
234/* namei.c */ 236/* namei.c */
235int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt, 237int ovl_verify_origin(struct dentry *dentry, struct vfsmount *mnt,
236 struct dentry *origin, bool set); 238 struct dentry *origin, bool is_upper, bool set);
237int ovl_path_next(int idx, struct dentry *dentry, struct path *path); 239int ovl_path_next(int idx, struct dentry *dentry, struct path *path);
238struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); 240struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags);
239bool ovl_lower_positive(struct dentry *dentry); 241bool ovl_lower_positive(struct dentry *dentry);
@@ -292,4 +294,4 @@ int ovl_copy_up(struct dentry *dentry);
292int ovl_copy_up_flags(struct dentry *dentry, int flags); 294int ovl_copy_up_flags(struct dentry *dentry, int flags);
293int ovl_copy_xattr(struct dentry *old, struct dentry *new); 295int ovl_copy_xattr(struct dentry *old, struct dentry *new);
294int ovl_set_attr(struct dentry *upper, struct kstat *stat); 296int ovl_set_attr(struct dentry *upper, struct kstat *stat);
295struct ovl_fh *ovl_encode_fh(struct dentry *lower); 297struct ovl_fh *ovl_encode_fh(struct dentry *lower, bool is_upper);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index bfdcff0f3168..a313af25dac2 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1050,7 +1050,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1050 if (!(ovl_force_readonly(ufs)) && ufs->config.index) { 1050 if (!(ovl_force_readonly(ufs)) && ufs->config.index) {
1051 /* Verify lower root is upper root origin */ 1051 /* Verify lower root is upper root origin */
1052 err = ovl_verify_origin(upperpath.dentry, ufs->lower_mnt[0], 1052 err = ovl_verify_origin(upperpath.dentry, ufs->lower_mnt[0],
1053 stack[0].dentry, true); 1053 stack[0].dentry, false, true);
1054 if (err) { 1054 if (err) {
1055 pr_err("overlayfs: failed to verify upper root origin\n"); 1055 pr_err("overlayfs: failed to verify upper root origin\n");
1056 goto out_put_lower_mnt; 1056 goto out_put_lower_mnt;
@@ -1062,8 +1062,17 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1062 if (IS_ERR(ufs->indexdir)) 1062 if (IS_ERR(ufs->indexdir))
1063 goto out_put_lower_mnt; 1063 goto out_put_lower_mnt;
1064 1064
1065 if (!ufs->indexdir) 1065 if (ufs->indexdir) {
1066 /* Verify upper root is index dir origin */
1067 err = ovl_verify_origin(ufs->indexdir, ufs->upper_mnt,
1068 upperpath.dentry, true, true);
1069 if (err)
1070 pr_err("overlayfs: failed to verify index dir origin\n");
1071 }
1072 if (err || !ufs->indexdir)
1066 pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n"); 1073 pr_warn("overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.\n");
1074 if (err)
1075 goto out_put_indexdir;
1067 } 1076 }
1068 1077
1069 /* Show index=off/on in /proc/mounts for any of the reasons above */ 1078 /* Show index=off/on in /proc/mounts for any of the reasons above */