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

hostfs: Fix ephemeral inodes

hostfs creates a new inode for each opened or created file, which
created useless inode allocations and forbade identifying a host file
with a kernel inode.

Fix this uncommon filesystem behavior by tying kernel inodes to host
file's inode and device IDs. Even if the host filesystem inodes may be
recycled, this cannot happen while a file referencing it is opened,
which is the case with hostfs. It should be noted that hostfs inode IDs
may not be unique for the same hostfs superblock because multiple host's
(backed) superblocks may be used.

Delete inodes when dropping them to force backed host's file descriptors
closing.

This enables to entirely remove ARCH_EPHEMERAL_INODES, and then makes
Landlock fully supported by UML. This is very useful for testing
changes.

These changes also factor out and simplify some helpers thanks to the
new hostfs_inode_update() and the hostfs_iget() revamp: read_name(),
hostfs_create(), hostfs_lookup(), hostfs_mknod(), and
hostfs_fill_sb_common().

A following commit with new Landlock tests check this new hostfs inode
consistency.

Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Acked-by: Richard Weinberger <richard@nod.at>
Link: https://lore.kernel.org/r/20230612191430.339153-2-mic@digikod.net
Signed-off-by: Mickaël Salaün <mic@digikod.net>

+109 -116
-7
arch/Kconfig
··· 1188 1188 config ARCH_NO_PREEMPT 1189 1189 bool 1190 1190 1191 - config ARCH_EPHEMERAL_INODES 1192 - def_bool n 1193 - help 1194 - An arch should select this symbol if it doesn't keep track of inode 1195 - instances on its own, but instead relies on something else (e.g. the 1196 - host kernel for an UML kernel). 1197 - 1198 1191 config ARCH_SUPPORTS_RT 1199 1192 bool 1200 1193
-1
arch/um/Kconfig
··· 5 5 config UML 6 6 bool 7 7 default y 8 - select ARCH_EPHEMERAL_INODES 9 8 select ARCH_HAS_FORTIFY_SOURCE 10 9 select ARCH_HAS_GCOV_PROFILE_ALL 11 10 select ARCH_HAS_KCOV
+1
fs/hostfs/hostfs.h
··· 65 65 unsigned long long blocks; 66 66 unsigned int maj; 67 67 unsigned int min; 68 + dev_t dev; 68 69 }; 69 70 70 71 extern int stat_file(const char *path, struct hostfs_stat *p, int fd);
+106 -107
fs/hostfs/hostfs_kern.c
··· 26 26 fmode_t mode; 27 27 struct inode vfs_inode; 28 28 struct mutex open_mutex; 29 + dev_t dev; 29 30 }; 30 31 31 32 static inline struct hostfs_inode_info *HOSTFS_I(struct inode *inode) ··· 183 182 return ERR_PTR(n); 184 183 } 185 184 186 - static struct inode *hostfs_iget(struct super_block *sb) 187 - { 188 - struct inode *inode = new_inode(sb); 189 - if (!inode) 190 - return ERR_PTR(-ENOMEM); 191 - return inode; 192 - } 193 - 194 185 static int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf) 195 186 { 196 187 /* ··· 221 228 return NULL; 222 229 hi->fd = -1; 223 230 hi->mode = 0; 231 + hi->dev = 0; 224 232 inode_init_once(&hi->vfs_inode); 225 233 mutex_init(&hi->open_mutex); 226 234 return &hi->vfs_inode; ··· 234 240 if (HOSTFS_I(inode)->fd != -1) { 235 241 close_file(&HOSTFS_I(inode)->fd); 236 242 HOSTFS_I(inode)->fd = -1; 243 + HOSTFS_I(inode)->dev = 0; 237 244 } 238 245 } 239 246 ··· 260 265 static const struct super_operations hostfs_sbops = { 261 266 .alloc_inode = hostfs_alloc_inode, 262 267 .free_inode = hostfs_free_inode, 268 + .drop_inode = generic_delete_inode, 263 269 .evict_inode = hostfs_evict_inode, 264 270 .statfs = hostfs_statfs, 265 271 .show_options = hostfs_show_options, ··· 508 512 .write_end = hostfs_write_end, 509 513 }; 510 514 511 - static int read_name(struct inode *ino, char *name) 515 + static int hostfs_inode_update(struct inode *ino, const struct hostfs_stat *st) 512 516 { 517 + set_nlink(ino, st->nlink); 518 + i_uid_write(ino, st->uid); 519 + i_gid_write(ino, st->gid); 520 + ino->i_atime = 521 + (struct timespec64){ st->atime.tv_sec, st->atime.tv_nsec }; 522 + ino->i_mtime = 523 + (struct timespec64){ st->mtime.tv_sec, st->mtime.tv_nsec }; 524 + ino->i_ctime = 525 + (struct timespec64){ st->ctime.tv_sec, st->ctime.tv_nsec }; 526 + ino->i_size = st->size; 527 + ino->i_blocks = st->blocks; 528 + return 0; 529 + } 530 + 531 + static int hostfs_inode_set(struct inode *ino, void *data) 532 + { 533 + struct hostfs_stat *st = data; 513 534 dev_t rdev; 514 - struct hostfs_stat st; 515 - int err = stat_file(name, &st, -1); 516 - if (err) 517 - return err; 518 535 519 536 /* Reencode maj and min with the kernel encoding.*/ 520 - rdev = MKDEV(st.maj, st.min); 537 + rdev = MKDEV(st->maj, st->min); 521 538 522 - switch (st.mode & S_IFMT) { 539 + switch (st->mode & S_IFMT) { 523 540 case S_IFLNK: 524 541 ino->i_op = &hostfs_link_iops; 525 542 break; ··· 544 535 case S_IFBLK: 545 536 case S_IFIFO: 546 537 case S_IFSOCK: 547 - init_special_inode(ino, st.mode & S_IFMT, rdev); 538 + init_special_inode(ino, st->mode & S_IFMT, rdev); 548 539 ino->i_op = &hostfs_iops; 549 540 break; 550 541 case S_IFREG: ··· 556 547 return -EIO; 557 548 } 558 549 559 - ino->i_ino = st.ino; 560 - ino->i_mode = st.mode; 561 - set_nlink(ino, st.nlink); 562 - i_uid_write(ino, st.uid); 563 - i_gid_write(ino, st.gid); 564 - ino->i_atime = (struct timespec64){ st.atime.tv_sec, st.atime.tv_nsec }; 565 - ino->i_mtime = (struct timespec64){ st.mtime.tv_sec, st.mtime.tv_nsec }; 566 - ino->i_ctime = (struct timespec64){ st.ctime.tv_sec, st.ctime.tv_nsec }; 567 - ino->i_size = st.size; 568 - ino->i_blocks = st.blocks; 569 - return 0; 550 + HOSTFS_I(ino)->dev = st->dev; 551 + ino->i_ino = st->ino; 552 + ino->i_mode = st->mode; 553 + return hostfs_inode_update(ino, st); 554 + } 555 + 556 + static int hostfs_inode_test(struct inode *inode, void *data) 557 + { 558 + const struct hostfs_stat *st = data; 559 + 560 + return inode->i_ino == st->ino && HOSTFS_I(inode)->dev == st->dev; 561 + } 562 + 563 + static struct inode *hostfs_iget(struct super_block *sb, char *name) 564 + { 565 + struct inode *inode; 566 + struct hostfs_stat st; 567 + int err = stat_file(name, &st, -1); 568 + 569 + if (err) 570 + return ERR_PTR(err); 571 + 572 + inode = iget5_locked(sb, st.ino, hostfs_inode_test, hostfs_inode_set, 573 + &st); 574 + if (!inode) 575 + return ERR_PTR(-ENOMEM); 576 + 577 + if (inode->i_state & I_NEW) { 578 + unlock_new_inode(inode); 579 + } else { 580 + spin_lock(&inode->i_lock); 581 + hostfs_inode_update(inode, &st); 582 + spin_unlock(&inode->i_lock); 583 + } 584 + 585 + return inode; 570 586 } 571 587 572 588 static int hostfs_create(struct mnt_idmap *idmap, struct inode *dir, ··· 599 565 { 600 566 struct inode *inode; 601 567 char *name; 602 - int error, fd; 568 + int fd; 603 569 604 - inode = hostfs_iget(dir->i_sb); 605 - if (IS_ERR(inode)) { 606 - error = PTR_ERR(inode); 607 - goto out; 608 - } 609 - 610 - error = -ENOMEM; 611 570 name = dentry_name(dentry); 612 571 if (name == NULL) 613 - goto out_put; 572 + return -ENOMEM; 614 573 615 574 fd = file_create(name, mode & 0777); 616 - if (fd < 0) 617 - error = fd; 618 - else 619 - error = read_name(inode, name); 575 + if (fd < 0) { 576 + __putname(name); 577 + return fd; 578 + } 620 579 580 + inode = hostfs_iget(dir->i_sb, name); 621 581 __putname(name); 622 - if (error) 623 - goto out_put; 582 + if (IS_ERR(inode)) 583 + return PTR_ERR(inode); 624 584 625 585 HOSTFS_I(inode)->fd = fd; 626 586 HOSTFS_I(inode)->mode = FMODE_READ | FMODE_WRITE; 627 587 d_instantiate(dentry, inode); 628 588 return 0; 629 - 630 - out_put: 631 - iput(inode); 632 - out: 633 - return error; 634 589 } 635 590 636 591 static struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, 637 592 unsigned int flags) 638 593 { 639 - struct inode *inode; 594 + struct inode *inode = NULL; 640 595 char *name; 641 - int err; 642 596 643 - inode = hostfs_iget(ino->i_sb); 644 - if (IS_ERR(inode)) 645 - goto out; 646 - 647 - err = -ENOMEM; 648 597 name = dentry_name(dentry); 649 - if (name) { 650 - err = read_name(inode, name); 651 - __putname(name); 598 + if (name == NULL) 599 + return ERR_PTR(-ENOMEM); 600 + 601 + inode = hostfs_iget(ino->i_sb, name); 602 + __putname(name); 603 + if (IS_ERR(inode)) { 604 + if (PTR_ERR(inode) == -ENOENT) 605 + inode = NULL; 606 + else 607 + return ERR_CAST(inode); 652 608 } 653 - if (err) { 654 - iput(inode); 655 - inode = (err == -ENOENT) ? NULL : ERR_PTR(err); 656 - } 657 - out: 609 + 658 610 return d_splice_alias(inode, dentry); 659 611 } 660 612 ··· 724 704 char *name; 725 705 int err; 726 706 727 - inode = hostfs_iget(dir->i_sb); 728 - if (IS_ERR(inode)) { 729 - err = PTR_ERR(inode); 730 - goto out; 731 - } 732 - 733 - err = -ENOMEM; 734 707 name = dentry_name(dentry); 735 708 if (name == NULL) 736 - goto out_put; 709 + return -ENOMEM; 737 710 738 711 err = do_mknod(name, mode, MAJOR(dev), MINOR(dev)); 739 - if (err) 740 - goto out_free; 712 + if (err) { 713 + __putname(name); 714 + return err; 715 + } 741 716 742 - err = read_name(inode, name); 717 + inode = hostfs_iget(dir->i_sb, name); 743 718 __putname(name); 744 - if (err) 745 - goto out_put; 719 + if (IS_ERR(inode)) 720 + return PTR_ERR(inode); 746 721 747 722 d_instantiate(dentry, inode); 748 723 return 0; 749 - 750 - out_free: 751 - __putname(name); 752 - out_put: 753 - iput(inode); 754 - out: 755 - return err; 756 724 } 757 725 758 726 static int hostfs_rename2(struct mnt_idmap *idmap, ··· 937 929 sb->s_maxbytes = MAX_LFS_FILESIZE; 938 930 err = super_setup_bdi(sb); 939 931 if (err) 940 - goto out; 932 + return err; 941 933 942 934 /* NULL is printed as '(null)' by printf(): avoid that. */ 943 935 if (req_root == NULL) 944 936 req_root = ""; 945 937 946 - err = -ENOMEM; 947 938 sb->s_fs_info = host_root_path = 948 939 kasprintf(GFP_KERNEL, "%s/%s", root_ino, req_root); 949 940 if (host_root_path == NULL) 950 - goto out; 941 + return -ENOMEM; 951 942 952 - root_inode = new_inode(sb); 953 - if (!root_inode) 954 - goto out; 955 - 956 - err = read_name(root_inode, host_root_path); 957 - if (err) 958 - goto out_put; 943 + root_inode = hostfs_iget(sb, host_root_path); 944 + if (IS_ERR(root_inode)) 945 + return PTR_ERR(root_inode); 959 946 960 947 if (S_ISLNK(root_inode->i_mode)) { 961 - char *name = follow_link(host_root_path); 962 - if (IS_ERR(name)) { 963 - err = PTR_ERR(name); 964 - goto out_put; 965 - } 966 - err = read_name(root_inode, name); 948 + char *name; 949 + 950 + iput(root_inode); 951 + name = follow_link(host_root_path); 952 + if (IS_ERR(name)) 953 + return PTR_ERR(name); 954 + 955 + root_inode = hostfs_iget(sb, name); 967 956 kfree(name); 968 - if (err) 969 - goto out_put; 957 + if (IS_ERR(root_inode)) 958 + return PTR_ERR(root_inode); 970 959 } 971 960 972 - err = -ENOMEM; 973 961 sb->s_root = d_make_root(root_inode); 974 962 if (sb->s_root == NULL) 975 - goto out; 963 + return -ENOMEM; 976 964 977 965 return 0; 978 - 979 - out_put: 980 - iput(root_inode); 981 - out: 982 - return err; 983 966 } 984 967 985 968 static struct dentry *hostfs_read_sb(struct file_system_type *type,
+1
fs/hostfs/hostfs_user.c
··· 36 36 p->blocks = buf->st_blocks; 37 37 p->maj = os_major(buf->st_rdev); 38 38 p->min = os_minor(buf->st_rdev); 39 + p->dev = buf->st_dev; 39 40 } 40 41 41 42 int stat_file(const char *path, struct hostfs_stat *p, int fd)
+1 -1
security/landlock/Kconfig
··· 2 2 3 3 config SECURITY_LANDLOCK 4 4 bool "Landlock support" 5 - depends on SECURITY && !ARCH_EPHEMERAL_INODES 5 + depends on SECURITY 6 6 select SECURITY_PATH 7 7 help 8 8 Landlock is a sandboxing mechanism that enables processes to restrict