Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+88 -42
+18 -4
fs/overlayfs/dir.c
··· 481 481 } 482 482 483 483 static 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 487 int err; 487 488 const struct cred *old_cred; 488 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 493 if (err) 492 494 return err; 493 495 494 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 508 err = -ENOMEM; 496 509 override_cred = prepare_creds(); 497 510 if (override_cred) { ··· 563 550 inode_init_owner(inode, dentry->d_parent->d_inode, mode); 564 551 attr.mode = inode->i_mode; 565 552 566 - err = ovl_create_or_link(dentry, inode, &attr, NULL); 553 + err = ovl_create_or_link(dentry, inode, &attr, NULL, false); 567 554 if (err) 568 555 iput(inode); 569 556 ··· 622 609 inode = d_inode(old); 623 610 ihold(inode); 624 611 625 - err = ovl_create_or_link(new, inode, NULL, ovl_dentry_upper(old)); 612 + err = ovl_create_or_link(new, inode, NULL, ovl_dentry_upper(old), 613 + ovl_type_origin(old)); 626 614 if (err) 627 615 iput(inode); 628 616
+17 -15
fs/overlayfs/inode.c
··· 202 202 sizeof(OVL_XATTR_PREFIX) - 1) == 0; 203 203 } 204 204 205 - int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value, 206 - size_t size, int flags) 205 + int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, 206 + const void *value, size_t size, int flags) 207 207 { 208 208 int err; 209 - struct path realpath; 210 - enum ovl_path_type type = ovl_path_real(dentry, &realpath); 209 + struct dentry *upperdentry = ovl_i_dentry_upper(inode); 210 + struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); 211 211 const struct cred *old_cred; 212 212 213 213 err = ovl_want_write(dentry); 214 214 if (err) 215 215 goto out; 216 216 217 - if (!value && !OVL_TYPE_UPPER(type)) { 218 - err = vfs_getxattr(realpath.dentry, name, NULL, 0); 217 + if (!value && !upperdentry) { 218 + err = vfs_getxattr(realdentry, name, NULL, 0); 219 219 if (err < 0) 220 220 goto out_drop_write; 221 221 } 222 222 223 - err = ovl_copy_up(dentry); 224 - if (err) 225 - goto out_drop_write; 223 + if (!upperdentry) { 224 + err = ovl_copy_up(dentry); 225 + if (err) 226 + goto out_drop_write; 226 227 227 - if (!OVL_TYPE_UPPER(type)) 228 - ovl_path_upper(dentry, &realpath); 228 + realdentry = ovl_dentry_upper(dentry); 229 + } 229 230 230 231 old_cred = ovl_override_creds(dentry->d_sb); 231 232 if (value) 232 - err = vfs_setxattr(realpath.dentry, name, value, size, flags); 233 + err = vfs_setxattr(realdentry, name, value, size, flags); 233 234 else { 234 235 WARN_ON(flags != XATTR_REPLACE); 235 - err = vfs_removexattr(realpath.dentry, name); 236 + err = vfs_removexattr(realdentry, name); 236 237 } 237 238 revert_creds(old_cred); 238 239 ··· 243 242 return err; 244 243 } 245 244 246 - int ovl_xattr_get(struct dentry *dentry, const char *name, 245 + int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, 247 246 void *value, size_t size) 248 247 { 249 - struct dentry *realdentry = ovl_dentry_real(dentry); 250 248 ssize_t res; 251 249 const struct cred *old_cred; 250 + struct dentry *realdentry = 251 + ovl_i_dentry_upper(inode) ?: ovl_dentry_lower(dentry); 252 252 253 253 old_cred = ovl_override_creds(dentry->d_sb); 254 254 res = vfs_getxattr(realdentry, name, value, size);
+32 -9
fs/overlayfs/namei.c
··· 397 397 if (!d_inode(index)) 398 398 return 0; 399 399 400 - err = -EISDIR; 401 - if (d_is_dir(index)) 400 + /* 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 413 goto fail; 403 414 404 415 err = -EINVAL; ··· 447 436 return err; 448 437 449 438 fail: 450 - pr_warn_ratelimited("overlayfs: failed to verify index (%pd2, err=%i)\n", 451 - index, err); 439 + pr_warn_ratelimited("overlayfs: failed to verify index (%pd2, ftype=%x, err=%i)\n", 440 + index, d_inode(index)->i_mode & S_IFMT, err); 452 441 goto out; 453 442 } 454 443 ··· 513 502 goto out; 514 503 } 515 504 505 + inode = d_inode(index); 516 506 if (d_is_negative(index)) { 517 507 if (upper && d_inode(origin)->i_nlink > 1) { 518 508 pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n", ··· 523 511 524 512 dput(index); 525 513 index = NULL; 526 - } else if (upper && d_inode(index) != d_inode(upper)) { 527 - inode = d_inode(index); 528 - pr_warn_ratelimited("overlayfs: wrong index found (index ino: %lu, upper ino: %lu).\n", 529 - d_inode(index)->i_ino, 530 - d_inode(upper)->i_ino); 514 + } else if (upper && d_inode(upper) != inode) { 515 + pr_warn_ratelimited("overlayfs: wrong index found (index=%pd2, ino=%lu, upper ino=%lu).\n", 516 + index, inode->i_ino, d_inode(upper)->i_ino); 517 + goto fail; 518 + } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || 519 + ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { 520 + /* 521 + * Index should always be of the same file type as origin 522 + * except for the case of a whiteout index. A whiteout 523 + * index should only exist if all lower aliases have been 524 + * unlinked, which means that finding a lower origin on lookup 525 + * whose index is a whiteout should be treated as an error. 526 + */ 527 + pr_warn_ratelimited("overlayfs: bad index found (index=%pd2, ftype=%x, origin ftype=%x).\n", 528 + index, d_inode(index)->i_mode & S_IFMT, 529 + d_inode(origin)->i_mode & S_IFMT); 531 530 goto fail; 532 531 } 533 532
+6 -4
fs/overlayfs/overlayfs.h
··· 47 47 /* Is the real inode encoded in fid an upper inode? */ 48 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 53 #if defined(__LITTLE_ENDIAN) 53 54 #define OVL_FH_FLAG_CPU_ENDIAN 0 ··· 200 199 struct dentry *ovl_dentry_upper(struct dentry *dentry); 201 200 struct dentry *ovl_dentry_lower(struct dentry *dentry); 202 201 struct dentry *ovl_dentry_real(struct dentry *dentry); 202 + struct dentry *ovl_i_dentry_upper(struct inode *inode); 203 203 struct inode *ovl_inode_upper(struct inode *inode); 204 204 struct inode *ovl_inode_lower(struct inode *inode); 205 205 struct inode *ovl_inode_real(struct inode *inode); ··· 272 270 int ovl_getattr(const struct path *path, struct kstat *stat, 273 271 u32 request_mask, unsigned int flags); 274 272 int ovl_permission(struct inode *inode, int mask); 275 - int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value, 276 - size_t size, int flags); 277 - int ovl_xattr_get(struct dentry *dentry, const char *name, 273 + int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, 274 + const void *value, size_t size, int flags); 275 + int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, 278 276 void *value, size_t size); 279 277 ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); 280 278 struct posix_acl *ovl_get_acl(struct inode *inode, int type);
+4 -1
fs/overlayfs/readdir.c
··· 703 703 err = PTR_ERR(index); 704 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 710 err = ovl_cleanup(dir, index); 708 711 if (err) 709 712 break;
+5 -8
fs/overlayfs/super.c
··· 692 692 struct dentry *dentry, struct inode *inode, 693 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 698 698 static int __maybe_unused ··· 742 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 746 if (!err) 747 747 ovl_copyattr(ovl_inode_real(inode), inode); 748 748 ··· 772 772 struct dentry *dentry, struct inode *inode, 773 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 778 778 static int ovl_other_xattr_set(const struct xattr_handler *handler, ··· 780 780 const char *name, const void *value, 781 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 786 786 static const struct xattr_handler __maybe_unused ··· 1058 1058 1059 1059 ufs->indexdir = ovl_workdir_create(sb, ufs, workpath.dentry, 1060 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 1061 if (ufs->indexdir) { 1066 1062 /* Verify upper root is index dir origin */ 1067 1063 err = ovl_verify_origin(ufs->indexdir, ufs->upper_mnt, ··· 1086 1090 else 1087 1091 sb->s_d_op = &ovl_dentry_operations; 1088 1092 1093 + err = -ENOMEM; 1089 1094 ufs->creator_cred = cred = prepare_creds(); 1090 1095 if (!cred) 1091 1096 goto out_put_indexdir;
+6 -1
fs/overlayfs/util.c
··· 157 157 return ovl_dentry_upper(dentry) ?: ovl_dentry_lower(dentry); 158 158 } 159 159 160 + struct dentry *ovl_i_dentry_upper(struct inode *inode) 161 + { 162 + return ovl_upperdentry_dereference(OVL_I(inode)); 163 + } 164 + 160 165 struct 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 169 return upperdentry ? d_inode(upperdentry) : NULL; 165 170 }