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:
"Fix several issues, most of them introduced in the last release"

* 'overlayfs-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: do not cleanup unsupported index entries
ovl: handle ENOENT on index lookup
ovl: fix EIO from lookup of non-indexed upper
ovl: Return -ENOMEM if an allocation fails ovl_lookup()
ovl: add NULL check in ovl_alloc_inode

+42 -27
+16 -4
fs/overlayfs/inode.c
··· 598 598 return true; 599 599 } 600 600 601 - struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry) 601 + struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, 602 + struct dentry *index) 602 603 { 603 604 struct dentry *lowerdentry = ovl_dentry_lower(dentry); 604 605 struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL; 605 606 struct inode *inode; 607 + /* Already indexed or could be indexed on copy up? */ 608 + bool indexed = (index || (ovl_indexdir(dentry->d_sb) && !upperdentry)); 609 + 610 + if (WARN_ON(upperdentry && indexed && !lowerdentry)) 611 + return ERR_PTR(-EIO); 606 612 607 613 if (!realinode) 608 614 realinode = d_inode(lowerdentry); 609 615 610 - if (!S_ISDIR(realinode->i_mode) && 611 - (upperdentry || (lowerdentry && ovl_indexdir(dentry->d_sb)))) { 612 - struct inode *key = d_inode(lowerdentry ?: upperdentry); 616 + /* 617 + * Copy up origin (lower) may exist for non-indexed upper, but we must 618 + * not use lower as hash key in that case. 619 + * Hash inodes that are or could be indexed by origin inode and 620 + * non-indexed upper inodes that could be hard linked by upper inode. 621 + */ 622 + if (!S_ISDIR(realinode->i_mode) && (upperdentry || indexed)) { 623 + struct inode *key = d_inode(indexed ? lowerdentry : 624 + upperdentry); 613 625 unsigned int nlink; 614 626 615 627 inode = iget5_locked(dentry->d_sb, (unsigned long) key,
+16 -16
fs/overlayfs/namei.c
··· 405 405 * be treated as stale (i.e. after unlink of the overlay inode). 406 406 * We don't know the verification rules for directory and whiteout 407 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. 408 + * EINVAL if those entries are found to abort the mount to avoid 409 + * corrupting an index that was created by a newer kernel. 410 410 */ 411 - err = -EROFS; 411 + err = -EINVAL; 412 412 if (d_is_dir(index) || ovl_is_whiteout(index)) 413 413 goto fail; 414 414 415 - err = -EINVAL; 416 415 if (index->d_name.len < sizeof(struct ovl_fh)*2) 417 416 goto fail; 418 417 ··· 506 507 index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len); 507 508 if (IS_ERR(index)) { 508 509 err = PTR_ERR(index); 510 + if (err == -ENOENT) { 511 + index = NULL; 512 + goto out; 513 + } 509 514 pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%*s, err=%i);\n" 510 515 "overlayfs: mount with '-o index=off' to disable inodes index.\n", 511 516 d_inode(origin)->i_ino, name.len, name.name, ··· 519 516 520 517 inode = d_inode(index); 521 518 if (d_is_negative(index)) { 522 - if (upper && d_inode(origin)->i_nlink > 1) { 523 - pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n", 524 - d_inode(origin)->i_ino); 525 - goto fail; 526 - } 527 - 528 - dput(index); 529 - index = NULL; 519 + goto out_dput; 530 520 } else if (upper && d_inode(upper) != inode) { 531 - pr_warn_ratelimited("overlayfs: wrong index found (index=%pd2, ino=%lu, upper ino=%lu).\n", 532 - index, inode->i_ino, d_inode(upper)->i_ino); 533 - goto fail; 521 + goto out_dput; 534 522 } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) || 535 523 ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) { 536 524 /* ··· 540 546 out: 541 547 kfree(name.name); 542 548 return index; 549 + 550 + out_dput: 551 + dput(index); 552 + index = NULL; 553 + goto out; 543 554 544 555 fail: 545 556 dput(index); ··· 634 635 } 635 636 636 637 if (d.redirect) { 638 + err = -ENOMEM; 637 639 upperredirect = kstrdup(d.redirect, GFP_KERNEL); 638 640 if (!upperredirect) 639 641 goto out_put_upper; ··· 709 709 upperdentry = dget(index); 710 710 711 711 if (upperdentry || ctr) { 712 - inode = ovl_get_inode(dentry, upperdentry); 712 + inode = ovl_get_inode(dentry, upperdentry, index); 713 713 err = PTR_ERR(inode); 714 714 if (IS_ERR(inode)) 715 715 goto out_free_oe;
+2 -1
fs/overlayfs/overlayfs.h
··· 286 286 bool ovl_is_private_xattr(const char *name); 287 287 288 288 struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev); 289 - struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry); 289 + struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry, 290 + struct dentry *index); 290 291 static inline void ovl_copyattr(struct inode *from, struct inode *to) 291 292 { 292 293 to->i_uid = from->i_uid;
+5 -6
fs/overlayfs/readdir.c
··· 1021 1021 break; 1022 1022 } 1023 1023 err = ovl_verify_index(index, lowerstack, numlower); 1024 - if (err) { 1025 - if (err == -EROFS) 1026 - break; 1024 + /* Cleanup stale and orphan index entries */ 1025 + if (err && (err == -ESTALE || err == -ENOENT)) 1027 1026 err = ovl_cleanup(dir, index); 1028 - if (err) 1029 - break; 1030 - } 1027 + if (err) 1028 + break; 1029 + 1031 1030 dput(index); 1032 1031 index = NULL; 1033 1032 }
+3
fs/overlayfs/super.c
··· 174 174 { 175 175 struct ovl_inode *oi = kmem_cache_alloc(ovl_inode_cachep, GFP_KERNEL); 176 176 177 + if (!oi) 178 + return NULL; 179 + 177 180 oi->cache = NULL; 178 181 oi->redirect = NULL; 179 182 oi->version = 0;