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

Merge tag 'ovl-fixes-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs into master

Pull overlayfs fixes from Miklos Szeredi:

- fix a regression introduced in v4.20 in handling a regenerated
squashfs lower layer

- two regression fixes for this cycle, one of which is Oops inducing

- miscellaneous issues

* tag 'ovl-fixes-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: fix lookup of indexed hardlinks with metacopy
ovl: fix unneeded call to ovl_change_flags()
ovl: fix mount option checks for nfs_export with no upperdir
ovl: force read-only sb on failure to create index dir
ovl: fix regression with re-formatted lower squashfs
ovl: fix oops in ovl_indexdir_cleanup() with nfs_export=on
ovl: relax WARN_ON() when decoding lower directory file handle
ovl: remove not used argument in ovl_check_origin
ovl: change ovl_copy_up_flags static
ovl: inode reference leak in ovl_is_inuse true case.

+65 -42
+2 -2
Documentation/filesystems/overlayfs.rst
··· 560 560 verified on mount time to check that upper file handles are not stale. 561 561 This verification may cause significant overhead in some cases. 562 562 563 - Note: the mount options index=off,nfs_export=on are conflicting and will 564 - result in an error. 563 + Note: the mount options index=off,nfs_export=on are conflicting for a 564 + read-write mount and will result in an error. 565 565 566 566 567 567 Testsuite
+1 -1
fs/overlayfs/copy_up.c
··· 895 895 return err; 896 896 } 897 897 898 - int ovl_copy_up_flags(struct dentry *dentry, int flags) 898 + static int ovl_copy_up_flags(struct dentry *dentry, int flags) 899 899 { 900 900 int err = 0; 901 901 const struct cred *old_cred = ovl_override_creds(dentry->d_sb);
+1 -1
fs/overlayfs/export.c
··· 476 476 if (IS_ERR_OR_NULL(this)) 477 477 return this; 478 478 479 - if (WARN_ON(ovl_dentry_real_at(this, layer->idx) != real)) { 479 + if (ovl_dentry_real_at(this, layer->idx) != real) { 480 480 dput(this); 481 481 this = ERR_PTR(-EIO); 482 482 }
+6 -4
fs/overlayfs/file.c
··· 33 33 return 'm'; 34 34 } 35 35 36 + /* No atime modificaton nor notify on underlying */ 37 + #define OVL_OPEN_FLAGS (O_NOATIME | FMODE_NONOTIFY) 38 + 36 39 static struct file *ovl_open_realfile(const struct file *file, 37 40 struct inode *realinode) 38 41 { 39 42 struct inode *inode = file_inode(file); 40 43 struct file *realfile; 41 44 const struct cred *old_cred; 42 - int flags = file->f_flags | O_NOATIME | FMODE_NONOTIFY; 45 + int flags = file->f_flags | OVL_OPEN_FLAGS; 43 46 int acc_mode = ACC_MODE(flags); 44 47 int err; 45 48 ··· 75 72 struct inode *inode = file_inode(file); 76 73 int err; 77 74 78 - /* No atime modificaton on underlying */ 79 - flags |= O_NOATIME | FMODE_NONOTIFY; 75 + flags |= OVL_OPEN_FLAGS; 80 76 81 77 /* If some flag changed that cannot be changed then something's amiss */ 82 78 if (WARN_ON((file->f_flags ^ flags) & ~OVL_SETFL_MASK)) ··· 128 126 } 129 127 130 128 /* Did the flags change since open? */ 131 - if (unlikely((file->f_flags ^ real->file->f_flags) & ~O_NOATIME)) 129 + if (unlikely((file->f_flags ^ real->file->f_flags) & ~OVL_OPEN_FLAGS)) 132 130 return ovl_change_flags(real->file, file->f_flags); 133 131 134 132 return 0;
+6 -9
fs/overlayfs/namei.c
··· 389 389 } 390 390 391 391 static int ovl_check_origin(struct ovl_fs *ofs, struct dentry *upperdentry, 392 - struct ovl_path **stackp, unsigned int *ctrp) 392 + struct ovl_path **stackp) 393 393 { 394 394 struct ovl_fh *fh = ovl_get_fh(upperdentry, OVL_XATTR_ORIGIN); 395 395 int err; ··· 406 406 return err; 407 407 } 408 408 409 - if (WARN_ON(*ctrp)) 410 - return -EIO; 411 - 412 - *ctrp = 1; 413 409 return 0; 414 410 } 415 411 ··· 857 861 goto out; 858 862 } 859 863 if (upperdentry && !d.is_dir) { 860 - unsigned int origin_ctr = 0; 861 - 862 864 /* 863 865 * Lookup copy up origin by decoding origin file handle. 864 866 * We may get a disconnected dentry, which is fine, ··· 867 873 * number - it's the same as if we held a reference 868 874 * to a dentry in lower layer that was moved under us. 869 875 */ 870 - err = ovl_check_origin(ofs, upperdentry, &origin_path, 871 - &origin_ctr); 876 + err = ovl_check_origin(ofs, upperdentry, &origin_path); 872 877 if (err) 873 878 goto out_put_upper; 874 879 ··· 1066 1073 upperredirect = NULL; 1067 1074 goto out_free_oe; 1068 1075 } 1076 + err = ovl_check_metacopy_xattr(upperdentry); 1077 + if (err < 0) 1078 + goto out_free_oe; 1079 + uppermetacopy = err; 1069 1080 } 1070 1081 1071 1082 if (upperdentry || ctr) {
-1
fs/overlayfs/overlayfs.h
··· 483 483 /* copy_up.c */ 484 484 int ovl_copy_up(struct dentry *dentry); 485 485 int ovl_copy_up_with_data(struct dentry *dentry); 486 - int ovl_copy_up_flags(struct dentry *dentry, int flags); 487 486 int ovl_maybe_copy_up(struct dentry *dentry, int flags); 488 487 int ovl_copy_xattr(struct dentry *old, struct dentry *new); 489 488 int ovl_set_attr(struct dentry *upper, struct kstat *stat);
+49 -24
fs/overlayfs/super.c
··· 580 580 } 581 581 } 582 582 583 - /* Workdir is useless in non-upper mount */ 584 - if (!config->upperdir && config->workdir) { 585 - pr_info("option \"workdir=%s\" is useless in a non-upper mount, ignore\n", 586 - config->workdir); 587 - kfree(config->workdir); 588 - config->workdir = NULL; 583 + /* Workdir/index are useless in non-upper mount */ 584 + if (!config->upperdir) { 585 + if (config->workdir) { 586 + pr_info("option \"workdir=%s\" is useless in a non-upper mount, ignore\n", 587 + config->workdir); 588 + kfree(config->workdir); 589 + config->workdir = NULL; 590 + } 591 + if (config->index && index_opt) { 592 + pr_info("option \"index=on\" is useless in a non-upper mount, ignore\n"); 593 + index_opt = false; 594 + } 595 + config->index = false; 589 596 } 590 597 591 598 err = ovl_parse_redirect_mode(config, config->redirect_mode); ··· 629 622 630 623 /* Resolve nfs_export -> index dependency */ 631 624 if (config->nfs_export && !config->index) { 632 - if (nfs_export_opt && index_opt) { 625 + if (!config->upperdir && config->redirect_follow) { 626 + pr_info("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n"); 627 + config->nfs_export = false; 628 + } else if (nfs_export_opt && index_opt) { 633 629 pr_err("conflicting options: nfs_export=on,index=off\n"); 634 630 return -EINVAL; 635 - } 636 - if (index_opt) { 631 + } else if (index_opt) { 637 632 /* 638 633 * There was an explicit index=off that resulted 639 634 * in this conflict. ··· 1361 1352 goto out; 1362 1353 } 1363 1354 1355 + /* index dir will act also as workdir */ 1356 + iput(ofs->workdir_trap); 1357 + ofs->workdir_trap = NULL; 1358 + dput(ofs->workdir); 1359 + ofs->workdir = NULL; 1364 1360 ofs->indexdir = ovl_workdir_create(ofs, OVL_INDEXDIR_NAME, true); 1365 1361 if (ofs->indexdir) { 1362 + ofs->workdir = dget(ofs->indexdir); 1363 + 1366 1364 err = ovl_setup_trap(sb, ofs->indexdir, &ofs->indexdir_trap, 1367 1365 "indexdir"); 1368 1366 if (err) ··· 1411 1395 1412 1396 if (!ofs->config.nfs_export && !ovl_upper_mnt(ofs)) 1413 1397 return true; 1398 + 1399 + /* 1400 + * We allow using single lower with null uuid for index and nfs_export 1401 + * for example to support those features with single lower squashfs. 1402 + * To avoid regressions in setups of overlay with re-formatted lower 1403 + * squashfs, do not allow decoding origin with lower null uuid unless 1404 + * user opted-in to one of the new features that require following the 1405 + * lower inode of non-dir upper. 1406 + */ 1407 + if (!ofs->config.index && !ofs->config.metacopy && !ofs->config.xino && 1408 + uuid_is_null(uuid)) 1409 + return false; 1414 1410 1415 1411 for (i = 0; i < ofs->numfs; i++) { 1416 1412 /* ··· 1521 1493 if (err < 0) 1522 1494 goto out; 1523 1495 1496 + /* 1497 + * Check if lower root conflicts with this overlay layers before 1498 + * checking if it is in-use as upperdir/workdir of "another" 1499 + * mount, because we do not bother to check in ovl_is_inuse() if 1500 + * the upperdir/workdir is in fact in-use by our 1501 + * upperdir/workdir. 1502 + */ 1524 1503 err = ovl_setup_trap(sb, stack[i].dentry, &trap, "lowerdir"); 1525 1504 if (err) 1526 1505 goto out; 1527 1506 1528 1507 if (ovl_is_inuse(stack[i].dentry)) { 1529 1508 err = ovl_report_in_use(ofs, "lowerdir"); 1530 - if (err) 1509 + if (err) { 1510 + iput(trap); 1531 1511 goto out; 1512 + } 1532 1513 } 1533 1514 1534 1515 mnt = clone_private_mount(&stack[i]); ··· 1612 1575 if (!ofs->config.upperdir && numlower == 1) { 1613 1576 pr_err("at least 2 lowerdir are needed while upperdir nonexistent\n"); 1614 1577 return ERR_PTR(-EINVAL); 1615 - } else if (!ofs->config.upperdir && ofs->config.nfs_export && 1616 - ofs->config.redirect_follow) { 1617 - pr_warn("NFS export requires \"redirect_dir=nofollow\" on non-upper mount, falling back to nfs_export=off.\n"); 1618 - ofs->config.nfs_export = false; 1619 1578 } 1620 1579 1621 1580 stack = kcalloc(numlower, sizeof(struct path), GFP_KERNEL); ··· 1875 1842 if (!ovl_upper_mnt(ofs)) 1876 1843 sb->s_flags |= SB_RDONLY; 1877 1844 1878 - if (!(ovl_force_readonly(ofs)) && ofs->config.index) { 1879 - /* index dir will act also as workdir */ 1880 - dput(ofs->workdir); 1881 - ofs->workdir = NULL; 1882 - iput(ofs->workdir_trap); 1883 - ofs->workdir_trap = NULL; 1884 - 1845 + if (!ovl_force_readonly(ofs) && ofs->config.index) { 1885 1846 err = ovl_get_indexdir(sb, ofs, oe, &upperpath); 1886 1847 if (err) 1887 1848 goto out_free_oe; 1888 1849 1889 1850 /* Force r/o mount with no index dir */ 1890 - if (ofs->indexdir) 1891 - ofs->workdir = dget(ofs->indexdir); 1892 - else 1851 + if (!ofs->indexdir) 1893 1852 sb->s_flags |= SB_RDONLY; 1894 1853 } 1895 1854