1// SPDX-License-Identifier: GPL-2.0
2#ifndef NO_BCACHEFS_FS
3
4#include "bcachefs.h"
5#include "chardev.h"
6#include "dirent.h"
7#include "fs.h"
8#include "fs-common.h"
9#include "fs-ioctl.h"
10#include "quota.h"
11
12#include <linux/compat.h>
13#include <linux/fsnotify.h>
14#include <linux/mount.h>
15#include <linux/namei.h>
16#include <linux/security.h>
17#include <linux/writeback.h>
18
19#define FS_IOC_GOINGDOWN	     _IOR('X', 125, __u32)
20#define FSOP_GOING_FLAGS_DEFAULT	0x0	/* going down */
21#define FSOP_GOING_FLAGS_LOGFLUSH	0x1	/* flush log but not data */
22#define FSOP_GOING_FLAGS_NOLOGFLUSH	0x2	/* don't flush log nor data */
23
24struct flags_set {
25	unsigned		mask;
26	unsigned		flags;
27
28	unsigned		projid;
29
30	bool			set_projinherit;
31	bool			projinherit;
32};
33
34static int bch2_inode_flags_set(struct btree_trans *trans,
35				struct bch_inode_info *inode,
36				struct bch_inode_unpacked *bi,
37				void *p)
38{
39	struct bch_fs *c = inode->v.i_sb->s_fs_info;
40	/*
41	 * We're relying on btree locking here for exclusion with other ioctl
42	 * calls - use the flags in the btree (@bi), not inode->i_flags:
43	 */
44	struct flags_set *s = p;
45	unsigned newflags = s->flags;
46	unsigned oldflags = bi->bi_flags & s->mask;
47
48	if (((newflags ^ oldflags) & (BCH_INODE_append|BCH_INODE_immutable)) &&
49	    !capable(CAP_LINUX_IMMUTABLE))
50		return -EPERM;
51
52	if (!S_ISREG(bi->bi_mode) &&
53	    !S_ISDIR(bi->bi_mode) &&
54	    (newflags & (BCH_INODE_nodump|BCH_INODE_noatime)) != newflags)
55		return -EINVAL;
56
57	if (s->set_projinherit) {
58		bi->bi_fields_set &= ~(1 << Inode_opt_project);
59		bi->bi_fields_set |= ((int) s->projinherit << Inode_opt_project);
60	}
61
62	bi->bi_flags &= ~s->mask;
63	bi->bi_flags |= newflags;
64
65	bi->bi_ctime = timespec_to_bch2_time(c, current_time(&inode->v));
66	return 0;
67}
68
69static int bch2_ioc_getflags(struct bch_inode_info *inode, int __user *arg)
70{
71	unsigned flags = map_flags(bch_flags_to_uflags, inode->ei_inode.bi_flags);
72
73	return put_user(flags, arg);
74}
75
76static int bch2_ioc_setflags(struct bch_fs *c,
77			     struct file *file,
78			     struct bch_inode_info *inode,
79			     void __user *arg)
80{
81	struct flags_set s = { .mask = map_defined(bch_flags_to_uflags) };
82	unsigned uflags;
83	int ret;
84
85	if (get_user(uflags, (int __user *) arg))
86		return -EFAULT;
87
88	s.flags = map_flags_rev(bch_flags_to_uflags, uflags);
89	if (uflags)
90		return -EOPNOTSUPP;
91
92	ret = mnt_want_write_file(file);
93	if (ret)
94		return ret;
95
96	inode_lock(&inode->v);
97	if (!inode_owner_or_capable(file_mnt_idmap(file), &inode->v)) {
98		ret = -EACCES;
99		goto setflags_out;
100	}
101
102	mutex_lock(&inode->ei_update_lock);
103	ret   = bch2_subvol_is_ro(c, inode->ei_subvol) ?:
104		bch2_write_inode(c, inode, bch2_inode_flags_set, &s,
105			       ATTR_CTIME);
106	mutex_unlock(&inode->ei_update_lock);
107
108setflags_out:
109	inode_unlock(&inode->v);
110	mnt_drop_write_file(file);
111	return ret;
112}
113
114static int bch2_ioc_fsgetxattr(struct bch_inode_info *inode,
115			       struct fsxattr __user *arg)
116{
117	struct fsxattr fa = { 0 };
118
119	fa.fsx_xflags = map_flags(bch_flags_to_xflags, inode->ei_inode.bi_flags);
120
121	if (inode->ei_inode.bi_fields_set & (1 << Inode_opt_project))
122		fa.fsx_xflags |= FS_XFLAG_PROJINHERIT;
123
124	fa.fsx_projid = inode->ei_qid.q[QTYP_PRJ];
125
126	if (copy_to_user(arg, &fa, sizeof(fa)))
127		return -EFAULT;
128
129	return 0;
130}
131
132static int fssetxattr_inode_update_fn(struct btree_trans *trans,
133				      struct bch_inode_info *inode,
134				      struct bch_inode_unpacked *bi,
135				      void *p)
136{
137	struct flags_set *s = p;
138
139	if (s->projid != bi->bi_project) {
140		bi->bi_fields_set |= 1U << Inode_opt_project;
141		bi->bi_project = s->projid;
142	}
143
144	return bch2_inode_flags_set(trans, inode, bi, p);
145}
146
147static int bch2_ioc_fssetxattr(struct bch_fs *c,
148			       struct file *file,
149			       struct bch_inode_info *inode,
150			       struct fsxattr __user *arg)
151{
152	struct flags_set s = { .mask = map_defined(bch_flags_to_xflags) };
153	struct fsxattr fa;
154	int ret;
155
156	if (copy_from_user(&fa, arg, sizeof(fa)))
157		return -EFAULT;
158
159	s.set_projinherit = true;
160	s.projinherit = (fa.fsx_xflags & FS_XFLAG_PROJINHERIT) != 0;
161	fa.fsx_xflags &= ~FS_XFLAG_PROJINHERIT;
162
163	s.flags = map_flags_rev(bch_flags_to_xflags, fa.fsx_xflags);
164	if (fa.fsx_xflags)
165		return -EOPNOTSUPP;
166
167	if (fa.fsx_projid >= U32_MAX)
168		return -EINVAL;
169
170	/*
171	 * inode fields accessible via the xattr interface are stored with a +1
172	 * bias, so that 0 means unset:
173	 */
174	s.projid = fa.fsx_projid + 1;
175
176	ret = mnt_want_write_file(file);
177	if (ret)
178		return ret;
179
180	inode_lock(&inode->v);
181	if (!inode_owner_or_capable(file_mnt_idmap(file), &inode->v)) {
182		ret = -EACCES;
183		goto err;
184	}
185
186	mutex_lock(&inode->ei_update_lock);
187	ret   = bch2_subvol_is_ro(c, inode->ei_subvol) ?:
188		bch2_set_projid(c, inode, fa.fsx_projid) ?:
189		bch2_write_inode(c, inode, fssetxattr_inode_update_fn, &s,
190			       ATTR_CTIME);
191	mutex_unlock(&inode->ei_update_lock);
192err:
193	inode_unlock(&inode->v);
194	mnt_drop_write_file(file);
195	return ret;
196}
197
198static int bch2_reinherit_attrs_fn(struct btree_trans *trans,
199				   struct bch_inode_info *inode,
200				   struct bch_inode_unpacked *bi,
201				   void *p)
202{
203	struct bch_inode_info *dir = p;
204
205	return !bch2_reinherit_attrs(bi, &dir->ei_inode);
206}
207
208static int bch2_ioc_reinherit_attrs(struct bch_fs *c,
209				    struct file *file,
210				    struct bch_inode_info *src,
211				    const char __user *name)
212{
213	struct bch_hash_info hash = bch2_hash_info_init(c, &src->ei_inode);
214	struct bch_inode_info *dst;
215	struct inode *vinode = NULL;
216	char *kname = NULL;
217	struct qstr qstr;
218	int ret = 0;
219	subvol_inum inum;
220
221	kname = kmalloc(BCH_NAME_MAX + 1, GFP_KERNEL);
222	if (!kname)
223		return -ENOMEM;
224
225	ret = strncpy_from_user(kname, name, BCH_NAME_MAX);
226	if (unlikely(ret < 0))
227		goto err1;
228
229	qstr.len	= ret;
230	qstr.name	= kname;
231
232	ret = bch2_dirent_lookup(c, inode_inum(src), &hash, &qstr, &inum);
233	if (ret)
234		goto err1;
235
236	vinode = bch2_vfs_inode_get(c, inum);
237	ret = PTR_ERR_OR_ZERO(vinode);
238	if (ret)
239		goto err1;
240
241	dst = to_bch_ei(vinode);
242
243	ret = mnt_want_write_file(file);
244	if (ret)
245		goto err2;
246
247	bch2_lock_inodes(INODE_UPDATE_LOCK, src, dst);
248
249	if (inode_attr_changing(src, dst, Inode_opt_project)) {
250		ret = bch2_fs_quota_transfer(c, dst,
251					     src->ei_qid,
252					     1 << QTYP_PRJ,
253					     KEY_TYPE_QUOTA_PREALLOC);
254		if (ret)
255			goto err3;
256	}
257
258	ret = bch2_write_inode(c, dst, bch2_reinherit_attrs_fn, src, 0);
259err3:
260	bch2_unlock_inodes(INODE_UPDATE_LOCK, src, dst);
261
262	/* return true if we did work */
263	if (ret >= 0)
264		ret = !ret;
265
266	mnt_drop_write_file(file);
267err2:
268	iput(vinode);
269err1:
270	kfree(kname);
271
272	return ret;
273}
274
275static int bch2_ioc_goingdown(struct bch_fs *c, u32 __user *arg)
276{
277	u32 flags;
278	int ret = 0;
279
280	if (!capable(CAP_SYS_ADMIN))
281		return -EPERM;
282
283	if (get_user(flags, arg))
284		return -EFAULT;
285
286	bch_notice(c, "shutdown by ioctl type %u", flags);
287
288	switch (flags) {
289	case FSOP_GOING_FLAGS_DEFAULT:
290		ret = bdev_freeze(c->vfs_sb->s_bdev);
291		if (ret)
292			break;
293		bch2_journal_flush(&c->journal);
294		bch2_fs_emergency_read_only(c);
295		bdev_thaw(c->vfs_sb->s_bdev);
296		break;
297	case FSOP_GOING_FLAGS_LOGFLUSH:
298		bch2_journal_flush(&c->journal);
299		fallthrough;
300	case FSOP_GOING_FLAGS_NOLOGFLUSH:
301		bch2_fs_emergency_read_only(c);
302		break;
303	default:
304		ret = -EINVAL;
305		break;
306	}
307
308	return ret;
309}
310
311static long __bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
312					  struct bch_ioctl_subvolume arg)
313{
314	struct inode *dir;
315	struct bch_inode_info *inode;
316	struct user_namespace *s_user_ns;
317	struct dentry *dst_dentry;
318	struct path src_path, dst_path;
319	int how = LOOKUP_FOLLOW;
320	int error;
321	subvol_inum snapshot_src = { 0 };
322	unsigned lookup_flags = 0;
323	unsigned create_flags = BCH_CREATE_SUBVOL;
324
325	if (arg.flags & ~(BCH_SUBVOL_SNAPSHOT_CREATE|
326			  BCH_SUBVOL_SNAPSHOT_RO))
327		return -EINVAL;
328
329	if (!(arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) &&
330	    (arg.src_ptr ||
331	     (arg.flags & BCH_SUBVOL_SNAPSHOT_RO)))
332		return -EINVAL;
333
334	if (arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE)
335		create_flags |= BCH_CREATE_SNAPSHOT;
336
337	if (arg.flags & BCH_SUBVOL_SNAPSHOT_RO)
338		create_flags |= BCH_CREATE_SNAPSHOT_RO;
339
340	if (arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) {
341		/* sync_inodes_sb enforce s_umount is locked */
342		down_read(&c->vfs_sb->s_umount);
343		sync_inodes_sb(c->vfs_sb);
344		up_read(&c->vfs_sb->s_umount);
345	}
346retry:
347	if (arg.src_ptr) {
348		error = user_path_at(arg.dirfd,
349				(const char __user *)(unsigned long)arg.src_ptr,
350				how, &src_path);
351		if (error)
352			goto err1;
353
354		if (src_path.dentry->d_sb->s_fs_info != c) {
355			path_put(&src_path);
356			error = -EXDEV;
357			goto err1;
358		}
359
360		snapshot_src = inode_inum(to_bch_ei(src_path.dentry->d_inode));
361	}
362
363	dst_dentry = user_path_create(arg.dirfd,
364			(const char __user *)(unsigned long)arg.dst_ptr,
365			&dst_path, lookup_flags);
366	error = PTR_ERR_OR_ZERO(dst_dentry);
367	if (error)
368		goto err2;
369
370	if (dst_dentry->d_sb->s_fs_info != c) {
371		error = -EXDEV;
372		goto err3;
373	}
374
375	if (dst_dentry->d_inode) {
376		error = -EEXIST;
377		goto err3;
378	}
379
380	dir = dst_path.dentry->d_inode;
381	if (IS_DEADDIR(dir)) {
382		error = -BCH_ERR_ENOENT_directory_dead;
383		goto err3;
384	}
385
386	s_user_ns = dir->i_sb->s_user_ns;
387	if (!kuid_has_mapping(s_user_ns, current_fsuid()) ||
388	    !kgid_has_mapping(s_user_ns, current_fsgid())) {
389		error = -EOVERFLOW;
390		goto err3;
391	}
392
393	error = inode_permission(file_mnt_idmap(filp),
394				 dir, MAY_WRITE | MAY_EXEC);
395	if (error)
396		goto err3;
397
398	if (!IS_POSIXACL(dir))
399		arg.mode &= ~current_umask();
400
401	error = security_path_mkdir(&dst_path, dst_dentry, arg.mode);
402	if (error)
403		goto err3;
404
405	if ((arg.flags & BCH_SUBVOL_SNAPSHOT_CREATE) &&
406	    !arg.src_ptr)
407		snapshot_src.subvol = inode_inum(to_bch_ei(dir)).subvol;
408
409	inode = __bch2_create(file_mnt_idmap(filp), to_bch_ei(dir),
410			      dst_dentry, arg.mode|S_IFDIR,
411			      0, snapshot_src, create_flags);
412	error = PTR_ERR_OR_ZERO(inode);
413	if (error)
414		goto err3;
415
416	d_instantiate(dst_dentry, &inode->v);
417	fsnotify_mkdir(dir, dst_dentry);
418err3:
419	done_path_create(&dst_path, dst_dentry);
420err2:
421	if (arg.src_ptr)
422		path_put(&src_path);
423
424	if (retry_estale(error, lookup_flags)) {
425		lookup_flags |= LOOKUP_REVAL;
426		goto retry;
427	}
428err1:
429	return error;
430}
431
432static long bch2_ioctl_subvolume_create(struct bch_fs *c, struct file *filp,
433					struct bch_ioctl_subvolume arg)
434{
435	down_write(&c->snapshot_create_lock);
436	long ret = __bch2_ioctl_subvolume_create(c, filp, arg);
437	up_write(&c->snapshot_create_lock);
438
439	return ret;
440}
441
442static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
443				struct bch_ioctl_subvolume arg)
444{
445	const char __user *name = (void __user *)(unsigned long)arg.dst_ptr;
446	struct path path;
447	struct inode *dir;
448	struct dentry *victim;
449	int ret = 0;
450
451	if (arg.flags)
452		return -EINVAL;
453
454	victim = user_path_locked_at(arg.dirfd, name, &path);
455	if (IS_ERR(victim))
456		return PTR_ERR(victim);
457
458	dir = d_inode(path.dentry);
459	if (victim->d_sb->s_fs_info != c) {
460		ret = -EXDEV;
461		goto err;
462	}
463	if (!d_is_positive(victim)) {
464		ret = -ENOENT;
465		goto err;
466	}
467	ret = __bch2_unlink(dir, victim, true);
468	if (!ret) {
469		fsnotify_rmdir(dir, victim);
470		d_delete(victim);
471	}
472err:
473	inode_unlock(dir);
474	dput(victim);
475	path_put(&path);
476	return ret;
477}
478
479long bch2_fs_file_ioctl(struct file *file, unsigned cmd, unsigned long arg)
480{
481	struct bch_inode_info *inode = file_bch_inode(file);
482	struct bch_fs *c = inode->v.i_sb->s_fs_info;
483	long ret;
484
485	switch (cmd) {
486	case FS_IOC_GETFLAGS:
487		ret = bch2_ioc_getflags(inode, (int __user *) arg);
488		break;
489
490	case FS_IOC_SETFLAGS:
491		ret = bch2_ioc_setflags(c, file, inode, (int __user *) arg);
492		break;
493
494	case FS_IOC_FSGETXATTR:
495		ret = bch2_ioc_fsgetxattr(inode, (void __user *) arg);
496		break;
497
498	case FS_IOC_FSSETXATTR:
499		ret = bch2_ioc_fssetxattr(c, file, inode,
500					  (void __user *) arg);
501		break;
502
503	case BCHFS_IOC_REINHERIT_ATTRS:
504		ret = bch2_ioc_reinherit_attrs(c, file, inode,
505					       (void __user *) arg);
506		break;
507
508	case FS_IOC_GETVERSION:
509		ret = -ENOTTY;
510		break;
511
512	case FS_IOC_SETVERSION:
513		ret = -ENOTTY;
514		break;
515
516	case FS_IOC_GOINGDOWN:
517		ret = bch2_ioc_goingdown(c, (u32 __user *) arg);
518		break;
519
520	case BCH_IOCTL_SUBVOLUME_CREATE: {
521		struct bch_ioctl_subvolume i;
522
523		ret = copy_from_user(&i, (void __user *) arg, sizeof(i))
524			? -EFAULT
525			: bch2_ioctl_subvolume_create(c, file, i);
526		break;
527	}
528
529	case BCH_IOCTL_SUBVOLUME_DESTROY: {
530		struct bch_ioctl_subvolume i;
531
532		ret = copy_from_user(&i, (void __user *) arg, sizeof(i))
533			? -EFAULT
534			: bch2_ioctl_subvolume_destroy(c, file, i);
535		break;
536	}
537
538	default:
539		ret = bch2_fs_ioctl(c, cmd, (void __user *) arg);
540		break;
541	}
542
543	return bch2_err_class(ret);
544}
545
546#ifdef CONFIG_COMPAT
547long bch2_compat_fs_ioctl(struct file *file, unsigned cmd, unsigned long arg)
548{
549	/* These are just misnamed, they actually get/put from/to user an int */
550	switch (cmd) {
551	case FS_IOC_GETFLAGS:
552		cmd = FS_IOC_GETFLAGS;
553		break;
554	case FS_IOC32_SETFLAGS:
555		cmd = FS_IOC_SETFLAGS;
556		break;
557	default:
558		return -ENOIOCTLCMD;
559	}
560	return bch2_fs_file_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
561}
562#endif
563
564#endif /* NO_BCACHEFS_FS */
565