xref: /openbsd-src/lib/libfuse/fuse.c (revision ae3cb403620ab940fbaabb3055fac045a63d56b7)
1 /* $OpenBSD: fuse.c,v 1.43 2017/12/18 14:20:23 helg Exp $ */
2 /*
3  * Copyright (c) 2013 Sylvestre Gallon <ccna.syl@gmail.com>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <sys/wait.h>
19 #include <sys/types.h>
20 #include <sys/ioctl.h>
21 
22 #include <miscfs/fuse/fusefs.h>
23 
24 #include <errno.h>
25 #include <signal.h>
26 #include <stddef.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 
31 #include "fuse_opt.h"
32 #include "fuse_private.h"
33 #include "debug.h"
34 
35 static volatile sig_atomic_t sigraised = 0;
36 static volatile sig_atomic_t signum = 0;
37 static struct fuse_context *ictx = NULL;
38 
39 enum {
40 	KEY_DEBUG,
41 	KEY_FOREGROUND,
42 	KEY_HELP,
43 	KEY_HELP_WITHOUT_HEADER,
44 	KEY_VERSION,
45 	KEY_MAXREAD,
46 	KEY_STUB
47 };
48 
49 /* options supported by fuse_parse_cmdline */
50 static struct fuse_opt fuse_core_opts[] = {
51 	FUSE_OPT_KEY("-d",			KEY_DEBUG),
52 	FUSE_OPT_KEY("debug",			KEY_DEBUG),
53 	FUSE_OPT_KEY("-f",			KEY_FOREGROUND),
54 	FUSE_OPT_KEY("-h",			KEY_HELP),
55 	FUSE_OPT_KEY("--help",			KEY_HELP),
56 	FUSE_OPT_KEY("-ho",			KEY_HELP_WITHOUT_HEADER),
57 	FUSE_OPT_KEY("-s",			KEY_STUB),
58 	FUSE_OPT_KEY("-V",			KEY_VERSION),
59 	FUSE_OPT_KEY("--version",		KEY_VERSION),
60 	FUSE_OPT_END
61 };
62 
63 /* options supported by fuse_new */
64 #define FUSE_LIB_OPT(o, m) {o, offsetof(struct fuse_config, m), 1}
65 static struct fuse_opt fuse_lib_opts[] = {
66 	FUSE_OPT_KEY("ac_attr_timeout=",	KEY_STUB),
67 	FUSE_OPT_KEY("allow_other",		KEY_STUB),
68 	FUSE_OPT_KEY("allow_root",		KEY_STUB),
69 	FUSE_OPT_KEY("attr_timeout=",		KEY_STUB),
70 	FUSE_OPT_KEY("auto_cache",		KEY_STUB),
71 	FUSE_OPT_KEY("noauto_cache",		KEY_STUB),
72 	FUSE_OPT_KEY("big_writes",		KEY_STUB),
73 	FUSE_OPT_KEY("debug",			KEY_DEBUG),
74 	FUSE_OPT_KEY("-d",			KEY_DEBUG),
75 	FUSE_OPT_KEY("entry_timeout=",		KEY_STUB),
76 	FUSE_LIB_OPT("gid=",			set_gid),
77 	FUSE_LIB_OPT("gid=%u",			gid),
78 	FUSE_OPT_KEY("hard_remove",		KEY_STUB),
79 	FUSE_OPT_KEY("intr_signal",		KEY_STUB),
80 	FUSE_OPT_KEY("kernel_cache",		KEY_STUB),
81 	FUSE_OPT_KEY("large_read",		KEY_STUB),
82 	FUSE_OPT_KEY("modules=",		KEY_STUB),
83 	FUSE_OPT_KEY("negative_timeout=",	KEY_STUB),
84 	FUSE_OPT_KEY("readdir_ino",		KEY_STUB),
85 	FUSE_OPT_KEY("relatime",		KEY_STUB),
86 	FUSE_OPT_KEY("subtype=",		KEY_STUB),
87 	FUSE_LIB_OPT("uid=",			set_uid),
88 	FUSE_LIB_OPT("uid=%u",			uid),
89 	FUSE_OPT_KEY("use_ino",			KEY_STUB),
90 	FUSE_OPT_KEY("dmask=%o",		KEY_STUB),
91 	FUSE_OPT_KEY("fmask=%o",		KEY_STUB),
92 	FUSE_LIB_OPT("umask=",			set_mode),
93 	FUSE_LIB_OPT("umask=%o",		umask),
94 	FUSE_OPT_END
95 };
96 
97 /* options supported by fuse_mount */
98 #define FUSE_MOUNT_OPT(o, m) {o, offsetof(struct fuse_mount_opts, m), 1}
99 static struct fuse_opt fuse_mount_opts[] = {
100 	FUSE_OPT_KEY("async_read",		KEY_STUB),
101 	FUSE_OPT_KEY("blkdev",			KEY_STUB),
102 	FUSE_OPT_KEY("blksize=",		KEY_STUB),
103 	FUSE_MOUNT_OPT("default_permissions",	def_perms),
104 	FUSE_OPT_KEY("direct_io",		KEY_STUB),
105 	FUSE_MOUNT_OPT("fsname=%s",		fsname),
106 	FUSE_MOUNT_OPT("max_read=%u",		max_read),
107 	FUSE_OPT_KEY("max_readahead",		KEY_STUB),
108 	FUSE_OPT_KEY("max_write",		KEY_STUB),
109 	FUSE_MOUNT_OPT("noatime",		noatime),
110 	FUSE_MOUNT_OPT("nonempty",		nonempty),
111 	FUSE_MOUNT_OPT("-r",			rdonly),
112 	FUSE_MOUNT_OPT("ro",			rdonly),
113 	FUSE_OPT_KEY("ro_fallback",		KEY_STUB),
114 	FUSE_OPT_KEY("sync_read",		KEY_STUB),
115 	FUSE_OPT_END
116 };
117 
118 static void
119 ifuse_sighdlr(int num)
120 {
121 	if (!sigraised || (num == SIGCHLD)) {
122 		sigraised = 1;
123 		signum = num;
124 	}
125 }
126 
127 static void
128 ifuse_try_unmount(struct fuse *f)
129 {
130 	pid_t child;
131 
132 	signal(SIGCHLD, ifuse_sighdlr);
133 
134 	/* unmount in another thread so fuse_loop() doesn't deadlock */
135 	child = fork();
136 
137 	if (child < 0) {
138 		DPERROR(__func__);
139 		return;
140 	}
141 
142 	if (child == 0) {
143 		fuse_remove_signal_handlers(fuse_get_session(f));
144 		errno = 0;
145 		fuse_unmount(f->fc->dir, f->fc);
146 		_exit(errno);
147 	}
148 }
149 
150 static void
151 ifuse_child_exit(const struct fuse *f)
152 {
153 	int status;
154 
155 	signal(SIGCHLD, SIG_DFL);
156 	if (waitpid(WAIT_ANY, &status, WNOHANG) == -1)
157 		fprintf(stderr, "fuse: %s\n", strerror(errno));
158 
159 	if (WIFEXITED(status) && (WEXITSTATUS(status) != 0))
160 		fprintf(stderr, "fuse: %s: %s\n",
161 			f->fc->dir, strerror(WEXITSTATUS(status)));
162 
163 	sigraised = 0;
164 	return;
165 }
166 
167 int
168 fuse_loop(struct fuse *fuse)
169 {
170 	struct fusebuf fbuf;
171 	struct fuse_context ctx;
172 	struct fb_ioctl_xch ioexch;
173 	struct kevent ev;
174 	ssize_t n;
175 	int ret;
176 
177 	if (fuse == NULL)
178 		return (-1);
179 
180 	fuse->fc->kq = kqueue();
181 	if (fuse->fc->kq == -1)
182 		return (-1);
183 
184 	EV_SET(&fuse->fc->event, fuse->fc->fd, EVFILT_READ, EV_ADD |
185 	    EV_ENABLE, 0, 0, 0);
186 
187 	while (!fuse->fc->dead) {
188 		ret = kevent(fuse->fc->kq, &fuse->fc->event, 1, &ev, 1, NULL);
189 		if (ret == -1) {
190 			if (errno == EINTR) {
191 				switch (signum) {
192 				case SIGCHLD:
193 					ifuse_child_exit(fuse);
194 					break;
195 				case SIGHUP:
196 				case SIGINT:
197 				case SIGTERM:
198 					ifuse_try_unmount(fuse);
199 					break;
200 				default:
201 					fprintf(stderr, "%s: %s\n", __func__,
202 					    strsignal(signum));
203 				}
204 			} else
205 				DPERROR(__func__);
206 		} else if (ret > 0) {
207 			n = read(fuse->fc->fd, &fbuf, sizeof(fbuf));
208 			if (n != sizeof(fbuf)) {
209 				fprintf(stderr, "%s: bad fusebuf read\n",
210 				    __func__);
211 				return (-1);
212 			}
213 
214 			/* check if there is data something present */
215 			if (fbuf.fb_len) {
216 				fbuf.fb_dat = malloc(fbuf.fb_len);
217 				if (fbuf.fb_dat == NULL)
218 					return (-1);
219 				ioexch.fbxch_uuid = fbuf.fb_uuid;
220 				ioexch.fbxch_len = fbuf.fb_len;
221 				ioexch.fbxch_data = fbuf.fb_dat;
222 
223 				if (ioctl(fuse->fc->fd, FIOCGETFBDAT,
224 				    &ioexch)) {
225 					free(fbuf.fb_dat);
226 					return (-1);
227 				}
228 			}
229 
230 			ctx.fuse = fuse;
231 			ctx.uid = fuse->conf.uid;
232 			ctx.gid = fuse->conf.gid;
233 			ctx.pid = fuse->conf.pid;
234 			ctx.umask = fuse->conf.umask;
235 			ctx.private_data = fuse->private_data;
236 			ictx = &ctx;
237 
238 			ret = ifuse_exec_opcode(fuse, &fbuf);
239 			if (ret) {
240 				ictx = NULL;
241 				return (-1);
242 			}
243 
244 			n = write(fuse->fc->fd, &fbuf, sizeof(fbuf));
245 			if (fbuf.fb_len) {
246 				if (fbuf.fb_dat == NULL) {
247 					fprintf(stderr, "%s: fb_dat is Null\n",
248 					    __func__);
249 					return (-1);
250 				}
251 				ioexch.fbxch_uuid = fbuf.fb_uuid;
252 				ioexch.fbxch_len = fbuf.fb_len;
253 				ioexch.fbxch_data = fbuf.fb_dat;
254 
255 				if (ioctl(fuse->fc->fd, FIOCSETFBDAT, &ioexch)) {
256 					free(fbuf.fb_dat);
257 					return (-1);
258 				}
259 				free(fbuf.fb_dat);
260 			}
261 			ictx = NULL;
262 
263 			if (n != FUSEBUFSIZE) {
264 				errno = EINVAL;
265 				return (-1);
266 			}
267 		}
268 	}
269 
270 	return (0);
271 }
272 DEF(fuse_loop);
273 
274 struct fuse_chan *
275 fuse_mount(const char *dir, struct fuse_args *args)
276 {
277 	struct fusefs_args fargs;
278 	struct fuse_mount_opts opts;
279 	struct fuse_chan *fc;
280 	const char *errcause;
281 	int mnt_flags;
282 
283 	if (dir == NULL)
284 		return (NULL);
285 
286 	fc = calloc(1, sizeof(*fc));
287 	if (fc == NULL)
288 		return (NULL);
289 
290 	fc->dir = realpath(dir, NULL);
291 	if (fc->dir == NULL)
292 		goto bad;
293 
294 	if ((fc->fd = open("/dev/fuse0", O_RDWR)) == -1) {
295 		perror(__func__);
296 		goto bad;
297 	}
298 
299 	bzero(&opts, sizeof(opts));
300 	if (fuse_opt_parse(args, &opts, fuse_mount_opts, NULL) == -1)
301 		goto bad;
302 
303 	mnt_flags = 0;
304 	if (opts.rdonly)
305 		mnt_flags |= MNT_RDONLY;
306 	if (opts.noatime)
307 		mnt_flags |= MNT_NOATIME;
308 
309 	if (opts.max_read > FUSEBUFMAXSIZE) {
310 		fprintf(stderr, "fuse: invalid max_read (%d > %d)\n",
311 		    opts.max_read, FUSEBUFMAXSIZE);
312 		goto bad;
313 	}
314 
315 	bzero(&fargs, sizeof(fargs));
316 	fargs.fd = fc->fd;
317 	fargs.max_read = opts.max_read;
318 
319 	if (mount(MOUNT_FUSEFS, fc->dir, mnt_flags, &fargs)) {
320 		switch (errno) {
321 		case EMFILE:
322 			errcause = "mount table full";
323 			break;
324 		case EOPNOTSUPP:
325 			errcause = "filesystem not supported by kernel";
326 			break;
327 		default:
328 			errcause = strerror(errno);
329 			break;
330 		}
331 		fprintf(stderr, "%s on %s: %s\n", __func__, dir, errcause);
332 		goto bad;
333 	}
334 
335 	return (fc);
336 bad:
337 	if (fc->fd != -1)
338 		close(fc->fd);
339 	free(fc->dir);
340 	free(fc);
341 	return (NULL);
342 }
343 DEF(fuse_mount);
344 
345 void
346 fuse_unmount(const char *dir, struct fuse_chan *ch)
347 {
348 	if (ch == NULL || ch->dead)
349 		return;
350 
351 	if (unmount(dir, MNT_UPDATE) == -1)
352 		DPERROR(__func__);
353 }
354 DEF(fuse_unmount);
355 
356 int
357 fuse_is_lib_option(const char *opt)
358 {
359 	return (fuse_opt_match(fuse_lib_opts, opt));
360 }
361 
362 int
363 fuse_chan_fd(struct fuse_chan *ch)
364 {
365 	if (ch == NULL)
366 		return (-1);
367 
368 	return (ch->fd);
369 }
370 
371 struct fuse_session *
372 fuse_get_session(struct fuse *f)
373 {
374 	return (&f->se);
375 }
376 DEF(fuse_get_session);
377 
378 int
379 fuse_loop_mt(unused struct fuse *fuse)
380 {
381 	return (-1);
382 }
383 
384 static int
385 ifuse_lib_opt_proc(void *data, const char *arg, int key,
386     unused struct fuse_args *args)
387 {
388 	switch (key) {
389 	case KEY_STUB:
390 		return (0);
391 	case KEY_DEBUG:
392 		ifuse_debug_init();
393 		break;
394 	default:
395 		fprintf(stderr, "fuse: unrecognised option %s\n", arg);
396 		return (-1);
397 	}
398 
399 	/* Keep unknown options. */
400 	return (1);
401 }
402 
403 struct fuse *
404 fuse_new(struct fuse_chan *fc, struct fuse_args *args,
405     const struct fuse_operations *ops, unused size_t size,
406     void *userdata)
407 {
408 	struct fuse *fuse;
409 	struct fuse_vnode *root;
410 
411 	if (fc == NULL || ops == NULL)
412 		return (NULL);
413 
414 	if ((fuse = calloc(1, sizeof(*fuse))) == NULL)
415 		return (NULL);
416 
417 	/* copy fuse ops to their own structure */
418 	memcpy(&fuse->op, ops, sizeof(fuse->op));
419 
420 	if (fuse_opt_parse(args, &fuse->conf, fuse_lib_opts,
421 	    ifuse_lib_opt_proc) == -1) {
422 		free(fuse);
423 		return (NULL);
424 	}
425 
426 	fuse->fc = fc;
427 	fuse->max_ino = FUSE_ROOT_INO;
428 	fuse->se.args = fuse;
429 	fuse->private_data = userdata;
430 
431 	if ((root = alloc_vn(fuse, "/", FUSE_ROOT_INO, 0)) == NULL) {
432 		free(fuse);
433 		return (NULL);
434 	}
435 
436 	tree_init(&fuse->vnode_tree);
437 	tree_init(&fuse->name_tree);
438 	if (!set_vn(fuse, root)) {
439 		free(fuse);
440 		return (NULL);
441 	}
442 
443 	return (fuse);
444 }
445 DEF(fuse_new);
446 
447 int
448 fuse_daemonize(int foreground)
449 {
450 	if (foreground)
451 		return (0);
452 
453 	return (daemon(0, 0));
454 }
455 DEF(fuse_daemonize);
456 
457 void
458 fuse_destroy(struct fuse *f)
459 {
460 	if (f == NULL)
461 		return;
462 
463 	/*
464   	 * Even though these were allocated in fuse_mount(), we can't free them
465  	 * in fuse_unmount() since fuse_loop() will not have terminated yet so
466  	 * we free them here.
467  	 */
468 	close(f->fc->fd);
469 	free(f->fc->dir);
470 	free(f->fc);
471 	free(f);
472 }
473 DEF(fuse_destroy);
474 
475 void
476 fuse_remove_signal_handlers(unused struct fuse_session *se)
477 {
478 	signal(SIGHUP, SIG_DFL);
479 	signal(SIGINT, SIG_DFL);
480 	signal(SIGTERM, SIG_DFL);
481 	signal(SIGPIPE, SIG_DFL);
482 }
483 DEF(fuse_remove_signal_handlers);
484 
485 int
486 fuse_set_signal_handlers(unused struct fuse_session *se)
487 {
488 	signal(SIGHUP, ifuse_sighdlr);
489 	signal(SIGINT, ifuse_sighdlr);
490 	signal(SIGTERM, ifuse_sighdlr);
491 	signal(SIGPIPE, SIG_IGN);
492 	return (0);
493 }
494 
495 static void
496 dump_help(void)
497 {
498 	fprintf(stderr, "FUSE options:\n"
499 	    "    -d   -o debug          enable debug output (implies -f)\n"
500 	    "    -f                     run in foreground\n"
501 	    "    -V   --version         print fuse version\n"
502 	    "\n");
503 }
504 
505 static void
506 dump_version(void)
507 {
508 	fprintf(stderr, "FUSE library version: %d.%d\n", FUSE_MAJOR_VERSION,
509 	    FUSE_MINOR_VERSION);
510 }
511 
512 static int
513 ifuse_process_opt(void *data, const char *arg, int key,
514     unused struct fuse_args *args)
515 {
516 	struct fuse_core_opts *opt = data;
517 	struct stat st;
518 	int res;
519 
520 	switch (key) {
521 	case KEY_STUB:
522 		return (0);
523 	case KEY_DEBUG:
524 		ifuse_debug_init();
525 		/* falls through */
526 	case KEY_FOREGROUND:
527 		opt->foreground = 1;
528 		return (0);
529 	case KEY_HELP:
530 	case KEY_HELP_WITHOUT_HEADER:
531 		dump_help();
532 		return (-1);
533 	case KEY_VERSION:
534 		dump_version();
535 		return (-1);
536 	case FUSE_OPT_KEY_NONOPT:
537 		if (opt->mp == NULL) {
538 			opt->mp = realpath(arg, opt->mp);
539 			if (opt->mp == NULL) {
540 				fprintf(stderr, "fuse: realpath: "
541 				    "%s : %s\n", arg, strerror(errno));
542 				return (-1);
543 			}
544 
545 			res = stat(opt->mp, &st);
546 			if (res == -1) {
547 				fprintf(stderr, "fuse: bad mount point "
548 				    "%s : %s\n", arg, strerror(errno));
549 				return (-1);
550 			}
551 
552 			if (!S_ISDIR(st.st_mode)) {
553 				fprintf(stderr, "fuse: bad mount point "
554 				    "%s : %s\n", arg, strerror(ENOTDIR));
555 				return (-1);
556 			}
557 		}
558 		return (0);
559 	}
560 
561 	/* Pass through unknown options. */
562 	return (1);
563 }
564 
565 int
566 fuse_parse_cmdline(struct fuse_args *args, char **mp, int *mt, int *fg)
567 {
568 	struct fuse_core_opts opt;
569 
570 	bzero(&opt, sizeof(opt));
571 	if (fuse_opt_parse(args, &opt, fuse_core_opts, ifuse_process_opt) == -1)
572 		return (-1);
573 
574 	if (opt.mp == NULL) {
575 		fprintf(stderr, "fuse: missing mountpoint parameter\n");
576 		return (-1);
577 	}
578 
579 	if (mp != NULL) {
580 		*mp = strdup(opt.mp);
581 		if (*mp == NULL)
582 			return (-1);
583 	}
584 
585 	if (mt != NULL)
586 		*mt = 0;
587 
588 	if (fg != NULL)
589 		*fg = opt.foreground;
590 
591 	return (0);
592 }
593 DEF(fuse_parse_cmdline);
594 
595 struct fuse_context *
596 fuse_get_context(void)
597 {
598 	return (ictx);
599 }
600 DEF(fuse_get_context);
601 
602 int
603 fuse_version(void)
604 {
605 	return (FUSE_VERSION);
606 }
607 
608 void
609 fuse_teardown(struct fuse *fuse, char *mp)
610 {
611 	if (fuse == NULL || mp == NULL)
612 		return;
613 
614 	fuse_remove_signal_handlers(fuse_get_session(fuse));
615 	fuse_unmount(mp, fuse->fc);
616 	fuse_destroy(fuse);
617 }
618 
619 int
620 fuse_invalidate(unused struct fuse *f, unused const char *path)
621 {
622 	return (EINVAL);
623 }
624 
625 struct fuse *
626 fuse_setup(int argc, char **argv, const struct fuse_operations *ops,
627     size_t size, char **mp, int *mt, void *data)
628 {
629 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
630 	struct fuse_chan *fc;
631 	struct fuse *fuse;
632 	char *dir;
633 	int fg;
634 
635 	dir = NULL;
636 	if (fuse_parse_cmdline(&args, &dir, mt, &fg))
637 		goto err;
638 
639 	fuse_daemonize(fg);
640 
641 	if ((fc = fuse_mount(dir, &args)) == NULL)
642 		goto err;
643 
644 	if ((fuse = fuse_new(fc, &args, ops, size, data)) == NULL) {
645 		fuse_unmount(dir, fc);
646 		close(fc->fd);
647 		free(fc->dir);
648 		free(fc);
649 		goto err;
650 	}
651 
652 	/* args are no longer needed */
653 	fuse_opt_free_args(&args);
654 
655 	if (fuse_set_signal_handlers(fuse_get_session(fuse)) == -1) {
656 		fuse_unmount(dir, fc);
657 		fuse_destroy(fuse);
658 		goto err;
659 	}
660 
661 	/* the caller frees dir, but we do it if the caller doesn't want it */
662 	if (mp == NULL)
663 		free(dir);
664 	else
665 		*mp = dir;
666 
667 	return (fuse);
668 err:
669 	free(dir);
670 	return (NULL);
671 }
672 DEF(fuse_setup);
673 
674 int
675 fuse_main(int argc, char **argv, const struct fuse_operations *ops, void *data)
676 {
677 	struct fuse *fuse;
678 
679 	fuse = fuse_setup(argc, argv, ops, sizeof(*ops), NULL, NULL, data);
680 	if (fuse == NULL)
681 		return (-1);
682 
683 	return (fuse_loop(fuse));
684 }
685