xref: /openbmc/linux/fs/nsfs.c (revision 6a6d6681ac1add9655b7ab5dd0b46b54aeb1b44f)
1  // SPDX-License-Identifier: GPL-2.0
2  #include <linux/mount.h>
3  #include <linux/file.h>
4  #include <linux/fs.h>
5  #include <linux/proc_ns.h>
6  #include <linux/magic.h>
7  #include <linux/ktime.h>
8  #include <linux/seq_file.h>
9  #include <linux/user_namespace.h>
10  #include <linux/nsfs.h>
11  #include <linux/uaccess.h>
12  
13  static struct vfsmount *nsfs_mnt;
14  
15  static long ns_ioctl(struct file *filp, unsigned int ioctl,
16  			unsigned long arg);
17  static const struct file_operations ns_file_operations = {
18  	.llseek		= no_llseek,
19  	.unlocked_ioctl = ns_ioctl,
20  };
21  
22  static char *ns_dname(struct dentry *dentry, char *buffer, int buflen)
23  {
24  	struct inode *inode = d_inode(dentry);
25  	const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
26  
27  	return dynamic_dname(dentry, buffer, buflen, "%s:[%lu]",
28  		ns_ops->name, inode->i_ino);
29  }
30  
31  static void ns_prune_dentry(struct dentry *dentry)
32  {
33  	struct inode *inode = d_inode(dentry);
34  	if (inode) {
35  		struct ns_common *ns = inode->i_private;
36  		atomic_long_set(&ns->stashed, 0);
37  	}
38  }
39  
40  const struct dentry_operations ns_dentry_operations =
41  {
42  	.d_prune	= ns_prune_dentry,
43  	.d_delete	= always_delete_dentry,
44  	.d_dname	= ns_dname,
45  };
46  
47  static void nsfs_evict(struct inode *inode)
48  {
49  	struct ns_common *ns = inode->i_private;
50  	clear_inode(inode);
51  	ns->ops->put(ns);
52  }
53  
54  static void *__ns_get_path(struct path *path, struct ns_common *ns)
55  {
56  	struct vfsmount *mnt = nsfs_mnt;
57  	struct dentry *dentry;
58  	struct inode *inode;
59  	unsigned long d;
60  
61  	rcu_read_lock();
62  	d = atomic_long_read(&ns->stashed);
63  	if (!d)
64  		goto slow;
65  	dentry = (struct dentry *)d;
66  	if (!lockref_get_not_dead(&dentry->d_lockref))
67  		goto slow;
68  	rcu_read_unlock();
69  	ns->ops->put(ns);
70  got_it:
71  	path->mnt = mntget(mnt);
72  	path->dentry = dentry;
73  	return NULL;
74  slow:
75  	rcu_read_unlock();
76  	inode = new_inode_pseudo(mnt->mnt_sb);
77  	if (!inode) {
78  		ns->ops->put(ns);
79  		return ERR_PTR(-ENOMEM);
80  	}
81  	inode->i_ino = ns->inum;
82  	inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
83  	inode->i_flags |= S_IMMUTABLE;
84  	inode->i_mode = S_IFREG | S_IRUGO;
85  	inode->i_fop = &ns_file_operations;
86  	inode->i_private = ns;
87  
88  	dentry = d_alloc_pseudo(mnt->mnt_sb, &empty_name);
89  	if (!dentry) {
90  		iput(inode);
91  		return ERR_PTR(-ENOMEM);
92  	}
93  	d_instantiate(dentry, inode);
94  	dentry->d_flags |= DCACHE_RCUACCESS;
95  	dentry->d_fsdata = (void *)ns->ops;
96  	d = atomic_long_cmpxchg(&ns->stashed, 0, (unsigned long)dentry);
97  	if (d) {
98  		d_delete(dentry);	/* make sure ->d_prune() does nothing */
99  		dput(dentry);
100  		cpu_relax();
101  		return ERR_PTR(-EAGAIN);
102  	}
103  	goto got_it;
104  }
105  
106  void *ns_get_path_cb(struct path *path, ns_get_path_helper_t *ns_get_cb,
107  		     void *private_data)
108  {
109  	struct ns_common *ns;
110  	void *ret;
111  
112  again:
113  	ns = ns_get_cb(private_data);
114  	if (!ns)
115  		return ERR_PTR(-ENOENT);
116  
117  	ret = __ns_get_path(path, ns);
118  	if (IS_ERR(ret) && PTR_ERR(ret) == -EAGAIN)
119  		goto again;
120  	return ret;
121  }
122  
123  struct ns_get_path_task_args {
124  	const struct proc_ns_operations *ns_ops;
125  	struct task_struct *task;
126  };
127  
128  static struct ns_common *ns_get_path_task(void *private_data)
129  {
130  	struct ns_get_path_task_args *args = private_data;
131  
132  	return args->ns_ops->get(args->task);
133  }
134  
135  void *ns_get_path(struct path *path, struct task_struct *task,
136  		  const struct proc_ns_operations *ns_ops)
137  {
138  	struct ns_get_path_task_args args = {
139  		.ns_ops	= ns_ops,
140  		.task	= task,
141  	};
142  
143  	return ns_get_path_cb(path, ns_get_path_task, &args);
144  }
145  
146  int open_related_ns(struct ns_common *ns,
147  		   struct ns_common *(*get_ns)(struct ns_common *ns))
148  {
149  	struct path path = {};
150  	struct file *f;
151  	void *err;
152  	int fd;
153  
154  	fd = get_unused_fd_flags(O_CLOEXEC);
155  	if (fd < 0)
156  		return fd;
157  
158  	while (1) {
159  		struct ns_common *relative;
160  
161  		relative = get_ns(ns);
162  		if (IS_ERR(relative)) {
163  			put_unused_fd(fd);
164  			return PTR_ERR(relative);
165  		}
166  
167  		err = __ns_get_path(&path, relative);
168  		if (IS_ERR(err) && PTR_ERR(err) == -EAGAIN)
169  			continue;
170  		break;
171  	}
172  	if (IS_ERR(err)) {
173  		put_unused_fd(fd);
174  		return PTR_ERR(err);
175  	}
176  
177  	f = dentry_open(&path, O_RDONLY, current_cred());
178  	path_put(&path);
179  	if (IS_ERR(f)) {
180  		put_unused_fd(fd);
181  		fd = PTR_ERR(f);
182  	} else
183  		fd_install(fd, f);
184  
185  	return fd;
186  }
187  EXPORT_SYMBOL_GPL(open_related_ns);
188  
189  static long ns_ioctl(struct file *filp, unsigned int ioctl,
190  			unsigned long arg)
191  {
192  	struct user_namespace *user_ns;
193  	struct ns_common *ns = get_proc_ns(file_inode(filp));
194  	uid_t __user *argp;
195  	uid_t uid;
196  
197  	switch (ioctl) {
198  	case NS_GET_USERNS:
199  		return open_related_ns(ns, ns_get_owner);
200  	case NS_GET_PARENT:
201  		if (!ns->ops->get_parent)
202  			return -EINVAL;
203  		return open_related_ns(ns, ns->ops->get_parent);
204  	case NS_GET_NSTYPE:
205  		return ns->ops->type;
206  	case NS_GET_OWNER_UID:
207  		if (ns->ops->type != CLONE_NEWUSER)
208  			return -EINVAL;
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);
213  	default:
214  		return -ENOTTY;
215  	}
216  }
217  
218  int ns_get_name(char *buf, size_t size, struct task_struct *task,
219  			const struct proc_ns_operations *ns_ops)
220  {
221  	struct ns_common *ns;
222  	int res = -ENOENT;
223  	const char *name;
224  	ns = ns_ops->get(task);
225  	if (ns) {
226  		name = ns_ops->real_ns_name ? : ns_ops->name;
227  		res = snprintf(buf, size, "%s:[%u]", name, ns->inum);
228  		ns_ops->put(ns);
229  	}
230  	return res;
231  }
232  
233  struct file *proc_ns_fget(int fd)
234  {
235  	struct file *file;
236  
237  	file = fget(fd);
238  	if (!file)
239  		return ERR_PTR(-EBADF);
240  
241  	if (file->f_op != &ns_file_operations)
242  		goto out_invalid;
243  
244  	return file;
245  
246  out_invalid:
247  	fput(file);
248  	return ERR_PTR(-EINVAL);
249  }
250  
251  static int nsfs_show_path(struct seq_file *seq, struct dentry *dentry)
252  {
253  	struct inode *inode = d_inode(dentry);
254  	const struct proc_ns_operations *ns_ops = dentry->d_fsdata;
255  
256  	seq_printf(seq, "%s:[%lu]", ns_ops->name, inode->i_ino);
257  	return 0;
258  }
259  
260  static const struct super_operations nsfs_ops = {
261  	.statfs = simple_statfs,
262  	.evict_inode = nsfs_evict,
263  	.show_path = nsfs_show_path,
264  };
265  static struct dentry *nsfs_mount(struct file_system_type *fs_type,
266  			int flags, const char *dev_name, void *data)
267  {
268  	return mount_pseudo(fs_type, "nsfs:", &nsfs_ops,
269  			&ns_dentry_operations, NSFS_MAGIC);
270  }
271  static struct file_system_type nsfs = {
272  	.name = "nsfs",
273  	.mount = nsfs_mount,
274  	.kill_sb = kill_anon_super,
275  };
276  
277  void __init nsfs_init(void)
278  {
279  	nsfs_mnt = kern_mount(&nsfs);
280  	if (IS_ERR(nsfs_mnt))
281  		panic("can't set nsfs up\n");
282  	nsfs_mnt->mnt_sb->s_flags &= ~SB_NOUSER;
283  }
284