#include <linux/proc_ns.h>
#include <linux/seq_file.h>
#include <linux/user_namespace.h>
#include <linux/uaccess.h>
static struct vfsmount *nsfs_mnt;
static long ns_ioctl(struct file *filp, unsigned int ioctl,
static const struct file_operations ns_file_operations = {
.unlocked_ioctl = ns_ioctl,
static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
struct inode *inode = d_inode(dentry);
const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
ns_ops->name, inode->i_ino);
static void ns_prune_dentry(struct dentry *dentry)
struct inode *inode = d_inode(dentry);
struct ns_common *ns = inode->i_private;
atomic_long_set(&ns->stashed, 0);
const struct dentry_operations ns_dentry_operations =
.d_prune = ns_prune_dentry,
.d_delete = always_delete_dentry,
static void nsfs_evict(struct inode *inode)
struct ns_common *ns = inode->i_private;
static void *__ns_get_path(struct path *path, struct ns_common *ns)
struct vfsmount *mnt = nsfs_mnt;
d = atomic_long_read(&ns->stashed);
dentry = (struct dentry *)d;
if (!lockref_get_not_dead(&dentry->d_lockref))
inode = new_inode_pseudo(mnt->mnt_sb);
inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
inode->i_flags |= S_IMMUTABLE;
inode->i_mode = S_IFREG | S_IRUGO;
inode->i_fop = &ns_file_operations;
dentry = d_alloc_pseudo(mnt->mnt_sb, &empty_name);