• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * FUSE-BPF: Filesystem in Userspace with BPF
4  * Copyright (c) 2021 Google LLC
5  */
6 
7 #include "fuse_i.h"
8 
9 #include <linux/fdtable.h>
10 #include <linux/filter.h>
11 #include <linux/fs_stack.h>
12 #include <linux/namei.h>
13 
14 #include "../internal.h"
15 
16 #define FUSE_BPF_IOCB_MASK (IOCB_APPEND | IOCB_DSYNC | IOCB_HIPRI | IOCB_NOWAIT | IOCB_SYNC)
17 
18 struct fuse_bpf_aio_req {
19 	struct kiocb iocb;
20 	refcount_t ref;
21 	struct kiocb *iocb_orig;
22 };
23 
24 static struct kmem_cache *fuse_bpf_aio_request_cachep;
25 
26 static void fuse_stat_to_attr(struct fuse_conn *fc, struct inode *inode,
27 		struct kstat *stat, struct fuse_attr *attr);
28 
fuse_file_accessed(struct file * dst_file,struct file * src_file)29 static void fuse_file_accessed(struct file *dst_file, struct file *src_file)
30 {
31 	struct inode *dst_inode;
32 	struct inode *src_inode;
33 
34 	if (dst_file->f_flags & O_NOATIME)
35 		return;
36 
37 	dst_inode = file_inode(dst_file);
38 	src_inode = file_inode(src_file);
39 
40 	if ((!timespec64_equal(&dst_inode->i_mtime, &src_inode->i_mtime) ||
41 	     !timespec64_equal(&dst_inode->i_ctime, &src_inode->i_ctime))) {
42 		dst_inode->i_mtime = src_inode->i_mtime;
43 		dst_inode->i_ctime = src_inode->i_ctime;
44 	}
45 
46 	touch_atime(&dst_file->f_path);
47 }
48 
fuse_get_bpf_prog(struct file * file)49 struct bpf_prog *fuse_get_bpf_prog(struct file *file)
50 {
51 	struct bpf_prog *bpf_prog = ERR_PTR(-EINVAL);
52 
53        if (!file || IS_ERR(file))
54                return bpf_prog;
55 	/**
56 	 * Two ways of getting a bpf prog from another task's fd, since
57 	 * bpf_prog_get_type_dev only works with an fd
58 	 *
59 	 * 1) Duplicate a little of the needed code. Requires access to
60 	 *    bpf_prog_fops for validation, which is not exported for modules
61 	 * 2) Insert the bpf_file object into a fd from the current task
62 	 *    Stupidly complex, but I think OK, as security checks are not run
63 	 *    during the existence of the handle
64 	 *
65 	 * Best would be to upstream 1) into kernel/bpf/syscall.c and export it
66 	 * for use here. Failing that, we have to use 2, since fuse must be
67 	 * compilable as a module.
68 	 */
69 #if 0
70 	if (file->f_op != &bpf_prog_fops)
71 		goto out;
72 
73 	bpf_prog = file->private_data;
74 	if (bpf_prog->type == BPF_PROG_TYPE_FUSE)
75 		bpf_prog_inc(bpf_prog);
76 	else
77 		bpf_prog = ERR_PTR(-EINVAL);
78 
79 #else
80 	{
81 		int task_fd = get_unused_fd_flags(file->f_flags);
82 
83 		if (task_fd < 0)
84 			goto out;
85 
86 		fd_install(task_fd, file);
87 
88 		bpf_prog = bpf_prog_get_type_dev(task_fd, BPF_PROG_TYPE_FUSE,
89 						 false);
90 
91 		/* Close the fd, which also closes the file */
92 		__close_fd(current->files, task_fd);
93 		file = NULL;
94 	}
95 #endif
96 
97 out:
98 	if (file)
99 		fput(file);
100 	return bpf_prog;
101 }
102 
fuse_open_initialize(struct fuse_bpf_args * fa,struct fuse_open_io * foio,struct inode * inode,struct file * file,bool isdir)103 int fuse_open_initialize(struct fuse_bpf_args *fa, struct fuse_open_io *foio,
104 			 struct inode *inode, struct file *file, bool isdir)
105 {
106 	foio->foi = (struct fuse_open_in) {
107 		.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY),
108 	};
109 
110 	foio->foo = (struct fuse_open_out) {0};
111 
112 	*fa = (struct fuse_bpf_args) {
113 		.nodeid = get_fuse_inode(inode)->nodeid,
114 		.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN,
115 		.in_numargs = 1,
116 		.out_numargs = 1,
117 		.in_args[0] = (struct fuse_bpf_in_arg) {
118 			.size = sizeof(foio->foi),
119 			.value = &foio->foi,
120 		},
121 		.out_args[0] = (struct fuse_bpf_arg) {
122 			.size = sizeof(foio->foo),
123 			.value = &foio->foo,
124 		},
125 	};
126 
127 	return 0;
128 }
129 
fuse_open_backing(struct fuse_bpf_args * fa,struct inode * inode,struct file * file,bool isdir)130 int fuse_open_backing(struct fuse_bpf_args *fa,
131 		      struct inode *inode, struct file *file, bool isdir)
132 {
133 	struct fuse_mount *fm = get_fuse_mount(inode);
134 	const struct fuse_open_in *foi = fa->in_args[0].value;
135 	struct fuse_file *ff;
136 	int retval;
137 	int mask;
138 	struct fuse_dentry *fd = get_fuse_dentry(file->f_path.dentry);
139 	struct file *backing_file;
140 
141 	ff = fuse_file_alloc(fm);
142 	if (!ff)
143 		return -ENOMEM;
144 	file->private_data = ff;
145 
146 	switch (foi->flags & O_ACCMODE) {
147 	case O_RDONLY:
148 		mask = MAY_READ;
149 		break;
150 
151 	case O_WRONLY:
152 		mask = MAY_WRITE;
153 		break;
154 
155 	case O_RDWR:
156 		mask = MAY_READ | MAY_WRITE;
157 		break;
158 
159 	default:
160 		return -EINVAL;
161 	}
162 
163 	retval = inode_permission(get_fuse_inode(inode)->backing_inode, mask);
164 	if (retval)
165 		return retval;
166 
167 	backing_file = dentry_open(&fd->backing_path,
168 				   foi->flags,
169 				   current_cred());
170 
171 	if (IS_ERR(backing_file)) {
172 		fuse_file_free(ff);
173 		file->private_data = NULL;
174 		return PTR_ERR(backing_file);
175 	}
176 	ff->backing_file = backing_file;
177 
178 	return 0;
179 }
180 
fuse_open_finalize(struct fuse_bpf_args * fa,struct inode * inode,struct file * file,bool isdir)181 void *fuse_open_finalize(struct fuse_bpf_args *fa,
182 		       struct inode *inode, struct file *file, bool isdir)
183 {
184 	struct fuse_file *ff = file->private_data;
185 	struct fuse_open_out *foo = fa->out_args[0].value;
186 
187 	if (ff) {
188 		ff->fh = foo->fh;
189 		ff->nodeid = get_fuse_inode(inode)->nodeid;
190 	}
191 	return 0;
192 }
193 
fuse_create_open_initialize(struct fuse_bpf_args * fa,struct fuse_create_open_io * fcoio,struct inode * dir,struct dentry * entry,struct file * file,unsigned int flags,umode_t mode)194 int fuse_create_open_initialize(
195 		struct fuse_bpf_args *fa, struct fuse_create_open_io *fcoio,
196 		struct inode *dir, struct dentry *entry,
197 		struct file *file, unsigned int flags, umode_t mode)
198 {
199 	fcoio->fci = (struct fuse_create_in) {
200 		.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY),
201 		.mode = mode,
202 	};
203 
204 	fcoio->feo = (struct fuse_entry_out) {0};
205 	fcoio->foo = (struct fuse_open_out) {0};
206 
207 	*fa = (struct fuse_bpf_args) {
208 		.nodeid = get_node_id(dir),
209 		.opcode = FUSE_CREATE,
210 		.in_numargs = 2,
211 		.out_numargs = 2,
212 		.in_args[0] = (struct fuse_bpf_in_arg) {
213 			.size = sizeof(fcoio->fci),
214 			.value = &fcoio->fci,
215 		},
216 		.in_args[1] = (struct fuse_bpf_in_arg) {
217 			.size = entry->d_name.len + 1,
218 			.value = entry->d_name.name,
219 		},
220 		.out_args[0] = (struct fuse_bpf_arg) {
221 			.size = sizeof(fcoio->feo),
222 			.value = &fcoio->feo,
223 		},
224 		.out_args[1] = (struct fuse_bpf_arg) {
225 			.size = sizeof(fcoio->foo),
226 			.value = &fcoio->foo,
227 		},
228 	};
229 
230 	return 0;
231 }
232 
fuse_open_file_backing(struct inode * inode,struct file * file)233 static int fuse_open_file_backing(struct inode *inode, struct file *file)
234 {
235 	struct fuse_mount *fm = get_fuse_mount(inode);
236 	struct dentry *entry = file->f_path.dentry;
237 	struct fuse_dentry *fuse_dentry = get_fuse_dentry(entry);
238 	struct fuse_file *fuse_file;
239 	struct file *backing_file;
240 
241 	fuse_file = fuse_file_alloc(fm);
242 	if (!fuse_file)
243 		return -ENOMEM;
244 	file->private_data = fuse_file;
245 
246 	backing_file = dentry_open(&fuse_dentry->backing_path, file->f_flags,
247 				   current_cred());
248 	if (IS_ERR(backing_file)) {
249 		fuse_file_free(fuse_file);
250 		file->private_data = NULL;
251 		return PTR_ERR(backing_file);
252 	}
253 	fuse_file->backing_file = backing_file;
254 
255 	return 0;
256 }
257 
fuse_create_open_backing(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,struct file * file,unsigned int flags,umode_t mode)258 int fuse_create_open_backing(
259 		struct fuse_bpf_args *fa,
260 		struct inode *dir, struct dentry *entry,
261 		struct file *file, unsigned int flags, umode_t mode)
262 {
263 	struct fuse_inode *dir_fuse_inode = get_fuse_inode(dir);
264 	struct fuse_dentry *fuse_entry = get_fuse_dentry(entry);
265 	struct fuse_dentry *dir_fuse_dentry = get_fuse_dentry(entry->d_parent);
266 	struct dentry *backing_dentry = NULL;
267 	struct inode *inode = NULL;
268 	struct dentry *newent;
269 	int err = 0;
270 	const struct fuse_create_in *fci = fa->in_args[0].value;
271 	struct inode *d_inode = entry->d_inode;
272 	u64 target_nodeid = 0;
273 
274 	if (!dir_fuse_inode || !dir_fuse_dentry)
275 		return -EIO;
276 
277 	inode_lock_nested(dir_fuse_inode->backing_inode, I_MUTEX_PARENT);
278 	backing_dentry = lookup_one_len(fa->in_args[1].value,
279 					dir_fuse_dentry->backing_path.dentry,
280 					strlen(fa->in_args[1].value));
281 	inode_unlock(dir_fuse_inode->backing_inode);
282 
283 	if (IS_ERR(backing_dentry))
284 		return PTR_ERR(backing_dentry);
285 
286 	if (d_really_is_positive(backing_dentry)) {
287 		err = -EIO;
288 		goto out;
289 	}
290 
291 	err = vfs_create(dir_fuse_inode->backing_inode, backing_dentry,
292 			 fci->mode, true);
293 	if (err)
294 		goto out;
295 
296 	if (fuse_entry->backing_path.dentry)
297 		path_put(&fuse_entry->backing_path);
298 	fuse_entry->backing_path = (struct path) {
299 		.mnt = dir_fuse_dentry->backing_path.mnt,
300 		.dentry = backing_dentry,
301 	};
302 	path_get(&fuse_entry->backing_path);
303 
304 	if (d_inode)
305 		target_nodeid = get_fuse_inode(d_inode)->nodeid;
306 
307 	inode = fuse_iget_backing(dir->i_sb, target_nodeid,
308 			fuse_entry->backing_path.dentry->d_inode);
309 	if (!inode) {
310 		err = -EIO;
311 		goto out;
312 	}
313 
314 	if (get_fuse_inode(inode)->bpf)
315 		bpf_prog_put(get_fuse_inode(inode)->bpf);
316 	get_fuse_inode(inode)->bpf = fuse_entry->bpf;
317 	fuse_entry->bpf = NULL;
318 
319 	newent = d_splice_alias(inode, entry);
320 	if (IS_ERR(newent)) {
321 		err = PTR_ERR(newent);
322 		goto out;
323 	}
324 
325 	inode = NULL;
326 	entry = newent ? newent : entry;
327 	err = finish_open(file, entry, fuse_open_file_backing);
328 
329 out:
330 	iput(inode);
331 	dput(backing_dentry);
332 	return err;
333 }
334 
fuse_create_open_finalize(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,struct file * file,unsigned int flags,umode_t mode)335 void *fuse_create_open_finalize(
336 		struct fuse_bpf_args *fa,
337 		struct inode *dir, struct dentry *entry,
338 		struct file *file, unsigned int flags, umode_t mode)
339 {
340 	struct fuse_file *ff = file->private_data;
341 	struct fuse_inode *fi = get_fuse_inode(file->f_inode);
342 	struct fuse_entry_out *feo = fa->out_args[0].value;
343 	struct fuse_open_out *foo = fa->out_args[1].value;
344 
345 	if (fi)
346 		fi->nodeid = feo->nodeid;
347 	if (ff)
348 		ff->fh = foo->fh;
349 	return 0;
350 }
351 
fuse_release_initialize(struct fuse_bpf_args * fa,struct fuse_release_in * fri,struct inode * inode,struct fuse_file * ff)352 int fuse_release_initialize(struct fuse_bpf_args *fa, struct fuse_release_in *fri,
353 			    struct inode *inode, struct fuse_file *ff)
354 {
355 	/* Always put backing file whatever bpf/userspace says */
356 	if (ff->backing_file) {
357 	    fput(ff->backing_file);
358 	}
359 
360 	*fri = (struct fuse_release_in) {
361 		.fh = ff->fh,
362 	};
363 
364 	*fa = (struct fuse_bpf_args) {
365 		.nodeid = get_fuse_inode(inode)->nodeid,
366 		.opcode = S_ISDIR(inode->i_mode) ? FUSE_RELEASEDIR
367 						 : FUSE_RELEASE,
368 		.in_numargs = 1,
369 		.in_args[0].size = sizeof(*fri),
370 		.in_args[0].value = fri,
371 	};
372 
373 	return 0;
374 }
375 
fuse_release_backing(struct fuse_bpf_args * fa,struct inode * inode,struct fuse_file * ff)376 int fuse_release_backing(struct fuse_bpf_args *fa,
377 			 struct inode *inode, struct fuse_file *ff)
378 {
379 	return 0;
380 }
381 
fuse_release_finalize(struct fuse_bpf_args * fa,struct inode * inode,struct fuse_file * ff)382 void *fuse_release_finalize(struct fuse_bpf_args *fa,
383 			    struct inode *inode, struct fuse_file *ff)
384 {
385 	return NULL;
386 }
387 
fuse_flush_initialize(struct fuse_bpf_args * fa,struct fuse_flush_in * ffi,struct file * file,fl_owner_t id)388 int fuse_flush_initialize(struct fuse_bpf_args *fa, struct fuse_flush_in *ffi,
389 			   struct file *file, fl_owner_t id)
390 {
391 	struct fuse_file *fuse_file = file->private_data;
392 
393 	*ffi = (struct fuse_flush_in) {
394 		.fh = fuse_file->fh,
395 	};
396 
397 	*fa = (struct fuse_bpf_args) {
398 		.nodeid = get_node_id(file->f_inode),
399 		.opcode = FUSE_FLUSH,
400 		.in_numargs = 1,
401 		.in_args[0].size = sizeof(*ffi),
402 		.in_args[0].value = ffi,
403 		.flags = FUSE_BPF_FORCE,
404 	};
405 
406 	return 0;
407 }
408 
fuse_flush_backing(struct fuse_bpf_args * fa,struct file * file,fl_owner_t id)409 int fuse_flush_backing(struct fuse_bpf_args *fa, struct file *file, fl_owner_t id)
410 {
411 	struct fuse_file *fuse_file = file->private_data;
412 	struct file *backing_file = fuse_file->backing_file;
413 
414 	if (backing_file->f_op->flush)
415 		return backing_file->f_op->flush(backing_file, id);
416 	return 0;
417 }
418 
fuse_flush_finalize(struct fuse_bpf_args * fa,struct file * file,fl_owner_t id)419 void *fuse_flush_finalize(struct fuse_bpf_args *fa, struct file *file, fl_owner_t id)
420 {
421 	return NULL;
422 }
423 
fuse_lseek_initialize(struct fuse_bpf_args * fa,struct fuse_lseek_io * flio,struct file * file,loff_t offset,int whence)424 int fuse_lseek_initialize(struct fuse_bpf_args *fa, struct fuse_lseek_io *flio,
425 			  struct file *file, loff_t offset, int whence)
426 {
427 	struct fuse_file *fuse_file = file->private_data;
428 
429 	flio->fli = (struct fuse_lseek_in) {
430 		.fh = fuse_file->fh,
431 		.offset = offset,
432 		.whence = whence,
433 	};
434 
435 	*fa = (struct fuse_bpf_args) {
436 		.nodeid = get_node_id(file->f_inode),
437 		.opcode = FUSE_LSEEK,
438 		.in_numargs = 1,
439 		.in_args[0].size = sizeof(flio->fli),
440 		.in_args[0].value = &flio->fli,
441 		.out_numargs = 1,
442 		.out_args[0].size = sizeof(flio->flo),
443 		.out_args[0].value = &flio->flo,
444 	};
445 
446 	return 0;
447 }
448 
fuse_lseek_backing(struct fuse_bpf_args * fa,struct file * file,loff_t offset,int whence)449 int fuse_lseek_backing(struct fuse_bpf_args *fa, struct file *file, loff_t offset, int whence)
450 {
451 	const struct fuse_lseek_in *fli = fa->in_args[0].value;
452 	struct fuse_lseek_out *flo = fa->out_args[0].value;
453 	struct fuse_file *fuse_file = file->private_data;
454 	struct file *backing_file = fuse_file->backing_file;
455 	loff_t ret;
456 
457 	if (offset == 0) {
458 		if (whence == SEEK_CUR) {
459 			flo->offset = file->f_pos;
460 			return 0;
461 		}
462 
463 		if (whence == SEEK_SET) {
464 			flo->offset = vfs_setpos(file, 0, 0);
465 			return 0;
466 		}
467 	}
468 
469 	inode_lock(file->f_inode);
470 	backing_file->f_pos = file->f_pos;
471 	ret = vfs_llseek(backing_file, fli->offset, fli->whence);
472 
473 	if (!IS_ERR(ERR_PTR(ret))) {
474 		flo->offset = ret;
475 		ret = 0;
476 	}
477 	inode_unlock(file->f_inode);
478 	return ret;
479 }
480 
fuse_lseek_finalize(struct fuse_bpf_args * fa,struct file * file,loff_t offset,int whence)481 void *fuse_lseek_finalize(struct fuse_bpf_args *fa, struct file *file, loff_t offset, int whence)
482 {
483 	struct fuse_lseek_out *flo = fa->out_args[0].value;
484 
485 	if (!fa->error_in)
486 		file->f_pos = flo->offset;
487 	return ERR_PTR(flo->offset);
488 }
489 
fuse_copy_file_range_initialize(struct fuse_bpf_args * fa,struct fuse_copy_file_range_io * fcf,struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,size_t len,unsigned int flags)490 int fuse_copy_file_range_initialize(struct fuse_bpf_args *fa, struct fuse_copy_file_range_io *fcf,
491 				   struct file *file_in, loff_t pos_in, struct file *file_out,
492 				   loff_t pos_out, size_t len, unsigned int flags)
493 {
494 	struct fuse_file *fuse_file_in = file_in->private_data;
495 	struct fuse_file *fuse_file_out = file_out->private_data;
496 
497 
498 	fcf->fci = (struct fuse_copy_file_range_in) {
499 		.fh_in = fuse_file_in->fh,
500 		.off_in = pos_in,
501 		.nodeid_out = fuse_file_out->nodeid,
502 		.fh_out = fuse_file_out->fh,
503 		.off_out = pos_out,
504 		.len = len,
505 		.flags = flags,
506 	};
507 
508 	*fa = (struct fuse_bpf_args) {
509 		.nodeid = get_node_id(file_in->f_inode),
510 		.opcode = FUSE_COPY_FILE_RANGE,
511 		.in_numargs = 1,
512 		.in_args[0].size = sizeof(fcf->fci),
513 		.in_args[0].value = &fcf->fci,
514 		.out_numargs = 1,
515 		.out_args[0].size = sizeof(fcf->fwo),
516 		.out_args[0].value = &fcf->fwo,
517 	};
518 
519 	return 0;
520 }
521 
fuse_copy_file_range_backing(struct fuse_bpf_args * fa,struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,size_t len,unsigned int flags)522 int fuse_copy_file_range_backing(struct fuse_bpf_args *fa, struct file *file_in, loff_t pos_in,
523 				 struct file *file_out, loff_t pos_out, size_t len,
524 				 unsigned int flags)
525 {
526 	const struct fuse_copy_file_range_in *fci = fa->in_args[0].value;
527 	struct fuse_file *fuse_file_in = file_in->private_data;
528 	struct file *backing_file_in = fuse_file_in->backing_file;
529 	struct fuse_file *fuse_file_out = file_out->private_data;
530 	struct file *backing_file_out = fuse_file_out->backing_file;
531 
532 	/* TODO: Handle changing of in/out files */
533 	if (backing_file_out)
534 		return vfs_copy_file_range(backing_file_in, fci->off_in, backing_file_out,
535 					   fci->off_out, fci->len, fci->flags);
536 	else
537 		return generic_copy_file_range(file_in, pos_in, file_out, pos_out, len,
538 					       flags);
539 }
540 
fuse_copy_file_range_finalize(struct fuse_bpf_args * fa,struct file * file_in,loff_t pos_in,struct file * file_out,loff_t pos_out,size_t len,unsigned int flags)541 void *fuse_copy_file_range_finalize(struct fuse_bpf_args *fa, struct file *file_in, loff_t pos_in,
542 				    struct file *file_out, loff_t pos_out, size_t len,
543 				    unsigned int flags)
544 {
545 	return NULL;
546 }
547 
fuse_fsync_initialize(struct fuse_bpf_args * fa,struct fuse_fsync_in * ffi,struct file * file,loff_t start,loff_t end,int datasync)548 int fuse_fsync_initialize(struct fuse_bpf_args *fa, struct fuse_fsync_in *ffi,
549 		   struct file *file, loff_t start, loff_t end, int datasync)
550 {
551 	struct fuse_file *fuse_file = file->private_data;
552 
553 	*ffi = (struct fuse_fsync_in) {
554 		.fh = fuse_file->fh,
555 		.fsync_flags = datasync ? FUSE_FSYNC_FDATASYNC : 0,
556 	};
557 
558 	*fa = (struct fuse_bpf_args) {
559 		.nodeid = get_fuse_inode(file->f_inode)->nodeid,
560 		.opcode = FUSE_FSYNC,
561 		.in_numargs = 1,
562 		.in_args[0].size = sizeof(*ffi),
563 		.in_args[0].value = ffi,
564 		.flags = FUSE_BPF_FORCE,
565 	};
566 
567 	return 0;
568 }
569 
fuse_fsync_backing(struct fuse_bpf_args * fa,struct file * file,loff_t start,loff_t end,int datasync)570 int fuse_fsync_backing(struct fuse_bpf_args *fa,
571 		   struct file *file, loff_t start, loff_t end, int datasync)
572 {
573 	struct fuse_file *fuse_file = file->private_data;
574 	struct file *backing_file = fuse_file->backing_file;
575 	const struct fuse_fsync_in *ffi = fa->in_args[0].value;
576 	int new_datasync = (ffi->fsync_flags & FUSE_FSYNC_FDATASYNC) ? 1 : 0;
577 
578 	return vfs_fsync(backing_file, new_datasync);
579 }
580 
fuse_fsync_finalize(struct fuse_bpf_args * fa,struct file * file,loff_t start,loff_t end,int datasync)581 void *fuse_fsync_finalize(struct fuse_bpf_args *fa,
582 		   struct file *file, loff_t start, loff_t end, int datasync)
583 {
584 	return NULL;
585 }
586 
fuse_dir_fsync_initialize(struct fuse_bpf_args * fa,struct fuse_fsync_in * ffi,struct file * file,loff_t start,loff_t end,int datasync)587 int fuse_dir_fsync_initialize(struct fuse_bpf_args *fa, struct fuse_fsync_in *ffi,
588 		   struct file *file, loff_t start, loff_t end, int datasync)
589 {
590 	struct fuse_file *fuse_file = file->private_data;
591 
592 	*ffi = (struct fuse_fsync_in) {
593 		.fh = fuse_file->fh,
594 		.fsync_flags = datasync ? FUSE_FSYNC_FDATASYNC : 0,
595 	};
596 
597 	*fa = (struct fuse_bpf_args) {
598 		.nodeid = get_fuse_inode(file->f_inode)->nodeid,
599 		.opcode = FUSE_FSYNCDIR,
600 		.in_numargs = 1,
601 		.in_args[0].size = sizeof(*ffi),
602 		.in_args[0].value = ffi,
603 		.flags = FUSE_BPF_FORCE,
604 	};
605 
606 	return 0;
607 }
608 
fuse_getxattr_initialize(struct fuse_bpf_args * fa,struct fuse_getxattr_io * fgio,struct dentry * dentry,const char * name,void * value,size_t size)609 int fuse_getxattr_initialize(struct fuse_bpf_args *fa,
610 		struct fuse_getxattr_io *fgio,
611 		struct dentry *dentry, const char *name, void *value,
612 		size_t size)
613 {
614 	*fgio = (struct fuse_getxattr_io) {
615 		.fgi.size = size,
616 	};
617 
618 	*fa = (struct fuse_bpf_args) {
619 		.nodeid = get_fuse_inode(dentry->d_inode)->nodeid,
620 		.opcode = FUSE_GETXATTR,
621 		.in_numargs = 2,
622 		.out_numargs = 1,
623 		.in_args[0] = (struct fuse_bpf_in_arg) {
624 			.size = sizeof(fgio->fgi),
625 			.value = &fgio->fgi,
626 		},
627 		.in_args[1] = (struct fuse_bpf_in_arg) {
628 			.size = strlen(name) + 1,
629 			.value = name,
630 		},
631 		.flags = size ? FUSE_BPF_OUT_ARGVAR : 0,
632 		.out_args[0].size = size ? size : sizeof(fgio->fgo),
633 		.out_args[0].value = size ? value : &fgio->fgo,
634 	};
635 	return 0;
636 }
637 
fuse_getxattr_backing(struct fuse_bpf_args * fa,struct dentry * dentry,const char * name,void * value,size_t size)638 int fuse_getxattr_backing(struct fuse_bpf_args *fa,
639 		struct dentry *dentry, const char *name, void *value,
640 		size_t size)
641 {
642 	ssize_t ret = vfs_getxattr(get_fuse_dentry(dentry)->backing_path.dentry,
643 				   fa->in_args[1].value, value, size);
644 
645 	if (fa->flags & FUSE_BPF_OUT_ARGVAR)
646 		fa->out_args[0].size = ret;
647 	else
648 		((struct fuse_getxattr_out *)fa->out_args[0].value)->size = ret;
649 
650 	return 0;
651 }
652 
fuse_getxattr_finalize(struct fuse_bpf_args * fa,struct dentry * dentry,const char * name,void * value,size_t size)653 void *fuse_getxattr_finalize(struct fuse_bpf_args *fa,
654 		struct dentry *dentry, const char *name, void *value,
655 		size_t size)
656 {
657 	struct fuse_getxattr_out *fgo;
658 
659 	if (fa->flags & FUSE_BPF_OUT_ARGVAR)
660 		return ERR_PTR(fa->out_args[0].size);
661 
662 	fgo = fa->out_args[0].value;
663 
664 	return ERR_PTR(fgo->size);
665 
666 }
667 
fuse_listxattr_initialize(struct fuse_bpf_args * fa,struct fuse_getxattr_io * fgio,struct dentry * dentry,char * list,size_t size)668 int fuse_listxattr_initialize(struct fuse_bpf_args *fa,
669 			      struct fuse_getxattr_io *fgio,
670 			      struct dentry *dentry, char *list, size_t size)
671 {
672 	*fgio = (struct fuse_getxattr_io){
673 		.fgi.size = size,
674 	};
675 
676 	*fa = (struct fuse_bpf_args){
677 		.nodeid = get_fuse_inode(dentry->d_inode)->nodeid,
678 		.opcode = FUSE_LISTXATTR,
679 		.in_numargs = 1,
680 		.out_numargs = 1,
681 		.in_args[0] =
682 			(struct fuse_bpf_in_arg){
683 				.size = sizeof(fgio->fgi),
684 				.value = &fgio->fgi,
685 			},
686 		.flags = size ? FUSE_BPF_OUT_ARGVAR : 0,
687 		.out_args[0].size = size ? size : sizeof(fgio->fgo),
688 		.out_args[0].value = size ? (void *)list : &fgio->fgo,
689 	};
690 
691 	return 0;
692 }
693 
fuse_listxattr_backing(struct fuse_bpf_args * fa,struct dentry * dentry,char * list,size_t size)694 int fuse_listxattr_backing(struct fuse_bpf_args *fa, struct dentry *dentry,
695 			   char *list, size_t size)
696 {
697 	ssize_t ret =
698 		vfs_listxattr(get_fuse_dentry(dentry)->backing_path.dentry,
699 			      list, size);
700 
701 	if (ret < 0)
702 		return ret;
703 
704 	if (fa->flags & FUSE_BPF_OUT_ARGVAR)
705 		fa->out_args[0].size = ret;
706 	else
707 		((struct fuse_getxattr_out *)fa->out_args[0].value)->size = ret;
708 
709 	return ret;
710 }
711 
fuse_listxattr_finalize(struct fuse_bpf_args * fa,struct dentry * dentry,char * list,size_t size)712 void *fuse_listxattr_finalize(struct fuse_bpf_args *fa, struct dentry *dentry,
713 			      char *list, size_t size)
714 {
715 	struct fuse_getxattr_out *fgo;
716 
717 	if (fa->error_in)
718 		return NULL;
719 
720 	if (fa->flags & FUSE_BPF_OUT_ARGVAR)
721 		return ERR_PTR(fa->out_args[0].size);
722 
723 	fgo = fa->out_args[0].value;
724 	return ERR_PTR(fgo->size);
725 }
726 
fuse_setxattr_initialize(struct fuse_bpf_args * fa,struct fuse_setxattr_in * fsxi,struct dentry * dentry,const char * name,const void * value,size_t size,int flags)727 int fuse_setxattr_initialize(struct fuse_bpf_args *fa,
728 			     struct fuse_setxattr_in *fsxi,
729 			     struct dentry *dentry, const char *name,
730 			     const void *value, size_t size, int flags)
731 {
732 	*fsxi = (struct fuse_setxattr_in) {
733 		.size = size,
734 		.flags = flags,
735 	};
736 
737 	*fa = (struct fuse_bpf_args) {
738 		.nodeid = get_fuse_inode(dentry->d_inode)->nodeid,
739 		.opcode = FUSE_SETXATTR,
740 		.in_numargs = 3,
741 		.in_args[0] = (struct fuse_bpf_in_arg) {
742 			.size = sizeof(*fsxi),
743 			.value = fsxi,
744 		},
745 		.in_args[1] = (struct fuse_bpf_in_arg) {
746 			.size = strlen(name) + 1,
747 			.value = name,
748 		},
749 		.in_args[2] = (struct fuse_bpf_in_arg) {
750 			.size = size,
751 			.value = value,
752 		},
753 	};
754 
755 	return 0;
756 }
757 
fuse_setxattr_backing(struct fuse_bpf_args * fa,struct dentry * dentry,const char * name,const void * value,size_t size,int flags)758 int fuse_setxattr_backing(struct fuse_bpf_args *fa, struct dentry *dentry,
759 			  const char *name, const void *value, size_t size,
760 			  int flags)
761 {
762 	return vfs_setxattr(get_fuse_dentry(dentry)->backing_path.dentry, name,
763 			    value, size, flags);
764 }
765 
fuse_setxattr_finalize(struct fuse_bpf_args * fa,struct dentry * dentry,const char * name,const void * value,size_t size,int flags)766 void *fuse_setxattr_finalize(struct fuse_bpf_args *fa, struct dentry *dentry,
767 			     const char *name, const void *value, size_t size,
768 			     int flags)
769 {
770 	return NULL;
771 }
772 
fuse_removexattr_initialize(struct fuse_bpf_args * fa,struct fuse_dummy_io * unused,struct dentry * dentry,const char * name)773 int fuse_removexattr_initialize(struct fuse_bpf_args *fa,
774 				struct fuse_dummy_io *unused,
775 				struct dentry *dentry, const char *name)
776 {
777 	*fa = (struct fuse_bpf_args) {
778 		.nodeid = get_fuse_inode(dentry->d_inode)->nodeid,
779 		.opcode = FUSE_REMOVEXATTR,
780 		.in_numargs = 1,
781 		.in_args[0] = (struct fuse_bpf_in_arg) {
782 			.size = strlen(name) + 1,
783 			.value = name,
784 		},
785 	};
786 
787 	return 0;
788 }
789 
fuse_removexattr_backing(struct fuse_bpf_args * fa,struct dentry * dentry,const char * name)790 int fuse_removexattr_backing(struct fuse_bpf_args *fa,
791 			     struct dentry *dentry, const char *name)
792 {
793 	struct path *backing_path =
794 		&get_fuse_dentry(dentry)->backing_path;
795 
796 	/* TODO account for changes of the name by prefilter */
797 	return vfs_removexattr(backing_path->dentry, name);
798 }
799 
fuse_removexattr_finalize(struct fuse_bpf_args * fa,struct dentry * dentry,const char * name)800 void *fuse_removexattr_finalize(struct fuse_bpf_args *fa,
801 				struct dentry *dentry, const char *name)
802 {
803 	return NULL;
804 }
805 
fuse_bpf_aio_put(struct fuse_bpf_aio_req * aio_req)806 static inline void fuse_bpf_aio_put(struct fuse_bpf_aio_req *aio_req)
807 {
808 	if (refcount_dec_and_test(&aio_req->ref))
809 		kmem_cache_free(fuse_bpf_aio_request_cachep, aio_req);
810 }
811 
fuse_bpf_aio_cleanup_handler(struct fuse_bpf_aio_req * aio_req)812 static void fuse_bpf_aio_cleanup_handler(struct fuse_bpf_aio_req *aio_req)
813 {
814 	struct kiocb *iocb = &aio_req->iocb;
815 	struct kiocb *iocb_orig = aio_req->iocb_orig;
816 
817 	if (iocb->ki_flags & IOCB_WRITE) {
818 		__sb_writers_acquired(file_inode(iocb->ki_filp)->i_sb,
819 				      SB_FREEZE_WRITE);
820 		file_end_write(iocb->ki_filp);
821 		fuse_copyattr(iocb_orig->ki_filp, iocb->ki_filp);
822 	}
823 	iocb_orig->ki_pos = iocb->ki_pos;
824 	fuse_bpf_aio_put(aio_req);
825 }
826 
fuse_bpf_aio_rw_complete(struct kiocb * iocb,long res,long res2)827 static void fuse_bpf_aio_rw_complete(struct kiocb *iocb, long res, long res2)
828 {
829 	struct fuse_bpf_aio_req *aio_req =
830 		container_of(iocb, struct fuse_bpf_aio_req, iocb);
831 	struct kiocb *iocb_orig = aio_req->iocb_orig;
832 
833 	fuse_bpf_aio_cleanup_handler(aio_req);
834 	iocb_orig->ki_complete(iocb_orig, res, res2);
835 }
836 
837 
fuse_file_read_iter_initialize(struct fuse_bpf_args * fa,struct fuse_file_read_iter_io * fri,struct kiocb * iocb,struct iov_iter * to)838 int fuse_file_read_iter_initialize(
839 		struct fuse_bpf_args *fa, struct fuse_file_read_iter_io *fri,
840 		struct kiocb *iocb, struct iov_iter *to)
841 {
842 	struct file *file = iocb->ki_filp;
843 	struct fuse_file *ff = file->private_data;
844 
845 	fri->fri = (struct fuse_read_in) {
846 		.fh = ff->fh,
847 		.offset = iocb->ki_pos,
848 		.size = to->count,
849 	};
850 
851 	fri->frio = (struct fuse_read_iter_out) {
852 		.ret = fri->fri.size,
853 	};
854 
855 	/* TODO we can't assume 'to' is a kvec */
856 	/* TODO we also can't assume the vector has only one component */
857 	*fa = (struct fuse_bpf_args) {
858 		.opcode = FUSE_READ,
859 		.nodeid = ff->nodeid,
860 		.in_numargs = 1,
861 		.in_args[0].size = sizeof(fri->fri),
862 		.in_args[0].value = &fri->fri,
863 		.out_numargs = 1,
864 		.out_args[0].size = sizeof(fri->frio),
865 		.out_args[0].value = &fri->frio,
866 		/*
867 		 * TODO Design this properly.
868 		 * Possible approach: do not pass buf to bpf
869 		 * If going to userland, do a deep copy
870 		 * For extra credit, do that to/from the vector, rather than
871 		 * making an extra copy in the kernel
872 		 */
873 	};
874 
875 	return 0;
876 }
877 
fuse_file_read_iter_backing(struct fuse_bpf_args * fa,struct kiocb * iocb,struct iov_iter * to)878 int fuse_file_read_iter_backing(struct fuse_bpf_args *fa,
879 		struct kiocb *iocb, struct iov_iter *to)
880 {
881 	struct fuse_read_iter_out *frio = fa->out_args[0].value;
882 	struct file *file = iocb->ki_filp;
883 	struct fuse_file *ff = file->private_data;
884 	ssize_t ret;
885 
886 	if (!iov_iter_count(to))
887 		return 0;
888 
889 	if ((iocb->ki_flags & IOCB_DIRECT) &&
890 	    (!ff->backing_file->f_mapping->a_ops ||
891 	     !ff->backing_file->f_mapping->a_ops->direct_IO))
892 		return -EINVAL;
893 
894 	/* TODO This just plain ignores any change to fuse_read_in */
895 	if (is_sync_kiocb(iocb)) {
896 		ret = vfs_iter_read(ff->backing_file, to, &iocb->ki_pos,
897 				iocb_to_rw_flags(iocb->ki_flags, FUSE_BPF_IOCB_MASK));
898 	} else {
899 		struct fuse_bpf_aio_req *aio_req;
900 
901 		ret = -ENOMEM;
902 		aio_req = kmem_cache_zalloc(fuse_bpf_aio_request_cachep, GFP_KERNEL);
903 		if (!aio_req)
904 			goto out;
905 
906 		aio_req->iocb_orig = iocb;
907 		kiocb_clone(&aio_req->iocb, iocb, ff->backing_file);
908 		aio_req->iocb.ki_complete = fuse_bpf_aio_rw_complete;
909 		refcount_set(&aio_req->ref, 2);
910 		ret = vfs_iocb_iter_read(ff->backing_file, &aio_req->iocb, to);
911 		fuse_bpf_aio_put(aio_req);
912 		if (ret != -EIOCBQUEUED)
913 			fuse_bpf_aio_cleanup_handler(aio_req);
914 	}
915 
916 	frio->ret = ret;
917 
918 	/* TODO Need to point value at the buffer for post-modification */
919 
920 out:
921 	fuse_file_accessed(file, ff->backing_file);
922 
923 	return ret;
924 }
925 
fuse_file_read_iter_finalize(struct fuse_bpf_args * fa,struct kiocb * iocb,struct iov_iter * to)926 void *fuse_file_read_iter_finalize(struct fuse_bpf_args *fa,
927 		struct kiocb *iocb, struct iov_iter *to)
928 {
929 	struct fuse_read_iter_out *frio = fa->out_args[0].value;
930 
931 	return ERR_PTR(frio->ret);
932 }
933 
fuse_file_write_iter_initialize(struct fuse_bpf_args * fa,struct fuse_file_write_iter_io * fwio,struct kiocb * iocb,struct iov_iter * from)934 int fuse_file_write_iter_initialize(
935 		struct fuse_bpf_args *fa, struct fuse_file_write_iter_io *fwio,
936 		struct kiocb *iocb, struct iov_iter *from)
937 {
938 	struct file *file = iocb->ki_filp;
939 	struct fuse_file *ff = file->private_data;
940 
941 	*fwio = (struct fuse_file_write_iter_io) {
942 		.fwi.fh = ff->fh,
943 		.fwi.offset = iocb->ki_pos,
944 		.fwi.size = from->count,
945 	};
946 
947 	/* TODO we can't assume 'from' is a kvec */
948 	*fa = (struct fuse_bpf_args) {
949 		.opcode = FUSE_WRITE,
950 		.nodeid = ff->nodeid,
951 		.in_numargs = 2,
952 		.in_args[0].size = sizeof(fwio->fwi),
953 		.in_args[0].value = &fwio->fwi,
954 		.in_args[1].size = fwio->fwi.size,
955 		.in_args[1].value = from->kvec->iov_base,
956 		.out_numargs = 1,
957 		.out_args[0].size = sizeof(fwio->fwio),
958 		.out_args[0].value = &fwio->fwio,
959 	};
960 
961 	return 0;
962 }
963 
fuse_file_write_iter_backing(struct fuse_bpf_args * fa,struct kiocb * iocb,struct iov_iter * from)964 int fuse_file_write_iter_backing(struct fuse_bpf_args *fa,
965 		struct kiocb *iocb, struct iov_iter *from)
966 {
967 	struct file *file = iocb->ki_filp;
968 	struct fuse_file *ff = file->private_data;
969 	struct fuse_write_iter_out *fwio = fa->out_args[0].value;
970 	ssize_t ret;
971 
972 	if (!iov_iter_count(from))
973 		return 0;
974 
975 	/* TODO This just plain ignores any change to fuse_write_in */
976 	/* TODO uint32_t seems smaller than ssize_t.... right? */
977 	inode_lock(file_inode(file));
978 
979 	fuse_copyattr(file, ff->backing_file);
980 
981 	if (is_sync_kiocb(iocb)) {
982 		file_start_write(ff->backing_file);
983 		ret = vfs_iter_write(ff->backing_file, from, &iocb->ki_pos,
984 					   iocb_to_rw_flags(iocb->ki_flags, FUSE_BPF_IOCB_MASK));
985 		file_end_write(ff->backing_file);
986 
987 		/* Must reflect change in size of backing file to upper file */
988 		if (ret > 0)
989 			fuse_copyattr(file, ff->backing_file);
990 	} else {
991 		struct fuse_bpf_aio_req *aio_req;
992 
993 		ret = -ENOMEM;
994 		aio_req = kmem_cache_zalloc(fuse_bpf_aio_request_cachep, GFP_KERNEL);
995 		if (!aio_req)
996 			goto out;
997 
998 		file_start_write(ff->backing_file);
999 		__sb_writers_release(file_inode(ff->backing_file)->i_sb, SB_FREEZE_WRITE);
1000 		aio_req->iocb_orig = iocb;
1001 		kiocb_clone(&aio_req->iocb, iocb, ff->backing_file);
1002 		aio_req->iocb.ki_complete = fuse_bpf_aio_rw_complete;
1003 		refcount_set(&aio_req->ref, 2);
1004 		ret = vfs_iocb_iter_write(ff->backing_file, &aio_req->iocb, from);
1005 		fuse_bpf_aio_put(aio_req);
1006 		if (ret != -EIOCBQUEUED)
1007 			fuse_bpf_aio_cleanup_handler(aio_req);
1008 	}
1009 
1010 out:
1011 	inode_unlock(file_inode(file));
1012 	fwio->ret = ret;
1013 	if (ret < 0)
1014 		return ret;
1015 	return 0;
1016 }
1017 
fuse_file_write_iter_finalize(struct fuse_bpf_args * fa,struct kiocb * iocb,struct iov_iter * from)1018 void *fuse_file_write_iter_finalize(struct fuse_bpf_args *fa,
1019 		struct kiocb *iocb, struct iov_iter *from)
1020 {
1021 	struct fuse_write_iter_out *fwio = fa->out_args[0].value;
1022 
1023 	return ERR_PTR(fwio->ret);
1024 }
1025 
fuse_backing_ioctl(struct file * file,unsigned int command,unsigned long arg,int flags)1026 long fuse_backing_ioctl(struct file *file, unsigned int command, unsigned long arg, int flags)
1027 {
1028 	struct fuse_file *ff = file->private_data;
1029 	long ret;
1030 
1031 	if (flags & FUSE_IOCTL_COMPAT)
1032 		ret = -ENOTTY;
1033 	else
1034 		ret = vfs_ioctl(ff->backing_file, command, arg);
1035 
1036 	return ret;
1037 }
1038 
fuse_file_flock_backing(struct file * file,int cmd,struct file_lock * fl)1039 int fuse_file_flock_backing(struct file *file, int cmd, struct file_lock *fl)
1040 {
1041 	struct fuse_file *ff = file->private_data;
1042 	struct file *backing_file = ff->backing_file;
1043 	int error;
1044 
1045 	fl->fl_file = backing_file;
1046 	if (backing_file->f_op->flock)
1047 		error = backing_file->f_op->flock(backing_file, cmd, fl);
1048 	else
1049 		error = locks_lock_file_wait(backing_file, fl);
1050 	return error;
1051 }
1052 
fuse_backing_mmap(struct file * file,struct vm_area_struct * vma)1053 ssize_t fuse_backing_mmap(struct file *file, struct vm_area_struct *vma)
1054 {
1055 	int ret;
1056 	struct fuse_file *ff = file->private_data;
1057 	struct inode *fuse_inode = file_inode(file);
1058 	struct file *backing_file = ff->backing_file;
1059 	struct inode *backing_inode = file_inode(backing_file);
1060 
1061 	if (!backing_file->f_op->mmap)
1062 		return -ENODEV;
1063 
1064 	if (WARN_ON(file != vma->vm_file))
1065 		return -EIO;
1066 
1067 	vma->vm_file = get_file(backing_file);
1068 
1069 	ret = call_mmap(vma->vm_file, vma);
1070 
1071 	if (ret)
1072 		fput(backing_file);
1073 	else
1074 		fput(file);
1075 
1076 	if (file->f_flags & O_NOATIME)
1077 		return ret;
1078 
1079 	if ((!timespec64_equal(&fuse_inode->i_mtime,
1080 			       &backing_inode->i_mtime) ||
1081 	     !timespec64_equal(&fuse_inode->i_ctime,
1082 			       &backing_inode->i_ctime))) {
1083 		fuse_inode->i_mtime = backing_inode->i_mtime;
1084 		fuse_inode->i_ctime = backing_inode->i_ctime;
1085 	}
1086 	touch_atime(&file->f_path);
1087 
1088 	return ret;
1089 }
1090 
fuse_file_fallocate_initialize(struct fuse_bpf_args * fa,struct fuse_fallocate_in * ffi,struct file * file,int mode,loff_t offset,loff_t length)1091 int fuse_file_fallocate_initialize(struct fuse_bpf_args *fa,
1092 		struct fuse_fallocate_in *ffi,
1093 		struct file *file, int mode, loff_t offset, loff_t length)
1094 {
1095 	struct fuse_file *ff = file->private_data;
1096 
1097 	*ffi = (struct fuse_fallocate_in) {
1098 		.fh = ff->fh,
1099 		.offset = offset,
1100 		.length = length,
1101 		.mode = mode
1102 	};
1103 
1104 	*fa = (struct fuse_bpf_args) {
1105 		.opcode = FUSE_FALLOCATE,
1106 		.nodeid = ff->nodeid,
1107 		.in_numargs = 1,
1108 		.in_args[0].size = sizeof(*ffi),
1109 		.in_args[0].value = ffi,
1110 	};
1111 
1112 	return 0;
1113 }
1114 
fuse_file_fallocate_backing(struct fuse_bpf_args * fa,struct file * file,int mode,loff_t offset,loff_t length)1115 int fuse_file_fallocate_backing(struct fuse_bpf_args *fa,
1116 		struct file *file, int mode, loff_t offset, loff_t length)
1117 {
1118 	const struct fuse_fallocate_in *ffi = fa->in_args[0].value;
1119 	struct fuse_file *ff = file->private_data;
1120 
1121 	return vfs_fallocate(ff->backing_file, ffi->mode, ffi->offset,
1122 			     ffi->length);
1123 }
1124 
fuse_file_fallocate_finalize(struct fuse_bpf_args * fa,struct file * file,int mode,loff_t offset,loff_t length)1125 void *fuse_file_fallocate_finalize(struct fuse_bpf_args *fa,
1126 		struct file *file, int mode, loff_t offset, loff_t length)
1127 {
1128 	return NULL;
1129 }
1130 
1131 /*******************************************************************************
1132  * Directory operations after here                                             *
1133  ******************************************************************************/
1134 
fuse_lookup_initialize(struct fuse_bpf_args * fa,struct fuse_lookup_io * fli,struct inode * dir,struct dentry * entry,unsigned int flags)1135 int fuse_lookup_initialize(struct fuse_bpf_args *fa, struct fuse_lookup_io *fli,
1136 	       struct inode *dir, struct dentry *entry, unsigned int flags)
1137 {
1138 	*fa = (struct fuse_bpf_args) {
1139 		.nodeid = get_fuse_inode(dir)->nodeid,
1140 		.opcode = FUSE_LOOKUP,
1141 		.in_numargs = 1,
1142 		.out_numargs = 2,
1143 		.flags = FUSE_BPF_OUT_ARGVAR,
1144 		.in_args[0] = (struct fuse_bpf_in_arg) {
1145 			.size = entry->d_name.len + 1,
1146 			.value = entry->d_name.name,
1147 		},
1148 		.out_args[0] = (struct fuse_bpf_arg) {
1149 			.size = sizeof(fli->feo),
1150 			.value = &fli->feo,
1151 		},
1152 		.out_args[1] = (struct fuse_bpf_arg) {
1153 			.size = sizeof(fli->feb.out),
1154 			.value = &fli->feb.out,
1155 		},
1156 	};
1157 
1158 	return 0;
1159 }
1160 
fuse_lookup_backing(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,unsigned int flags)1161 int fuse_lookup_backing(struct fuse_bpf_args *fa, struct inode *dir,
1162 			  struct dentry *entry, unsigned int flags)
1163 {
1164 	struct fuse_dentry *fuse_entry = get_fuse_dentry(entry);
1165 	struct fuse_dentry *dir_fuse_entry = get_fuse_dentry(entry->d_parent);
1166 	struct dentry *dir_backing_entry = dir_fuse_entry->backing_path.dentry;
1167 	struct inode *dir_backing_inode = dir_backing_entry->d_inode;
1168 	struct dentry *backing_entry;
1169 	struct fuse_entry_out *feo = (void *)fa->out_args[0].value;
1170 	struct kstat stat;
1171 	int err;
1172 
1173 	inode_lock_nested(dir_backing_inode, I_MUTEX_PARENT);
1174 	backing_entry = lookup_one_len(entry->d_name.name, dir_backing_entry,
1175 					strlen(entry->d_name.name));
1176 	inode_unlock(dir_backing_inode);
1177 
1178 	if (IS_ERR(backing_entry))
1179 		return PTR_ERR(backing_entry);
1180 
1181 	fuse_entry->backing_path = (struct path) {
1182 		.dentry = backing_entry,
1183 		.mnt = mntget(dir_fuse_entry->backing_path.mnt),
1184 	};
1185 
1186 	if (d_is_negative(backing_entry)) {
1187 		fa->error_in = -ENOENT;
1188 		return 0;
1189 	}
1190 
1191 	err = follow_down(&fuse_entry->backing_path);
1192 	if (err)
1193 		goto err_out;
1194 
1195 	err = vfs_getattr(&fuse_entry->backing_path, &stat,
1196 				  STATX_BASIC_STATS, 0);
1197 	if (err)
1198 		goto err_out;
1199 
1200 	fuse_stat_to_attr(get_fuse_conn(dir),
1201 			  backing_entry->d_inode, &stat, &feo->attr);
1202 	return 0;
1203 
1204 err_out:
1205 	path_put_init(&fuse_entry->backing_path);
1206 	return err;
1207 }
1208 
fuse_handle_backing(struct fuse_entry_bpf * feb,struct inode ** backing_inode,struct path * backing_path)1209 int fuse_handle_backing(struct fuse_entry_bpf *feb, struct inode **backing_inode,
1210 			struct path *backing_path) {
1211 	switch (feb->out.backing_action) {
1212 	case FUSE_ACTION_KEEP:
1213 		/* backing inode/path are added in fuse_lookup_backing */
1214 		break;
1215 
1216 	case FUSE_ACTION_REMOVE:
1217 		iput(*backing_inode);
1218 		*backing_inode = NULL;
1219 		path_put_init(backing_path);
1220 		break;
1221 
1222 	case FUSE_ACTION_REPLACE: {
1223 		struct file *backing_file = feb->backing_file;
1224 
1225 		if (!backing_file)
1226 			return -EINVAL;
1227 		if (IS_ERR(backing_file))
1228 			return PTR_ERR(backing_file);
1229 
1230 		if (backing_inode)
1231 			iput(*backing_inode);
1232 		*backing_inode = backing_file->f_inode;
1233 		ihold(*backing_inode);
1234 
1235 		path_put(backing_path);
1236 		*backing_path = backing_file->f_path;
1237 		path_get(backing_path);
1238 		break;
1239 	}
1240 
1241 	default:
1242 		return -EINVAL;
1243 	}
1244 
1245 	return 0;
1246 }
1247 
fuse_handle_bpf_prog(struct fuse_entry_bpf * feb,struct inode * parent,struct bpf_prog ** bpf)1248 int fuse_handle_bpf_prog(struct fuse_entry_bpf *feb, struct inode *parent,
1249 			 struct bpf_prog **bpf)
1250 {
1251 	struct bpf_prog *new_bpf = NULL;
1252 
1253 	switch (feb->out.bpf_action) {
1254 	case FUSE_ACTION_KEEP: {
1255 		/* Parent isn't presented, but we want to keep
1256 		 * Don't touch bpf program at all in this case
1257 		 */
1258 		if (!parent)
1259 			return 0;
1260 
1261 		new_bpf = get_fuse_inode(parent)->bpf;
1262 		if (new_bpf)
1263 			bpf_prog_inc(new_bpf);
1264 		break;
1265 	}
1266 
1267 	case FUSE_ACTION_REMOVE:
1268 		break;
1269 
1270 	case FUSE_ACTION_REPLACE: {
1271 		struct file *bpf_file = feb->bpf_file;
1272 
1273 		if (!bpf_file)
1274 			return -EINVAL;
1275 		if (IS_ERR(bpf_file))
1276 			return PTR_ERR(bpf_file);
1277 
1278 		new_bpf = fuse_get_bpf_prog(bpf_file);
1279 		if (IS_ERR(new_bpf))
1280 			return PTR_ERR(new_bpf);
1281 		break;
1282 	}
1283 
1284 	default:
1285 		return -EINVAL;
1286 	}
1287 
1288 	/* Cannot change existing program */
1289 	if (*bpf) {
1290 		if (new_bpf)
1291 			bpf_prog_put(new_bpf);
1292 		return new_bpf == *bpf ? 0 : -EINVAL;
1293 	}
1294 
1295 	*bpf = new_bpf;
1296 	return 0;
1297 }
1298 
fuse_lookup_finalize(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,unsigned int flags)1299 struct dentry *fuse_lookup_finalize(struct fuse_bpf_args *fa, struct inode *dir,
1300 			   struct dentry *entry, unsigned int flags)
1301 {
1302 	struct fuse_dentry *fuse_entry;
1303 	struct dentry *backing_entry;
1304 	struct inode *inode = NULL, *backing_inode;
1305 	struct inode *entry_inode = entry->d_inode;
1306 	struct fuse_entry_out *feo = fa->out_args[0].value;
1307 	struct fuse_entry_bpf_out *febo = fa->out_args[1].value;
1308 	struct fuse_entry_bpf *feb = container_of(febo, struct fuse_entry_bpf,
1309 						  out);
1310 	int error = -1;
1311 	u64 target_nodeid = 0;
1312 	struct dentry *ret = NULL;
1313 
1314 	fuse_entry = get_fuse_dentry(entry);
1315 	if (!fuse_entry) {
1316 		ret = ERR_PTR(-EIO);
1317 		goto out;
1318 	}
1319 
1320 	backing_entry = fuse_entry->backing_path.dentry;
1321 	if (!backing_entry) {
1322 		ret = ERR_PTR(-ENOENT);
1323 		goto out;
1324 	}
1325 
1326 	if (entry_inode)
1327 		target_nodeid = get_fuse_inode(entry_inode)->nodeid;
1328 
1329 	backing_inode = backing_entry->d_inode;
1330 	if (backing_inode)
1331 		inode = fuse_iget_backing(dir->i_sb, target_nodeid,
1332 					  backing_inode);
1333 
1334 	error = inode ?
1335 		fuse_handle_bpf_prog(feb, dir, &get_fuse_inode(inode)->bpf) :
1336 		fuse_handle_bpf_prog(feb, dir, &fuse_entry->bpf);
1337 	if (error) {
1338 		ret = ERR_PTR(error);
1339 		goto out;
1340 	}
1341 
1342 	if (inode) {
1343 		error = fuse_handle_backing(feb,
1344 					&get_fuse_inode(inode)->backing_inode,
1345 					&fuse_entry->backing_path);
1346 		if (error) {
1347 			ret = ERR_PTR(error);
1348 			goto out;
1349 		}
1350 
1351 		get_fuse_inode(inode)->nodeid = feo->nodeid;
1352 		ret = d_splice_alias(inode, entry);
1353 		if (!IS_ERR(ret))
1354 			inode = NULL;
1355 	}
1356 out:
1357 	iput(inode);
1358 	if (feb->backing_file)
1359 		fput(feb->backing_file);
1360 	return ret;
1361 }
1362 
fuse_revalidate_backing(struct dentry * entry,unsigned int flags)1363 int fuse_revalidate_backing(struct dentry *entry, unsigned int flags)
1364 {
1365 	struct fuse_dentry *fuse_dentry = get_fuse_dentry(entry);
1366 	struct dentry *backing_entry = fuse_dentry->backing_path.dentry;
1367 
1368 	spin_lock(&backing_entry->d_lock);
1369 	if (d_unhashed(backing_entry)) {
1370 		spin_unlock(&backing_entry->d_lock);
1371 			return 0;
1372 	}
1373 	spin_unlock(&backing_entry->d_lock);
1374 
1375 	if (unlikely(backing_entry->d_flags & DCACHE_OP_REVALIDATE))
1376 		return backing_entry->d_op->d_revalidate(backing_entry, flags);
1377 	return 1;
1378 }
1379 
fuse_canonical_path_initialize(struct fuse_bpf_args * fa,struct fuse_dummy_io * fdi,const struct path * path,struct path * canonical_path)1380 int fuse_canonical_path_initialize(struct fuse_bpf_args *fa,
1381 				   struct fuse_dummy_io *fdi,
1382 				   const struct path *path,
1383 				   struct path *canonical_path)
1384 {
1385 	fa->opcode = FUSE_CANONICAL_PATH;
1386 	return 0;
1387 }
1388 
fuse_canonical_path_backing(struct fuse_bpf_args * fa,const struct path * path,struct path * canonical_path)1389 int fuse_canonical_path_backing(struct fuse_bpf_args *fa, const struct path *path,
1390 				struct path *canonical_path)
1391 {
1392 	get_fuse_backing_path(path->dentry, canonical_path);
1393 	return 0;
1394 }
1395 
fuse_canonical_path_finalize(struct fuse_bpf_args * fa,const struct path * path,struct path * canonical_path)1396 void *fuse_canonical_path_finalize(struct fuse_bpf_args *fa,
1397 				   const struct path *path,
1398 				   struct path *canonical_path)
1399 {
1400 	return NULL;
1401 }
1402 
fuse_mknod_initialize(struct fuse_bpf_args * fa,struct fuse_mknod_in * fmi,struct inode * dir,struct dentry * entry,umode_t mode,dev_t rdev)1403 int fuse_mknod_initialize(
1404 		struct fuse_bpf_args *fa, struct fuse_mknod_in *fmi,
1405 		struct inode *dir, struct dentry *entry, umode_t mode, dev_t rdev)
1406 {
1407 	*fmi = (struct fuse_mknod_in) {
1408 		.mode = mode,
1409 		.rdev = new_encode_dev(rdev),
1410 		.umask = current_umask(),
1411 	};
1412 	*fa = (struct fuse_bpf_args) {
1413 		.nodeid = get_node_id(dir),
1414 		.opcode = FUSE_MKNOD,
1415 		.in_numargs = 2,
1416 		.in_args[0] = (struct fuse_bpf_in_arg) {
1417 			.size = sizeof(*fmi),
1418 			.value = fmi,
1419 		},
1420 		.in_args[1] = (struct fuse_bpf_in_arg) {
1421 			.size = entry->d_name.len + 1,
1422 			.value = entry->d_name.name,
1423 		},
1424 	};
1425 
1426 	return 0;
1427 }
1428 
fuse_mknod_backing(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,umode_t mode,dev_t rdev)1429 int fuse_mknod_backing(
1430 		struct fuse_bpf_args *fa,
1431 		struct inode *dir, struct dentry *entry, umode_t mode, dev_t rdev)
1432 {
1433 	int err = 0;
1434 	const struct fuse_mknod_in *fmi = fa->in_args[0].value;
1435 	struct fuse_inode *fuse_inode = get_fuse_inode(dir);
1436 	struct inode *backing_inode = fuse_inode->backing_inode;
1437 	struct path backing_path = {};
1438 	struct inode *inode = NULL;
1439 
1440 	//TODO Actually deal with changing the backing entry in mknod
1441 	get_fuse_backing_path(entry, &backing_path);
1442 	if (!backing_path.dentry)
1443 		return -EBADF;
1444 
1445 	inode_lock_nested(backing_inode, I_MUTEX_PARENT);
1446 	mode = fmi->mode;
1447 	if (!IS_POSIXACL(backing_inode))
1448 		mode &= ~fmi->umask;
1449 	err = vfs_mknod(backing_inode, backing_path.dentry,
1450 			mode, new_decode_dev(fmi->rdev));
1451 	inode_unlock(backing_inode);
1452 	if (err)
1453 		goto out;
1454 	if (d_really_is_negative(backing_path.dentry) ||
1455 		unlikely(d_unhashed(backing_path.dentry))) {
1456 		err = -EINVAL;
1457 		/**
1458 		 * TODO: overlayfs responds to this situation with a
1459 		 * lookupOneLen. Should we do that too?
1460 		 */
1461 		goto out;
1462 	}
1463 	inode = fuse_iget_backing(dir->i_sb, fuse_inode->nodeid, backing_inode);
1464 	if (IS_ERR(inode)) {
1465 		err = PTR_ERR(inode);
1466 		goto out;
1467 	}
1468 	d_instantiate(entry, inode);
1469 out:
1470 	path_put(&backing_path);
1471 	return err;
1472 }
1473 
fuse_mknod_finalize(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,umode_t mode,dev_t rdev)1474 void *fuse_mknod_finalize(
1475 		struct fuse_bpf_args *fa,
1476 		struct inode *dir, struct dentry *entry, umode_t mode, dev_t rdev)
1477 {
1478 	return NULL;
1479 }
1480 
fuse_mkdir_initialize(struct fuse_bpf_args * fa,struct fuse_mkdir_in * fmi,struct inode * dir,struct dentry * entry,umode_t mode)1481 int fuse_mkdir_initialize(
1482 		struct fuse_bpf_args *fa, struct fuse_mkdir_in *fmi,
1483 		struct inode *dir, struct dentry *entry, umode_t mode)
1484 {
1485 	*fmi = (struct fuse_mkdir_in) {
1486 		.mode = mode,
1487 		.umask = current_umask(),
1488 	};
1489 	*fa = (struct fuse_bpf_args) {
1490 		.nodeid = get_node_id(dir),
1491 		.opcode = FUSE_MKDIR,
1492 		.in_numargs = 2,
1493 		.in_args[0] = (struct fuse_bpf_in_arg) {
1494 			.size = sizeof(*fmi),
1495 			.value = fmi,
1496 		},
1497 		.in_args[1] = (struct fuse_bpf_in_arg) {
1498 			.size = entry->d_name.len + 1,
1499 			.value = entry->d_name.name,
1500 		},
1501 	};
1502 
1503 	return 0;
1504 }
1505 
fuse_mkdir_backing(struct fuse_bpf_args * fa,struct inode * dir_inode,struct dentry * entry,umode_t mode)1506 int fuse_mkdir_backing(
1507 		struct fuse_bpf_args *fa,
1508 		struct inode *dir_inode, struct dentry *entry, umode_t mode)
1509 {
1510 	int err = 0;
1511 	const struct fuse_mkdir_in *fmi = fa->in_args[0].value;
1512 	struct fuse_inode *dir_fuse_inode = get_fuse_inode(dir_inode);
1513 	struct inode *dir_backing_inode = dir_fuse_inode->backing_inode;
1514 	struct path backing_path = {};
1515 	struct inode *inode = NULL;
1516 
1517 	//TODO Actually deal with changing the backing entry in mkdir
1518 	get_fuse_backing_path(entry, &backing_path);
1519 	if (!backing_path.dentry)
1520 		return -EBADF;
1521 
1522 	inode_lock_nested(dir_backing_inode, I_MUTEX_PARENT);
1523 	mode = fmi->mode;
1524 	if (!IS_POSIXACL(dir_backing_inode))
1525 		mode &= ~fmi->umask;
1526 	err = vfs_mkdir(dir_backing_inode, backing_path.dentry, mode);
1527 	if (err)
1528 		goto out;
1529 	if (d_really_is_negative(backing_path.dentry) ||
1530 		unlikely(d_unhashed(backing_path.dentry))) {
1531 		struct dentry *d = lookup_one_len(entry->d_name.name,
1532 					backing_path.dentry->d_parent,
1533 					entry->d_name.len);
1534 
1535 		if (IS_ERR(d)) {
1536 			err = PTR_ERR(d);
1537 			goto out;
1538 		}
1539 		dput(backing_path.dentry);
1540 		backing_path.dentry = d;
1541 	}
1542 	inode = fuse_iget_backing(dir_inode->i_sb, 0,
1543 				  backing_path.dentry->d_inode);
1544 	if (IS_ERR(inode)) {
1545 		err = PTR_ERR(inode);
1546 		goto out;
1547 	}
1548 	d_instantiate(entry, inode);
1549 	if (get_fuse_inode(inode)->bpf)
1550 		bpf_prog_put(get_fuse_inode(inode)->bpf);
1551 	get_fuse_inode(inode)->bpf = get_fuse_dentry(entry)->bpf;
1552 	get_fuse_dentry(entry)->bpf = NULL;
1553 out:
1554 	inode_unlock(dir_backing_inode);
1555 	path_put(&backing_path);
1556 	return err;
1557 }
1558 
fuse_mkdir_finalize(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,umode_t mode)1559 void *fuse_mkdir_finalize(
1560 		struct fuse_bpf_args *fa,
1561 		struct inode *dir, struct dentry *entry, umode_t mode)
1562 {
1563 	return NULL;
1564 }
1565 
fuse_rmdir_initialize(struct fuse_bpf_args * fa,struct fuse_dummy_io * dummy,struct inode * dir,struct dentry * entry)1566 int fuse_rmdir_initialize(
1567 		struct fuse_bpf_args *fa, struct fuse_dummy_io *dummy,
1568 		struct inode *dir, struct dentry *entry)
1569 {
1570 	*fa = (struct fuse_bpf_args) {
1571 		.nodeid = get_node_id(dir),
1572 		.opcode = FUSE_RMDIR,
1573 		.in_numargs = 1,
1574 		.in_args[0] = (struct fuse_bpf_in_arg) {
1575 			.size = entry->d_name.len + 1,
1576 			.value = entry->d_name.name,
1577 		},
1578 	};
1579 
1580 	return 0;
1581 }
1582 
fuse_rmdir_backing(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry)1583 int fuse_rmdir_backing(
1584 		struct fuse_bpf_args *fa,
1585 		struct inode *dir, struct dentry *entry)
1586 {
1587 	int err = 0;
1588 	struct path backing_path = {};
1589 	struct dentry *backing_parent_dentry;
1590 	struct inode *backing_inode;
1591 
1592 	/* TODO Actually deal with changing the backing entry in rmdir */
1593 	get_fuse_backing_path(entry, &backing_path);
1594 	if (!backing_path.dentry)
1595 		return -EBADF;
1596 
1597 	/* TODO Not sure if we should reverify like overlayfs, or get inode from d_parent */
1598 	backing_parent_dentry = dget_parent(backing_path.dentry);
1599 	backing_inode = d_inode(backing_parent_dentry);
1600 
1601 	inode_lock_nested(backing_inode, I_MUTEX_PARENT);
1602 	err = vfs_rmdir(backing_inode, backing_path.dentry);
1603 	inode_unlock(backing_inode);
1604 
1605 	dput(backing_parent_dentry);
1606 	if (!err)
1607 		d_drop(entry);
1608 	path_put(&backing_path);
1609 	return err;
1610 }
1611 
fuse_rmdir_finalize(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry)1612 void *fuse_rmdir_finalize(
1613 		struct fuse_bpf_args *fa,
1614 		struct inode *dir, struct dentry *entry)
1615 {
1616 	return NULL;
1617 }
1618 
fuse_rename_backing_common(struct inode * olddir,struct dentry * oldent,struct inode * newdir,struct dentry * newent,unsigned int flags)1619 static int fuse_rename_backing_common(
1620 			 struct inode *olddir, struct dentry *oldent,
1621 			 struct inode *newdir, struct dentry *newent,
1622 			 unsigned int flags)
1623 {
1624 	int err = 0;
1625 	struct path old_backing_path;
1626 	struct path new_backing_path;
1627 	struct dentry *old_backing_dir_dentry;
1628 	struct dentry *old_backing_dentry;
1629 	struct dentry *new_backing_dir_dentry;
1630 	struct dentry *new_backing_dentry;
1631 	struct dentry *trap = NULL;
1632 	struct inode *target_inode;
1633 
1634 	//TODO Actually deal with changing anything that isn't a flag
1635 	get_fuse_backing_path(oldent, &old_backing_path);
1636 	if (!old_backing_path.dentry)
1637 		return -EBADF;
1638 	get_fuse_backing_path(newent, &new_backing_path);
1639 	if (!new_backing_path.dentry) {
1640 		/*
1641 		 * TODO A file being moved from a backing path to another
1642 		 * backing path which is not yet instrumented with FUSE-BPF.
1643 		 * This may be slow and should be substituted with something
1644 		 * more clever.
1645 		 */
1646 		err = -EXDEV;
1647 		goto put_old_path;
1648 	}
1649 	if (new_backing_path.mnt != old_backing_path.mnt) {
1650 		err = -EXDEV;
1651 		goto put_new_path;
1652 	}
1653 	old_backing_dentry = old_backing_path.dentry;
1654 	new_backing_dentry = new_backing_path.dentry;
1655 	old_backing_dir_dentry = dget_parent(old_backing_dentry);
1656 	new_backing_dir_dentry = dget_parent(new_backing_dentry);
1657 	target_inode = d_inode(newent);
1658 
1659 	trap = lock_rename(old_backing_dir_dentry, new_backing_dir_dentry);
1660 	if (trap == old_backing_dentry) {
1661 		err = -EINVAL;
1662 		goto put_parents;
1663 	}
1664 	if (trap == new_backing_dentry) {
1665 		err = -ENOTEMPTY;
1666 		goto put_parents;
1667 	}
1668 	err = vfs_rename(d_inode(old_backing_dir_dentry), old_backing_dentry,
1669 			 d_inode(new_backing_dir_dentry), new_backing_dentry,
1670 			 NULL, flags);
1671 	if (err)
1672 		goto unlock;
1673 	if (target_inode)
1674 		fsstack_copy_attr_all(target_inode,
1675 				get_fuse_inode(target_inode)->backing_inode);
1676 	fsstack_copy_attr_all(d_inode(oldent), d_inode(old_backing_dentry));
1677 unlock:
1678 	unlock_rename(old_backing_dir_dentry, new_backing_dir_dentry);
1679 put_parents:
1680 	dput(new_backing_dir_dentry);
1681 	dput(old_backing_dir_dentry);
1682 put_new_path:
1683 	path_put(&new_backing_path);
1684 put_old_path:
1685 	path_put(&old_backing_path);
1686 	return err;
1687 }
1688 
fuse_rename2_initialize(struct fuse_bpf_args * fa,struct fuse_rename2_in * fri,struct inode * olddir,struct dentry * oldent,struct inode * newdir,struct dentry * newent,unsigned int flags)1689 int fuse_rename2_initialize(struct fuse_bpf_args *fa, struct fuse_rename2_in *fri,
1690 			    struct inode *olddir, struct dentry *oldent,
1691 			    struct inode *newdir, struct dentry *newent,
1692 			    unsigned int flags)
1693 {
1694 	*fri = (struct fuse_rename2_in) {
1695 		.newdir = get_node_id(newdir),
1696 		.flags = flags,
1697 	};
1698 	*fa = (struct fuse_bpf_args) {
1699 		.nodeid = get_node_id(olddir),
1700 		.opcode = FUSE_RENAME2,
1701 		.in_numargs = 3,
1702 		.in_args[0] = (struct fuse_bpf_in_arg) {
1703 			.size = sizeof(*fri),
1704 			.value = fri,
1705 		},
1706 		.in_args[1] = (struct fuse_bpf_in_arg) {
1707 			.size = oldent->d_name.len + 1,
1708 			.value = oldent->d_name.name,
1709 		},
1710 		.in_args[2] = (struct fuse_bpf_in_arg) {
1711 			.size = newent->d_name.len + 1,
1712 			.value = newent->d_name.name,
1713 		},
1714 	};
1715 
1716 	return 0;
1717 }
1718 
fuse_rename2_backing(struct fuse_bpf_args * fa,struct inode * olddir,struct dentry * oldent,struct inode * newdir,struct dentry * newent,unsigned int flags)1719 int fuse_rename2_backing(struct fuse_bpf_args *fa,
1720 			 struct inode *olddir, struct dentry *oldent,
1721 			 struct inode *newdir, struct dentry *newent,
1722 			 unsigned int flags)
1723 {
1724 	const struct fuse_rename2_in *fri = fa->in_args[0].value;
1725 
1726 	/* TODO: deal with changing dirs/ents */
1727 	return fuse_rename_backing_common(olddir, oldent, newdir, newent, fri->flags);
1728 }
1729 
fuse_rename2_finalize(struct fuse_bpf_args * fa,struct inode * olddir,struct dentry * oldent,struct inode * newdir,struct dentry * newent,unsigned int flags)1730 void *fuse_rename2_finalize(struct fuse_bpf_args *fa,
1731 			    struct inode *olddir, struct dentry *oldent,
1732 			    struct inode *newdir, struct dentry *newent,
1733 			    unsigned int flags)
1734 {
1735 	return NULL;
1736 }
1737 
fuse_rename_initialize(struct fuse_bpf_args * fa,struct fuse_rename_in * fri,struct inode * olddir,struct dentry * oldent,struct inode * newdir,struct dentry * newent)1738 int fuse_rename_initialize(struct fuse_bpf_args *fa, struct fuse_rename_in *fri,
1739 			   struct inode *olddir, struct dentry *oldent,
1740 			   struct inode *newdir, struct dentry *newent)
1741 {
1742 	*fri = (struct fuse_rename_in) {
1743 		.newdir = get_node_id(newdir),
1744 	};
1745 	*fa = (struct fuse_bpf_args) {
1746 		.nodeid = get_node_id(olddir),
1747 		.opcode = FUSE_RENAME,
1748 		.in_numargs = 3,
1749 		.in_args[0] = (struct fuse_bpf_in_arg) {
1750 			.size = sizeof(*fri),
1751 			.value = fri,
1752 		},
1753 		.in_args[1] = (struct fuse_bpf_in_arg) {
1754 			.size = oldent->d_name.len + 1,
1755 			.value = oldent->d_name.name,
1756 		},
1757 		.in_args[2] = (struct fuse_bpf_in_arg) {
1758 			.size = newent->d_name.len + 1,
1759 			.value = newent->d_name.name,
1760 		},
1761 	};
1762 
1763 	return 0;
1764 }
1765 
fuse_rename_backing(struct fuse_bpf_args * fa,struct inode * olddir,struct dentry * oldent,struct inode * newdir,struct dentry * newent)1766 int fuse_rename_backing(struct fuse_bpf_args *fa,
1767 			struct inode *olddir, struct dentry *oldent,
1768 			struct inode *newdir, struct dentry *newent)
1769 {
1770 	/* TODO: deal with changing dirs/ents */
1771 	return fuse_rename_backing_common(olddir, oldent, newdir, newent, 0);
1772 }
1773 
fuse_rename_finalize(struct fuse_bpf_args * fa,struct inode * olddir,struct dentry * oldent,struct inode * newdir,struct dentry * newent)1774 void *fuse_rename_finalize(struct fuse_bpf_args *fa,
1775 			   struct inode *olddir, struct dentry *oldent,
1776 			   struct inode *newdir, struct dentry *newent)
1777 {
1778 	return NULL;
1779 }
1780 
fuse_unlink_initialize(struct fuse_bpf_args * fa,struct fuse_dummy_io * dummy,struct inode * dir,struct dentry * entry)1781 int fuse_unlink_initialize(
1782 		struct fuse_bpf_args *fa, struct fuse_dummy_io *dummy,
1783 		struct inode *dir, struct dentry *entry)
1784 {
1785 	*fa = (struct fuse_bpf_args) {
1786 		.nodeid = get_node_id(dir),
1787 		.opcode = FUSE_UNLINK,
1788 		.in_numargs = 1,
1789 		.in_args[0] = (struct fuse_bpf_in_arg) {
1790 			.size = entry->d_name.len + 1,
1791 			.value = entry->d_name.name,
1792 		},
1793 	};
1794 
1795 	return 0;
1796 }
1797 
fuse_unlink_backing(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry)1798 int fuse_unlink_backing(
1799 		struct fuse_bpf_args *fa,
1800 		struct inode *dir, struct dentry *entry)
1801 {
1802 	int err = 0;
1803 	struct path backing_path = {};
1804 	struct dentry *backing_parent_dentry;
1805 	struct inode *backing_inode;
1806 
1807 	/* TODO Actually deal with changing the backing entry in unlink */
1808 	get_fuse_backing_path(entry, &backing_path);
1809 	if (!backing_path.dentry)
1810 		return -EBADF;
1811 
1812 	/* TODO Not sure if we should reverify like overlayfs, or get inode from d_parent */
1813 	backing_parent_dentry = dget_parent(backing_path.dentry);
1814 	backing_inode = d_inode(backing_parent_dentry);
1815 
1816 	inode_lock_nested(backing_inode, I_MUTEX_PARENT);
1817 	err = vfs_unlink(backing_inode, backing_path.dentry, NULL);
1818 	inode_unlock(backing_inode);
1819 
1820 	dput(backing_parent_dentry);
1821 	if (!err)
1822 		d_drop(entry);
1823 	path_put(&backing_path);
1824 	return err;
1825 }
1826 
fuse_unlink_finalize(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry)1827 void *fuse_unlink_finalize(
1828 		struct fuse_bpf_args *fa,
1829 		struct inode *dir, struct dentry *entry)
1830 {
1831 	return NULL;
1832 }
1833 
fuse_link_initialize(struct fuse_bpf_args * fa,struct fuse_link_in * fli,struct dentry * entry,struct inode * dir,struct dentry * newent)1834 int fuse_link_initialize(struct fuse_bpf_args *fa, struct fuse_link_in *fli,
1835 			 struct dentry *entry, struct inode *dir,
1836 			 struct dentry *newent)
1837 {
1838 	struct inode *src_inode = entry->d_inode;
1839 
1840 	*fli = (struct fuse_link_in){
1841 		.oldnodeid = get_node_id(src_inode),
1842 	};
1843 
1844 	fa->opcode = FUSE_LINK;
1845 	fa->in_numargs = 2;
1846 	fa->in_args[0].size = sizeof(*fli);
1847 	fa->in_args[0].value = fli;
1848 	fa->in_args[1].size = newent->d_name.len + 1;
1849 	fa->in_args[1].value = newent->d_name.name;
1850 
1851 	return 0;
1852 }
1853 
fuse_link_backing(struct fuse_bpf_args * fa,struct dentry * entry,struct inode * dir,struct dentry * newent)1854 int fuse_link_backing(struct fuse_bpf_args *fa, struct dentry *entry,
1855 		      struct inode *dir, struct dentry *newent)
1856 {
1857 	int err = 0;
1858 	struct path backing_old_path = {};
1859 	struct path backing_new_path = {};
1860 	struct dentry *backing_dir_dentry;
1861 	struct inode *fuse_new_inode = NULL;
1862 	struct fuse_inode *fuse_dir_inode = get_fuse_inode(dir);
1863 	struct inode *backing_dir_inode = fuse_dir_inode->backing_inode;
1864 
1865 	get_fuse_backing_path(entry, &backing_old_path);
1866 	if (!backing_old_path.dentry)
1867 		return -EBADF;
1868 
1869 	get_fuse_backing_path(newent, &backing_new_path);
1870 	if (!backing_new_path.dentry) {
1871 		err = -EBADF;
1872 		goto err_dst_path;
1873 	}
1874 
1875 	backing_dir_dentry = dget_parent(backing_new_path.dentry);
1876 	backing_dir_inode = d_inode(backing_dir_dentry);
1877 
1878 	inode_lock_nested(backing_dir_inode, I_MUTEX_PARENT);
1879 	err = vfs_link(backing_old_path.dentry, backing_dir_inode, backing_new_path.dentry, NULL);
1880 	inode_unlock(backing_dir_inode);
1881 	if (err)
1882 		goto out;
1883 
1884 	if (d_really_is_negative(backing_new_path.dentry) ||
1885 	    unlikely(d_unhashed(backing_new_path.dentry))) {
1886 		err = -EINVAL;
1887 		/**
1888 		 * TODO: overlayfs responds to this situation with a
1889 		 * lookupOneLen. Should we do that too?
1890 		 */
1891 		goto out;
1892 	}
1893 
1894 	fuse_new_inode = fuse_iget_backing(dir->i_sb, fuse_dir_inode->nodeid, backing_dir_inode);
1895 	if (IS_ERR(fuse_new_inode)) {
1896 		err = PTR_ERR(fuse_new_inode);
1897 		goto out;
1898 	}
1899 	d_instantiate(newent, fuse_new_inode);
1900 
1901 out:
1902 	dput(backing_dir_dentry);
1903 	path_put(&backing_new_path);
1904 err_dst_path:
1905 	path_put(&backing_old_path);
1906 	return err;
1907 }
1908 
fuse_link_finalize(struct fuse_bpf_args * fa,struct dentry * entry,struct inode * dir,struct dentry * newent)1909 void *fuse_link_finalize(struct fuse_bpf_args *fa, struct dentry *entry,
1910 			 struct inode *dir, struct dentry *newent)
1911 {
1912 	return NULL;
1913 }
1914 
fuse_getattr_initialize(struct fuse_bpf_args * fa,struct fuse_getattr_io * fgio,const struct dentry * entry,struct kstat * stat,u32 request_mask,unsigned int flags)1915 int fuse_getattr_initialize(struct fuse_bpf_args *fa, struct fuse_getattr_io *fgio,
1916 			const struct dentry *entry, struct kstat *stat,
1917 			u32 request_mask, unsigned int flags)
1918 {
1919 	fgio->fgi = (struct fuse_getattr_in) {
1920 		.getattr_flags = flags,
1921 		.fh = -1, /* TODO is this OK? */
1922 	};
1923 
1924 	fgio->fao = (struct fuse_attr_out) {0};
1925 
1926 	*fa = (struct fuse_bpf_args) {
1927 		.nodeid = get_node_id(entry->d_inode),
1928 		.opcode = FUSE_GETATTR,
1929 		.in_numargs = 1,
1930 		.out_numargs = 1,
1931 		.in_args[0] = (struct fuse_bpf_in_arg) {
1932 			.size = sizeof(fgio->fgi),
1933 			.value = &fgio->fgi,
1934 		},
1935 		.out_args[0] = (struct fuse_bpf_arg) {
1936 			.size = sizeof(fgio->fao),
1937 			.value = &fgio->fao,
1938 		},
1939 	};
1940 
1941 	return 0;
1942 }
1943 
fuse_stat_to_attr(struct fuse_conn * fc,struct inode * inode,struct kstat * stat,struct fuse_attr * attr)1944 static void fuse_stat_to_attr(struct fuse_conn *fc, struct inode *inode,
1945 		struct kstat *stat, struct fuse_attr *attr)
1946 {
1947 	unsigned int blkbits;
1948 
1949 	/* see the comment in fuse_change_attributes() */
1950 	if (fc->writeback_cache && S_ISREG(inode->i_mode)) {
1951 		stat->size = i_size_read(inode);
1952 		stat->mtime.tv_sec = inode->i_mtime.tv_sec;
1953 		stat->mtime.tv_nsec = inode->i_mtime.tv_nsec;
1954 		stat->ctime.tv_sec = inode->i_ctime.tv_sec;
1955 		stat->ctime.tv_nsec = inode->i_ctime.tv_nsec;
1956 	}
1957 
1958 	attr->ino = stat->ino;
1959 	attr->mode = (inode->i_mode & S_IFMT) | (stat->mode & 07777);
1960 	attr->nlink = stat->nlink;
1961 	attr->uid = from_kuid(fc->user_ns, stat->uid);
1962 	attr->gid = from_kgid(fc->user_ns, stat->gid);
1963 	attr->atime = stat->atime.tv_sec;
1964 	attr->atimensec = stat->atime.tv_nsec;
1965 	attr->mtime = stat->mtime.tv_sec;
1966 	attr->mtimensec = stat->mtime.tv_nsec;
1967 	attr->ctime = stat->ctime.tv_sec;
1968 	attr->ctimensec = stat->ctime.tv_nsec;
1969 	attr->size = stat->size;
1970 	attr->blocks = stat->blocks;
1971 
1972 	if (stat->blksize != 0)
1973 		blkbits = ilog2(stat->blksize);
1974 	else
1975 		blkbits = inode->i_sb->s_blocksize_bits;
1976 
1977 	attr->blksize = 1 << blkbits;
1978 }
1979 
fuse_getattr_backing(struct fuse_bpf_args * fa,const struct dentry * entry,struct kstat * stat,u32 request_mask,unsigned int flags)1980 int fuse_getattr_backing(struct fuse_bpf_args *fa,
1981 		const struct dentry *entry, struct kstat *stat,
1982 			u32 request_mask, unsigned int flags)
1983 {
1984 	struct path *backing_path =
1985 		&get_fuse_dentry(entry)->backing_path;
1986 	struct inode *backing_inode = backing_path->dentry->d_inode;
1987 	struct fuse_attr_out *fao = fa->out_args[0].value;
1988 	struct kstat tmp;
1989 	int err;
1990 
1991 	if (!stat)
1992 		stat = &tmp;
1993 
1994 	err = vfs_getattr(backing_path, stat, request_mask, flags);
1995 
1996 	if (!err)
1997 		fuse_stat_to_attr(get_fuse_conn(entry->d_inode),
1998 				  backing_inode, stat, &fao->attr);
1999 
2000 	return err;
2001 }
2002 
fuse_getattr_finalize(struct fuse_bpf_args * fa,const struct dentry * entry,struct kstat * stat,u32 request_mask,unsigned int flags)2003 void *fuse_getattr_finalize(struct fuse_bpf_args *fa,
2004 			const struct dentry *entry, struct kstat *stat,
2005 			u32 request_mask, unsigned int flags)
2006 {
2007 	struct fuse_attr_out *outarg = fa->out_args[0].value;
2008 	struct inode *inode = entry->d_inode;
2009 	u64 attr_version = fuse_get_attr_version(get_fuse_mount(inode)->fc);
2010 	int err = 0;
2011 
2012 	/* TODO: Ensure this doesn't happen if we had an error getting attrs in
2013 	 * backing.
2014 	 */
2015 	err = finalize_attr(inode, outarg, attr_version, stat);
2016 	return ERR_PTR(err);
2017 }
2018 
fattr_to_iattr(struct fuse_conn * fc,const struct fuse_setattr_in * arg,struct iattr * iattr)2019 static void fattr_to_iattr(struct fuse_conn *fc,
2020 			   const struct fuse_setattr_in *arg,
2021 			   struct iattr *iattr)
2022 {
2023 	unsigned int fvalid = arg->valid;
2024 
2025 	if (fvalid & FATTR_MODE)
2026 		iattr->ia_valid |= ATTR_MODE, iattr->ia_mode = arg->mode;
2027 	if (fvalid & FATTR_UID) {
2028 		iattr->ia_valid |= ATTR_UID;
2029 		iattr->ia_uid = make_kuid(fc->user_ns, arg->uid);
2030 	}
2031 	if (fvalid & FATTR_GID) {
2032 		iattr->ia_valid |= ATTR_GID;
2033 		iattr->ia_gid = make_kgid(fc->user_ns, arg->gid);
2034 	}
2035 	if (fvalid & FATTR_SIZE)
2036 		iattr->ia_valid |= ATTR_SIZE,  iattr->ia_size = arg->size;
2037 	if (fvalid & FATTR_ATIME) {
2038 		iattr->ia_valid |= ATTR_ATIME;
2039 		iattr->ia_atime.tv_sec = arg->atime;
2040 		iattr->ia_atime.tv_nsec = arg->atimensec;
2041 		if (!(fvalid & FATTR_ATIME_NOW))
2042 			iattr->ia_valid |= ATTR_ATIME_SET;
2043 	}
2044 	if (fvalid & FATTR_MTIME) {
2045 		iattr->ia_valid |= ATTR_MTIME;
2046 		iattr->ia_mtime.tv_sec = arg->mtime;
2047 		iattr->ia_mtime.tv_nsec = arg->mtimensec;
2048 		if (!(fvalid & FATTR_MTIME_NOW))
2049 			iattr->ia_valid |= ATTR_MTIME_SET;
2050 	}
2051 	if (fvalid & FATTR_CTIME) {
2052 		iattr->ia_valid |= ATTR_CTIME;
2053 		iattr->ia_ctime.tv_sec = arg->ctime;
2054 		iattr->ia_ctime.tv_nsec = arg->ctimensec;
2055 	}
2056 }
2057 
fuse_setattr_initialize(struct fuse_bpf_args * fa,struct fuse_setattr_io * fsio,struct dentry * dentry,struct iattr * attr,struct file * file)2058 int fuse_setattr_initialize(struct fuse_bpf_args *fa, struct fuse_setattr_io *fsio,
2059 		struct dentry *dentry, struct iattr *attr, struct file *file)
2060 {
2061 	struct fuse_conn *fc = get_fuse_conn(dentry->d_inode);
2062 
2063 	*fsio = (struct fuse_setattr_io) {0};
2064 	iattr_to_fattr(fc, attr, &fsio->fsi, true);
2065 
2066 	*fa = (struct fuse_bpf_args) {
2067 		.opcode = FUSE_SETATTR,
2068 		.nodeid = get_node_id(dentry->d_inode),
2069 		.in_numargs = 1,
2070 		.in_args[0].size = sizeof(fsio->fsi),
2071 		.in_args[0].value = &fsio->fsi,
2072 		.out_numargs = 1,
2073 		.out_args[0].size = sizeof(fsio->fao),
2074 		.out_args[0].value = &fsio->fao,
2075 	};
2076 
2077 	return 0;
2078 }
2079 
fuse_setattr_backing(struct fuse_bpf_args * fa,struct dentry * dentry,struct iattr * attr,struct file * file)2080 int fuse_setattr_backing(struct fuse_bpf_args *fa,
2081 		struct dentry *dentry, struct iattr *attr, struct file *file)
2082 {
2083 	struct fuse_conn *fc = get_fuse_conn(dentry->d_inode);
2084 	const struct fuse_setattr_in *fsi = fa->in_args[0].value;
2085 	struct iattr new_attr = {0};
2086 	struct path *backing_path = &get_fuse_dentry(dentry)->backing_path;
2087 	int res;
2088 
2089 	fattr_to_iattr(fc, fsi, &new_attr);
2090 	/* TODO: Some info doesn't get saved by the attr->fattr->attr transition
2091 	 * When we actually allow the bpf to change these, we may have to consider
2092 	 * the extra flags more, or pass more info into the bpf. Until then we can
2093 	 * keep everything except for ATTR_FILE, since we'd need a file on the
2094 	 * lower fs. For what it's worth, neither f2fs nor ext4 make use of that
2095 	 * even if it is present.
2096 	 */
2097 	new_attr.ia_valid = attr->ia_valid & ~ATTR_FILE;
2098 	inode_lock(d_inode(backing_path->dentry));
2099 	res = notify_change(backing_path->dentry, &new_attr, NULL);
2100 	inode_unlock(d_inode(backing_path->dentry));
2101 
2102 	if (res == 0 && (new_attr.ia_valid & ATTR_SIZE))
2103 		i_size_write(dentry->d_inode, new_attr.ia_size);
2104 	return res;
2105 }
2106 
fuse_setattr_finalize(struct fuse_bpf_args * fa,struct dentry * dentry,struct iattr * attr,struct file * file)2107 void *fuse_setattr_finalize(struct fuse_bpf_args *fa,
2108 		struct dentry *dentry, struct iattr *attr, struct file *file)
2109 {
2110 	return NULL;
2111 }
2112 
fuse_statfs_initialize(struct fuse_bpf_args * fa,struct fuse_statfs_out * fso,struct dentry * dentry,struct kstatfs * buf)2113 int fuse_statfs_initialize(
2114 		struct fuse_bpf_args *fa, struct fuse_statfs_out *fso,
2115 		struct dentry *dentry, struct kstatfs *buf)
2116 {
2117 	*fso = (struct fuse_statfs_out) {0};
2118 	*fa = (struct fuse_bpf_args) {
2119 		.nodeid = get_node_id(d_inode(dentry)),
2120 		.opcode = FUSE_STATFS,
2121 		.out_numargs = 1,
2122 		.out_numargs = 1,
2123 		.out_args[0].size = sizeof(fso),
2124 		.out_args[0].value = fso,
2125 	};
2126 
2127 	return 0;
2128 }
2129 
fuse_statfs_backing(struct fuse_bpf_args * fa,struct dentry * dentry,struct kstatfs * buf)2130 int fuse_statfs_backing(
2131 		struct fuse_bpf_args *fa,
2132 		struct dentry *dentry, struct kstatfs *buf)
2133 {
2134 	int err = 0;
2135 	struct path backing_path;
2136 	struct fuse_statfs_out *fso = fa->out_args[0].value;
2137 
2138 	get_fuse_backing_path(dentry, &backing_path);
2139 	if (!backing_path.dentry)
2140 		return -EBADF;
2141 	err = vfs_statfs(&backing_path, buf);
2142 	path_put(&backing_path);
2143 	buf->f_type = FUSE_SUPER_MAGIC;
2144 
2145 	//TODO Provide postfilter opportunity to modify
2146 	if (!err)
2147 		convert_statfs_to_fuse(&fso->st, buf);
2148 
2149 	return err;
2150 }
2151 
fuse_statfs_finalize(struct fuse_bpf_args * fa,struct dentry * dentry,struct kstatfs * buf)2152 void *fuse_statfs_finalize(
2153 		struct fuse_bpf_args *fa,
2154 		struct dentry *dentry, struct kstatfs *buf)
2155 {
2156 	struct fuse_statfs_out *fso = fa->out_args[0].value;
2157 
2158 	if (!fa->error_in)
2159 		convert_fuse_statfs(buf, &fso->st);
2160 	return NULL;
2161 }
2162 
fuse_get_link_initialize(struct fuse_bpf_args * fa,struct fuse_dummy_io * unused,struct inode * inode,struct dentry * dentry,struct delayed_call * callback,const char ** out)2163 int fuse_get_link_initialize(struct fuse_bpf_args *fa, struct fuse_dummy_io *unused,
2164 		struct inode *inode, struct dentry *dentry,
2165 		struct delayed_call *callback, const char **out)
2166 {
2167 	/*
2168 	 * TODO
2169 	 * If we want to handle changing these things, we'll need to copy
2170 	 * the lower fs's data into our own buffer, and provide our own callback
2171 	 * to free that buffer.
2172 	 *
2173 	 * Pre could change the name we're looking at
2174 	 * postfilter can change the name we return
2175 	 *
2176 	 * We ought to only make that buffer if it's been requested, so leaving
2177 	 * this unimplemented for the moment
2178 	 */
2179 	*fa = (struct fuse_bpf_args) {
2180 		.opcode = FUSE_READLINK,
2181 		.nodeid = get_node_id(inode),
2182 		.in_numargs = 1,
2183 		.in_args[0] = (struct fuse_bpf_in_arg) {
2184 			.size = dentry->d_name.len + 1,
2185 			.value = dentry->d_name.name,
2186 		},
2187 		/*
2188 		 * .out_argvar = 1,
2189 		 * .out_numargs = 1,
2190 		 * .out_args[0].size = ,
2191 		 * .out_args[0].value = ,
2192 		 */
2193 	};
2194 
2195 	return 0;
2196 }
2197 
fuse_get_link_backing(struct fuse_bpf_args * fa,struct inode * inode,struct dentry * dentry,struct delayed_call * callback,const char ** out)2198 int fuse_get_link_backing(struct fuse_bpf_args *fa,
2199 		struct inode *inode, struct dentry *dentry,
2200 		struct delayed_call *callback, const char **out)
2201 {
2202 	struct path backing_path;
2203 
2204 	if (!dentry) {
2205 		*out = ERR_PTR(-ECHILD);
2206 		return PTR_ERR(*out);
2207 	}
2208 
2209 	get_fuse_backing_path(dentry, &backing_path);
2210 	if (!backing_path.dentry) {
2211 		*out = ERR_PTR(-ECHILD);
2212 		return PTR_ERR(*out);
2213 	}
2214 
2215 	/*
2216 	 * TODO: If we want to do our own thing, copy the data and then call the
2217 	 * callback
2218 	 */
2219 	*out = vfs_get_link(backing_path.dentry, callback);
2220 
2221 	path_put(&backing_path);
2222 	return 0;
2223 }
2224 
fuse_get_link_finalize(struct fuse_bpf_args * fa,struct inode * inode,struct dentry * dentry,struct delayed_call * callback,const char ** out)2225 void *fuse_get_link_finalize(struct fuse_bpf_args *fa,
2226 		struct inode *inode, struct dentry *dentry,
2227 		struct delayed_call *callback,  const char **out)
2228 {
2229 	return NULL;
2230 }
2231 
fuse_symlink_initialize(struct fuse_bpf_args * fa,struct fuse_dummy_io * unused,struct inode * dir,struct dentry * entry,const char * link,int len)2232 int fuse_symlink_initialize(
2233 		struct fuse_bpf_args *fa, struct fuse_dummy_io *unused,
2234 		struct inode *dir, struct dentry *entry, const char *link, int len)
2235 {
2236 	*fa = (struct fuse_bpf_args) {
2237 		.nodeid = get_node_id(dir),
2238 		.opcode = FUSE_SYMLINK,
2239 		.in_numargs = 2,
2240 		.in_args[0] = (struct fuse_bpf_in_arg) {
2241 			.size = entry->d_name.len + 1,
2242 			.value = entry->d_name.name,
2243 		},
2244 		.in_args[1] = (struct fuse_bpf_in_arg) {
2245 			.size = len,
2246 			.value = link,
2247 		},
2248 	};
2249 
2250 	return 0;
2251 }
2252 
fuse_symlink_backing(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,const char * link,int len)2253 int fuse_symlink_backing(
2254 		struct fuse_bpf_args *fa,
2255 		struct inode *dir, struct dentry *entry, const char *link, int len)
2256 {
2257 	int err = 0;
2258 	struct fuse_inode *fuse_inode = get_fuse_inode(dir);
2259 	struct inode *backing_inode = fuse_inode->backing_inode;
2260 	struct path backing_path = {};
2261 	struct inode *inode = NULL;
2262 
2263 	//TODO Actually deal with changing the backing entry in symlink
2264 	get_fuse_backing_path(entry, &backing_path);
2265 	if (!backing_path.dentry)
2266 		return -EBADF;
2267 
2268 	inode_lock_nested(backing_inode, I_MUTEX_PARENT);
2269 	err = vfs_symlink(backing_inode, backing_path.dentry, link);
2270 	inode_unlock(backing_inode);
2271 	if (err)
2272 		goto out;
2273 	if (d_really_is_negative(backing_path.dentry) ||
2274 		unlikely(d_unhashed(backing_path.dentry))) {
2275 		err = -EINVAL;
2276 		/**
2277 		 * TODO: overlayfs responds to this situation with a
2278 		 * lookupOneLen. Should we do that too?
2279 		 */
2280 		goto out;
2281 	}
2282 	inode = fuse_iget_backing(dir->i_sb, fuse_inode->nodeid, backing_inode);
2283 	if (IS_ERR(inode)) {
2284 		err = PTR_ERR(inode);
2285 		goto out;
2286 	}
2287 	d_instantiate(entry, inode);
2288 out:
2289 	path_put(&backing_path);
2290 	return err;
2291 }
2292 
fuse_symlink_finalize(struct fuse_bpf_args * fa,struct inode * dir,struct dentry * entry,const char * link,int len)2293 void *fuse_symlink_finalize(
2294 		struct fuse_bpf_args *fa,
2295 		struct inode *dir, struct dentry *entry, const char *link, int len)
2296 {
2297 	return NULL;
2298 }
2299 
fuse_readdir_initialize(struct fuse_bpf_args * fa,struct fuse_read_io * frio,struct file * file,struct dir_context * ctx,bool * force_again,bool * allow_force,bool is_continued)2300 int fuse_readdir_initialize(struct fuse_bpf_args *fa, struct fuse_read_io *frio,
2301 			    struct file *file, struct dir_context *ctx,
2302 			    bool *force_again, bool *allow_force, bool is_continued)
2303 {
2304 	struct fuse_file *ff = file->private_data;
2305 	u8 *page = (u8 *)__get_free_page(GFP_KERNEL);
2306 
2307 	if (!page)
2308 		return -ENOMEM;
2309 
2310 	*fa = (struct fuse_bpf_args) {
2311 		.nodeid = ff->nodeid,
2312 		.opcode = FUSE_READDIR,
2313 		.in_numargs = 1,
2314 		.flags = FUSE_BPF_OUT_ARGVAR,
2315 		.out_numargs = 2,
2316 		.in_args[0] = (struct fuse_bpf_in_arg) {
2317 			.size = sizeof(frio->fri),
2318 			.value = &frio->fri,
2319 		},
2320 		.out_args[0] = (struct fuse_bpf_arg) {
2321 			.size = sizeof(frio->fro),
2322 			.value = &frio->fro,
2323 		},
2324 		.out_args[1] = (struct fuse_bpf_arg) {
2325 			.size = PAGE_SIZE,
2326 			.value = page,
2327 		},
2328 	};
2329 
2330 	frio->fri = (struct fuse_read_in) {
2331 		.fh = ff->fh,
2332 		.offset = ctx->pos,
2333 		.size = PAGE_SIZE,
2334 	};
2335 	frio->fro = (struct fuse_read_out) {
2336 		.again = 0,
2337 		.offset = 0,
2338 	};
2339 	*force_again = false;
2340 	*allow_force = true;
2341 	return 0;
2342 }
2343 
2344 struct extfuse_ctx {
2345 	struct dir_context ctx;
2346 	u8 *addr;
2347 	size_t offset;
2348 };
2349 
filldir(struct dir_context * ctx,const char * name,int namelen,loff_t offset,u64 ino,unsigned int d_type)2350 static int filldir(struct dir_context *ctx, const char *name, int namelen,
2351 				   loff_t offset, u64 ino, unsigned int d_type)
2352 {
2353 	struct extfuse_ctx *ec = container_of(ctx, struct extfuse_ctx, ctx);
2354 	struct fuse_dirent *fd = (struct fuse_dirent *) (ec->addr + ec->offset);
2355 
2356 	if (ec->offset + sizeof(struct fuse_dirent) + namelen > PAGE_SIZE)
2357 		return -ENOMEM;
2358 
2359 	*fd = (struct fuse_dirent) {
2360 		.ino = ino,
2361 		.off = offset,
2362 		.namelen = namelen,
2363 		.type = d_type,
2364 	};
2365 
2366 	memcpy(fd->name, name, namelen);
2367 	ec->offset += FUSE_DIRENT_SIZE(fd);
2368 
2369 	return 0;
2370 }
2371 
parse_dirfile(char * buf,size_t nbytes,struct dir_context * ctx)2372 static int parse_dirfile(char *buf, size_t nbytes, struct dir_context *ctx)
2373 {
2374 	while (nbytes >= FUSE_NAME_OFFSET) {
2375 		struct fuse_dirent *dirent = (struct fuse_dirent *) buf;
2376 		size_t reclen = FUSE_DIRENT_SIZE(dirent);
2377 
2378 		if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX)
2379 			return -EIO;
2380 		if (reclen > nbytes)
2381 			break;
2382 		if (memchr(dirent->name, '/', dirent->namelen) != NULL)
2383 			return -EIO;
2384 
2385 		ctx->pos = dirent->off;
2386 		if (!dir_emit(ctx, dirent->name, dirent->namelen, dirent->ino,
2387 				dirent->type))
2388 			break;
2389 
2390 		buf += reclen;
2391 		nbytes -= reclen;
2392 	}
2393 
2394 	return 0;
2395 }
2396 
2397 
fuse_readdir_backing(struct fuse_bpf_args * fa,struct file * file,struct dir_context * ctx,bool * force_again,bool * allow_force,bool is_continued)2398 int fuse_readdir_backing(struct fuse_bpf_args *fa,
2399 			 struct file *file, struct dir_context *ctx,
2400 			 bool *force_again, bool *allow_force, bool is_continued)
2401 {
2402 	struct fuse_file *ff = file->private_data;
2403 	struct file *backing_dir = ff->backing_file;
2404 	struct fuse_read_out *fro = fa->out_args[0].value;
2405 	struct extfuse_ctx ec;
2406 	int err;
2407 
2408 	ec = (struct extfuse_ctx) {
2409 		.ctx.actor = filldir,
2410 		.ctx.pos = ctx->pos,
2411 		.addr = fa->out_args[1].value,
2412 	};
2413 
2414 	if (!ec.addr)
2415 		return -ENOMEM;
2416 
2417 	if (!is_continued)
2418 		backing_dir->f_pos = file->f_pos;
2419 
2420 	err = iterate_dir(backing_dir, &ec.ctx);
2421 	if (ec.offset == 0)
2422 		*allow_force = false;
2423 	fa->out_args[1].size = ec.offset;
2424 
2425 	fro->offset = ec.ctx.pos;
2426 	fro->again = false;
2427 	return err;
2428 }
2429 
fuse_readdir_finalize(struct fuse_bpf_args * fa,struct file * file,struct dir_context * ctx,bool * force_again,bool * allow_force,bool is_continued)2430 void *fuse_readdir_finalize(struct fuse_bpf_args *fa,
2431 			    struct file *file, struct dir_context *ctx,
2432 			    bool *force_again, bool *allow_force, bool is_continued)
2433 {
2434 	struct fuse_read_out *fro = fa->out_args[0].value;
2435 	struct fuse_file *ff = file->private_data;
2436 	struct file *backing_dir = ff->backing_file;
2437 	int err = 0;
2438 
2439 	err = parse_dirfile(fa->out_args[1].value, fa->out_args[1].size, ctx);
2440 	*force_again = !!fro->again;
2441 	if (*force_again && !*allow_force)
2442 		err = -EINVAL;
2443 
2444 	ctx->pos = fro->offset;
2445 	backing_dir->f_pos = fro->offset;
2446 
2447 	free_page((unsigned long) fa->out_args[1].value);
2448 	return ERR_PTR(err);
2449 }
2450 
fuse_access_initialize(struct fuse_bpf_args * fa,struct fuse_access_in * fai,struct inode * inode,int mask)2451 int fuse_access_initialize(struct fuse_bpf_args *fa, struct fuse_access_in *fai,
2452 			    struct inode *inode, int mask)
2453 {
2454 	*fai = (struct fuse_access_in) {
2455 		.mask = mask,
2456 	};
2457 
2458 	*fa = (struct fuse_bpf_args) {
2459 		.opcode = FUSE_ACCESS,
2460 		.nodeid = get_node_id(inode),
2461 		.in_numargs = 1,
2462 		.in_args[0].size = sizeof(*fai),
2463 		.in_args[0].value = fai,
2464 	};
2465 
2466 	return 0;
2467 }
2468 
fuse_access_backing(struct fuse_bpf_args * fa,struct inode * inode,int mask)2469 int fuse_access_backing(struct fuse_bpf_args *fa, struct inode *inode, int mask)
2470 {
2471 	struct fuse_inode *fi = get_fuse_inode(inode);
2472 	const struct fuse_access_in *fai = fa->in_args[0].value;
2473 
2474 	return inode_permission(/* For mainline: init_user_ns,*/
2475 				fi->backing_inode, fai->mask);
2476 }
2477 
fuse_access_finalize(struct fuse_bpf_args * fa,struct inode * inode,int mask)2478 void *fuse_access_finalize(struct fuse_bpf_args *fa, struct inode *inode, int mask)
2479 {
2480 	return NULL;
2481 }
2482 
fuse_bpf_init(void)2483 int __init fuse_bpf_init(void)
2484 {
2485 	fuse_bpf_aio_request_cachep = kmem_cache_create("fuse_bpf_aio_req",
2486 						   sizeof(struct fuse_bpf_aio_req),
2487 						   0, SLAB_HWCACHE_ALIGN, NULL);
2488 	if (!fuse_bpf_aio_request_cachep)
2489 		return -ENOMEM;
2490 
2491 	return 0;
2492 }
2493 
fuse_bpf_cleanup(void)2494 void __exit fuse_bpf_cleanup(void)
2495 {
2496 	kmem_cache_destroy(fuse_bpf_aio_request_cachep);
2497 }
2498 
fuse_bpf_simple_request(struct fuse_mount * fm,struct fuse_bpf_args * bpf_args)2499 ssize_t fuse_bpf_simple_request(struct fuse_mount *fm, struct fuse_bpf_args *bpf_args)
2500 {
2501 	int i;
2502 	ssize_t res;
2503 	struct fuse_args args = {
2504 		.nodeid = bpf_args->nodeid,
2505 		.opcode = bpf_args->opcode,
2506 		.error_in = bpf_args->error_in,
2507 		.in_numargs = bpf_args->in_numargs,
2508 		.out_numargs = bpf_args->out_numargs,
2509 		.force = !!(bpf_args->flags & FUSE_BPF_FORCE),
2510 		.out_argvar = !!(bpf_args->flags & FUSE_BPF_OUT_ARGVAR),
2511 	};
2512 
2513 	for (i = 0; i < args.in_numargs; ++i)
2514 		args.in_args[i] = (struct fuse_in_arg) {
2515 			.size = bpf_args->in_args[i].size,
2516 			.value = bpf_args->in_args[i].value,
2517 		};
2518 	for (i = 0; i < args.out_numargs; ++i)
2519 		args.out_args[i] = (struct fuse_arg) {
2520 			.size = bpf_args->out_args[i].size,
2521 			.value = bpf_args->out_args[i].value,
2522 		};
2523 
2524 	res = fuse_simple_request(fm, &args);
2525 
2526 	*bpf_args = (struct fuse_bpf_args) {
2527 		.nodeid = args.nodeid,
2528 		.opcode = args.opcode,
2529 		.error_in = args.error_in,
2530 		.in_numargs = args.in_numargs,
2531 		.out_numargs = args.out_numargs,
2532 	};
2533 	if (args.force)
2534 		bpf_args->flags |= FUSE_BPF_FORCE;
2535 	if (args.out_argvar)
2536 		bpf_args->flags |= FUSE_BPF_OUT_ARGVAR;
2537 	for (i = 0; i < args.in_numargs; ++i)
2538 		bpf_args->in_args[i] = (struct fuse_bpf_in_arg) {
2539 			.size = args.in_args[i].size,
2540 			.value = args.in_args[i].value,
2541 		};
2542 	for (i = 0; i < args.out_numargs; ++i)
2543 		bpf_args->out_args[i] = (struct fuse_bpf_arg) {
2544 			.size = args.out_args[i].size,
2545 			.value = args.out_args[i].value,
2546 		};
2547 	return res;
2548 }
2549