1/*
2 * fs/proc_namespace.c - handling of /proc/<pid>/{mounts,mountinfo,mountstats}
3 *
4 * In fact, that's a piece of procfs; it's *almost* isolated from
5 * the rest of fs/proc, but has rather close relationships with
6 * fs/namespace.c, thus here instead of fs/proc
7 *
8 */
9#include <linux/mnt_namespace.h>
10#include <linux/nsproxy.h>
11#include <linux/security.h>
12#include <linux/fs_struct.h>
13#include "proc/internal.h" /* only for get_proc_task() in ->open() */
14
15#include "pnode.h"
16#include "internal.h"
17
18static unsigned mounts_poll(struct file *file, poll_table *wait)
19{
20	struct proc_mounts *p = proc_mounts(file->private_data);
21	struct mnt_namespace *ns = p->ns;
22	unsigned res = POLLIN | POLLRDNORM;
23	int event;
24
25	poll_wait(file, &p->ns->poll, wait);
26
27	event = ACCESS_ONCE(ns->event);
28	if (p->m.poll_event != event) {
29		p->m.poll_event = event;
30		res |= POLLERR | POLLPRI;
31	}
32
33	return res;
34}
35
36struct proc_fs_info {
37	int flag;
38	const char *str;
39};
40
41static int show_sb_opts(struct seq_file *m, struct super_block *sb)
42{
43	static const struct proc_fs_info fs_info[] = {
44		{ MS_SYNCHRONOUS, ",sync" },
45		{ MS_DIRSYNC, ",dirsync" },
46		{ MS_MANDLOCK, ",mand" },
47		{ MS_LAZYTIME, ",lazytime" },
48		{ 0, NULL }
49	};
50	const struct proc_fs_info *fs_infop;
51
52	for (fs_infop = fs_info; fs_infop->flag; fs_infop++) {
53		if (sb->s_flags & fs_infop->flag)
54			seq_puts(m, fs_infop->str);
55	}
56
57	return security_sb_show_options(m, sb);
58}
59
60static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
61{
62	static const struct proc_fs_info mnt_info[] = {
63		{ MNT_NOSUID, ",nosuid" },
64		{ MNT_NODEV, ",nodev" },
65		{ MNT_NOEXEC, ",noexec" },
66		{ MNT_NOATIME, ",noatime" },
67		{ MNT_NODIRATIME, ",nodiratime" },
68		{ MNT_RELATIME, ",relatime" },
69		{ 0, NULL }
70	};
71	const struct proc_fs_info *fs_infop;
72
73	for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) {
74		if (mnt->mnt_flags & fs_infop->flag)
75			seq_puts(m, fs_infop->str);
76	}
77}
78
79static inline void mangle(struct seq_file *m, const char *s)
80{
81	seq_escape(m, s, " \t\n\\");
82}
83
84static void show_type(struct seq_file *m, struct super_block *sb)
85{
86	mangle(m, sb->s_type->name);
87	if (sb->s_subtype && sb->s_subtype[0]) {
88		seq_putc(m, '.');
89		mangle(m, sb->s_subtype);
90	}
91}
92
93static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
94{
95	struct proc_mounts *p = proc_mounts(m);
96	struct mount *r = real_mount(mnt);
97	int err = 0;
98	struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
99	struct super_block *sb = mnt_path.dentry->d_sb;
100
101	if (sb->s_op->show_devname) {
102		err = sb->s_op->show_devname(m, mnt_path.dentry);
103		if (err)
104			goto out;
105	} else {
106		mangle(m, r->mnt_devname ? r->mnt_devname : "none");
107	}
108	seq_putc(m, ' ');
109	/* mountpoints outside of chroot jail will give SEQ_SKIP on this */
110	err = seq_path_root(m, &mnt_path, &p->root, " \t\n\\");
111	if (err)
112		goto out;
113	seq_putc(m, ' ');
114	show_type(m, sb);
115	seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
116	err = show_sb_opts(m, sb);
117	if (err)
118		goto out;
119	show_mnt_opts(m, mnt);
120	if (sb->s_op->show_options)
121		err = sb->s_op->show_options(m, mnt_path.dentry);
122	seq_puts(m, " 0 0\n");
123out:
124	return err;
125}
126
127static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
128{
129	struct proc_mounts *p = proc_mounts(m);
130	struct mount *r = real_mount(mnt);
131	struct super_block *sb = mnt->mnt_sb;
132	struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
133	int err = 0;
134
135	seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
136		   MAJOR(sb->s_dev), MINOR(sb->s_dev));
137	if (sb->s_op->show_path)
138		err = sb->s_op->show_path(m, mnt->mnt_root);
139	else
140		seq_dentry(m, mnt->mnt_root, " \t\n\\");
141	if (err)
142		goto out;
143	seq_putc(m, ' ');
144
145	/* mountpoints outside of chroot jail will give SEQ_SKIP on this */
146	err = seq_path_root(m, &mnt_path, &p->root, " \t\n\\");
147	if (err)
148		goto out;
149
150	seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw");
151	show_mnt_opts(m, mnt);
152
153	/* Tagged fields ("foo:X" or "bar") */
154	if (IS_MNT_SHARED(r))
155		seq_printf(m, " shared:%i", r->mnt_group_id);
156	if (IS_MNT_SLAVE(r)) {
157		int master = r->mnt_master->mnt_group_id;
158		int dom = get_dominating_id(r, &p->root);
159		seq_printf(m, " master:%i", master);
160		if (dom && dom != master)
161			seq_printf(m, " propagate_from:%i", dom);
162	}
163	if (IS_MNT_UNBINDABLE(r))
164		seq_puts(m, " unbindable");
165
166	/* Filesystem specific data */
167	seq_puts(m, " - ");
168	show_type(m, sb);
169	seq_putc(m, ' ');
170	if (sb->s_op->show_devname)
171		err = sb->s_op->show_devname(m, mnt->mnt_root);
172	else
173		mangle(m, r->mnt_devname ? r->mnt_devname : "none");
174	if (err)
175		goto out;
176	seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw");
177	err = show_sb_opts(m, sb);
178	if (err)
179		goto out;
180	if (sb->s_op->show_options)
181		err = sb->s_op->show_options(m, mnt->mnt_root);
182	seq_putc(m, '\n');
183out:
184	return err;
185}
186
187static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
188{
189	struct proc_mounts *p = proc_mounts(m);
190	struct mount *r = real_mount(mnt);
191	struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
192	struct super_block *sb = mnt_path.dentry->d_sb;
193	int err = 0;
194
195	/* device */
196	if (sb->s_op->show_devname) {
197		seq_puts(m, "device ");
198		err = sb->s_op->show_devname(m, mnt_path.dentry);
199		if (err)
200			goto out;
201	} else {
202		if (r->mnt_devname) {
203			seq_puts(m, "device ");
204			mangle(m, r->mnt_devname);
205		} else
206			seq_puts(m, "no device");
207	}
208
209	/* mount point */
210	seq_puts(m, " mounted on ");
211	/* mountpoints outside of chroot jail will give SEQ_SKIP on this */
212	err = seq_path_root(m, &mnt_path, &p->root, " \t\n\\");
213	if (err)
214		goto out;
215	seq_putc(m, ' ');
216
217	/* file system type */
218	seq_puts(m, "with fstype ");
219	show_type(m, sb);
220
221	/* optional statistics */
222	if (sb->s_op->show_stats) {
223		seq_putc(m, ' ');
224		if (!err)
225			err = sb->s_op->show_stats(m, mnt_path.dentry);
226	}
227
228	seq_putc(m, '\n');
229out:
230	return err;
231}
232
233static int mounts_open_common(struct inode *inode, struct file *file,
234			      int (*show)(struct seq_file *, struct vfsmount *))
235{
236	struct task_struct *task = get_proc_task(inode);
237	struct nsproxy *nsp;
238	struct mnt_namespace *ns = NULL;
239	struct path root;
240	struct proc_mounts *p;
241	int ret = -EINVAL;
242
243	if (!task)
244		goto err;
245
246	task_lock(task);
247	nsp = task->nsproxy;
248	if (!nsp || !nsp->mnt_ns) {
249		task_unlock(task);
250		put_task_struct(task);
251		goto err;
252	}
253	ns = nsp->mnt_ns;
254	get_mnt_ns(ns);
255	if (!task->fs) {
256		task_unlock(task);
257		put_task_struct(task);
258		ret = -ENOENT;
259		goto err_put_ns;
260	}
261	get_fs_root(task->fs, &root);
262	task_unlock(task);
263	put_task_struct(task);
264
265	ret = -ENOMEM;
266	p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
267	if (!p)
268		goto err_put_path;
269
270	file->private_data = &p->m;
271	ret = seq_open(file, &mounts_op);
272	if (ret)
273		goto err_free;
274
275	p->ns = ns;
276	p->root = root;
277	p->m.poll_event = ns->event;
278	p->show = show;
279	p->cached_event = ~0ULL;
280
281	return 0;
282
283 err_free:
284	kfree(p);
285 err_put_path:
286	path_put(&root);
287 err_put_ns:
288	put_mnt_ns(ns);
289 err:
290	return ret;
291}
292
293static int mounts_release(struct inode *inode, struct file *file)
294{
295	struct proc_mounts *p = proc_mounts(file->private_data);
296	path_put(&p->root);
297	put_mnt_ns(p->ns);
298	return seq_release(inode, file);
299}
300
301static int mounts_open(struct inode *inode, struct file *file)
302{
303	return mounts_open_common(inode, file, show_vfsmnt);
304}
305
306static int mountinfo_open(struct inode *inode, struct file *file)
307{
308	return mounts_open_common(inode, file, show_mountinfo);
309}
310
311static int mountstats_open(struct inode *inode, struct file *file)
312{
313	return mounts_open_common(inode, file, show_vfsstat);
314}
315
316const struct file_operations proc_mounts_operations = {
317	.open		= mounts_open,
318	.read		= seq_read,
319	.llseek		= seq_lseek,
320	.release	= mounts_release,
321	.poll		= mounts_poll,
322};
323
324const struct file_operations proc_mountinfo_operations = {
325	.open		= mountinfo_open,
326	.read		= seq_read,
327	.llseek		= seq_lseek,
328	.release	= mounts_release,
329	.poll		= mounts_poll,
330};
331
332const struct file_operations proc_mountstats_operations = {
333	.open		= mountstats_open,
334	.read		= seq_read,
335	.llseek		= seq_lseek,
336	.release	= mounts_release,
337};
338