1 // SPDX-License-Identifier: GPL-2.0
3 * fs/proc_namespace.c - handling of /proc/<pid>/{mounts,mountinfo,mountstats}
5 * In fact, that's a piece of procfs; it's *almost* isolated from
6 * the rest of fs/proc, but has rather close relationships with
7 * fs/namespace.c, thus here instead of fs/proc
10 #include <linux/mnt_namespace.h>
11 #include <linux/nsproxy.h>
12 #include <linux/security.h>
13 #include <linux/fs_struct.h>
14 #include <linux/sched/task.h>
16 #include "proc/internal.h" /* only for get_proc_task() in ->open() */
21 static __poll_t
mounts_poll(struct file
*file
, poll_table
*wait
)
23 struct seq_file
*m
= file
->private_data
;
24 struct proc_mounts
*p
= m
->private;
25 struct mnt_namespace
*ns
= p
->ns
;
26 __poll_t res
= EPOLLIN
| EPOLLRDNORM
;
29 poll_wait(file
, &p
->ns
->poll
, wait
);
31 event
= READ_ONCE(ns
->event
);
32 if (m
->poll_event
!= event
) {
33 m
->poll_event
= event
;
34 res
|= EPOLLERR
| EPOLLPRI
;
45 static int show_sb_opts(struct seq_file
*m
, struct super_block
*sb
)
47 static const struct proc_fs_opts fs_opts
[] = {
48 { SB_SYNCHRONOUS
, ",sync" },
49 { SB_DIRSYNC
, ",dirsync" },
50 { SB_MANDLOCK
, ",mand" },
51 { SB_LAZYTIME
, ",lazytime" },
54 const struct proc_fs_opts
*fs_infop
;
56 for (fs_infop
= fs_opts
; fs_infop
->flag
; fs_infop
++) {
57 if (sb
->s_flags
& fs_infop
->flag
)
58 seq_puts(m
, fs_infop
->str
);
61 return security_sb_show_options(m
, sb
);
64 static void show_mnt_opts(struct seq_file
*m
, struct vfsmount
*mnt
)
66 static const struct proc_fs_opts mnt_opts
[] = {
67 { MNT_NOSUID
, ",nosuid" },
68 { MNT_NODEV
, ",nodev" },
69 { MNT_NOEXEC
, ",noexec" },
70 { MNT_NOATIME
, ",noatime" },
71 { MNT_NODIRATIME
, ",nodiratime" },
72 { MNT_RELATIME
, ",relatime" },
73 { MNT_NOSYMFOLLOW
, ",nosymfollow" },
76 const struct proc_fs_opts
*fs_infop
;
78 for (fs_infop
= mnt_opts
; fs_infop
->flag
; fs_infop
++) {
79 if (mnt
->mnt_flags
& fs_infop
->flag
)
80 seq_puts(m
, fs_infop
->str
);
83 if (is_idmapped_mnt(mnt
))
84 seq_puts(m
, ",idmapped");
87 static inline void mangle(struct seq_file
*m
, const char *s
)
89 seq_escape(m
, s
, " \t\n\\#");
92 static void show_type(struct seq_file
*m
, struct super_block
*sb
)
94 mangle(m
, sb
->s_type
->name
);
97 mangle(m
, sb
->s_subtype
);
101 static int show_vfsmnt(struct seq_file
*m
, struct vfsmount
*mnt
)
103 struct proc_mounts
*p
= m
->private;
104 struct mount
*r
= real_mount(mnt
);
105 struct path mnt_path
= { .dentry
= mnt
->mnt_root
, .mnt
= mnt
};
106 struct super_block
*sb
= mnt_path
.dentry
->d_sb
;
109 if (sb
->s_op
->show_devname
) {
110 err
= sb
->s_op
->show_devname(m
, mnt_path
.dentry
);
114 mangle(m
, r
->mnt_devname
? r
->mnt_devname
: "none");
117 /* mountpoints outside of chroot jail will give SEQ_SKIP on this */
118 err
= seq_path_root(m
, &mnt_path
, &p
->root
, " \t\n\\");
123 seq_puts(m
, __mnt_is_readonly(mnt
) ? " ro" : " rw");
124 err
= show_sb_opts(m
, sb
);
127 show_mnt_opts(m
, mnt
);
128 if (sb
->s_op
->show_options
)
129 err
= sb
->s_op
->show_options(m
, mnt_path
.dentry
);
130 seq_puts(m
, " 0 0\n");
135 static int show_mountinfo(struct seq_file
*m
, struct vfsmount
*mnt
)
137 struct proc_mounts
*p
= m
->private;
138 struct mount
*r
= real_mount(mnt
);
139 struct super_block
*sb
= mnt
->mnt_sb
;
140 struct path mnt_path
= { .dentry
= mnt
->mnt_root
, .mnt
= mnt
};
143 seq_printf(m
, "%i %i %u:%u ", r
->mnt_id
, r
->mnt_parent
->mnt_id
,
144 MAJOR(sb
->s_dev
), MINOR(sb
->s_dev
));
145 if (sb
->s_op
->show_path
) {
146 err
= sb
->s_op
->show_path(m
, mnt
->mnt_root
);
150 seq_dentry(m
, mnt
->mnt_root
, " \t\n\\");
154 /* mountpoints outside of chroot jail will give SEQ_SKIP on this */
155 err
= seq_path_root(m
, &mnt_path
, &p
->root
, " \t\n\\");
159 seq_puts(m
, mnt
->mnt_flags
& MNT_READONLY
? " ro" : " rw");
160 show_mnt_opts(m
, mnt
);
162 /* Tagged fields ("foo:X" or "bar") */
163 if (IS_MNT_SHARED(r
))
164 seq_printf(m
, " shared:%i", r
->mnt_group_id
);
165 if (IS_MNT_SLAVE(r
)) {
166 int master
= r
->mnt_master
->mnt_group_id
;
167 int dom
= get_dominating_id(r
, &p
->root
);
168 seq_printf(m
, " master:%i", master
);
169 if (dom
&& dom
!= master
)
170 seq_printf(m
, " propagate_from:%i", dom
);
172 if (IS_MNT_UNBINDABLE(r
))
173 seq_puts(m
, " unbindable");
175 /* Filesystem specific data */
179 if (sb
->s_op
->show_devname
) {
180 err
= sb
->s_op
->show_devname(m
, mnt
->mnt_root
);
184 mangle(m
, r
->mnt_devname
? r
->mnt_devname
: "none");
186 seq_puts(m
, sb_rdonly(sb
) ? " ro" : " rw");
187 err
= show_sb_opts(m
, sb
);
190 if (sb
->s_op
->show_options
)
191 err
= sb
->s_op
->show_options(m
, mnt
->mnt_root
);
197 static int show_vfsstat(struct seq_file
*m
, struct vfsmount
*mnt
)
199 struct proc_mounts
*p
= m
->private;
200 struct mount
*r
= real_mount(mnt
);
201 struct path mnt_path
= { .dentry
= mnt
->mnt_root
, .mnt
= mnt
};
202 struct super_block
*sb
= mnt_path
.dentry
->d_sb
;
206 if (sb
->s_op
->show_devname
) {
207 seq_puts(m
, "device ");
208 err
= sb
->s_op
->show_devname(m
, mnt_path
.dentry
);
212 if (r
->mnt_devname
) {
213 seq_puts(m
, "device ");
214 mangle(m
, r
->mnt_devname
);
216 seq_puts(m
, "no device");
220 seq_puts(m
, " mounted on ");
221 /* mountpoints outside of chroot jail will give SEQ_SKIP on this */
222 err
= seq_path_root(m
, &mnt_path
, &p
->root
, " \t\n\\");
227 /* file system type */
228 seq_puts(m
, "with fstype ");
231 /* optional statistics */
232 if (sb
->s_op
->show_stats
) {
234 err
= sb
->s_op
->show_stats(m
, mnt_path
.dentry
);
242 static int mounts_open_common(struct inode
*inode
, struct file
*file
,
243 int (*show
)(struct seq_file
*, struct vfsmount
*))
245 struct task_struct
*task
= get_proc_task(inode
);
247 struct mnt_namespace
*ns
= NULL
;
249 struct proc_mounts
*p
;
258 if (!nsp
|| !nsp
->mnt_ns
) {
260 put_task_struct(task
);
267 put_task_struct(task
);
271 get_fs_root(task
->fs
, &root
);
273 put_task_struct(task
);
275 ret
= seq_open_private(file
, &mounts_op
, sizeof(struct proc_mounts
));
279 m
= file
->private_data
;
280 m
->poll_event
= ns
->event
;
286 INIT_LIST_HEAD(&p
->cursor
.mnt_list
);
287 p
->cursor
.mnt
.mnt_flags
= MNT_CURSOR
;
299 static int mounts_release(struct inode
*inode
, struct file
*file
)
301 struct seq_file
*m
= file
->private_data
;
302 struct proc_mounts
*p
= m
->private;
304 mnt_cursor_del(p
->ns
, &p
->cursor
);
306 return seq_release_private(inode
, file
);
309 static int mounts_open(struct inode
*inode
, struct file
*file
)
311 return mounts_open_common(inode
, file
, show_vfsmnt
);
314 static int mountinfo_open(struct inode
*inode
, struct file
*file
)
316 return mounts_open_common(inode
, file
, show_mountinfo
);
319 static int mountstats_open(struct inode
*inode
, struct file
*file
)
321 return mounts_open_common(inode
, file
, show_vfsstat
);
324 const struct file_operations proc_mounts_operations
= {
326 .read_iter
= seq_read_iter
,
327 .splice_read
= generic_file_splice_read
,
329 .release
= mounts_release
,
333 const struct file_operations proc_mountinfo_operations
= {
334 .open
= mountinfo_open
,
335 .read_iter
= seq_read_iter
,
336 .splice_read
= generic_file_splice_read
,
338 .release
= mounts_release
,
342 const struct file_operations proc_mountstats_operations
= {
343 .open
= mountstats_open
,
344 .read_iter
= seq_read_iter
,
345 .splice_read
= generic_file_splice_read
,
347 .release
= mounts_release
,