1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/mount.h>
3 #include <linux/pseudo_fs.h>
4 #include <linux/file.h>
6 #include <linux/proc_fs.h>
7 #include <linux/proc_ns.h>
8 #include <linux/magic.h>
9 #include <linux/ktime.h>
10 #include <linux/seq_file.h>
11 #include <linux/user_namespace.h>
12 #include <linux/nsfs.h>
13 #include <linux/uaccess.h>
17 static struct vfsmount
*nsfs_mnt
;
19 static long ns_ioctl(struct file
*filp
, unsigned int ioctl
,
21 static const struct file_operations ns_file_operations
= {
23 .unlocked_ioctl
= ns_ioctl
,
26 static char *ns_dname(struct dentry
*dentry
, char *buffer
, int buflen
)
28 struct inode
*inode
= d_inode(dentry
);
29 const struct proc_ns_operations
*ns_ops
= dentry
->d_fsdata
;
31 return dynamic_dname(dentry
, buffer
, buflen
, "%s:[%lu]",
32 ns_ops
->name
, inode
->i_ino
);
35 static void ns_prune_dentry(struct dentry
*dentry
)
37 struct inode
*inode
= d_inode(dentry
);
39 struct ns_common
*ns
= inode
->i_private
;
40 atomic_long_set(&ns
->stashed
, 0);
44 const struct dentry_operations ns_dentry_operations
=
46 .d_prune
= ns_prune_dentry
,
47 .d_delete
= always_delete_dentry
,
51 static void nsfs_evict(struct inode
*inode
)
53 struct ns_common
*ns
= inode
->i_private
;
58 static void *__ns_get_path(struct path
*path
, struct ns_common
*ns
)
60 struct vfsmount
*mnt
= nsfs_mnt
;
61 struct dentry
*dentry
;
66 d
= atomic_long_read(&ns
->stashed
);
69 dentry
= (struct dentry
*)d
;
70 if (!lockref_get_not_dead(&dentry
->d_lockref
))
75 path
->mnt
= mntget(mnt
);
76 path
->dentry
= dentry
;
80 inode
= new_inode_pseudo(mnt
->mnt_sb
);
83 return ERR_PTR(-ENOMEM
);
85 inode
->i_ino
= ns
->inum
;
86 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= current_time(inode
);
87 inode
->i_flags
|= S_IMMUTABLE
;
88 inode
->i_mode
= S_IFREG
| S_IRUGO
;
89 inode
->i_fop
= &ns_file_operations
;
90 inode
->i_private
= ns
;
92 dentry
= d_alloc_anon(mnt
->mnt_sb
);
95 return ERR_PTR(-ENOMEM
);
97 d_instantiate(dentry
, inode
);
98 dentry
->d_fsdata
= (void *)ns
->ops
;
99 d
= atomic_long_cmpxchg(&ns
->stashed
, 0, (unsigned long)dentry
);
101 d_delete(dentry
); /* make sure ->d_prune() does nothing */
104 return ERR_PTR(-EAGAIN
);
109 void *ns_get_path_cb(struct path
*path
, ns_get_path_helper_t
*ns_get_cb
,
115 struct ns_common
*ns
= ns_get_cb(private_data
);
117 return ERR_PTR(-ENOENT
);
119 ret
= __ns_get_path(path
, ns
);
120 } while (ret
== ERR_PTR(-EAGAIN
));
125 struct ns_get_path_task_args
{
126 const struct proc_ns_operations
*ns_ops
;
127 struct task_struct
*task
;
130 static struct ns_common
*ns_get_path_task(void *private_data
)
132 struct ns_get_path_task_args
*args
= private_data
;
134 return args
->ns_ops
->get(args
->task
);
137 void *ns_get_path(struct path
*path
, struct task_struct
*task
,
138 const struct proc_ns_operations
*ns_ops
)
140 struct ns_get_path_task_args args
= {
145 return ns_get_path_cb(path
, ns_get_path_task
, &args
);
148 int open_related_ns(struct ns_common
*ns
,
149 struct ns_common
*(*get_ns
)(struct ns_common
*ns
))
151 struct path path
= {};
156 fd
= get_unused_fd_flags(O_CLOEXEC
);
161 struct ns_common
*relative
;
163 relative
= get_ns(ns
);
164 if (IS_ERR(relative
)) {
166 return PTR_ERR(relative
);
169 err
= __ns_get_path(&path
, relative
);
170 } while (err
== ERR_PTR(-EAGAIN
));
177 f
= dentry_open(&path
, O_RDONLY
, current_cred());
187 EXPORT_SYMBOL_GPL(open_related_ns
);
189 static long ns_ioctl(struct file
*filp
, unsigned int ioctl
,
192 struct user_namespace
*user_ns
;
193 struct ns_common
*ns
= get_proc_ns(file_inode(filp
));
199 return open_related_ns(ns
, ns_get_owner
);
201 if (!ns
->ops
->get_parent
)
203 return open_related_ns(ns
, ns
->ops
->get_parent
);
205 return ns
->ops
->type
;
206 case NS_GET_OWNER_UID
:
207 if (ns
->ops
->type
!= CLONE_NEWUSER
)
209 user_ns
= container_of(ns
, struct user_namespace
, ns
);
210 argp
= (uid_t __user
*) arg
;
211 uid
= from_kuid_munged(current_user_ns(), user_ns
->owner
);
212 return put_user(uid
, argp
);
218 int ns_get_name(char *buf
, size_t size
, struct task_struct
*task
,
219 const struct proc_ns_operations
*ns_ops
)
221 struct ns_common
*ns
;
224 ns
= ns_ops
->get(task
);
226 name
= ns_ops
->real_ns_name
? : ns_ops
->name
;
227 res
= snprintf(buf
, size
, "%s:[%u]", name
, ns
->inum
);
233 struct file
*proc_ns_fget(int fd
)
239 return ERR_PTR(-EBADF
);
241 if (file
->f_op
!= &ns_file_operations
)
248 return ERR_PTR(-EINVAL
);
251 static int nsfs_show_path(struct seq_file
*seq
, struct dentry
*dentry
)
253 struct inode
*inode
= d_inode(dentry
);
254 const struct proc_ns_operations
*ns_ops
= dentry
->d_fsdata
;
256 seq_printf(seq
, "%s:[%lu]", ns_ops
->name
, inode
->i_ino
);
260 static const struct super_operations nsfs_ops
= {
261 .statfs
= simple_statfs
,
262 .evict_inode
= nsfs_evict
,
263 .show_path
= nsfs_show_path
,
266 static int nsfs_init_fs_context(struct fs_context
*fc
)
268 struct pseudo_fs_context
*ctx
= init_pseudo(fc
, NSFS_MAGIC
);
271 ctx
->ops
= &nsfs_ops
;
272 ctx
->dops
= &ns_dentry_operations
;
276 static struct file_system_type nsfs
= {
278 .init_fs_context
= nsfs_init_fs_context
,
279 .kill_sb
= kill_anon_super
,
282 void __init
nsfs_init(void)
284 nsfs_mnt
= kern_mount(&nsfs
);
285 if (IS_ERR(nsfs_mnt
))
286 panic("can't set nsfs up\n");
287 nsfs_mnt
->mnt_sb
->s_flags
&= ~SB_NOUSER
;