b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 2) /*
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 3) * fs/proc_namespace.c - handling of /proc/<pid>/{mounts,mountinfo,mountstats}
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 4) *
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 5) * In fact, that's a piece of procfs; it's *almost* isolated from
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 6) * the rest of fs/proc, but has rather close relationships with
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 7) * fs/namespace.c, thus here instead of fs/proc
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 8) *
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 9) */
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 10) #include <linux/mnt_namespace.h>
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 11) #include <linux/nsproxy.h>
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 12) #include <linux/security.h>
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 13) #include <linux/fs_struct.h>
f719ff9bcee2a (Ingo Molnar 2017-02-06 10:57:33 +0100 14) #include <linux/sched/task.h>
f719ff9bcee2a (Ingo Molnar 2017-02-06 10:57:33 +0100 15)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 16) #include "proc/internal.h" /* only for get_proc_task() in ->open() */
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 17)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 18) #include "pnode.h"
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 19) #include "internal.h"
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 20)
076ccb76e1a6c (Al Viro 2017-07-03 01:02:18 -0400 21) static __poll_t mounts_poll(struct file *file, poll_table *wait)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 22) {
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 23) struct seq_file *m = file->private_data;
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 24) struct proc_mounts *p = m->private;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 25) struct mnt_namespace *ns = p->ns;
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 26) __poll_t res = EPOLLIN | EPOLLRDNORM;
aab407fc5c0ce (Al Viro 2013-09-29 10:59:59 -0400 27) int event;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 28)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 29) poll_wait(file, &p->ns->poll, wait);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 30)
6aa7de059173a (Mark Rutland 2017-10-23 14:07:29 -0700 31) event = READ_ONCE(ns->event);
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 32) if (m->poll_event != event) {
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 33) m->poll_event = event;
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 34) res |= EPOLLERR | EPOLLPRI;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 35) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 36)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 37) return res;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 38) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 39)
1e88c420190be (Alexey Gladkov 2020-04-19 16:10:51 +0200 40) struct proc_fs_opts {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 41) int flag;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 42) const char *str;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 43) };
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 44)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 45) static int show_sb_opts(struct seq_file *m, struct super_block *sb)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 46) {
1e88c420190be (Alexey Gladkov 2020-04-19 16:10:51 +0200 47) static const struct proc_fs_opts fs_opts[] = {
1751e8a6cb935 (Linus Torvalds 2017-11-27 13:05:09 -0800 48) { SB_SYNCHRONOUS, ",sync" },
1751e8a6cb935 (Linus Torvalds 2017-11-27 13:05:09 -0800 49) { SB_DIRSYNC, ",dirsync" },
1751e8a6cb935 (Linus Torvalds 2017-11-27 13:05:09 -0800 50) { SB_MANDLOCK, ",mand" },
1751e8a6cb935 (Linus Torvalds 2017-11-27 13:05:09 -0800 51) { SB_LAZYTIME, ",lazytime" },
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 52) { 0, NULL }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 53) };
1e88c420190be (Alexey Gladkov 2020-04-19 16:10:51 +0200 54) const struct proc_fs_opts *fs_infop;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 55)
1e88c420190be (Alexey Gladkov 2020-04-19 16:10:51 +0200 56) for (fs_infop = fs_opts; fs_infop->flag; fs_infop++) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 57) if (sb->s_flags & fs_infop->flag)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 58) seq_puts(m, fs_infop->str);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 59) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 60)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 61) return security_sb_show_options(m, sb);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 62) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 63)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 64) static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 65) {
1e88c420190be (Alexey Gladkov 2020-04-19 16:10:51 +0200 66) static const struct proc_fs_opts mnt_opts[] = {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 67) { MNT_NOSUID, ",nosuid" },
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 68) { MNT_NODEV, ",nodev" },
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 69) { MNT_NOEXEC, ",noexec" },
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 70) { MNT_NOATIME, ",noatime" },
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 71) { MNT_NODIRATIME, ",nodiratime" },
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 72) { MNT_RELATIME, ",relatime" },
dab741e0e02bd (Mattias Nissler 2020-08-27 11:09:46 -0600 73) { MNT_NOSYMFOLLOW, ",nosymfollow" },
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 74) { 0, NULL }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 75) };
1e88c420190be (Alexey Gladkov 2020-04-19 16:10:51 +0200 76) const struct proc_fs_opts *fs_infop;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 77)
1e88c420190be (Alexey Gladkov 2020-04-19 16:10:51 +0200 78) for (fs_infop = mnt_opts; fs_infop->flag; fs_infop++) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 79) if (mnt->mnt_flags & fs_infop->flag)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 80) seq_puts(m, fs_infop->str);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 81) }
9caccd41541a6 (Christian Brauner 2021-01-21 14:19:54 +0100 82)
9caccd41541a6 (Christian Brauner 2021-01-21 14:19:54 +0100 83) if (mnt_user_ns(mnt) != &init_user_ns)
9caccd41541a6 (Christian Brauner 2021-01-21 14:19:54 +0100 84) seq_puts(m, ",idmapped");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 85) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 86)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 87) static inline void mangle(struct seq_file *m, const char *s)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 88) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 89) seq_escape(m, s, " \t\n\\");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 90) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 91)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 92) static void show_type(struct seq_file *m, struct super_block *sb)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 93) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 94) mangle(m, sb->s_type->name);
c7eb6869632a5 (David Howells 2019-03-25 16:38:31 +0000 95) if (sb->s_subtype) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 96) seq_putc(m, '.');
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 97) mangle(m, sb->s_subtype);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 98) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 99) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 100)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 101) static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 102) {
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 103) struct proc_mounts *p = m->private;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 104) struct mount *r = real_mount(mnt);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 105) struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 106) struct super_block *sb = mnt_path.dentry->d_sb;
5d9f3c7b620f6 (Dmitry V. Levin 2015-11-19 00:57:52 +0300 107) int err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 108)
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 109) if (sb->s_op->show_devname) {
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 110) err = sb->s_op->show_devname(m, mnt_path.dentry);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 111) if (err)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 112) goto out;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 113) } else {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 114) mangle(m, r->mnt_devname ? r->mnt_devname : "none");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 115) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 116) seq_putc(m, ' ');
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 117) /* mountpoints outside of chroot jail will give SEQ_SKIP on this */
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 118) err = seq_path_root(m, &mnt_path, &p->root, " \t\n\\");
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 119) if (err)
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 120) goto out;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 121) seq_putc(m, ' ');
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 122) show_type(m, sb);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 123) seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 124) err = show_sb_opts(m, sb);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 125) if (err)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 126) goto out;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 127) show_mnt_opts(m, mnt);
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 128) if (sb->s_op->show_options)
34c80b1d93e6e (Al Viro 2011-12-08 21:32:45 -0500 129) err = sb->s_op->show_options(m, mnt_path.dentry);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 130) seq_puts(m, " 0 0\n");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 131) out:
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 132) return err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 133) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 134)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 135) static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 136) {
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 137) struct proc_mounts *p = m->private;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 138) struct mount *r = real_mount(mnt);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 139) struct super_block *sb = mnt->mnt_sb;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 140) struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 141) int err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 142)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 143) seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 144) MAJOR(sb->s_dev), MINOR(sb->s_dev));
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 145) if (sb->s_op->show_path) {
a6322de67b58a (Al Viro 2011-12-08 21:37:57 -0500 146) err = sb->s_op->show_path(m, mnt->mnt_root);
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 147) if (err)
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 148) goto out;
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 149) } else {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 150) seq_dentry(m, mnt->mnt_root, " \t\n\\");
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 151) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 152) seq_putc(m, ' ');
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 153)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 154) /* mountpoints outside of chroot jail will give SEQ_SKIP on this */
9ad4dc4f73180 (Dmitry V. Levin 2012-10-17 20:29:36 +0400 155) err = seq_path_root(m, &mnt_path, &p->root, " \t\n\\");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 156) if (err)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 157) goto out;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 158)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 159) seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 160) show_mnt_opts(m, mnt);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 161)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 162) /* Tagged fields ("foo:X" or "bar") */
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 163) if (IS_MNT_SHARED(r))
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 164) seq_printf(m, " shared:%i", r->mnt_group_id);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 165) if (IS_MNT_SLAVE(r)) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 166) int master = r->mnt_master->mnt_group_id;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 167) int dom = get_dominating_id(r, &p->root);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 168) seq_printf(m, " master:%i", master);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 169) if (dom && dom != master)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 170) seq_printf(m, " propagate_from:%i", dom);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 171) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 172) if (IS_MNT_UNBINDABLE(r))
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 173) seq_puts(m, " unbindable");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 174)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 175) /* Filesystem specific data */
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 176) seq_puts(m, " - ");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 177) show_type(m, sb);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 178) seq_putc(m, ' ');
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 179) if (sb->s_op->show_devname) {
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 180) err = sb->s_op->show_devname(m, mnt->mnt_root);
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 181) if (err)
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 182) goto out;
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 183) } else {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 184) mangle(m, r->mnt_devname ? r->mnt_devname : "none");
6ce4bca0adfde (Dmitry V. Levin 2015-11-19 00:58:20 +0300 185) }
bc98a42c1f7d0 (David Howells 2017-07-17 08:45:34 +0100 186) seq_puts(m, sb_rdonly(sb) ? " ro" : " rw");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 187) err = show_sb_opts(m, sb);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 188) if (err)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 189) goto out;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 190) if (sb->s_op->show_options)
34c80b1d93e6e (Al Viro 2011-12-08 21:32:45 -0500 191) err = sb->s_op->show_options(m, mnt->mnt_root);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 192) seq_putc(m, '\n');
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 193) out:
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 194) return err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 195) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 196)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 197) static int show_vfsstat(struct seq_file *m, struct vfsmount *mnt)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 198) {
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 199) struct proc_mounts *p = m->private;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 200) struct mount *r = real_mount(mnt);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 201) struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
64132379d5091 (Al Viro 2011-12-08 20:51:13 -0500 202) struct super_block *sb = mnt_path.dentry->d_sb;
b896fb35ca904 (Dmitry V. Levin 2015-11-19 00:58:32 +0300 203) int err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 204)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 205) /* device */
64132379d5091 (Al Viro 2011-12-08 20:51:13 -0500 206) if (sb->s_op->show_devname) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 207) seq_puts(m, "device ");
d861c630e99fe (Al Viro 2011-12-08 21:32:45 -0500 208) err = sb->s_op->show_devname(m, mnt_path.dentry);
5f8d498d4364f (Dmitry V. Levin 2015-03-19 11:10:54 +0000 209) if (err)
5f8d498d4364f (Dmitry V. Levin 2015-03-19 11:10:54 +0000 210) goto out;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 211) } else {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 212) if (r->mnt_devname) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 213) seq_puts(m, "device ");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 214) mangle(m, r->mnt_devname);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 215) } else
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 216) seq_puts(m, "no device");
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 217) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 218)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 219) /* mount point */
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 220) seq_puts(m, " mounted on ");
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 221) /* mountpoints outside of chroot jail will give SEQ_SKIP on this */
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 222) err = seq_path_root(m, &mnt_path, &p->root, " \t\n\\");
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 223) if (err)
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 224) goto out;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 225) seq_putc(m, ' ');
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 226)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 227) /* file system type */
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 228) seq_puts(m, "with fstype ");
64132379d5091 (Al Viro 2011-12-08 20:51:13 -0500 229) show_type(m, sb);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 230)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 231) /* optional statistics */
64132379d5091 (Al Viro 2011-12-08 20:51:13 -0500 232) if (sb->s_op->show_stats) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 233) seq_putc(m, ' ');
b896fb35ca904 (Dmitry V. Levin 2015-11-19 00:58:32 +0300 234) err = sb->s_op->show_stats(m, mnt_path.dentry);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 235) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 236)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 237) seq_putc(m, '\n');
9d4d65748a5ca (Dmitry V. Levin 2014-12-16 06:59:37 +0300 238) out:
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 239) return err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 240) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 241)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 242) static int mounts_open_common(struct inode *inode, struct file *file,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 243) int (*show)(struct seq_file *, struct vfsmount *))
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 244) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 245) struct task_struct *task = get_proc_task(inode);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 246) struct nsproxy *nsp;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 247) struct mnt_namespace *ns = NULL;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 248) struct path root;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 249) struct proc_mounts *p;
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 250) struct seq_file *m;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 251) int ret = -EINVAL;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 252)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 253) if (!task)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 254) goto err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 255)
728dba3a39c66 (Eric W. Biederman 2014-02-03 19:13:49 -0800 256) task_lock(task);
728dba3a39c66 (Eric W. Biederman 2014-02-03 19:13:49 -0800 257) nsp = task->nsproxy;
3d93116cef306 (Axel Lin 2014-01-23 15:55:44 -0800 258) if (!nsp || !nsp->mnt_ns) {
728dba3a39c66 (Eric W. Biederman 2014-02-03 19:13:49 -0800 259) task_unlock(task);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 260) put_task_struct(task);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 261) goto err;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 262) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 263) ns = nsp->mnt_ns;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 264) get_mnt_ns(ns);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 265) if (!task->fs) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 266) task_unlock(task);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 267) put_task_struct(task);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 268) ret = -ENOENT;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 269) goto err_put_ns;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 270) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 271) get_fs_root(task->fs, &root);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 272) task_unlock(task);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 273) put_task_struct(task);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 274)
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 275) ret = seq_open_private(file, &mounts_op, sizeof(struct proc_mounts));
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 276) if (ret)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 277) goto err_put_path;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 278)
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 279) m = file->private_data;
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 280) m->poll_event = ns->event;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 281)
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 282) p = m->private;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 283) p->ns = ns;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 284) p->root = root;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 285) p->show = show;
9f6c61f96f2d9 (Miklos Szeredi 2020-05-14 16:44:24 +0200 286) INIT_LIST_HEAD(&p->cursor.mnt_list);
9f6c61f96f2d9 (Miklos Szeredi 2020-05-14 16:44:24 +0200 287) p->cursor.mnt.mnt_flags = MNT_CURSOR;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 288)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 289) return 0;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 290)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 291) err_put_path:
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 292) path_put(&root);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 293) err_put_ns:
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 294) put_mnt_ns(ns);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 295) err:
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 296) return ret;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 297) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 298)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 299) static int mounts_release(struct inode *inode, struct file *file)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 300) {
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 301) struct seq_file *m = file->private_data;
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 302) struct proc_mounts *p = m->private;
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 303) path_put(&p->root);
9f6c61f96f2d9 (Miklos Szeredi 2020-05-14 16:44:24 +0200 304) mnt_cursor_del(p->ns, &p->cursor);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 305) put_mnt_ns(p->ns);
ede1bf0dcff2b (Yann Droneaud 2015-06-30 14:57:30 -0700 306) return seq_release_private(inode, file);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 307) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 308)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 309) static int mounts_open(struct inode *inode, struct file *file)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 310) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 311) return mounts_open_common(inode, file, show_vfsmnt);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 312) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 313)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 314) static int mountinfo_open(struct inode *inode, struct file *file)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 315) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 316) return mounts_open_common(inode, file, show_mountinfo);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 317) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 318)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 319) static int mountstats_open(struct inode *inode, struct file *file)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 320) {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 321) return mounts_open_common(inode, file, show_vfsstat);
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 322) }
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 323)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 324) const struct file_operations proc_mounts_operations = {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 325) .open = mounts_open,
14e3e989f6a5d (Linus Torvalds 2020-12-27 10:56:33 -0800 326) .read_iter = seq_read_iter,
14e3e989f6a5d (Linus Torvalds 2020-12-27 10:56:33 -0800 327) .splice_read = generic_file_splice_read,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 328) .llseek = seq_lseek,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 329) .release = mounts_release,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 330) .poll = mounts_poll,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 331) };
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 332)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 333) const struct file_operations proc_mountinfo_operations = {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 334) .open = mountinfo_open,
14e3e989f6a5d (Linus Torvalds 2020-12-27 10:56:33 -0800 335) .read_iter = seq_read_iter,
14e3e989f6a5d (Linus Torvalds 2020-12-27 10:56:33 -0800 336) .splice_read = generic_file_splice_read,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 337) .llseek = seq_lseek,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 338) .release = mounts_release,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 339) .poll = mounts_poll,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 340) };
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 341)
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 342) const struct file_operations proc_mountstats_operations = {
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 343) .open = mountstats_open,
14e3e989f6a5d (Linus Torvalds 2020-12-27 10:56:33 -0800 344) .read_iter = seq_read_iter,
14e3e989f6a5d (Linus Torvalds 2020-12-27 10:56:33 -0800 345) .splice_read = generic_file_splice_read,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 346) .llseek = seq_lseek,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 347) .release = mounts_release,
0226f4923f6c9 (Al Viro 2011-12-06 12:21:54 -0500 348) };