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