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