libfuse: fuse-3.2.5/util/fusermount.c Source File

libfuse

fusermount.c
1 /*
2 FUSE: Filesystem in Userspace
3 Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
4
5 This program can be distributed under the terms of the GNU GPL.
6 See the file COPYING.
7 */
8 /* This program does the mounting and unmounting of FUSE filesystems */
9
10 #define _GNU_SOURCE /* for clone */
11 #include <config.h>
12
13 #include "mount_util.h"
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <unistd.h>
19 #include <getopt.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <pwd.h>
23 #include <paths.h>
24 #include <mntent.h>
25 #include <sys/wait.h>
26 #include <sys/stat.h>
27 #include <sys/mount.h>
28 #include <sys/fsuid.h>
29 #include <sys/socket.h>
30 #include <sys/utsname.h>
31 #include <sched.h>
32 #include <stdbool.h>
33 #include <sys/vfs.h>
34
35 #define FUSE_COMMFD_ENV "_FUSE_COMMFD"
36
37 #define FUSE_DEV "/dev/fuse"
38 #define FUSE_CONF "/etc/fuse.conf"
39
40 #ifndef MS_DIRSYNC
41 #define MS_DIRSYNC 128
42 #endif
43 #ifndef MS_REC
44 #define MS_REC 16384
45 #endif
46 #ifndef MS_PRIVATE
47 #define MS_PRIVATE (1<<18)
48 #endif
49
50 #ifndef UMOUNT_DETACH
51 #define UMOUNT_DETACH 0x00000002 /* Just detach from the tree */
52 #endif
53 #ifndef UMOUNT_NOFOLLOW
54 #define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
55 #endif
56 #ifndef UMOUNT_UNUSED
57 #define UMOUNT_UNUSED 0x80000000 /* Flag guaranteed to be unused */
58 #endif
59
60 static const char *progname;
61
62 static int user_allow_other = 0;
63 static int mount_max = 1000;
64
65 static int auto_unmount = 0;
66
67 static const char *get_user_name(void)
68 {
69 struct passwd *pw = getpwuid(getuid());
70 if (pw != NULL && pw->pw_name != NULL)
71 return pw->pw_name;
72 else {
73 fprintf(stderr, "%s: could not determine username\n", progname);
74 return NULL;
75 }
76 }
77
78 static uid_t oldfsuid;
79 static gid_t oldfsgid;
80
81 static void drop_privs(void)
82 {
83 if (getuid() != 0) {
84 oldfsuid = setfsuid(getuid());
85 oldfsgid = setfsgid(getgid());
86 }
87 }
88
89 static void restore_privs(void)
90 {
91 if (getuid() != 0) {
92 setfsuid(oldfsuid);
93 setfsgid(oldfsgid);
94 }
95 }
96
97 #ifndef IGNORE_MTAB
98 /*
99 * Make sure that /etc/mtab is checked and updated atomically
100 */
101 static int lock_umount(void)
102 {
103 const char *mtab_lock = _PATH_MOUNTED ".fuselock";
104 int mtablock;
105 int res;
106 struct stat mtab_stat;
107
108 /* /etc/mtab could be a symlink to /proc/mounts */
109 if (lstat(_PATH_MOUNTED, &mtab_stat) == 0 && S_ISLNK(mtab_stat.st_mode))
110 return -1;
111
112 mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
113 if (mtablock == -1) {
114 fprintf(stderr, "%s: unable to open fuse lock file: %s\n",
115 progname, strerror(errno));
116 return -1;
117 }
118 res = lockf(mtablock, F_LOCK, 0);
119 if (res < 0) {
120 fprintf(stderr, "%s: error getting lock: %s\n", progname,
121 strerror(errno));
122 close(mtablock);
123 return -1;
124 }
125
126 return mtablock;
127 }
128
129 static void unlock_umount(int mtablock)
130 {
131 if (mtablock >= 0) {
132 int res;
133
134 res = lockf(mtablock, F_ULOCK, 0);
135 if (res < 0) {
136 fprintf(stderr, "%s: error releasing lock: %s\n",
137 progname, strerror(errno));
138 }
139 close(mtablock);
140 }
141 }
142
143 static int add_mount(const char *source, const char *mnt, const char *type,
144 const char *opts)
145 {
146 return fuse_mnt_add_mount(progname, source, mnt, type, opts);
147 }
148
149 static int may_unmount(const char *mnt, int quiet)
150 {
151 struct mntent *entp;
152 FILE *fp;
153 const char *user = NULL;
154 char uidstr[32];
155 unsigned uidlen = 0;
156 int found;
157 const char *mtab = _PATH_MOUNTED;
158
159 user = get_user_name();
160 if (user == NULL)
161 return -1;
162
163 fp = setmntent(mtab, "r");
164 if (fp == NULL) {
165 fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
166 strerror(errno));
167 return -1;
168 }
169
170 uidlen = sprintf(uidstr, "%u", getuid());
171
172 found = 0;
173 while ((entp = getmntent(fp)) != NULL) {
174 if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
175 (strcmp(entp->mnt_type, "fuse") == 0 ||
176 strcmp(entp->mnt_type, "fuseblk") == 0 ||
177 strncmp(entp->mnt_type, "fuse.", 5) == 0 ||
178 strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) {
179 char *p = strstr(entp->mnt_opts, "user=");
180 if (p &&
181 (p == entp->mnt_opts || *(p-1) == ',') &&
182 strcmp(p + 5, user) == 0) {
183 found = 1;
184 break;
185 }
186 /* /etc/mtab is a link pointing to
187 /proc/mounts: */
188 else if ((p =
189 strstr(entp->mnt_opts, "user_id=")) &&
190 (p == entp->mnt_opts ||
191 *(p-1) == ',') &&
192 strncmp(p + 8, uidstr, uidlen) == 0 &&
193 (*(p+8+uidlen) == ',' ||
194 *(p+8+uidlen) == '\0')) {
195 found = 1;
196 break;
197 }
198 }
199 }
200 endmntent(fp);
201
202 if (!found) {
203 if (!quiet)
204 fprintf(stderr,
205 "%s: entry for %s not found in %s\n",
206 progname, mnt, mtab);
207 return -1;
208 }
209
210 return 0;
211 }
212
213 /*
214 * Check whether the file specified in "fusermount3 -u" is really a
215 * mountpoint and not a symlink. This is necessary otherwise the user
216 * could move the mountpoint away and replace it with a symlink
217 * pointing to an arbitrary mount, thereby tricking fusermount3 into
218 * unmounting that (umount(2) will follow symlinks).
219 *
220 * This is the child process running in a separate mount namespace, so
221 * we don't mess with the global namespace and if the process is
222 * killed for any reason, mounts are automatically cleaned up.
223 *
224 * First make sure nothing is propagated back into the parent
225 * namespace by marking all mounts "private".
226 *
227 * Then bind mount parent onto a stable base where the user can't move
228 * it around.
229 *
230 * Finally check /proc/mounts for an entry matching the requested
231 * mountpoint. If it's found then we are OK, and the user can't move
232 * it around within the parent directory as rename() will return
233 * EBUSY. Be careful to ignore any mounts that existed before the
234 * bind.
235 */
236 static int check_is_mount_child(void *p)
237 {
238 const char **a = p;
239 const char *last = a[0];
240 const char *mnt = a[1];
241 int res;
242 const char *procmounts = "/proc/mounts";
243 int found;
244 FILE *fp;
245 struct mntent *entp;
246 int count;
247
248 res = mount("", "/", "", MS_PRIVATE | MS_REC, NULL);
249 if (res == -1) {
250 fprintf(stderr, "%s: failed to mark mounts private: %s\n",
251 progname, strerror(errno));
252 return 1;
253 }
254
255 fp = setmntent(procmounts, "r");
256 if (fp == NULL) {
257 fprintf(stderr, "%s: failed to open %s: %s\n", progname,
258 procmounts, strerror(errno));
259 return 1;
260 }
261
262 count = 0;
263 while (getmntent(fp) != NULL)
264 count++;
265 endmntent(fp);
266
267 fp = setmntent(procmounts, "r");
268 if (fp == NULL) {
269 fprintf(stderr, "%s: failed to open %s: %s\n", progname,
270 procmounts, strerror(errno));
271 return 1;
272 }
273
274 res = mount(".", "/", "", MS_BIND | MS_REC, NULL);
275 if (res == -1) {
276 fprintf(stderr, "%s: failed to bind parent to /: %s\n",
277 progname, strerror(errno));
278 return 1;
279 }
280
281 found = 0;
282 while ((entp = getmntent(fp)) != NULL) {
283 if (count > 0) {
284 count--;
285 continue;
286 }
287 if (entp->mnt_dir[0] == '/' &&
288 strcmp(entp->mnt_dir + 1, last) == 0) {
289 found = 1;
290 break;
291 }
292 }
293 endmntent(fp);
294
295 if (!found) {
296 fprintf(stderr, "%s: %s not mounted\n", progname, mnt);
297 return 1;
298 }
299
300 return 0;
301 }
302
303 static pid_t clone_newns(void *a)
304 {
305 char buf[131072];
306 char *stack = buf + (sizeof(buf) / 2 - ((size_t) buf & 15));
307
308 #ifdef __ia64__
309 extern int __clone2(int (*fn)(void *),
310 void *child_stack_base, size_t stack_size,
311 int flags, void *arg, pid_t *ptid,
312 void *tls, pid_t *ctid);
313
314 return __clone2(check_is_mount_child, stack, sizeof(buf) / 2,
315 CLONE_NEWNS, a, NULL, NULL, NULL);
316 #else
317 return clone(check_is_mount_child, stack, CLONE_NEWNS, a);
318 #endif
319 }
320
321 static int check_is_mount(const char *last, const char *mnt)
322 {
323 pid_t pid, p;
324 int status;
325 const char *a[2] = { last, mnt };
326
327 pid = clone_newns((void *) a);
328 if (pid == (pid_t) -1) {
329 fprintf(stderr, "%s: failed to clone namespace: %s\n",
330 progname, strerror(errno));
331 return -1;
332 }
333 p = waitpid(pid, &status, __WCLONE);
334 if (p == (pid_t) -1) {
335 fprintf(stderr, "%s: waitpid failed: %s\n",
336 progname, strerror(errno));
337 return -1;
338 }
339 if (!WIFEXITED(status)) {
340 fprintf(stderr, "%s: child terminated abnormally (status %i)\n",
341 progname, status);
342 return -1;
343 }
344 if (WEXITSTATUS(status) != 0)
345 return -1;
346
347 return 0;
348 }
349
350 static int chdir_to_parent(char *copy, const char **lastp)
351 {
352 char *tmp;
353 const char *parent;
354 char buf[65536];
355 int res;
356
357 tmp = strrchr(copy, '/');
358 if (tmp == NULL || tmp[1] == '\0') {
359 fprintf(stderr, "%s: internal error: invalid abs path: <%s>\n",
360 progname, copy);
361 return -1;
362 }
363 if (tmp != copy) {
364 *tmp = '\0';
365 parent = copy;
366 *lastp = tmp + 1;
367 } else if (tmp[1] != '\0') {
368 *lastp = tmp + 1;
369 parent = "/";
370 } else {
371 *lastp = ".";
372 parent = "/";
373 }
374
375 res = chdir(parent);
376 if (res == -1) {
377 fprintf(stderr, "%s: failed to chdir to %s: %s\n",
378 progname, parent, strerror(errno));
379 return -1;
380 }
381
382 if (getcwd(buf, sizeof(buf)) == NULL) {
383 fprintf(stderr, "%s: failed to obtain current directory: %s\n",
384 progname, strerror(errno));
385 return -1;
386 }
387 if (strcmp(buf, parent) != 0) {
388 fprintf(stderr, "%s: mountpoint moved (%s -> %s)\n", progname,
389 parent, buf);
390 return -1;
391
392 }
393
394 return 0;
395 }
396
397 /* Check whether the kernel supports UMOUNT_NOFOLLOW flag */
398 static int umount_nofollow_support(void)
399 {
400 int res = umount2("", UMOUNT_UNUSED);
401 if (res != -1 || errno != EINVAL)
402 return 0;
403
404 res = umount2("", UMOUNT_NOFOLLOW);
405 if (res != -1 || errno != ENOENT)
406 return 0;
407
408 return 1;
409 }
410
411 static int unmount_fuse_locked(const char *mnt, int quiet, int lazy)
412 {
413 int res;
414 char *copy;
415 const char *last;
416 int umount_flags = lazy ? UMOUNT_DETACH : 0;
417
418 if (getuid() != 0) {
419 res = may_unmount(mnt, quiet);
420 if (res == -1)
421 return -1;
422 }
423
424 copy = strdup(mnt);
425 if (copy == NULL) {
426 fprintf(stderr, "%s: failed to allocate memory\n", progname);
427 return -1;
428 }
429
430 res = chdir_to_parent(copy, &last);
431 if (res == -1)
432 goto out;
433
434 if (umount_nofollow_support()) {
435 umount_flags |= UMOUNT_NOFOLLOW;
436 } else {
437 res = check_is_mount(last, mnt);
438 if (res == -1)
439 goto out;
440 }
441
442 res = umount2(last, umount_flags);
443 if (res == -1 && !quiet) {
444 fprintf(stderr, "%s: failed to unmount %s: %s\n",
445 progname, mnt, strerror(errno));
446 }
447
448 out:
449 free(copy);
450 if (res == -1)
451 return -1;
452
453 res = chdir("/");
454 if (res == -1) {
455 fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
456 return -1;
457 }
458
459 return fuse_mnt_remove_mount(progname, mnt);
460 }
461
462 static int unmount_fuse(const char *mnt, int quiet, int lazy)
463 {
464 int res;
465 int mtablock = lock_umount();
466
467 res = unmount_fuse_locked(mnt, quiet, lazy);
468 unlock_umount(mtablock);
469
470 return res;
471 }
472
473 static int count_fuse_fs(void)
474 {
475 struct mntent *entp;
476 int count = 0;
477 const char *mtab = _PATH_MOUNTED;
478 FILE *fp = setmntent(mtab, "r");
479 if (fp == NULL) {
480 fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
481 strerror(errno));
482 return -1;
483 }
484 while ((entp = getmntent(fp)) != NULL) {
485 if (strcmp(entp->mnt_type, "fuse") == 0 ||
486 strncmp(entp->mnt_type, "fuse.", 5) == 0)
487 count ++;
488 }
489 endmntent(fp);
490 return count;
491 }
492
493
494 #else /* IGNORE_MTAB */
495 static int count_fuse_fs(void)
496 {
497 return 0;
498 }
499
500 static int add_mount(const char *source, const char *mnt, const char *type,
501 const char *opts)
502 {
503 (void) source;
504 (void) mnt;
505 (void) type;
506 (void) opts;
507 return 0;
508 }
509
510 static int unmount_fuse(const char *mnt, int quiet, int lazy)
511 {
512 (void) quiet;
513 return fuse_mnt_umount(progname, mnt, mnt, lazy);
514 }
515 #endif /* IGNORE_MTAB */
516
517 static void strip_line(char *line)
518 {
519 char *s = strchr(line, '#');
520 if (s != NULL)
521 s[0] = '\0';
522 for (s = line + strlen(line) - 1;
523 s >= line && isspace((unsigned char) *s); s--);
524 s[1] = '\0';
525 for (s = line; isspace((unsigned char) *s); s++);
526 if (s != line)
527 memmove(line, s, strlen(s)+1);
528 }
529
530 static void parse_line(char *line, int linenum)
531 {
532 int tmp;
533 if (strcmp(line, "user_allow_other") == 0)
534 user_allow_other = 1;
535 else if (sscanf(line, "mount_max = %i", &tmp) == 1)
536 mount_max = tmp;
537 else if(line[0])
538 fprintf(stderr,
539 "%s: unknown parameter in %s at line %i: '%s'\n",
540 progname, FUSE_CONF, linenum, line);
541 }
542
543 static void read_conf(void)
544 {
545 FILE *fp = fopen(FUSE_CONF, "r");
546 if (fp != NULL) {
547 int linenum = 1;
548 char line[256];
549 int isnewline = 1;
550 while (fgets(line, sizeof(line), fp) != NULL) {
551 if (isnewline) {
552 if (line[strlen(line)-1] == '\n') {
553 strip_line(line);
554 parse_line(line, linenum);
555 } else {
556 isnewline = 0;
557 }
558 } else if(line[strlen(line)-1] == '\n') {
559 fprintf(stderr, "%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum);
560
561 isnewline = 1;
562 }
563 if (isnewline)
564 linenum ++;
565 }
566 if (!isnewline) {
567 fprintf(stderr, "%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF);
568
569 }
570 if (ferror(fp)) {
571 fprintf(stderr, "%s: reading %s: read failed\n", progname, FUSE_CONF);
572 exit(1);
573 }
574 fclose(fp);
575 } else if (errno != ENOENT) {
576 bool fatal = (errno != EACCES && errno != ELOOP &&
577 errno != ENAMETOOLONG && errno != ENOTDIR &&
578 errno != EOVERFLOW);
579 fprintf(stderr, "%s: failed to open %s: %s\n",
580 progname, FUSE_CONF, strerror(errno));
581 if (fatal)
582 exit(1);
583 }
584 }
585
586 static int begins_with(const char *s, const char *beg)
587 {
588 if (strncmp(s, beg, strlen(beg)) == 0)
589 return 1;
590 else
591 return 0;
592 }
593
594 struct mount_flags {
595 const char *opt;
596 unsigned long flag;
597 int on;
598 int safe;
599 };
600
601 static struct mount_flags mount_flags[] = {
602 {"rw", MS_RDONLY, 0, 1},
603 {"ro", MS_RDONLY, 1, 1},
604 {"suid", MS_NOSUID, 0, 0},
605 {"nosuid", MS_NOSUID, 1, 1},
606 {"dev", MS_NODEV, 0, 0},
607 {"nodev", MS_NODEV, 1, 1},
608 {"exec", MS_NOEXEC, 0, 1},
609 {"noexec", MS_NOEXEC, 1, 1},
610 {"async", MS_SYNCHRONOUS, 0, 1},
611 {"sync", MS_SYNCHRONOUS, 1, 1},
612 {"atime", MS_NOATIME, 0, 1},
613 {"noatime", MS_NOATIME, 1, 1},
614 {"dirsync", MS_DIRSYNC, 1, 1},
615 {NULL, 0, 0, 0}
616 };
617
618 static int find_mount_flag(const char *s, unsigned len, int *on, int *flag)
619 {
620 int i;
621
622 for (i = 0; mount_flags[i].opt != NULL; i++) {
623 const char *opt = mount_flags[i].opt;
624 if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
625 *on = mount_flags[i].on;
626 *flag = mount_flags[i].flag;
627 if (!mount_flags[i].safe && getuid() != 0) {
628 *flag = 0;
629 fprintf(stderr,
630 "%s: unsafe option %s ignored\n",
631 progname, opt);
632 }
633 return 1;
634 }
635 }
636 return 0;
637 }
638
639 static int add_option(char **optsp, const char *opt, unsigned expand)
640 {
641 char *newopts;
642 if (*optsp == NULL)
643 newopts = strdup(opt);
644 else {
645 unsigned oldsize = strlen(*optsp);
646 unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
647 newopts = (char *) realloc(*optsp, newsize);
648 if (newopts)
649 sprintf(newopts + oldsize, ",%s", opt);
650 }
651 if (newopts == NULL) {
652 fprintf(stderr, "%s: failed to allocate memory\n", progname);
653 return -1;
654 }
655 *optsp = newopts;
656 return 0;
657 }
658
659 static int get_mnt_opts(int flags, char *opts, char **mnt_optsp)
660 {
661 int i;
662 int l;
663
664 if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1)
665 return -1;
666
667 for (i = 0; mount_flags[i].opt != NULL; i++) {
668 if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
669 add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
670 return -1;
671 }
672
673 if (add_option(mnt_optsp, opts, 0) == -1)
674 return -1;
675 /* remove comma from end of opts*/
676 l = strlen(*mnt_optsp);
677 if ((*mnt_optsp)[l-1] == ',')
678 (*mnt_optsp)[l-1] = '\0';
679 if (getuid() != 0) {
680 const char *user = get_user_name();
681 if (user == NULL)
682 return -1;
683
684 if (add_option(mnt_optsp, "user=", strlen(user)) == -1)
685 return -1;
686 strcat(*mnt_optsp, user);
687 }
688 return 0;
689 }
690
691 static int opt_eq(const char *s, unsigned len, const char *opt)
692 {
693 if(strlen(opt) == len && strncmp(s, opt, len) == 0)
694 return 1;
695 else
696 return 0;
697 }
698
699 static int get_string_opt(const char *s, unsigned len, const char *opt,
700 char **val)
701 {
702 int i;
703 unsigned opt_len = strlen(opt);
704 char *d;
705
706 if (*val)
707 free(*val);
708 *val = (char *) malloc(len - opt_len + 1);
709 if (!*val) {
710 fprintf(stderr, "%s: failed to allocate memory\n", progname);
711 return 0;
712 }
713
714 d = *val;
715 s += opt_len;
716 len -= opt_len;
717 for (i = 0; i < len; i++) {
718 if (s[i] == '\\' && i + 1 < len)
719 i++;
720 *d++ = s[i];
721 }
722 *d = '\0';
723 return 1;
724 }
725
726 /* The kernel silently truncates the "data" argument to PAGE_SIZE-1 characters.
727 * This can be dangerous if it e.g. truncates the option "group_id=1000" to
728 * "group_id=1".
729 * This wrapper detects this case and bails out with an error.
730 */
731 static int mount_notrunc(const char *source, const char *target,
732 const char *filesystemtype, unsigned long mountflags,
733 const char *data) {
734 if (strlen(data) > sysconf(_SC_PAGESIZE) - 1) {
735 fprintf(stderr, "%s: mount options too long\n", progname);
736 errno = EINVAL;
737 return -1;
738 }
739 return mount(source, target, filesystemtype, mountflags, data);
740 }
741
742
743 static int do_mount(const char *mnt, char **typep, mode_t rootmode,
744 int fd, const char *opts, const char *dev, char **sourcep,
745 char **mnt_optsp)
746 {
747 int res;
748 int flags = MS_NOSUID | MS_NODEV;
749 char *optbuf;
750 char *mnt_opts = NULL;
751 const char *s;
752 char *d;
753 char *fsname = NULL;
754 char *subtype = NULL;
755 char *source = NULL;
756 char *type = NULL;
757 int blkdev = 0;
758
759 optbuf = (char *) malloc(strlen(opts) + 128);
760 if (!optbuf) {
761 fprintf(stderr, "%s: failed to allocate memory\n", progname);
762 return -1;
763 }
764
765 for (s = opts, d = optbuf; *s;) {
766 unsigned len;
767 const char *fsname_str = "fsname=";
768 const char *subtype_str = "subtype=";
769 bool escape_ok = begins_with(s, fsname_str) ||
770 begins_with(s, subtype_str);
771 for (len = 0; s[len]; len++) {
772 if (escape_ok && s[len] == '\\' && s[len + 1])
773 len++;
774 else if (s[len] == ',')
775 break;
776 }
777 if (begins_with(s, fsname_str)) {
778 if (!get_string_opt(s, len, fsname_str, &fsname))
779 goto err;
780 } else if (begins_with(s, subtype_str)) {
781 if (!get_string_opt(s, len, subtype_str, &subtype))
782 goto err;
783 } else if (opt_eq(s, len, "blkdev")) {
784 if (getuid() != 0) {
785 fprintf(stderr,
786 "%s: option blkdev is privileged\n",
787 progname);
788 goto err;
789 }
790 blkdev = 1;
791 } else if (opt_eq(s, len, "auto_unmount")) {
792 auto_unmount = 1;
793 } else if (!begins_with(s, "fd=") &&
794 !begins_with(s, "rootmode=") &&
795 !begins_with(s, "user_id=") &&
796 !begins_with(s, "group_id=")) {
797 int on;
798 int flag;
799 int skip_option = 0;
800 if (opt_eq(s, len, "large_read")) {
801 struct utsname utsname;
802 unsigned kmaj, kmin;
803 res = uname(&utsname);
804 if (res == 0 &&
805 sscanf(utsname.release, "%u.%u",
806 &kmaj, &kmin) == 2 &&
807 (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
808 fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
809 skip_option = 1;
810 }
811 }
812 if (getuid() != 0 && !user_allow_other &&
813 (opt_eq(s, len, "allow_other") ||
814 opt_eq(s, len, "allow_root"))) {
815 fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in %s\n", progname, len, s, FUSE_CONF);
816 goto err;
817 }
818 if (!skip_option) {
819 if (find_mount_flag(s, len, &on, &flag)) {
820 if (on)
821 flags |= flag;
822 else
823 flags &= ~flag;
824 } else if (opt_eq(s, len, "default_permissions") ||
825 opt_eq(s, len, "allow_other") ||
826 begins_with(s, "max_read=") ||
827 begins_with(s, "blksize=")) {
828 memcpy(d, s, len);
829 d += len;
830 *d++ = ',';
831 } else {
832 fprintf(stderr, "%s: unknown option '%.*s'\n", progname, len, s);
833 exit(1);
834 }
835 }
836 }
837 s += len;
838 if (*s)
839 s++;
840 }
841 *d = '\0';
842 res = get_mnt_opts(flags, optbuf, &mnt_opts);
843 if (res == -1)
844 goto err;
845
846 sprintf(d, "fd=%i,rootmode=%o,user_id=%u,group_id=%u",
847 fd, rootmode, getuid(), getgid());
848
849 source = malloc((fsname ? strlen(fsname) : 0) +
850 (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
851
852 type = malloc((subtype ? strlen(subtype) : 0) + 32);
853 if (!type || !source) {
854 fprintf(stderr, "%s: failed to allocate memory\n", progname);
855 goto err;
856 }
857
858 if (subtype)
859 sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype);
860 else
861 strcpy(type, blkdev ? "fuseblk" : "fuse");
862
863 if (fsname)
864 strcpy(source, fsname);
865 else
866 strcpy(source, subtype ? subtype : dev);
867
868 res = mount_notrunc(source, mnt, type, flags, optbuf);
869 if (res == -1 && errno == ENODEV && subtype) {
870 /* Probably missing subtype support */
871 strcpy(type, blkdev ? "fuseblk" : "fuse");
872 if (fsname) {
873 if (!blkdev)
874 sprintf(source, "%s#%s", subtype, fsname);
875 } else {
876 strcpy(source, type);
877 }
878
879 res = mount_notrunc(source, mnt, type, flags, optbuf);
880 }
881 if (res == -1 && errno == EINVAL) {
882 /* It could be an old version not supporting group_id */
883 sprintf(d, "fd=%i,rootmode=%o,user_id=%u",
884 fd, rootmode, getuid());
885 res = mount_notrunc(source, mnt, type, flags, optbuf);
886 }
887 if (res == -1) {
888 int errno_save = errno;
889 if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
890 fprintf(stderr, "%s: 'fuseblk' support missing\n",
891 progname);
892 else
893 fprintf(stderr, "%s: mount failed: %s\n", progname,
894 strerror(errno_save));
895 goto err;
896 }
897 *sourcep = source;
898 *typep = type;
899 *mnt_optsp = mnt_opts;
900 free(fsname);
901 free(optbuf);
902
903 return 0;
904
905 err:
906 free(fsname);
907 free(subtype);
908 free(source);
909 free(type);
910 free(mnt_opts);
911 free(optbuf);
912 return -1;
913 }
914
915 static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd)
916 {
917 int res;
918 const char *mnt = *mntp;
919 const char *origmnt = mnt;
920 struct statfs fs_buf;
921 size_t i;
922
923 res = lstat(mnt, stbuf);
924 if (res == -1) {
925 fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
926 progname, mnt, strerror(errno));
927 return -1;
928 }
929
930 /* No permission checking is done for root */
931 if (getuid() == 0)
932 return 0;
933
934 if (S_ISDIR(stbuf->st_mode)) {
935 res = chdir(mnt);
936 if (res == -1) {
937 fprintf(stderr,
938 "%s: failed to chdir to mountpoint: %s\n",
939 progname, strerror(errno));
940 return -1;
941 }
942 mnt = *mntp = ".";
943 res = lstat(mnt, stbuf);
944 if (res == -1) {
945 fprintf(stderr,
946 "%s: failed to access mountpoint %s: %s\n",
947 progname, origmnt, strerror(errno));
948 return -1;
949 }
950
951 if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
952 fprintf(stderr, "%s: mountpoint %s not owned by user\n",
953 progname, origmnt);
954 return -1;
955 }
956
957 res = access(mnt, W_OK);
958 if (res == -1) {
959 fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
960 progname, origmnt);
961 return -1;
962 }
963 } else if (S_ISREG(stbuf->st_mode)) {
964 static char procfile[256];
965 *mountpoint_fd = open(mnt, O_WRONLY);
966 if (*mountpoint_fd == -1) {
967 fprintf(stderr, "%s: failed to open %s: %s\n",
968 progname, mnt, strerror(errno));
969 return -1;
970 }
971 res = fstat(*mountpoint_fd, stbuf);
972 if (res == -1) {
973 fprintf(stderr,
974 "%s: failed to access mountpoint %s: %s\n",
975 progname, mnt, strerror(errno));
976 return -1;
977 }
978 if (!S_ISREG(stbuf->st_mode)) {
979 fprintf(stderr,
980 "%s: mountpoint %s is no longer a regular file\n",
981 progname, mnt);
982 return -1;
983 }
984
985 sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd);
986 *mntp = procfile;
987 } else {
988 fprintf(stderr,
989 "%s: mountpoint %s is not a directory or a regular file\n",
990 progname, mnt);
991 return -1;
992 }
993
994 /* Do not permit mounting over anything in procfs - it has a couple
995 * places to which we have "write access" without being supposed to be
996 * able to just put anything we want there.
997 * Luckily, without allow_other, we can't get other users to actually
998 * use any fake information we try to put there anyway.
999 * Use a whitelist to be safe. */
1000 if (statfs(*mntp, &fs_buf)) {
1001 fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
1002 progname, mnt, strerror(errno));
1003 return -1;
1004 }
1005
1006 /* Use the same list of permitted filesystems for the mount target as
1007 * the ecryptfs mount helper
1008 * (https://bazaar.launchpad.net/~ecryptfs/ecryptfs/trunk/view/head:/src/utils/mount.ecryptfs_private.c#L225). */
1009 typeof(fs_buf.f_type) f_type_whitelist[] = {
1010 0x61756673 /* AUFS_SUPER_MAGIC */,
1011 0x9123683E /* BTRFS_SUPER_MAGIC */,
1012 0x00C36400 /* CEPH_SUPER_MAGIC */,
1013 0xFF534D42 /* CIFS_MAGIC_NUMBER */,
1014 0x0000F15F /* ECRYPTFS_SUPER_MAGIC */,
1015 0x0000EF53 /* EXT[234]_SUPER_MAGIC */,
1016 0xF2F52010 /* F2FS_SUPER_MAGIC */,
1017 0x65735546 /* FUSE_SUPER_MAGIC */,
1018 0x01161970 /* GFS2_MAGIC */,
1019 0x3153464A /* JFS_SUPER_MAGIC */,
1020 0x000072B6 /* JFFS2_SUPER_MAGIC */,
1021 0x0000564C /* NCP_SUPER_MAGIC */,
1022 0x00006969 /* NFS_SUPER_MAGIC */,
1023 0x00003434 /* NILFS_SUPER_MAGIC */,
1024 0x5346544E /* NTFS_SB_MAGIC */,
1025 0x794C7630 /* OVERLAYFS_SUPER_MAGIC */,
1026 0x52654973 /* REISERFS_SUPER_MAGIC */,
1027 0x73717368 /* SQUASHFS_MAGIC */,
1028 0x01021994 /* TMPFS_MAGIC */,
1029 0x24051905 /* UBIFS_SUPER_MAGIC */,
1030 0x58465342 /* XFS_SB_MAGIC */,
1031 0x2FC12FC1 /* ZFS_SUPER_MAGIC */,
1032 };
1033 for (i = 0; i < sizeof(f_type_whitelist)/sizeof(f_type_whitelist[0]); i++) {
1034 if (f_type_whitelist[i] == fs_buf.f_type)
1035 return 0;
1036 }
1037
1038 fprintf(stderr, "%s: mounting over filesystem type %#010lx is forbidden\n",
1039 progname, (unsigned long)fs_buf.f_type);
1040 return -1;
1041 }
1042
1043 static int try_open(const char *dev, char **devp, int silent)
1044 {
1045 int fd = open(dev, O_RDWR);
1046 if (fd != -1) {
1047 *devp = strdup(dev);
1048 if (*devp == NULL) {
1049 fprintf(stderr, "%s: failed to allocate memory\n",
1050 progname);
1051 close(fd);
1052 fd = -1;
1053 }
1054 } else if (errno == ENODEV ||
1055 errno == ENOENT)/* check for ENOENT too, for the udev case */
1056 return -2;
1057 else if (!silent) {
1058 fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
1059 strerror(errno));
1060 }
1061 return fd;
1062 }
1063
1064 static int try_open_fuse_device(char **devp)
1065 {
1066 int fd;
1067
1068 drop_privs();
1069 fd = try_open(FUSE_DEV, devp, 0);
1070 restore_privs();
1071 return fd;
1072 }
1073
1074 static int open_fuse_device(char **devp)
1075 {
1076 int fd = try_open_fuse_device(devp);
1077 if (fd >= -1)
1078 return fd;
1079
1080 fprintf(stderr,
1081 "%s: fuse device not found, try 'modprobe fuse' first\n",
1082 progname);
1083
1084 return -1;
1085 }
1086
1087
1088 static int mount_fuse(const char *mnt, const char *opts)
1089 {
1090 int res;
1091 int fd;
1092 char *dev;
1093 struct stat stbuf;
1094 char *type = NULL;
1095 char *source = NULL;
1096 char *mnt_opts = NULL;
1097 const char *real_mnt = mnt;
1098 int mountpoint_fd = -1;
1099
1100 fd = open_fuse_device(&dev);
1101 if (fd == -1)
1102 return -1;
1103
1104 drop_privs();
1105 read_conf();
1106
1107 if (getuid() != 0 && mount_max != -1) {
1108 int mount_count = count_fuse_fs();
1109 if (mount_count >= mount_max) {
1110 fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in %s\n", progname, FUSE_CONF);
1111 goto fail_close_fd;
1112 }
1113 }
1114
1115 res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
1116 restore_privs();
1117 if (res != -1)
1118 res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
1119 fd, opts, dev, &source, &mnt_opts);
1120
1121 if (mountpoint_fd != -1)
1122 close(mountpoint_fd);
1123
1124 if (res == -1)
1125 goto fail_close_fd;
1126
1127 res = chdir("/");
1128 if (res == -1) {
1129 fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1130 goto fail_close_fd;
1131 }
1132
1133 if (geteuid() == 0) {
1134 res = add_mount(source, mnt, type, mnt_opts);
1135 if (res == -1) {
1136 /* Can't clean up mount in a non-racy way */
1137 goto fail_close_fd;
1138 }
1139 }
1140
1141 out_free:
1142 free(source);
1143 free(type);
1144 free(mnt_opts);
1145 free(dev);
1146
1147 return fd;
1148
1149 fail_close_fd:
1150 close(fd);
1151 fd = -1;
1152 goto out_free;
1153 }
1154
1155 static int send_fd(int sock_fd, int fd)
1156 {
1157 int retval;
1158 struct msghdr msg;
1159 struct cmsghdr *p_cmsg;
1160 struct iovec vec;
1161 size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
1162 int *p_fds;
1163 char sendchar = 0;
1164
1165 msg.msg_control = cmsgbuf;
1166 msg.msg_controllen = sizeof(cmsgbuf);
1167 p_cmsg = CMSG_FIRSTHDR(&msg);
1168 p_cmsg->cmsg_level = SOL_SOCKET;
1169 p_cmsg->cmsg_type = SCM_RIGHTS;
1170 p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
1171 p_fds = (int *) CMSG_DATA(p_cmsg);
1172 *p_fds = fd;
1173 msg.msg_controllen = p_cmsg->cmsg_len;
1174 msg.msg_name = NULL;
1175 msg.msg_namelen = 0;
1176 msg.msg_iov = &vec;
1177 msg.msg_iovlen = 1;
1178 msg.msg_flags = 0;
1179 /* "To pass file descriptors or credentials you need to send/read at
1180 * least one byte" (man 7 unix) */
1181 vec.iov_base = &sendchar;
1182 vec.iov_len = sizeof(sendchar);
1183 while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
1184 if (retval != 1) {
1185 perror("sending file descriptor");
1186 return -1;
1187 }
1188 return 0;
1189 }
1190
1191 static void usage(void)
1192 {
1193 printf("%s: [options] mountpoint\n"
1194 "Options:\n"
1195 " -h print help\n"
1196 " -V print version\n"
1197 " -o opt[,opt...] mount options\n"
1198 " -u unmount\n"
1199 " -q quiet\n"
1200 " -z lazy unmount\n",
1201 progname);
1202 exit(1);
1203 }
1204
1205 static void show_version(void)
1206 {
1207 printf("fusermount3 version: %s\n", PACKAGE_VERSION);
1208 exit(0);
1209 }
1210
1211 int main(int argc, char *argv[])
1212 {
1213 sigset_t sigset;
1214 int ch;
1215 int fd;
1216 int res;
1217 char *origmnt;
1218 char *mnt;
1219 static int unmount = 0;
1220 static int lazy = 0;
1221 static int quiet = 0;
1222 char *commfd;
1223 int cfd;
1224 const char *opts = "";
1225
1226 static const struct option long_opts[] = {
1227 {"unmount", no_argument, NULL, 'u'},
1228 {"lazy", no_argument, NULL, 'z'},
1229 {"quiet", no_argument, NULL, 'q'},
1230 {"help", no_argument, NULL, 'h'},
1231 {"version", no_argument, NULL, 'V'},
1232 {0, 0, 0, 0}};
1233
1234 progname = strdup(argv[0]);
1235 if (progname == NULL) {
1236 fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
1237 exit(1);
1238 }
1239
1240 while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts,
1241 NULL)) != -1) {
1242 switch (ch) {
1243 case 'h':
1244 usage();
1245 break;
1246
1247 case 'V':
1248 show_version();
1249 break;
1250
1251 case 'o':
1252 opts = optarg;
1253 break;
1254
1255 case 'u':
1256 unmount = 1;
1257 break;
1258
1259 case 'z':
1260 lazy = 1;
1261 break;
1262
1263 case 'q':
1264 quiet = 1;
1265 break;
1266
1267 default:
1268 exit(1);
1269 }
1270 }
1271
1272 if (lazy && !unmount) {
1273 fprintf(stderr, "%s: -z can only be used with -u\n", progname);
1274 exit(1);
1275 }
1276
1277 if (optind >= argc) {
1278 fprintf(stderr, "%s: missing mountpoint argument\n", progname);
1279 exit(1);
1280 } else if (argc > optind + 1) {
1281 fprintf(stderr, "%s: extra arguments after the mountpoint\n",
1282 progname);
1283 exit(1);
1284 }
1285
1286 origmnt = argv[optind];
1287
1288 drop_privs();
1289 mnt = fuse_mnt_resolve_path(progname, origmnt);
1290 if (mnt != NULL) {
1291 res = chdir("/");
1292 if (res == -1) {
1293 fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1294 goto err_out;
1295 }
1296 }
1297 restore_privs();
1298 if (mnt == NULL)
1299 exit(1);
1300
1301 umask(033);
1302 if (unmount)
1303 goto do_unmount;
1304
1305 commfd = getenv(FUSE_COMMFD_ENV);
1306 if (commfd == NULL) {
1307 fprintf(stderr, "%s: old style mounting not supported\n",
1308 progname);
1309 goto err_out;
1310 }
1311
1312 fd = mount_fuse(mnt, opts);
1313 if (fd == -1)
1314 goto err_out;
1315
1316 cfd = atoi(commfd);
1317 res = send_fd(cfd, fd);
1318 if (res == -1)
1319 goto err_out;
1320 close(fd);
1321
1322 if (!auto_unmount) {
1323 free(mnt);
1324 return 0;
1325 }
1326
1327 /* Become a daemon and wait for the parent to exit or die.
1328 ie For the control socket to get closed.
1329 btw We don't want to use daemon() function here because
1330 it forks and messes with the file descriptors. */
1331 setsid();
1332 res = chdir("/");
1333 if (res == -1) {
1334 fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1335 goto err_out;
1336 }
1337
1338 sigfillset(&sigset);
1339 sigprocmask(SIG_BLOCK, &sigset, NULL);
1340
1341 lazy = 1;
1342 quiet = 1;
1343
1344 while (1) {
1345 unsigned char buf[16];
1346 int n = recv(cfd, buf, sizeof(buf), 0);
1347 if (!n)
1348 break;
1349
1350 if (n < 0) {
1351 if (errno == EINTR)
1352 continue;
1353 break;
1354 }
1355 }
1356
1357 do_unmount:
1358 if (geteuid() == 0)
1359 res = unmount_fuse(mnt, quiet, lazy);
1360 else {
1361 res = umount2(mnt, lazy ? UMOUNT_DETACH : 0);
1362 if (res == -1 && !quiet)
1363 fprintf(stderr,
1364 "%s: failed to unmount %s: %s\n",
1365 progname, mnt, strerror(errno));
1366 }
1367 if (res == -1)
1368 goto err_out;
1369 free(mnt);
1370 return 0;
1371
1372 err_out:
1373 free(mnt);
1374 exit(1);
1375 }