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