1e149ed2bSAl Viro #include <linux/mount.h> 2e149ed2bSAl Viro #include <linux/file.h> 3e149ed2bSAl Viro #include <linux/fs.h> 4e149ed2bSAl Viro #include <linux/proc_ns.h> 5e149ed2bSAl Viro #include <linux/magic.h> 6e149ed2bSAl Viro #include <linux/ktime.h> 7e149ed2bSAl Viro 8e149ed2bSAl Viro static struct vfsmount *nsfs_mnt; 9e149ed2bSAl Viro 10e149ed2bSAl Viro static const struct file_operations ns_file_operations = { 11e149ed2bSAl Viro .llseek = no_llseek, 12e149ed2bSAl Viro }; 13e149ed2bSAl Viro 14e149ed2bSAl Viro static char *ns_dname(struct dentry *dentry, char *buffer, int buflen) 15e149ed2bSAl Viro { 16e149ed2bSAl Viro struct inode *inode = dentry->d_inode; 17e149ed2bSAl Viro const struct proc_ns_operations *ns_ops = dentry->d_fsdata; 18e149ed2bSAl Viro 19e149ed2bSAl Viro return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]", 20e149ed2bSAl Viro ns_ops->name, inode->i_ino); 21e149ed2bSAl Viro } 22e149ed2bSAl Viro 23e149ed2bSAl Viro static void ns_prune_dentry(struct dentry *dentry) 24e149ed2bSAl Viro { 25e149ed2bSAl Viro struct inode *inode = dentry->d_inode; 26e149ed2bSAl Viro if (inode) { 27e149ed2bSAl Viro struct ns_common *ns = inode->i_private; 28e149ed2bSAl Viro atomic_long_set(&ns->stashed, 0); 29e149ed2bSAl Viro } 30e149ed2bSAl Viro } 31e149ed2bSAl Viro 32e149ed2bSAl Viro const struct dentry_operations ns_dentry_operations = 33e149ed2bSAl Viro { 34e149ed2bSAl Viro .d_prune = ns_prune_dentry, 35e149ed2bSAl Viro .d_delete = always_delete_dentry, 36e149ed2bSAl Viro .d_dname = ns_dname, 37e149ed2bSAl Viro }; 38e149ed2bSAl Viro 39e149ed2bSAl Viro static void nsfs_evict(struct inode *inode) 40e149ed2bSAl Viro { 41e149ed2bSAl Viro struct ns_common *ns = inode->i_private; 42e149ed2bSAl Viro clear_inode(inode); 43e149ed2bSAl Viro ns->ops->put(ns); 44e149ed2bSAl Viro } 45e149ed2bSAl Viro 46e149ed2bSAl Viro void *ns_get_path(struct path *path, struct task_struct *task, 47e149ed2bSAl Viro const struct proc_ns_operations *ns_ops) 48e149ed2bSAl Viro { 49e149ed2bSAl Viro struct vfsmount *mnt = mntget(nsfs_mnt); 50e149ed2bSAl Viro struct qstr qname = { .name = "", }; 51e149ed2bSAl Viro struct dentry *dentry; 52e149ed2bSAl Viro struct inode *inode; 53e149ed2bSAl Viro struct ns_common *ns; 54e149ed2bSAl Viro unsigned long d; 55e149ed2bSAl Viro 56e149ed2bSAl Viro again: 57e149ed2bSAl Viro ns = ns_ops->get(task); 58e149ed2bSAl Viro if (!ns) { 59e149ed2bSAl Viro mntput(mnt); 60e149ed2bSAl Viro return ERR_PTR(-ENOENT); 61e149ed2bSAl Viro } 62e149ed2bSAl Viro rcu_read_lock(); 63e149ed2bSAl Viro d = atomic_long_read(&ns->stashed); 64e149ed2bSAl Viro if (!d) 65e149ed2bSAl Viro goto slow; 66e149ed2bSAl Viro dentry = (struct dentry *)d; 67e149ed2bSAl Viro if (!lockref_get_not_dead(&dentry->d_lockref)) 68e149ed2bSAl Viro goto slow; 69e149ed2bSAl Viro rcu_read_unlock(); 70e149ed2bSAl Viro ns_ops->put(ns); 71e149ed2bSAl Viro got_it: 72e149ed2bSAl Viro path->mnt = mnt; 73e149ed2bSAl Viro path->dentry = dentry; 74e149ed2bSAl Viro return NULL; 75e149ed2bSAl Viro slow: 76e149ed2bSAl Viro rcu_read_unlock(); 77e149ed2bSAl Viro inode = new_inode_pseudo(mnt->mnt_sb); 78e149ed2bSAl Viro if (!inode) { 79e149ed2bSAl Viro ns_ops->put(ns); 80e149ed2bSAl Viro mntput(mnt); 81e149ed2bSAl Viro return ERR_PTR(-ENOMEM); 82e149ed2bSAl Viro } 83e149ed2bSAl Viro inode->i_ino = ns->inum; 84e149ed2bSAl Viro inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; 85e149ed2bSAl Viro inode->i_flags |= S_IMMUTABLE; 86e149ed2bSAl Viro inode->i_mode = S_IFREG | S_IRUGO; 87e149ed2bSAl Viro inode->i_fop = &ns_file_operations; 88e149ed2bSAl Viro inode->i_private = ns; 89e149ed2bSAl Viro 90e149ed2bSAl Viro dentry = d_alloc_pseudo(mnt->mnt_sb, &qname); 91e149ed2bSAl Viro if (!dentry) { 92e149ed2bSAl Viro iput(inode); 93e149ed2bSAl Viro mntput(mnt); 94e149ed2bSAl Viro return ERR_PTR(-ENOMEM); 95e149ed2bSAl Viro } 96e149ed2bSAl Viro d_instantiate(dentry, inode); 97e149ed2bSAl Viro dentry->d_fsdata = (void *)ns_ops; 98e149ed2bSAl Viro d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry); 99e149ed2bSAl Viro if (d) { 100e149ed2bSAl Viro d_delete(dentry); /* make sure ->d_prune() does nothing */ 101e149ed2bSAl Viro dput(dentry); 102e149ed2bSAl Viro cpu_relax(); 103e149ed2bSAl Viro goto again; 104e149ed2bSAl Viro } 105e149ed2bSAl Viro goto got_it; 106e149ed2bSAl Viro } 107e149ed2bSAl Viro 108e149ed2bSAl Viro int ns_get_name(char *buf, size_t size, struct task_struct *task, 109e149ed2bSAl Viro const struct proc_ns_operations *ns_ops) 110e149ed2bSAl Viro { 111e149ed2bSAl Viro struct ns_common *ns; 112e149ed2bSAl Viro int res = -ENOENT; 113e149ed2bSAl Viro ns = ns_ops->get(task); 114e149ed2bSAl Viro if (ns) { 115e149ed2bSAl Viro res = snprintf(buf, size, "%s:[%u]", ns_ops->name, ns->inum); 116e149ed2bSAl Viro ns_ops->put(ns); 117e149ed2bSAl Viro } 118e149ed2bSAl Viro return res; 119e149ed2bSAl Viro } 120e149ed2bSAl Viro 121e149ed2bSAl Viro struct file *proc_ns_fget(int fd) 122e149ed2bSAl Viro { 123e149ed2bSAl Viro struct file *file; 124e149ed2bSAl Viro 125e149ed2bSAl Viro file = fget(fd); 126e149ed2bSAl Viro if (!file) 127e149ed2bSAl Viro return ERR_PTR(-EBADF); 128e149ed2bSAl Viro 129e149ed2bSAl Viro if (file->f_op != &ns_file_operations) 130e149ed2bSAl Viro goto out_invalid; 131e149ed2bSAl Viro 132e149ed2bSAl Viro return file; 133e149ed2bSAl Viro 134e149ed2bSAl Viro out_invalid: 135e149ed2bSAl Viro fput(file); 136e149ed2bSAl Viro return ERR_PTR(-EINVAL); 137e149ed2bSAl Viro } 138e149ed2bSAl Viro 139e149ed2bSAl Viro static const struct super_operations nsfs_ops = { 140e149ed2bSAl Viro .statfs = simple_statfs, 141e149ed2bSAl Viro .evict_inode = nsfs_evict, 142e149ed2bSAl Viro }; 143e149ed2bSAl Viro static struct dentry *nsfs_mount(struct file_system_type *fs_type, 144e149ed2bSAl Viro int flags, const char *dev_name, void *data) 145e149ed2bSAl Viro { 146e149ed2bSAl Viro return mount_pseudo(fs_type, "nsfs:", &nsfs_ops, 147e149ed2bSAl Viro &ns_dentry_operations, NSFS_MAGIC); 148e149ed2bSAl Viro } 149e149ed2bSAl Viro static struct file_system_type nsfs = { 150e149ed2bSAl Viro .name = "nsfs", 151e149ed2bSAl Viro .mount = nsfs_mount, 152e149ed2bSAl Viro .kill_sb = kill_anon_super, 153e149ed2bSAl Viro }; 154e149ed2bSAl Viro 155e149ed2bSAl Viro void __init nsfs_init(void) 156e149ed2bSAl Viro { 157e149ed2bSAl Viro nsfs_mnt = kern_mount(&nsfs); 158e149ed2bSAl Viro if (IS_ERR(nsfs_mnt)) 159e149ed2bSAl Viro panic("can't set nsfs up\n"); 160e149ed2bSAl Viro nsfs_mnt->mnt_sb->s_flags &= ~MS_NOUSER; 161e149ed2bSAl Viro } 162