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
,
24 .compat_ioctl
= compat_ptr_ioctl
,
27 static char *ns_dname(struct dentry
*dentry
, char *buffer
, int buflen
)
29 struct inode
*inode
= d_inode(dentry
);
30 struct ns_common
*ns
= inode
->i_private
;
31 const struct proc_ns_operations
*ns_ops
= ns
->ops
;
33 return dynamic_dname(buffer
, buflen
, "%s:[%lu]",
34 ns_ops
->name
, inode
->i_ino
);
37 const struct dentry_operations ns_dentry_operations
= {
38 .d_delete
= always_delete_dentry
,
40 .d_prune
= stashed_dentry_prune
,
43 static void nsfs_evict(struct inode
*inode
)
45 struct ns_common
*ns
= inode
->i_private
;
50 int ns_get_path_cb(struct path
*path
, ns_get_path_helper_t
*ns_get_cb
,
55 ns
= ns_get_cb(private_data
);
59 return path_from_stashed(&ns
->stashed
, nsfs_mnt
, ns
, path
);
62 struct ns_get_path_task_args
{
63 const struct proc_ns_operations
*ns_ops
;
64 struct task_struct
*task
;
67 static struct ns_common
*ns_get_path_task(void *private_data
)
69 struct ns_get_path_task_args
*args
= private_data
;
71 return args
->ns_ops
->get(args
->task
);
74 int ns_get_path(struct path
*path
, struct task_struct
*task
,
75 const struct proc_ns_operations
*ns_ops
)
77 struct ns_get_path_task_args args
= {
82 return ns_get_path_cb(path
, ns_get_path_task
, &args
);
85 int open_related_ns(struct ns_common
*ns
,
86 struct ns_common
*(*get_ns
)(struct ns_common
*ns
))
88 struct path path
= {};
89 struct ns_common
*relative
;
94 fd
= get_unused_fd_flags(O_CLOEXEC
);
98 relative
= get_ns(ns
);
99 if (IS_ERR(relative
)) {
101 return PTR_ERR(relative
);
104 err
= path_from_stashed(&relative
->stashed
, nsfs_mnt
, relative
, &path
);
110 f
= dentry_open(&path
, O_RDONLY
, current_cred());
120 EXPORT_SYMBOL_GPL(open_related_ns
);
122 static long ns_ioctl(struct file
*filp
, unsigned int ioctl
,
125 struct user_namespace
*user_ns
;
126 struct ns_common
*ns
= get_proc_ns(file_inode(filp
));
132 return open_related_ns(ns
, ns_get_owner
);
134 if (!ns
->ops
->get_parent
)
136 return open_related_ns(ns
, ns
->ops
->get_parent
);
138 return ns
->ops
->type
;
139 case NS_GET_OWNER_UID
:
140 if (ns
->ops
->type
!= CLONE_NEWUSER
)
142 user_ns
= container_of(ns
, struct user_namespace
, ns
);
143 argp
= (uid_t __user
*) arg
;
144 uid
= from_kuid_munged(current_user_ns(), user_ns
->owner
);
145 return put_user(uid
, argp
);
151 int ns_get_name(char *buf
, size_t size
, struct task_struct
*task
,
152 const struct proc_ns_operations
*ns_ops
)
154 struct ns_common
*ns
;
157 ns
= ns_ops
->get(task
);
159 name
= ns_ops
->real_ns_name
? : ns_ops
->name
;
160 res
= snprintf(buf
, size
, "%s:[%u]", name
, ns
->inum
);
166 bool proc_ns_file(const struct file
*file
)
168 return file
->f_op
== &ns_file_operations
;
172 * ns_match() - Returns true if current namespace matches dev/ino provided.
173 * @ns: current namespace
174 * @dev: dev_t from nsfs that will be matched against current nsfs
175 * @ino: ino_t from nsfs that will be matched against current nsfs
177 * Return: true if dev and ino matches the current nsfs.
179 bool ns_match(const struct ns_common
*ns
, dev_t dev
, ino_t ino
)
181 return (ns
->inum
== ino
) && (nsfs_mnt
->mnt_sb
->s_dev
== dev
);
185 static int nsfs_show_path(struct seq_file
*seq
, struct dentry
*dentry
)
187 struct inode
*inode
= d_inode(dentry
);
188 const struct ns_common
*ns
= inode
->i_private
;
189 const struct proc_ns_operations
*ns_ops
= ns
->ops
;
191 seq_printf(seq
, "%s:[%lu]", ns_ops
->name
, inode
->i_ino
);
195 static const struct super_operations nsfs_ops
= {
196 .statfs
= simple_statfs
,
197 .evict_inode
= nsfs_evict
,
198 .show_path
= nsfs_show_path
,
201 static int nsfs_init_inode(struct inode
*inode
, void *data
)
203 struct ns_common
*ns
= data
;
205 inode
->i_private
= data
;
206 inode
->i_mode
|= S_IRUGO
;
207 inode
->i_fop
= &ns_file_operations
;
208 inode
->i_ino
= ns
->inum
;
212 static void nsfs_put_data(void *data
)
214 struct ns_common
*ns
= data
;
218 static const struct stashed_operations nsfs_stashed_ops
= {
219 .init_inode
= nsfs_init_inode
,
220 .put_data
= nsfs_put_data
,
223 static int nsfs_init_fs_context(struct fs_context
*fc
)
225 struct pseudo_fs_context
*ctx
= init_pseudo(fc
, NSFS_MAGIC
);
228 ctx
->ops
= &nsfs_ops
;
229 ctx
->dops
= &ns_dentry_operations
;
230 fc
->s_fs_info
= (void *)&nsfs_stashed_ops
;
234 static struct file_system_type nsfs
= {
236 .init_fs_context
= nsfs_init_fs_context
,
237 .kill_sb
= kill_anon_super
,
240 void __init
nsfs_init(void)
242 nsfs_mnt
= kern_mount(&nsfs
);
243 if (IS_ERR(nsfs_mnt
))
244 panic("can't set nsfs up\n");
245 nsfs_mnt
->mnt_sb
->s_flags
&= ~SB_NOUSER
;