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

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

Pull overlayfs fixes from Miklos Szeredi:
"Fix two regressions in this cycle, and a couple of older bugs"

* tag 'ovl-fixes-5.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs:
ovl: make i_ino consistent with st_ino in more cases
ovl: fix typo in MODULE_PARM_DESC
ovl: fix bogus -Wmaybe-unitialized warning
ovl: don't fail with disconnected lower NFS
ovl: fix wrong flags check in FS_IOC_FS[SG]ETXATTR ioctls

+90 -59
+1 -1
fs/overlayfs/copy_up.c
··· 37 37 } 38 38 39 39 module_param_call(check_copy_up, ovl_ccup_set, ovl_ccup_get, NULL, 0644); 40 - MODULE_PARM_DESC(ovl_check_copy_up, "Obsolete; does nothing"); 40 + MODULE_PARM_DESC(check_copy_up, "Obsolete; does nothing"); 41 41 42 42 int ovl_copy_xattr(struct dentry *old, struct dentry *new) 43 43 {
+1 -1
fs/overlayfs/dir.c
··· 21 21 22 22 static unsigned short ovl_redirect_max = 256; 23 23 module_param_named(redirect_max, ovl_redirect_max, ushort, 0644); 24 - MODULE_PARM_DESC(ovl_redirect_max, 24 + MODULE_PARM_DESC(redirect_max, 25 25 "Maximum length of absolute redirect xattr value"); 26 26 27 27 static int ovl_set_redirect(struct dentry *dentry, bool samedir);
+65 -26
fs/overlayfs/file.c
··· 409 409 return ret; 410 410 } 411 411 412 - static unsigned int ovl_get_inode_flags(struct inode *inode) 413 - { 414 - unsigned int flags = READ_ONCE(inode->i_flags); 415 - unsigned int ovl_iflags = 0; 416 - 417 - if (flags & S_SYNC) 418 - ovl_iflags |= FS_SYNC_FL; 419 - if (flags & S_APPEND) 420 - ovl_iflags |= FS_APPEND_FL; 421 - if (flags & S_IMMUTABLE) 422 - ovl_iflags |= FS_IMMUTABLE_FL; 423 - if (flags & S_NOATIME) 424 - ovl_iflags |= FS_NOATIME_FL; 425 - 426 - return ovl_iflags; 427 - } 428 - 429 412 static long ovl_ioctl_set_flags(struct file *file, unsigned int cmd, 430 - unsigned long arg) 413 + unsigned long arg, unsigned int iflags) 431 414 { 432 415 long ret; 433 416 struct inode *inode = file_inode(file); 434 - unsigned int flags; 435 - unsigned int old_flags; 417 + unsigned int old_iflags; 436 418 437 419 if (!inode_owner_or_capable(inode)) 438 420 return -EACCES; 439 - 440 - if (get_user(flags, (int __user *) arg)) 441 - return -EFAULT; 442 421 443 422 ret = mnt_want_write_file(file); 444 423 if (ret) ··· 427 448 428 449 /* Check the capability before cred override */ 429 450 ret = -EPERM; 430 - old_flags = ovl_get_inode_flags(inode); 431 - if (((flags ^ old_flags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) && 451 + old_iflags = READ_ONCE(inode->i_flags); 452 + if (((iflags ^ old_iflags) & (S_APPEND | S_IMMUTABLE)) && 432 453 !capable(CAP_LINUX_IMMUTABLE)) 433 454 goto unlock; 434 455 ··· 448 469 449 470 } 450 471 472 + static unsigned int ovl_fsflags_to_iflags(unsigned int flags) 473 + { 474 + unsigned int iflags = 0; 475 + 476 + if (flags & FS_SYNC_FL) 477 + iflags |= S_SYNC; 478 + if (flags & FS_APPEND_FL) 479 + iflags |= S_APPEND; 480 + if (flags & FS_IMMUTABLE_FL) 481 + iflags |= S_IMMUTABLE; 482 + if (flags & FS_NOATIME_FL) 483 + iflags |= S_NOATIME; 484 + 485 + return iflags; 486 + } 487 + 488 + static long ovl_ioctl_set_fsflags(struct file *file, unsigned int cmd, 489 + unsigned long arg) 490 + { 491 + unsigned int flags; 492 + 493 + if (get_user(flags, (int __user *) arg)) 494 + return -EFAULT; 495 + 496 + return ovl_ioctl_set_flags(file, cmd, arg, 497 + ovl_fsflags_to_iflags(flags)); 498 + } 499 + 500 + static unsigned int ovl_fsxflags_to_iflags(unsigned int xflags) 501 + { 502 + unsigned int iflags = 0; 503 + 504 + if (xflags & FS_XFLAG_SYNC) 505 + iflags |= S_SYNC; 506 + if (xflags & FS_XFLAG_APPEND) 507 + iflags |= S_APPEND; 508 + if (xflags & FS_XFLAG_IMMUTABLE) 509 + iflags |= S_IMMUTABLE; 510 + if (xflags & FS_XFLAG_NOATIME) 511 + iflags |= S_NOATIME; 512 + 513 + return iflags; 514 + } 515 + 516 + static long ovl_ioctl_set_fsxflags(struct file *file, unsigned int cmd, 517 + unsigned long arg) 518 + { 519 + struct fsxattr fa; 520 + 521 + memset(&fa, 0, sizeof(fa)); 522 + if (copy_from_user(&fa, (void __user *) arg, sizeof(fa))) 523 + return -EFAULT; 524 + 525 + return ovl_ioctl_set_flags(file, cmd, arg, 526 + ovl_fsxflags_to_iflags(fa.fsx_xflags)); 527 + } 528 + 451 529 static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 452 530 { 453 531 long ret; ··· 516 480 break; 517 481 518 482 case FS_IOC_SETFLAGS: 483 + ret = ovl_ioctl_set_fsflags(file, cmd, arg); 484 + break; 485 + 519 486 case FS_IOC_FSSETXATTR: 520 - ret = ovl_ioctl_set_flags(file, cmd, arg); 487 + ret = ovl_ioctl_set_fsxflags(file, cmd, arg); 521 488 break; 522 489 523 490 default:
+6 -6
fs/overlayfs/inode.c
··· 553 553 int xinobits = ovl_xino_bits(inode->i_sb); 554 554 555 555 /* 556 - * When NFS export is enabled and d_ino is consistent with st_ino 557 - * (samefs or i_ino has enough bits to encode layer), set the same 558 - * value used for d_ino to i_ino, because nfsd readdirplus compares 559 - * d_ino values to i_ino values of child entries. When called from 556 + * When d_ino is consistent with st_ino (samefs or i_ino has enough 557 + * bits to encode layer), set the same value used for st_ino to i_ino, 558 + * so inode number exposed via /proc/locks and a like will be 559 + * consistent with d_ino and st_ino values. An i_ino value inconsistent 560 + * with d_ino also causes nfsd readdirplus to fail. When called from 560 561 * ovl_new_inode(), ino arg is 0, so i_ino will be updated to real 561 562 * upper inode i_ino on ovl_inode_init() or ovl_inode_update(). 562 563 */ 563 - if (inode->i_sb->s_export_op && 564 - (ovl_same_sb(inode->i_sb) || xinobits)) { 564 + if (ovl_same_sb(inode->i_sb) || xinobits) { 565 565 inode->i_ino = ino; 566 566 if (xinobits && fsid && !(ino >> (64 - xinobits))) 567 567 inode->i_ino |= (unsigned long)fsid << (64 - xinobits);
+17 -25
fs/overlayfs/super.c
··· 31 31 32 32 static bool ovl_redirect_dir_def = IS_ENABLED(CONFIG_OVERLAY_FS_REDIRECT_DIR); 33 33 module_param_named(redirect_dir, ovl_redirect_dir_def, bool, 0644); 34 - MODULE_PARM_DESC(ovl_redirect_dir_def, 34 + MODULE_PARM_DESC(redirect_dir, 35 35 "Default to on or off for the redirect_dir feature"); 36 36 37 37 static bool ovl_redirect_always_follow = 38 38 IS_ENABLED(CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW); 39 39 module_param_named(redirect_always_follow, ovl_redirect_always_follow, 40 40 bool, 0644); 41 - MODULE_PARM_DESC(ovl_redirect_always_follow, 41 + MODULE_PARM_DESC(redirect_always_follow, 42 42 "Follow redirects even if redirect_dir feature is turned off"); 43 43 44 44 static bool ovl_index_def = IS_ENABLED(CONFIG_OVERLAY_FS_INDEX); 45 45 module_param_named(index, ovl_index_def, bool, 0644); 46 - MODULE_PARM_DESC(ovl_index_def, 46 + MODULE_PARM_DESC(index, 47 47 "Default to on or off for the inodes index feature"); 48 48 49 49 static bool ovl_nfs_export_def = IS_ENABLED(CONFIG_OVERLAY_FS_NFS_EXPORT); 50 50 module_param_named(nfs_export, ovl_nfs_export_def, bool, 0644); 51 - MODULE_PARM_DESC(ovl_nfs_export_def, 51 + MODULE_PARM_DESC(nfs_export, 52 52 "Default to on or off for the NFS export feature"); 53 53 54 54 static bool ovl_xino_auto_def = IS_ENABLED(CONFIG_OVERLAY_FS_XINO_AUTO); 55 55 module_param_named(xino_auto, ovl_xino_auto_def, bool, 0644); 56 - MODULE_PARM_DESC(ovl_xino_auto_def, 56 + MODULE_PARM_DESC(xino_auto, 57 57 "Auto enable xino feature"); 58 58 59 59 static void ovl_entry_stack_free(struct ovl_entry *oe) ··· 66 66 67 67 static bool ovl_metacopy_def = IS_ENABLED(CONFIG_OVERLAY_FS_METACOPY); 68 68 module_param_named(metacopy, ovl_metacopy_def, bool, 0644); 69 - MODULE_PARM_DESC(ovl_metacopy_def, 69 + MODULE_PARM_DESC(metacopy, 70 70 "Default to on or off for the metadata only copy up feature"); 71 71 72 72 static void ovl_dentry_release(struct dentry *dentry) ··· 995 995 int err; 996 996 997 997 trap = ovl_get_trap_inode(sb, dir); 998 - err = PTR_ERR(trap); 999 - if (IS_ERR(trap)) { 998 + err = PTR_ERR_OR_ZERO(trap); 999 + if (err) { 1000 1000 if (err == -ELOOP) 1001 1001 pr_err("overlayfs: conflicting %s path\n", name); 1002 1002 return err; ··· 1471 1471 * Check if this layer root is a descendant of: 1472 1472 * - another layer of this overlayfs instance 1473 1473 * - upper/work dir of any overlayfs instance 1474 - * - a disconnected dentry (detached root) 1475 1474 */ 1476 1475 static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, 1477 1476 const char *name) 1478 1477 { 1479 - struct dentry *next, *parent; 1480 - bool is_root = false; 1478 + struct dentry *next = dentry, *parent; 1481 1479 int err = 0; 1482 1480 1483 - if (!dentry || dentry == dentry->d_sb->s_root) 1481 + if (!dentry) 1484 1482 return 0; 1485 1483 1486 - next = dget(dentry); 1487 - /* Walk back ancestors to fs root (inclusive) looking for traps */ 1488 - do { 1489 - parent = dget_parent(next); 1490 - is_root = (parent == next); 1484 + parent = dget_parent(next); 1485 + 1486 + /* Walk back ancestors to root (inclusive) looking for traps */ 1487 + while (!err && parent != next) { 1491 1488 if (ovl_is_inuse(parent)) { 1492 1489 err = -EBUSY; 1493 1490 pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n", ··· 1493 1496 err = -ELOOP; 1494 1497 pr_err("overlayfs: overlapping %s path\n", name); 1495 1498 } 1496 - dput(next); 1497 1499 next = parent; 1498 - } while (!err && !is_root); 1499 - 1500 - /* Did we really walk to fs root or found a detached root? */ 1501 - if (!err && next != dentry->d_sb->s_root) { 1502 - err = -ESTALE; 1503 - pr_err("overlayfs: disconnected %s path\n", name); 1500 + parent = dget_parent(next); 1501 + dput(next); 1504 1502 } 1505 1503 1506 - dput(next); 1504 + dput(parent); 1507 1505 1508 1506 return err; 1509 1507 }