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

Merge tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull mount fixes from Al Viro:
"Several mount-related fixes"

* tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
userns and mnt_idmap leak in open_tree_attr(2)
attach_recursive_mnt(): do not lock the covering tree when sliding something under it
replace collect_mounts()/drop_collected_mounts() with a safer variant

+112 -85
+9
Documentation/filesystems/porting.rst
··· 1249 1249 1250 1250 Calling conventions for ->d_automount() have changed; we should *not* grab 1251 1251 an extra reference to new mount - it should be returned with refcount 1. 1252 + 1253 + --- 1254 + 1255 + collect_mounts()/drop_collected_mounts()/iterate_mounts() are gone now. 1256 + Replacement is collect_paths()/drop_collected_path(), with no special 1257 + iterator needed. Instead of a cloned mount tree, the new interface returns 1258 + an array of struct path, one for each mount collect_mounts() would've 1259 + created. These struct path point to locations in the caller's namespace 1260 + that would be roots of the cloned mounts.
+67 -50
fs/namespace.c
··· 2310 2310 return dst_mnt; 2311 2311 } 2312 2312 2313 - /* Caller should check returned pointer for errors */ 2314 - 2315 - struct vfsmount *collect_mounts(const struct path *path) 2313 + static inline bool extend_array(struct path **res, struct path **to_free, 2314 + unsigned n, unsigned *count, unsigned new_count) 2316 2315 { 2317 - struct mount *tree; 2318 - namespace_lock(); 2319 - if (!check_mnt(real_mount(path->mnt))) 2320 - tree = ERR_PTR(-EINVAL); 2321 - else 2322 - tree = copy_tree(real_mount(path->mnt), path->dentry, 2323 - CL_COPY_ALL | CL_PRIVATE); 2324 - namespace_unlock(); 2325 - if (IS_ERR(tree)) 2326 - return ERR_CAST(tree); 2327 - return &tree->mnt; 2316 + struct path *p; 2317 + 2318 + if (likely(n < *count)) 2319 + return true; 2320 + p = kmalloc_array(new_count, sizeof(struct path), GFP_KERNEL); 2321 + if (p && *count) 2322 + memcpy(p, *res, *count * sizeof(struct path)); 2323 + *count = new_count; 2324 + kfree(*to_free); 2325 + *to_free = *res = p; 2326 + return p; 2327 + } 2328 + 2329 + struct path *collect_paths(const struct path *path, 2330 + struct path *prealloc, unsigned count) 2331 + { 2332 + struct mount *root = real_mount(path->mnt); 2333 + struct mount *child; 2334 + struct path *res = prealloc, *to_free = NULL; 2335 + unsigned n = 0; 2336 + 2337 + guard(rwsem_read)(&namespace_sem); 2338 + 2339 + if (!check_mnt(root)) 2340 + return ERR_PTR(-EINVAL); 2341 + if (!extend_array(&res, &to_free, 0, &count, 32)) 2342 + return ERR_PTR(-ENOMEM); 2343 + res[n++] = *path; 2344 + list_for_each_entry(child, &root->mnt_mounts, mnt_child) { 2345 + if (!is_subdir(child->mnt_mountpoint, path->dentry)) 2346 + continue; 2347 + for (struct mount *m = child; m; m = next_mnt(m, child)) { 2348 + if (!extend_array(&res, &to_free, n, &count, 2 * count)) 2349 + return ERR_PTR(-ENOMEM); 2350 + res[n].mnt = &m->mnt; 2351 + res[n].dentry = m->mnt.mnt_root; 2352 + n++; 2353 + } 2354 + } 2355 + if (!extend_array(&res, &to_free, n, &count, count + 1)) 2356 + return ERR_PTR(-ENOMEM); 2357 + memset(res + n, 0, (count - n) * sizeof(struct path)); 2358 + for (struct path *p = res; p->mnt; p++) 2359 + path_get(p); 2360 + return res; 2361 + } 2362 + 2363 + void drop_collected_paths(struct path *paths, struct path *prealloc) 2364 + { 2365 + for (struct path *p = paths; p->mnt; p++) 2366 + path_put(p); 2367 + if (paths != prealloc) 2368 + kfree(paths); 2328 2369 } 2329 2370 2330 2371 static void free_mnt_ns(struct mnt_namespace *); ··· 2440 2399 /* Make sure we notice when we leak mounts. */ 2441 2400 VFS_WARN_ON_ONCE(!mnt_ns_empty(ns)); 2442 2401 free_mnt_ns(ns); 2443 - } 2444 - 2445 - void drop_collected_mounts(struct vfsmount *mnt) 2446 - { 2447 - namespace_lock(); 2448 - lock_mount_hash(); 2449 - umount_tree(real_mount(mnt), 0); 2450 - unlock_mount_hash(); 2451 - namespace_unlock(); 2452 2402 } 2453 2403 2454 2404 static bool __has_locked_children(struct mount *mnt, struct dentry *dentry) ··· 2542 2510 return &new_mnt->mnt; 2543 2511 } 2544 2512 EXPORT_SYMBOL_GPL(clone_private_mount); 2545 - 2546 - int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, 2547 - struct vfsmount *root) 2548 - { 2549 - struct mount *mnt; 2550 - int res = f(root, arg); 2551 - if (res) 2552 - return res; 2553 - list_for_each_entry(mnt, &real_mount(root)->mnt_list, mnt_list) { 2554 - res = f(&mnt->mnt, arg); 2555 - if (res) 2556 - return res; 2557 - } 2558 - return 0; 2559 - } 2560 2513 2561 2514 static void lock_mnt_tree(struct mount *mnt) 2562 2515 { ··· 2768 2751 hlist_for_each_entry_safe(child, n, &tree_list, mnt_hash) { 2769 2752 struct mount *q; 2770 2753 hlist_del_init(&child->mnt_hash); 2771 - q = __lookup_mnt(&child->mnt_parent->mnt, 2772 - child->mnt_mountpoint); 2773 - if (q) 2774 - mnt_change_mountpoint(child, smp, q); 2775 2754 /* Notice when we are propagating across user namespaces */ 2776 2755 if (child->mnt_parent->mnt_ns->user_ns != user_ns) 2777 2756 lock_mnt_tree(child); 2778 2757 child->mnt.mnt_flags &= ~MNT_LOCKED; 2758 + q = __lookup_mnt(&child->mnt_parent->mnt, 2759 + child->mnt_mountpoint); 2760 + if (q) 2761 + mnt_change_mountpoint(child, smp, q); 2779 2762 commit_tree(child); 2780 2763 } 2781 2764 put_mountpoint(smp); ··· 5307 5290 kattr.kflags |= MOUNT_KATTR_RECURSE; 5308 5291 5309 5292 ret = wants_mount_setattr(uattr, usize, &kattr); 5310 - if (ret < 0) 5311 - return ret; 5312 - 5313 - if (ret) { 5293 + if (ret > 0) { 5314 5294 ret = do_mount_setattr(&file->f_path, &kattr); 5315 - if (ret) 5316 - return ret; 5317 - 5318 5295 finish_mount_kattr(&kattr); 5319 5296 } 5297 + if (ret) 5298 + return ret; 5320 5299 } 5321 5300 5322 5301 fd = get_unused_fd_flags(flags & O_CLOEXEC); ··· 6275 6262 { 6276 6263 if (!refcount_dec_and_test(&ns->ns.count)) 6277 6264 return; 6278 - drop_collected_mounts(&ns->root->mnt); 6265 + namespace_lock(); 6266 + lock_mount_hash(); 6267 + umount_tree(ns->root, 0); 6268 + unlock_mount_hash(); 6269 + namespace_unlock(); 6279 6270 free_mnt_ns(ns); 6280 6271 } 6281 6272
-2
fs/pnode.h
··· 28 28 #define CL_SHARED_TO_SLAVE 0x20 29 29 #define CL_COPY_MNT_NS_FILE 0x40 30 30 31 - #define CL_COPY_ALL (CL_COPY_UNBINDABLE | CL_COPY_MNT_NS_FILE) 32 - 33 31 static inline void set_mnt_shared(struct mount *mnt) 34 32 { 35 33 mnt->mnt.mnt_flags &= ~MNT_SHARED_MASK;
+2 -4
include/linux/mount.h
··· 116 116 extern int may_umount(struct vfsmount *); 117 117 int do_mount(const char *, const char __user *, 118 118 const char *, unsigned long, void *); 119 - extern struct vfsmount *collect_mounts(const struct path *); 120 - extern void drop_collected_mounts(struct vfsmount *); 121 - extern int iterate_mounts(int (*)(struct vfsmount *, void *), void *, 122 - struct vfsmount *); 119 + extern struct path *collect_paths(const struct path *, struct path *, unsigned); 120 + extern void drop_collected_paths(struct path *, struct path *); 123 121 extern void kern_unmount_array(struct vfsmount *mnt[], unsigned int num); 124 122 125 123 extern int cifs_root_data(char **dev, char **opts);
+34 -29
kernel/audit_tree.c
··· 668 668 return 0; 669 669 } 670 670 671 - static int compare_root(struct vfsmount *mnt, void *arg) 672 - { 673 - return inode_to_key(d_backing_inode(mnt->mnt_root)) == 674 - (unsigned long)arg; 675 - } 676 - 677 671 void audit_trim_trees(void) 678 672 { 679 673 struct list_head cursor; ··· 677 683 while (cursor.next != &tree_list) { 678 684 struct audit_tree *tree; 679 685 struct path path; 680 - struct vfsmount *root_mnt; 681 686 struct audit_node *node; 687 + struct path *paths; 688 + struct path array[16]; 682 689 int err; 683 690 684 691 tree = container_of(cursor.next, struct audit_tree, list); ··· 691 696 if (err) 692 697 goto skip_it; 693 698 694 - root_mnt = collect_mounts(&path); 699 + paths = collect_paths(&path, array, 16); 695 700 path_put(&path); 696 - if (IS_ERR(root_mnt)) 701 + if (IS_ERR(paths)) 697 702 goto skip_it; 698 703 699 704 spin_lock(&hash_lock); ··· 701 706 struct audit_chunk *chunk = find_chunk(node); 702 707 /* this could be NULL if the watch is dying else where... */ 703 708 node->index |= 1U<<31; 704 - if (iterate_mounts(compare_root, 705 - (void *)(chunk->key), 706 - root_mnt)) 707 - node->index &= ~(1U<<31); 709 + for (struct path *p = paths; p->dentry; p++) { 710 + struct inode *inode = p->dentry->d_inode; 711 + if (inode_to_key(inode) == chunk->key) { 712 + node->index &= ~(1U<<31); 713 + break; 714 + } 715 + } 708 716 } 709 717 spin_unlock(&hash_lock); 710 718 trim_marked(tree); 711 - drop_collected_mounts(root_mnt); 719 + drop_collected_paths(paths, array); 712 720 skip_it: 713 721 put_tree(tree); 714 722 mutex_lock(&audit_filter_mutex); ··· 740 742 put_tree(tree); 741 743 } 742 744 743 - static int tag_mount(struct vfsmount *mnt, void *arg) 745 + static int tag_mounts(struct path *paths, struct audit_tree *tree) 744 746 { 745 - return tag_chunk(d_backing_inode(mnt->mnt_root), arg); 747 + for (struct path *p = paths; p->dentry; p++) { 748 + int err = tag_chunk(p->dentry->d_inode, tree); 749 + if (err) 750 + return err; 751 + } 752 + return 0; 746 753 } 747 754 748 755 /* ··· 804 801 { 805 802 struct audit_tree *seed = rule->tree, *tree; 806 803 struct path path; 807 - struct vfsmount *mnt; 804 + struct path array[16]; 805 + struct path *paths; 808 806 int err; 809 807 810 808 rule->tree = NULL; ··· 832 828 err = kern_path(tree->pathname, 0, &path); 833 829 if (err) 834 830 goto Err; 835 - mnt = collect_mounts(&path); 831 + paths = collect_paths(&path, array, 16); 836 832 path_put(&path); 837 - if (IS_ERR(mnt)) { 838 - err = PTR_ERR(mnt); 833 + if (IS_ERR(paths)) { 834 + err = PTR_ERR(paths); 839 835 goto Err; 840 836 } 841 837 842 838 get_tree(tree); 843 - err = iterate_mounts(tag_mount, tree, mnt); 844 - drop_collected_mounts(mnt); 839 + err = tag_mounts(paths, tree); 840 + drop_collected_paths(paths, array); 845 841 846 842 if (!err) { 847 843 struct audit_node *node; ··· 876 872 struct list_head cursor, barrier; 877 873 int failed = 0; 878 874 struct path path1, path2; 879 - struct vfsmount *tagged; 875 + struct path array[16]; 876 + struct path *paths; 880 877 int err; 881 878 882 879 err = kern_path(new, 0, &path2); 883 880 if (err) 884 881 return err; 885 - tagged = collect_mounts(&path2); 882 + paths = collect_paths(&path2, array, 16); 886 883 path_put(&path2); 887 - if (IS_ERR(tagged)) 888 - return PTR_ERR(tagged); 884 + if (IS_ERR(paths)) 885 + return PTR_ERR(paths); 889 886 890 887 err = kern_path(old, 0, &path1); 891 888 if (err) { 892 - drop_collected_mounts(tagged); 889 + drop_collected_paths(paths, array); 893 890 return err; 894 891 } 895 892 ··· 919 914 continue; 920 915 } 921 916 922 - failed = iterate_mounts(tag_mount, tree, tagged); 917 + failed = tag_mounts(paths, tree); 923 918 if (failed) { 924 919 put_tree(tree); 925 920 mutex_lock(&audit_filter_mutex); ··· 960 955 list_del(&cursor); 961 956 mutex_unlock(&audit_filter_mutex); 962 957 path_put(&path1); 963 - drop_collected_mounts(tagged); 958 + drop_collected_paths(paths, array); 964 959 return failed; 965 960 } 966 961