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