^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) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/pseudo_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/proc_ns.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/magic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/user_namespace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/nsfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static struct vfsmount *nsfs_mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static long ns_ioctl(struct file *filp, unsigned int ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) unsigned long arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) static const struct file_operations ns_file_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) .llseek = no_llseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .unlocked_ioctl = ns_ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ns_ops->name, inode->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static void ns_prune_dentry(struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) if (inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct ns_common *ns = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) atomic_long_set(&ns->stashed, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) const struct dentry_operations ns_dentry_operations =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .d_prune = ns_prune_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .d_delete = always_delete_dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .d_dname = ns_dname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static void nsfs_evict(struct inode *inode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct ns_common *ns = inode->i_private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) clear_inode(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) ns->ops->put(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static int __ns_get_path(struct path *path, struct ns_common *ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct vfsmount *mnt = nsfs_mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned long d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) d = atomic_long_read(&ns->stashed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (!d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) goto slow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) dentry = (struct dentry *)d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!lockref_get_not_dead(&dentry->d_lockref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) goto slow;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) ns->ops->put(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) got_it:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) path->mnt = mntget(mnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) path->dentry = dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) slow:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) inode = new_inode_pseudo(mnt->mnt_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!inode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) ns->ops->put(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) inode->i_ino = ns->inum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) inode->i_flags |= S_IMMUTABLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) inode->i_mode = S_IFREG | S_IRUGO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) inode->i_fop = &ns_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) inode->i_private = ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) dentry = d_alloc_anon(mnt->mnt_sb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (!dentry) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) d_instantiate(dentry, inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) dentry->d_fsdata = (void *)ns->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) d_delete(dentry); /* make sure ->d_prune() does nothing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dput(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto got_it;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int ns_get_path_cb(struct path *path, ns_get_path_helper_t *ns_get_cb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) void *private_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) struct ns_common *ns = ns_get_cb(private_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = __ns_get_path(path, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) } while (ret == -EAGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct ns_get_path_task_args {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) const struct proc_ns_operations *ns_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct task_struct *task;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static struct ns_common *ns_get_path_task(void *private_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct ns_get_path_task_args *args = private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return args->ns_ops->get(args->task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int ns_get_path(struct path *path, struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) const struct proc_ns_operations *ns_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) struct ns_get_path_task_args args = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .ns_ops = ns_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .task = task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) return ns_get_path_cb(path, ns_get_path_task, &args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) int open_related_ns(struct ns_common *ns,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct ns_common *(*get_ns)(struct ns_common *ns))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct path path = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct file *f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) fd = get_unused_fd_flags(O_CLOEXEC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (fd < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct ns_common *relative;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) relative = get_ns(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (IS_ERR(relative)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) put_unused_fd(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return PTR_ERR(relative);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) err = __ns_get_path(&path, relative);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) } while (err == -EAGAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) put_unused_fd(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) f = dentry_open(&path, O_RDONLY, current_cred());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) path_put(&path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (IS_ERR(f)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) put_unused_fd(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) fd = PTR_ERR(f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) fd_install(fd, f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) EXPORT_SYMBOL_GPL(open_related_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static long ns_ioctl(struct file *filp, unsigned int ioctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) unsigned long arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct user_namespace *user_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct ns_common *ns = get_proc_ns(file_inode(filp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) uid_t __user *argp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) uid_t uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) switch (ioctl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) case NS_GET_USERNS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return open_related_ns(ns, ns_get_owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) case NS_GET_PARENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!ns->ops->get_parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return open_related_ns(ns, ns->ops->get_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) case NS_GET_NSTYPE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return ns->ops->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) case NS_GET_OWNER_UID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (ns->ops->type != CLONE_NEWUSER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) user_ns = container_of(ns, struct user_namespace, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) argp = (uid_t __user *) arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) uid = from_kuid_munged(current_user_ns(), user_ns->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) return put_user(uid, argp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return -ENOTTY;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) int ns_get_name(char *buf, size_t size, struct task_struct *task,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) const struct proc_ns_operations *ns_ops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct ns_common *ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) int res = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) ns = ns_ops->get(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (ns) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) name = ns_ops->real_ns_name ? : ns_ops->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) res = snprintf(buf, size, "%s:[%u]", name, ns->inum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) ns_ops->put(ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) bool proc_ns_file(const struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return file->f_op == &ns_file_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct file *proc_ns_fget(int fd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct file *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) file = fget(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (!file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return ERR_PTR(-EBADF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (file->f_op != &ns_file_operations)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto out_invalid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) out_invalid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) fput(file);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * ns_match() - Returns true if current namespace matches dev/ino provided.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * @ns_common: current ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * @dev: dev_t from nsfs that will be matched against current nsfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * @ino: ino_t from nsfs that will be matched against current nsfs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * Return: true if dev and ino matches the current nsfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) bool ns_match(const struct ns_common *ns, dev_t dev, ino_t ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return (ns->inum == ino) && (nsfs_mnt->mnt_sb->s_dev == dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static int nsfs_show_path(struct seq_file *seq, struct dentry *dentry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) struct inode *inode = d_inode(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) seq_printf(seq, "%s:[%lu]", ns_ops->name, inode->i_ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) static const struct super_operations nsfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .statfs = simple_statfs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .evict_inode = nsfs_evict,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .show_path = nsfs_show_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int nsfs_init_fs_context(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) struct pseudo_fs_context *ctx = init_pseudo(fc, NSFS_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (!ctx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) ctx->ops = &nsfs_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ctx->dops = &ns_dentry_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static struct file_system_type nsfs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .name = "nsfs",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) .init_fs_context = nsfs_init_fs_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .kill_sb = kill_anon_super,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) void __init nsfs_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) nsfs_mnt = kern_mount(&nsfs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) if (IS_ERR(nsfs_mnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) panic("can't set nsfs up\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) nsfs_mnt->mnt_sb->s_flags &= ~SB_NOUSER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }