18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#include <linux/mount.h>
38c2ecf20Sopenharmony_ci#include <linux/seq_file.h>
48c2ecf20Sopenharmony_ci#include <linux/poll.h>
58c2ecf20Sopenharmony_ci#include <linux/ns_common.h>
68c2ecf20Sopenharmony_ci#include <linux/fs_pin.h>
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_cistruct mnt_namespace {
98c2ecf20Sopenharmony_ci	atomic_t		count;
108c2ecf20Sopenharmony_ci	struct ns_common	ns;
118c2ecf20Sopenharmony_ci	struct mount *	root;
128c2ecf20Sopenharmony_ci	/*
138c2ecf20Sopenharmony_ci	 * Traversal and modification of .list is protected by either
148c2ecf20Sopenharmony_ci	 * - taking namespace_sem for write, OR
158c2ecf20Sopenharmony_ci	 * - taking namespace_sem for read AND taking .ns_lock.
168c2ecf20Sopenharmony_ci	 */
178c2ecf20Sopenharmony_ci	struct list_head	list;
188c2ecf20Sopenharmony_ci	spinlock_t		ns_lock;
198c2ecf20Sopenharmony_ci	struct user_namespace	*user_ns;
208c2ecf20Sopenharmony_ci	struct ucounts		*ucounts;
218c2ecf20Sopenharmony_ci	u64			seq;	/* Sequence number to prevent loops */
228c2ecf20Sopenharmony_ci	wait_queue_head_t poll;
238c2ecf20Sopenharmony_ci	u64 event;
248c2ecf20Sopenharmony_ci	unsigned int		mounts; /* # of mounts in the namespace */
258c2ecf20Sopenharmony_ci	unsigned int		pending_mounts;
268c2ecf20Sopenharmony_ci} __randomize_layout;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistruct mnt_pcp {
298c2ecf20Sopenharmony_ci	int mnt_count;
308c2ecf20Sopenharmony_ci	int mnt_writers;
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistruct mountpoint {
348c2ecf20Sopenharmony_ci	struct hlist_node m_hash;
358c2ecf20Sopenharmony_ci	struct dentry *m_dentry;
368c2ecf20Sopenharmony_ci	struct hlist_head m_list;
378c2ecf20Sopenharmony_ci	int m_count;
388c2ecf20Sopenharmony_ci};
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistruct mount {
418c2ecf20Sopenharmony_ci	struct hlist_node mnt_hash;
428c2ecf20Sopenharmony_ci	struct mount *mnt_parent;
438c2ecf20Sopenharmony_ci	struct dentry *mnt_mountpoint;
448c2ecf20Sopenharmony_ci	struct vfsmount mnt;
458c2ecf20Sopenharmony_ci	union {
468c2ecf20Sopenharmony_ci		struct rcu_head mnt_rcu;
478c2ecf20Sopenharmony_ci		struct llist_node mnt_llist;
488c2ecf20Sopenharmony_ci	};
498c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
508c2ecf20Sopenharmony_ci	struct mnt_pcp __percpu *mnt_pcp;
518c2ecf20Sopenharmony_ci#else
528c2ecf20Sopenharmony_ci	int mnt_count;
538c2ecf20Sopenharmony_ci	int mnt_writers;
548c2ecf20Sopenharmony_ci#endif
558c2ecf20Sopenharmony_ci	struct list_head mnt_mounts;	/* list of children, anchored here */
568c2ecf20Sopenharmony_ci	struct list_head mnt_child;	/* and going through their mnt_child */
578c2ecf20Sopenharmony_ci	struct list_head mnt_instance;	/* mount instance on sb->s_mounts */
588c2ecf20Sopenharmony_ci	const char *mnt_devname;	/* Name of device e.g. /dev/dsk/hda1 */
598c2ecf20Sopenharmony_ci	struct list_head mnt_list;
608c2ecf20Sopenharmony_ci	struct list_head mnt_expire;	/* link in fs-specific expiry list */
618c2ecf20Sopenharmony_ci	struct list_head mnt_share;	/* circular list of shared mounts */
628c2ecf20Sopenharmony_ci	struct list_head mnt_slave_list;/* list of slave mounts */
638c2ecf20Sopenharmony_ci	struct list_head mnt_slave;	/* slave list entry */
648c2ecf20Sopenharmony_ci	struct mount *mnt_master;	/* slave is on master->mnt_slave_list */
658c2ecf20Sopenharmony_ci	struct mnt_namespace *mnt_ns;	/* containing namespace */
668c2ecf20Sopenharmony_ci	struct mountpoint *mnt_mp;	/* where is it mounted */
678c2ecf20Sopenharmony_ci	union {
688c2ecf20Sopenharmony_ci		struct hlist_node mnt_mp_list;	/* list mounts with the same mountpoint */
698c2ecf20Sopenharmony_ci		struct hlist_node mnt_umount;
708c2ecf20Sopenharmony_ci	};
718c2ecf20Sopenharmony_ci	struct list_head mnt_umounting; /* list entry for umount propagation */
728c2ecf20Sopenharmony_ci#ifdef CONFIG_FSNOTIFY
738c2ecf20Sopenharmony_ci	struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
748c2ecf20Sopenharmony_ci	__u32 mnt_fsnotify_mask;
758c2ecf20Sopenharmony_ci#endif
768c2ecf20Sopenharmony_ci	int mnt_id;			/* mount identifier */
778c2ecf20Sopenharmony_ci	int mnt_group_id;		/* peer group identifier */
788c2ecf20Sopenharmony_ci	int mnt_expiry_mark;		/* true if marked for expiry */
798c2ecf20Sopenharmony_ci	struct hlist_head mnt_pins;
808c2ecf20Sopenharmony_ci	struct hlist_head mnt_stuck_children;
818c2ecf20Sopenharmony_ci} __randomize_layout;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic inline struct mount *real_mount(struct vfsmount *mnt)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	return container_of(mnt, struct mount, mnt);
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_cistatic inline int mnt_has_parent(struct mount *mnt)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	return mnt != mnt->mnt_parent;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic inline int is_mounted(struct vfsmount *mnt)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	/* neither detached nor internal? */
988c2ecf20Sopenharmony_ci	return !IS_ERR_OR_NULL(real_mount(mnt)->mnt_ns);
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciextern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *);
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ciextern int __legitimize_mnt(struct vfsmount *, unsigned);
1048c2ecf20Sopenharmony_ciextern bool legitimize_mnt(struct vfsmount *, unsigned);
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_cistatic inline bool __path_is_mountpoint(const struct path *path)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	struct mount *m = __lookup_mnt(path->mnt, path->dentry);
1098c2ecf20Sopenharmony_ci	return m && likely(!(m->mnt.mnt_flags & MNT_SYNC_UMOUNT));
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_ciextern void __detach_mounts(struct dentry *dentry);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_cistatic inline void detach_mounts(struct dentry *dentry)
1158c2ecf20Sopenharmony_ci{
1168c2ecf20Sopenharmony_ci	if (!d_mountpoint(dentry))
1178c2ecf20Sopenharmony_ci		return;
1188c2ecf20Sopenharmony_ci	__detach_mounts(dentry);
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic inline void get_mnt_ns(struct mnt_namespace *ns)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	atomic_inc(&ns->count);
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ciextern seqlock_t mount_lock;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_cistatic inline void lock_mount_hash(void)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	write_seqlock(&mount_lock);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic inline void unlock_mount_hash(void)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	write_sequnlock(&mount_lock);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistruct proc_mounts {
1398c2ecf20Sopenharmony_ci	struct mnt_namespace *ns;
1408c2ecf20Sopenharmony_ci	struct path root;
1418c2ecf20Sopenharmony_ci	int (*show)(struct seq_file *, struct vfsmount *);
1428c2ecf20Sopenharmony_ci	struct mount cursor;
1438c2ecf20Sopenharmony_ci};
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ciextern const struct seq_operations mounts_op;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ciextern bool __is_local_mountpoint(struct dentry *dentry);
1488c2ecf20Sopenharmony_cistatic inline bool is_local_mountpoint(struct dentry *dentry)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	if (!d_mountpoint(dentry))
1518c2ecf20Sopenharmony_ci		return false;
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci	return __is_local_mountpoint(dentry);
1548c2ecf20Sopenharmony_ci}
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistatic inline bool is_anon_ns(struct mnt_namespace *ns)
1578c2ecf20Sopenharmony_ci{
1588c2ecf20Sopenharmony_ci	return ns->seq == 0;
1598c2ecf20Sopenharmony_ci}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ciextern void mnt_cursor_del(struct mnt_namespace *ns, struct mount *cursor);
162