aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-07-21 19:24:22 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-21 19:24:22 -0400
commit99313414dda451a8c00b139afc77a803e647f309 (patch)
tree8f23042ffbbd231154c6eceb469fcb9c941c4b7f
parent0151ef0085f946eed75da851297577f88d74c50c (diff)
parent0e082555cec9510d276965fe391f709acb32c0f4 (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 crash with SELinux and several other old and new bugs" * 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs: ovl: check for bad and whiteout index on lookup ovl: do not cleanup directory and whiteout index entries ovl: fix xattr get and set with selinux ovl: remove unneeded check for IS_ERR() ovl: fix origin verification of index dir ovl: mark parent impure on ovl_link() ovl: fix random return value on mount
-rw-r--r--fs/overlayfs/dir.c22
-rw-r--r--fs/overlayfs/inode.c32
-rw-r--r--fs/overlayfs/namei.c41
-rw-r--r--fs/overlayfs/overlayfs.h10
-rw-r--r--fs/overlayfs/readdir.c5
-rw-r--r--fs/overlayfs/super.c13
-rw-r--r--fs/overlayfs/util.c7
7 files changed, 88 insertions, 42 deletions
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 641d9ee97f91..48b70e6490f3 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -481,17 +481,30 @@ out_cleanup:
481} 481}
482 482
483static int ovl_create_or_link(struct dentry *dentry, struct inode *inode, 483static int ovl_create_or_link(struct dentry *dentry, struct inode *inode,
484 struct cattr *attr, struct dentry *hardlink) 484 struct cattr *attr, struct dentry *hardlink,
485 bool origin)
485{ 486{
486 int err; 487 int err;
487 const struct cred *old_cred; 488 const struct cred *old_cred;
488 struct cred *override_cred; 489 struct cred *override_cred;
490 struct dentry *parent = dentry->d_parent;
489 491
490 err = ovl_copy_up(dentry->d_parent); 492 err = ovl_copy_up(parent);
491 if (err) 493 if (err)
492 return err; 494 return err;
493 495
494 old_cred = ovl_override_creds(dentry->d_sb); 496 old_cred = ovl_override_creds(dentry->d_sb);
497
498 /*
499 * When linking a file with copy up origin into a new parent, mark the
500 * new parent dir "impure".
501 */
502 if (origin) {
503 err = ovl_set_impure(parent, ovl_dentry_upper(parent));
504 if (err)
505 goto out_revert_creds;
506 }
507
495 err = -ENOMEM; 508 err = -ENOMEM;
496 override_cred = prepare_creds(); 509 override_cred = prepare_creds();
497 if (override_cred) { 510 if (override_cred) {
@@ -550,7 +563,7 @@ static int ovl_create_object(struct dentry *dentry, int mode, dev_t rdev,
550 inode_init_owner(inode, dentry->d_parent->d_inode, mode); 563 inode_init_owner(inode, dentry->d_parent->d_inode, mode);
551 attr.mode = inode->i_mode; 564 attr.mode = inode->i_mode;
552 565
553 err = ovl_create_or_link(dentry, inode, &attr, NULL); 566 err = ovl_create_or_link(dentry, inode, &attr, NULL, false);
554 if (err) 567 if (err)
555 iput(inode); 568 iput(inode);
556 569
@@ -609,7 +622,8 @@ static int ovl_link(struct dentry *old, struct inode *newdir,
609 inode = d_inode(old); 622 inode = d_inode(old);
610 ihold(inode); 623 ihold(inode);
611 624
612 err = ovl_create_or_link(new, inode, NULL, ovl_dentry_upper(old)); 625 err = ovl_create_or_link(new, inode, NULL, ovl_dentry_upper(old),
626 ovl_type_origin(old));
613 if (err) 627 if (err)
614 iput(inode); 628 iput(inode);
615 629
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 69f4fc26ee39..5bc71642b226 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -202,37 +202,38 @@ bool ovl_is_private_xattr(const char *name)
202 sizeof(OVL_XATTR_PREFIX) - 1) == 0; 202 sizeof(OVL_XATTR_PREFIX) - 1) == 0;
203} 203}
204 204
205int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value, 205int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
206 size_t size, int flags) 206 const void *value, size_t size, int flags)
207{ 207{
208 int err; 208 int err;
209 struct path realpath; 209 struct dentry *upperdentry = ovl_i_dentry_upper(inode);
210 enum ovl_path_type type = ovl_path_real(dentry, &realpath); 210 struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry);
211 const struct cred *old_cred; 211 const struct cred *old_cred;
212 212
213 err = ovl_want_write(dentry); 213 err = ovl_want_write(dentry);
214 if (err) 214 if (err)
215 goto out; 215 goto out;
216 216
217 if (!value && !OVL_TYPE_UPPER(type)) { 217 if (!value && !upperdentry) {
218 err = vfs_getxattr(realpath.dentry, name, NULL, 0); 218 err = vfs_getxattr(realdentry, name, NULL, 0);
219 if (err < 0) 219 if (err < 0)
220 goto out_drop_write; 220 goto out_drop_write;
221 } 221 }
222 222
223 err = ovl_copy_up(dentry); 223 if (!upperdentry) {
224 if (err) 224 err = ovl_copy_up(dentry);
225 goto out_drop_write; 225 if (err)
226 goto out_drop_write;
226 227
227 if (!OVL_TYPE_UPPER(type)) 228 realdentry = ovl_dentry_upper(dentry);
228 ovl_path_upper(dentry, &realpath); 229 }
229 230
230 old_cred = ovl_override_creds(dentry->d_sb); 231 old_cred = ovl_override_creds(dentry->d_sb);
231 if (value) 232 if (value)
232 err = vfs_setxattr(realpath.dentry, name, value, size, flags); 233 err = vfs_setxattr(realdentry, name, value, size, flags);
233 else { 234 else {
234 WARN_ON(flags != XATTR_REPLACE); 235 WARN_ON(flags != XATTR_REPLACE);
235 err = vfs_removexattr(realpath.dentry, name); 236 err = vfs_removexattr(realdentry, name);
236 } 237 }
237 revert_creds(old_cred); 238 revert_creds(old_cred);
238 239
@@ -242,12 +243,13 @@ out:
242 return err; 243 return err;
243} 244}
244 245
245int ovl_xattr_get(struct dentry *dentry, const char *name, 246int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
246 void *value, size_t size) 247 void *value, size_t size)
247{ 248{
248 struct dentry *realdentry = ovl_dentry_real(dentry);
249 ssize_t res; 249 ssize_t res;
250 const struct cred *old_cred; 250 const struct cred *old_cred;
251 struct dentry *realdentry =
252 ovl_i_dentry_upper(inode) ?: ovl_dentry_lower(dentry);
251 253
252 old_cred = ovl_override_creds(dentry->d_sb); 254 old_cred = ovl_override_creds(dentry->d_sb);
253 res = vfs_getxattr(realdentry, name, value, size); 255 res = vfs_getxattr(realdentry, name, value, size);
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 9bc0e580a5b3..8aef2b304b2d 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -397,8 +397,19 @@ int ovl_verify_index(struct dentry *index, struct path *lowerstack,
397 if (!d_inode(index)) 397 if (!d_inode(index))
398 return 0; 398 return 0;
399 399
400 err = -EISDIR; 400 /*
401 if (d_is_dir(index)) 401 * Directory index entries are going to be used for looking up
402 * redirected upper dirs by lower dir fh when decoding an overlay
403 * file handle of a merge dir. Whiteout index entries are going to be
404 * used as an indication that an exported overlay file handle should
405 * be treated as stale (i.e. after unlink of the overlay inode).
406 * We don't know the verification rules for directory and whiteout
407 * index entries, because they have not been implemented yet, so return
408 * EROFS if those entries are found to avoid corrupting an index that
409 * was created by a newer kernel.
410 */
411 err = -EROFS;
412 if (d_is_dir(index) || ovl_is_whiteout(index))
402 goto fail; 413 goto fail;
403 414
404 err = -EINVAL; 415 err = -EINVAL;
@@ -436,8 +447,8 @@ out:
436 return err; 447 return err;
437 448
438fail: 449fail:
439 pr_warn_ratelimited("overlayfs: failed to verify index (%pd2, err=%i)\n", 450 pr_warn_ratelimited("overlayfs: failed to verify index (%pd2, ftype=%x, err=%i)\n",
440 index, err); 451 index, d_inode(index)->i_mode & S_IFMT, err);
441 goto out; 452 goto out;
442} 453}
443 454
@@ -502,6 +513,7 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
502 goto out; 513 goto out;
503 } 514 }
504 515
516 inode = d_inode(index);
505 if (d_is_negative(index)) { 517 if (d_is_negative(index)) {
506 if (upper && d_inode(origin)->i_nlink > 1) { 518 if (upper && d_inode(origin)->i_nlink > 1) {
507 pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n", 519 pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n",
@@ -511,11 +523,22 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
511 523
512 dput(index); 524 dput(index);
513 index = NULL; 525 index = NULL;
514 } else if (upper && d_inode(index) != d_inode(upper)) { 526 } else if (upper && d_inode(upper) != inode) {
515 inode = d_inode(index); 527 pr_warn_ratelimited("overlayfs: wrong index found (index=%pd2, ino=%lu, upper ino=%lu).\n",
516 pr_warn_ratelimited("overlayfs: wrong index found (index ino: %lu, upper ino: %lu).\n", 528 index, inode->i_ino, d_inode(upper)->i_ino);
517 d_inode(index)->i_ino, 529 goto fail;
518 d_inode(upper)->i_ino); 530 } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) ||
531 ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) {
532 /*
533 * Index should always be of the same file type as origin
534 * except for the case of a whiteout index. A whiteout
535 * index should only exist if all lower aliases have been
536 * unlinked, which means that finding a lower origin on lookup
537 * whose index is a whiteout should be treated as an error.
538 */
539 pr_warn_ratelimited("overlayfs: bad index found (index=%pd2, ftype=%x, origin ftype=%x).\n",
540 index, d_inode(index)->i_mode & S_IFMT,
541 d_inode(origin)->i_mode & S_IFMT);
519 goto fail; 542 goto fail;
520 } 543 }
521 544
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 60d26605e039..e927a62c97ae 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -47,7 +47,8 @@ enum ovl_flag {
47/* Is the real inode encoded in fid an upper inode? */ 47/* Is the real inode encoded in fid an upper inode? */
48#define OVL_FH_FLAG_PATH_UPPER (1 << 2) 48#define OVL_FH_FLAG_PATH_UPPER (1 << 2)
49 49
50#define OVL_FH_FLAG_ALL (OVL_FH_FLAG_BIG_ENDIAN | OVL_FH_FLAG_ANY_ENDIAN) 50#define OVL_FH_FLAG_ALL (OVL_FH_FLAG_BIG_ENDIAN | OVL_FH_FLAG_ANY_ENDIAN | \
51 OVL_FH_FLAG_PATH_UPPER)
51 52
52#if defined(__LITTLE_ENDIAN) 53#if defined(__LITTLE_ENDIAN)
53#define OVL_FH_FLAG_CPU_ENDIAN 0 54#define OVL_FH_FLAG_CPU_ENDIAN 0
@@ -199,6 +200,7 @@ enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path);
199struct dentry *ovl_dentry_upper(struct dentry *dentry); 200struct dentry *ovl_dentry_upper(struct dentry *dentry);
200struct dentry *ovl_dentry_lower(struct dentry *dentry); 201struct dentry *ovl_dentry_lower(struct dentry *dentry);
201struct dentry *ovl_dentry_real(struct dentry *dentry); 202struct dentry *ovl_dentry_real(struct dentry *dentry);
203struct dentry *ovl_i_dentry_upper(struct inode *inode);
202struct inode *ovl_inode_upper(struct inode *inode); 204struct inode *ovl_inode_upper(struct inode *inode);
203struct inode *ovl_inode_lower(struct inode *inode); 205struct inode *ovl_inode_lower(struct inode *inode);
204struct inode *ovl_inode_real(struct inode *inode); 206struct inode *ovl_inode_real(struct inode *inode);
@@ -270,9 +272,9 @@ int ovl_setattr(struct dentry *dentry, struct iattr *attr);
270int ovl_getattr(const struct path *path, struct kstat *stat, 272int ovl_getattr(const struct path *path, struct kstat *stat,
271 u32 request_mask, unsigned int flags); 273 u32 request_mask, unsigned int flags);
272int ovl_permission(struct inode *inode, int mask); 274int ovl_permission(struct inode *inode, int mask);
273int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value, 275int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name,
274 size_t size, int flags); 276 const void *value, size_t size, int flags);
275int ovl_xattr_get(struct dentry *dentry, const char *name, 277int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
276 void *value, size_t size); 278 void *value, size_t size);
277ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); 279ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
278struct posix_acl *ovl_get_acl(struct inode *inode, int type); 280struct posix_acl *ovl_get_acl(struct inode *inode, int type);
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 0298463cf9c3..3d424a51cabb 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -703,7 +703,10 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
703 err = PTR_ERR(index); 703 err = PTR_ERR(index);
704 break; 704 break;
705 } 705 }
706 if (ovl_verify_index(index, lowerstack, numlower)) { 706 err = ovl_verify_index(index, lowerstack, numlower);
707 if (err) {
708 if (err == -EROFS)
709 break;
707 err = ovl_cleanup(dir, index); 710 err = ovl_cleanup(dir, index);
708 if (err) 711 if (err)
709 break; 712 break;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 44dc2d6ffe0f..d86e89f97201 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -692,7 +692,7 @@ ovl_posix_acl_xattr_get(const struct xattr_handler *handler,
692 struct dentry *dentry, struct inode *inode, 692 struct dentry *dentry, struct inode *inode,
693 const char *name, void *buffer, size_t size) 693 const char *name, void *buffer, size_t size)
694{ 694{
695 return ovl_xattr_get(dentry, handler->name, buffer, size); 695 return ovl_xattr_get(dentry, inode, handler->name, buffer, size);
696} 696}
697 697
698static int __maybe_unused 698static int __maybe_unused
@@ -742,7 +742,7 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler,
742 return err; 742 return err;
743 } 743 }
744 744
745 err = ovl_xattr_set(dentry, handler->name, value, size, flags); 745 err = ovl_xattr_set(dentry, inode, handler->name, value, size, flags);
746 if (!err) 746 if (!err)
747 ovl_copyattr(ovl_inode_real(inode), inode); 747 ovl_copyattr(ovl_inode_real(inode), inode);
748 748
@@ -772,7 +772,7 @@ static int ovl_other_xattr_get(const struct xattr_handler *handler,
772 struct dentry *dentry, struct inode *inode, 772 struct dentry *dentry, struct inode *inode,
773 const char *name, void *buffer, size_t size) 773 const char *name, void *buffer, size_t size)
774{ 774{
775 return ovl_xattr_get(dentry, name, buffer, size); 775 return ovl_xattr_get(dentry, inode, name, buffer, size);
776} 776}
777 777
778static int ovl_other_xattr_set(const struct xattr_handler *handler, 778static int ovl_other_xattr_set(const struct xattr_handler *handler,
@@ -780,7 +780,7 @@ static int ovl_other_xattr_set(const struct xattr_handler *handler,
780 const char *name, const void *value, 780 const char *name, const void *value,
781 size_t size, int flags) 781 size_t size, int flags)
782{ 782{
783 return ovl_xattr_set(dentry, name, value, size, flags); 783 return ovl_xattr_set(dentry, inode, name, value, size, flags);
784} 784}
785 785
786static const struct xattr_handler __maybe_unused 786static const struct xattr_handler __maybe_unused
@@ -1058,10 +1058,6 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1058 1058
1059 ufs->indexdir = ovl_workdir_create(sb, ufs, workpath.dentry, 1059 ufs->indexdir = ovl_workdir_create(sb, ufs, workpath.dentry,
1060 OVL_INDEXDIR_NAME, true); 1060 OVL_INDEXDIR_NAME, true);
1061 err = PTR_ERR(ufs->indexdir);
1062 if (IS_ERR(ufs->indexdir))
1063 goto out_put_lower_mnt;
1064
1065 if (ufs->indexdir) { 1061 if (ufs->indexdir) {
1066 /* Verify upper root is index dir origin */ 1062 /* Verify upper root is index dir origin */
1067 err = ovl_verify_origin(ufs->indexdir, ufs->upper_mnt, 1063 err = ovl_verify_origin(ufs->indexdir, ufs->upper_mnt,
@@ -1090,6 +1086,7 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
1090 else 1086 else
1091 sb->s_d_op = &ovl_dentry_operations; 1087 sb->s_d_op = &ovl_dentry_operations;
1092 1088
1089 err = -ENOMEM;
1093 ufs->creator_cred = cred = prepare_creds(); 1090 ufs->creator_cred = cred = prepare_creds();
1094 if (!cred) 1091 if (!cred)
1095 goto out_put_indexdir; 1092 goto out_put_indexdir;
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c
index c492ba75c659..f46ad75dc96a 100644
--- a/fs/overlayfs/util.c
+++ b/fs/overlayfs/util.c
@@ -157,9 +157,14 @@ struct dentry *ovl_dentry_real(struct dentry *dentry)
157 return ovl_dentry_upper(dentry) ?: ovl_dentry_lower(dentry); 157 return ovl_dentry_upper(dentry) ?: ovl_dentry_lower(dentry);
158} 158}
159 159
160struct dentry *ovl_i_dentry_upper(struct inode *inode)
161{
162 return ovl_upperdentry_dereference(OVL_I(inode));
163}
164
160struct inode *ovl_inode_upper(struct inode *inode) 165struct inode *ovl_inode_upper(struct inode *inode)
161{ 166{
162 struct dentry *upperdentry = ovl_upperdentry_dereference(OVL_I(inode)); 167 struct dentry *upperdentry = ovl_i_dentry_upper(inode);
163 168
164 return upperdentry ? d_inode(upperdentry) : NULL; 169 return upperdentry ? d_inode(upperdentry) : NULL;
165} 170}