1 #include <linux/mount.h>
2 #include <linux/file.h>
4 #include <linux/proc_ns.h>
5 #include <linux/magic.h>
6 #include <linux/ktime.h>
7 #include <linux/seq_file.h>
8 #include <linux/user_namespace.h>
9 #include <linux/nsfs.h>
11 static struct vfsmount
*nsfs_mnt
;
13 static long ns_ioctl(struct file
*filp
, unsigned int ioctl
,
15 static const struct file_operations ns_file_operations
= {
17 .unlocked_ioctl
= ns_ioctl
,
20 static char *ns_dname(struct dentry
*dentry
, char *buffer
, int buflen
)
22 struct inode
*inode
= d_inode(dentry
);
23 const struct proc_ns_operations
*ns_ops
= dentry
->d_fsdata
;
25 return dynamic_dname(dentry
, buffer
, buflen
, "%s:[%lu]",
26 ns_ops
->name
, inode
->i_ino
);
29 static void ns_prune_dentry(struct dentry
*dentry
)
31 struct inode
*inode
= d_inode(dentry
);
33 struct ns_common
*ns
= inode
->i_private
;
34 atomic_long_set(&ns
->stashed
, 0);
38 const struct dentry_operations ns_dentry_operations
=
40 .d_prune
= ns_prune_dentry
,
41 .d_delete
= always_delete_dentry
,
45 static void nsfs_evict(struct inode
*inode
)
47 struct ns_common
*ns
= inode
->i_private
;
52 static void *__ns_get_path(struct path
*path
, struct ns_common
*ns
)
54 struct vfsmount
*mnt
= nsfs_mnt
;
55 struct qstr qname
= { .name
= "", };
56 struct dentry
*dentry
;
61 d
= atomic_long_read(&ns
->stashed
);
64 dentry
= (struct dentry
*)d
;
65 if (!lockref_get_not_dead(&dentry
->d_lockref
))
70 path
->mnt
= mntget(mnt
);
71 path
->dentry
= dentry
;
75 inode
= new_inode_pseudo(mnt
->mnt_sb
);
78 return ERR_PTR(-ENOMEM
);
80 inode
->i_ino
= ns
->inum
;
81 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= current_time(inode
);
82 inode
->i_flags
|= S_IMMUTABLE
;
83 inode
->i_mode
= S_IFREG
| S_IRUGO
;
84 inode
->i_fop
= &ns_file_operations
;
85 inode
->i_private
= ns
;
87 dentry
= d_alloc_pseudo(mnt
->mnt_sb
, &qname
);
90 return ERR_PTR(-ENOMEM
);
92 d_instantiate(dentry
, inode
);
93 dentry
->d_flags
|= DCACHE_RCUACCESS
;
94 dentry
->d_fsdata
= (void *)ns
->ops
;
95 d
= atomic_long_cmpxchg(&ns
->stashed
, 0, (unsigned long)dentry
);
97 d_delete(dentry
); /* make sure ->d_prune() does nothing */
100 return ERR_PTR(-EAGAIN
);
105 void *ns_get_path(struct path
*path
, struct task_struct
*task
,
106 const struct proc_ns_operations
*ns_ops
)
108 struct ns_common
*ns
;
112 ns
= ns_ops
->get(task
);
114 return ERR_PTR(-ENOENT
);
116 ret
= __ns_get_path(path
, ns
);
117 if (IS_ERR(ret
) && PTR_ERR(ret
) == -EAGAIN
)
122 static int open_related_ns(struct ns_common
*ns
,
123 struct ns_common
*(*get_ns
)(struct ns_common
*ns
))
125 struct path path
= {};
130 fd
= get_unused_fd_flags(O_CLOEXEC
);
135 struct ns_common
*relative
;
137 relative
= get_ns(ns
);
138 if (IS_ERR(relative
)) {
140 return PTR_ERR(relative
);
143 err
= __ns_get_path(&path
, relative
);
144 if (IS_ERR(err
) && PTR_ERR(err
) == -EAGAIN
)
153 f
= dentry_open(&path
, O_RDONLY
, current_cred());
164 static long ns_ioctl(struct file
*filp
, unsigned int ioctl
,
167 struct ns_common
*ns
= get_proc_ns(file_inode(filp
));
171 return open_related_ns(ns
, ns_get_owner
);
173 if (!ns
->ops
->get_parent
)
175 return open_related_ns(ns
, ns
->ops
->get_parent
);
181 int ns_get_name(char *buf
, size_t size
, struct task_struct
*task
,
182 const struct proc_ns_operations
*ns_ops
)
184 struct ns_common
*ns
;
186 ns
= ns_ops
->get(task
);
188 res
= snprintf(buf
, size
, "%s:[%u]", ns_ops
->name
, ns
->inum
);
194 struct file
*proc_ns_fget(int fd
)
200 return ERR_PTR(-EBADF
);
202 if (file
->f_op
!= &ns_file_operations
)
209 return ERR_PTR(-EINVAL
);
212 static int nsfs_show_path(struct seq_file
*seq
, struct dentry
*dentry
)
214 struct inode
*inode
= d_inode(dentry
);
215 const struct proc_ns_operations
*ns_ops
= dentry
->d_fsdata
;
217 seq_printf(seq
, "%s:[%lu]", ns_ops
->name
, inode
->i_ino
);
221 static const struct super_operations nsfs_ops
= {
222 .statfs
= simple_statfs
,
223 .evict_inode
= nsfs_evict
,
224 .show_path
= nsfs_show_path
,
226 static struct dentry
*nsfs_mount(struct file_system_type
*fs_type
,
227 int flags
, const char *dev_name
, void *data
)
229 return mount_pseudo(fs_type
, "nsfs:", &nsfs_ops
,
230 &ns_dentry_operations
, NSFS_MAGIC
);
232 static struct file_system_type nsfs
= {
235 .kill_sb
= kill_anon_super
,
238 void __init
nsfs_init(void)
240 nsfs_mnt
= kern_mount(&nsfs
);
241 if (IS_ERR(nsfs_mnt
))
242 panic("can't set nsfs up\n");
243 nsfs_mnt
->mnt_sb
->s_flags
&= ~MS_NOUSER
;