1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2b2dba1afSAl Viro #include <linux/mount.h> 30226f492SAl Viro #include <linux/seq_file.h> 40226f492SAl Viro #include <linux/poll.h> 5435d5f4bSAl Viro #include <linux/ns_common.h> 687b95ce0SAl Viro #include <linux/fs_pin.h> 70226f492SAl Viro 80226f492SAl Viro struct mnt_namespace { 9435d5f4bSAl Viro struct ns_common ns; 10be08d6d2SAl Viro struct mount * root; 119f6c61f9SMiklos Szeredi /* 129f6c61f9SMiklos Szeredi * Traversal and modification of .list is protected by either 139f6c61f9SMiklos Szeredi * - taking namespace_sem for write, OR 149f6c61f9SMiklos Szeredi * - taking namespace_sem for read AND taking .ns_lock. 159f6c61f9SMiklos Szeredi */ 160226f492SAl Viro struct list_head list; 179f6c61f9SMiklos Szeredi spinlock_t ns_lock; 18771b1371SEric W. Biederman struct user_namespace *user_ns; 19537f7ccbSEric W. Biederman struct ucounts *ucounts; 208823c079SEric W. Biederman u64 seq; /* Sequence number to prevent loops */ 210226f492SAl Viro wait_queue_head_t poll; 22c7999c36SAl Viro u64 event; 23d2921684SEric W. Biederman unsigned int mounts; /* # of mounts in the namespace */ 24d2921684SEric W. Biederman unsigned int pending_mounts; 253859a271SKees Cook } __randomize_layout; 26b2dba1afSAl Viro 2768e8a9feSAl Viro struct mnt_pcp { 2868e8a9feSAl Viro int mnt_count; 2968e8a9feSAl Viro int mnt_writers; 3068e8a9feSAl Viro }; 3168e8a9feSAl Viro 3284d17192SAl Viro struct mountpoint { 330818bf27SAl Viro struct hlist_node m_hash; 3484d17192SAl Viro struct dentry *m_dentry; 350a5eb7c8SEric W. Biederman struct hlist_head m_list; 3684d17192SAl Viro int m_count; 3784d17192SAl Viro }; 3884d17192SAl Viro 397d6fec45SAl Viro struct mount { 4038129a13SAl Viro struct hlist_node mnt_hash; 410714a533SAl Viro struct mount *mnt_parent; 42a73324daSAl Viro struct dentry *mnt_mountpoint; 437d6fec45SAl Viro struct vfsmount mnt; 449ea459e1SAl Viro union { 4548a066e7SAl Viro struct rcu_head mnt_rcu; 469ea459e1SAl Viro struct llist_node mnt_llist; 479ea459e1SAl Viro }; 4868e8a9feSAl Viro #ifdef CONFIG_SMP 4968e8a9feSAl Viro struct mnt_pcp __percpu *mnt_pcp; 5068e8a9feSAl Viro #else 5168e8a9feSAl Viro int mnt_count; 5268e8a9feSAl Viro int mnt_writers; 5368e8a9feSAl Viro #endif 546b41d536SAl Viro struct list_head mnt_mounts; /* list of children, anchored here */ 556b41d536SAl Viro struct list_head mnt_child; /* and going through their mnt_child */ 5639f7c4dbSMiklos Szeredi struct list_head mnt_instance; /* mount instance on sb->s_mounts */ 5752ba1621SAl Viro const char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ 581a4eeaf2SAl Viro struct list_head mnt_list; 596776db3dSAl Viro struct list_head mnt_expire; /* link in fs-specific expiry list */ 606776db3dSAl Viro struct list_head mnt_share; /* circular list of shared mounts */ 616776db3dSAl Viro struct list_head mnt_slave_list;/* list of slave mounts */ 626776db3dSAl Viro struct list_head mnt_slave; /* slave list entry */ 6332301920SAl Viro struct mount *mnt_master; /* slave is on master->mnt_slave_list */ 64143c8c91SAl Viro struct mnt_namespace *mnt_ns; /* containing namespace */ 6584d17192SAl Viro struct mountpoint *mnt_mp; /* where is it mounted */ 6656cbb429SAl Viro union { 670a5eb7c8SEric W. Biederman struct hlist_node mnt_mp_list; /* list mounts with the same mountpoint */ 6856cbb429SAl Viro struct hlist_node mnt_umount; 6956cbb429SAl Viro }; 7099b19d16SEric W. Biederman struct list_head mnt_umounting; /* list entry for umount propagation */ 71c63181e6SAl Viro #ifdef CONFIG_FSNOTIFY 7208991e83SJan Kara struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks; 73c63181e6SAl Viro __u32 mnt_fsnotify_mask; 74c63181e6SAl Viro #endif 7515169fe7SAl Viro int mnt_id; /* mount identifier */ 7615169fe7SAl Viro int mnt_group_id; /* peer group identifier */ 77863d684fSAl Viro int mnt_expiry_mark; /* true if marked for expiry */ 78215752fcSAl Viro struct hlist_head mnt_pins; 7956cbb429SAl Viro struct hlist_head mnt_stuck_children; 803859a271SKees Cook } __randomize_layout; 817d6fec45SAl Viro 82f7a99c5bSAl Viro #define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */ 83f7a99c5bSAl Viro real_mount(struct vfsmount * mnt)847d6fec45SAl Virostatic inline struct mount *real_mount(struct vfsmount *mnt) 857d6fec45SAl Viro { 867d6fec45SAl Viro return container_of(mnt, struct mount, mnt); 877d6fec45SAl Viro } 887d6fec45SAl Viro mnt_has_parent(struct mount * mnt)89676da58dSAl Virostatic inline int mnt_has_parent(struct mount *mnt) 90b2dba1afSAl Viro { 910714a533SAl Viro return mnt != mnt->mnt_parent; 92b2dba1afSAl Viro } 93c7105365SAl Viro is_mounted(struct vfsmount * mnt)94f7a99c5bSAl Virostatic inline int is_mounted(struct vfsmount *mnt) 95f7a99c5bSAl Viro { 96f7a99c5bSAl Viro /* neither detached nor internal? */ 97260a459dSEric W. Biederman return !IS_ERR_OR_NULL(real_mount(mnt)->mnt_ns); 98f7a99c5bSAl Viro } 99f7a99c5bSAl Viro 100474279dcSAl Viro extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *); 1010226f492SAl Viro 102294d71ffSAl Viro extern int __legitimize_mnt(struct vfsmount *, unsigned); 10348a066e7SAl Viro __path_is_mountpoint(const struct path * path)104c6609c0aSIan Kentstatic inline bool __path_is_mountpoint(const struct path *path) 105c6609c0aSIan Kent { 106c6609c0aSIan Kent struct mount *m = __lookup_mnt(path->mnt, path->dentry); 107c6609c0aSIan Kent return m && likely(!(m->mnt.mnt_flags & MNT_SYNC_UMOUNT)); 108c6609c0aSIan Kent } 109c6609c0aSIan Kent 11080b5dce8SEric W. Biederman extern void __detach_mounts(struct dentry *dentry); 11180b5dce8SEric W. Biederman detach_mounts(struct dentry * dentry)11280b5dce8SEric W. Biedermanstatic inline void detach_mounts(struct dentry *dentry) 11380b5dce8SEric W. Biederman { 11480b5dce8SEric W. Biederman if (!d_mountpoint(dentry)) 11580b5dce8SEric W. Biederman return; 11680b5dce8SEric W. Biederman __detach_mounts(dentry); 11780b5dce8SEric W. Biederman } 11880b5dce8SEric W. Biederman get_mnt_ns(struct mnt_namespace * ns)1190226f492SAl Virostatic inline void get_mnt_ns(struct mnt_namespace *ns) 1200226f492SAl Viro { 121*1a7b8969SKirill Tkhai refcount_inc(&ns->ns.count); 1220226f492SAl Viro } 1230226f492SAl Viro 12448a066e7SAl Viro extern seqlock_t mount_lock; 125719ea2fbSAl Viro 1260226f492SAl Viro struct proc_mounts { 1270226f492SAl Viro struct mnt_namespace *ns; 1280226f492SAl Viro struct path root; 1290226f492SAl Viro int (*show)(struct seq_file *, struct vfsmount *); 1309f6c61f9SMiklos Szeredi struct mount cursor; 1310226f492SAl Viro }; 1320226f492SAl Viro 1330226f492SAl Viro extern const struct seq_operations mounts_op; 1347af1364fSEric W. Biederman 1357af1364fSEric W. Biederman extern bool __is_local_mountpoint(struct dentry *dentry); is_local_mountpoint(struct dentry * dentry)1367af1364fSEric W. Biedermanstatic inline bool is_local_mountpoint(struct dentry *dentry) 1377af1364fSEric W. Biederman { 1387af1364fSEric W. Biederman if (!d_mountpoint(dentry)) 1397af1364fSEric W. Biederman return false; 1407af1364fSEric W. Biederman 1417af1364fSEric W. Biederman return __is_local_mountpoint(dentry); 1427af1364fSEric W. Biederman } 14374e83122SAl Viro is_anon_ns(struct mnt_namespace * ns)14474e83122SAl Virostatic inline bool is_anon_ns(struct mnt_namespace *ns) 14574e83122SAl Viro { 14674e83122SAl Viro return ns->seq == 0; 14774e83122SAl Viro } 1489f6c61f9SMiklos Szeredi 1499f6c61f9SMiklos Szeredi extern void mnt_cursor_del(struct mnt_namespace *ns, struct mount *cursor); 150