libfuse: fuse-3.9.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 GPLv2.
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 0x736675005346544e /* UFSD */,
1046 0x58465342 /* XFS_SB_MAGIC */,
1047 0x2FC12FC1 /* ZFS_SUPER_MAGIC */,
1048 };
1049 for (i = 0; i < sizeof(f_type_whitelist)/sizeof(f_type_whitelist[0]); i++) {
1050 if (f_type_whitelist[i] == fs_buf.f_type)
1051 return 0;
1052 }
1053
1054 fprintf(stderr, "%s: mounting over filesystem type %#010lx is forbidden\n",
1055 progname, (unsigned long)fs_buf.f_type);
1056 return -1;
1057 }
1058
1059 static int try_open(const char *dev, char **devp, int silent)
1060 {
1061 int fd = open(dev, O_RDWR);
1062 if (fd != -1) {
1063 *devp = strdup(dev);
1064 if (*devp == NULL) {
1065 fprintf(stderr, "%s: failed to allocate memory\n",
1066 progname);
1067 close(fd);
1068 fd = -1;
1069 }
1070 } else if (errno == ENODEV ||
1071 errno == ENOENT)/* check for ENOENT too, for the udev case */
1072 return -2;
1073 else if (!silent) {
1074 fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
1075 strerror(errno));
1076 }
1077 return fd;
1078 }
1079
1080 static int try_open_fuse_device(char **devp)
1081 {
1082 int fd;
1083
1084 drop_privs();
1085 fd = try_open(FUSE_DEV, devp, 0);
1086 restore_privs();
1087 return fd;
1088 }
1089
1090 static int open_fuse_device(char **devp)
1091 {
1092 int fd = try_open_fuse_device(devp);
1093 if (fd >= -1)
1094 return fd;
1095
1096 fprintf(stderr,
1097 "%s: fuse device not found, try 'modprobe fuse' first\n",
1098 progname);
1099
1100 return -1;
1101 }
1102
1103
1104 static int mount_fuse(const char *mnt, const char *opts, const char **type)
1105 {
1106 int res;
1107 int fd;
1108 char *dev;
1109 struct stat stbuf;
1110 char *source = NULL;
1111 char *mnt_opts = NULL;
1112 const char *real_mnt = mnt;
1113 int mountpoint_fd = -1;
1114
1115 fd = open_fuse_device(&dev);
1116 if (fd == -1)
1117 return -1;
1118
1119 drop_privs();
1120 read_conf();
1121
1122 if (getuid() != 0 && mount_max != -1) {
1123 int mount_count = count_fuse_fs();
1124 if (mount_count >= mount_max) {
1125 fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in %s\n", progname, FUSE_CONF);
1126 goto fail_close_fd;
1127 }
1128 }
1129
1130 res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
1131 restore_privs();
1132 if (res != -1)
1133 res = do_mount(real_mnt, type, stbuf.st_mode & S_IFMT,
1134 fd, opts, dev, &source, &mnt_opts);
1135
1136 if (mountpoint_fd != -1)
1137 close(mountpoint_fd);
1138
1139 if (res == -1)
1140 goto fail_close_fd;
1141
1142 res = chdir("/");
1143 if (res == -1) {
1144 fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1145 goto fail_close_fd;
1146 }
1147
1148 if (geteuid() == 0) {
1149 res = add_mount(source, mnt, *type, mnt_opts);
1150 if (res == -1) {
1151 /* Can't clean up mount in a non-racy way */
1152 goto fail_close_fd;
1153 }
1154 }
1155
1156 out_free:
1157 free(source);
1158 free(mnt_opts);
1159 free(dev);
1160
1161 return fd;
1162
1163 fail_close_fd:
1164 close(fd);
1165 fd = -1;
1166 goto out_free;
1167 }
1168
1169 static int send_fd(int sock_fd, int fd)
1170 {
1171 int retval;
1172 struct msghdr msg;
1173 struct cmsghdr *p_cmsg;
1174 struct iovec vec;
1175 size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
1176 int *p_fds;
1177 char sendchar = 0;
1178
1179 msg.msg_control = cmsgbuf;
1180 msg.msg_controllen = sizeof(cmsgbuf);
1181 p_cmsg = CMSG_FIRSTHDR(&msg);
1182 p_cmsg->cmsg_level = SOL_SOCKET;
1183 p_cmsg->cmsg_type = SCM_RIGHTS;
1184 p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
1185 p_fds = (int *) CMSG_DATA(p_cmsg);
1186 *p_fds = fd;
1187 msg.msg_controllen = p_cmsg->cmsg_len;
1188 msg.msg_name = NULL;
1189 msg.msg_namelen = 0;
1190 msg.msg_iov = &vec;
1191 msg.msg_iovlen = 1;
1192 msg.msg_flags = 0;
1193 /* "To pass file descriptors or credentials you need to send/read at
1194 * least one byte" (man 7 unix) */
1195 vec.iov_base = &sendchar;
1196 vec.iov_len = sizeof(sendchar);
1197 while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
1198 if (retval != 1) {
1199 perror("sending file descriptor");
1200 return -1;
1201 }
1202 return 0;
1203 }
1204
1205 /* The parent fuse process has died: decide whether to auto_unmount.
1206 *
1207 * In the normal case (umount or fusermount -u), the filesystem
1208 * has already been unmounted. If we simply unmount again we can
1209 * cause problems with stacked mounts (e.g. autofs).
1210 *
1211 * So we unmount here only in abnormal case where fuse process has
1212 * died without unmount happening. To detect this, we first look in
1213 * the mount table to make sure the mountpoint is still mounted and
1214 * has proper type. If so, we then see if opening the mount dir is
1215 * returning 'Transport endpoint is not connected'.
1216 *
1217 * The order of these is important, because if autofs is in use,
1218 * opening the dir to check for ENOTCONN will cause a new mount
1219 * in the normal case where filesystem has been unmounted cleanly.
1220 */
1221 static int should_auto_unmount(const char *mnt, const char *type)
1222 {
1223 char *copy;
1224 const char *last;
1225 int result = 0;
1226 int fd;
1227
1228 copy = strdup(mnt);
1229 if (copy == NULL) {
1230 fprintf(stderr, "%s: failed to allocate memory\n", progname);
1231 return 0;
1232 }
1233
1234 if (chdir_to_parent(copy, &last) == -1)
1235 goto out;
1236 if (check_is_mount(last, mnt, type) == -1)
1237 goto out;
1238
1239 fd = open(mnt, O_RDONLY);
1240 if (fd != -1) {
1241 close(fd);
1242 } else {
1243 result = errno == ENOTCONN;
1244 }
1245 out:
1246 free(copy);
1247 return result;
1248 }
1249
1250 static void usage(void)
1251 {
1252 printf("%s: [options] mountpoint\n"
1253 "Options:\n"
1254 " -h print help\n"
1255 " -V print version\n"
1256 " -o opt[,opt...] mount options\n"
1257 " -u unmount\n"
1258 " -q quiet\n"
1259 " -z lazy unmount\n",
1260 progname);
1261 exit(1);
1262 }
1263
1264 static void show_version(void)
1265 {
1266 printf("fusermount3 version: %s\n", PACKAGE_VERSION);
1267 exit(0);
1268 }
1269
1270 int main(int argc, char *argv[])
1271 {
1272 sigset_t sigset;
1273 int ch;
1274 int fd;
1275 int res;
1276 char *origmnt;
1277 char *mnt;
1278 static int unmount = 0;
1279 static int lazy = 0;
1280 static int quiet = 0;
1281 char *commfd;
1282 int cfd;
1283 const char *opts = "";
1284 const char *type = NULL;
1285
1286 static const struct option long_opts[] = {
1287 {"unmount", no_argument, NULL, 'u'},
1288 {"lazy", no_argument, NULL, 'z'},
1289 {"quiet", no_argument, NULL, 'q'},
1290 {"help", no_argument, NULL, 'h'},
1291 {"version", no_argument, NULL, 'V'},
1292 {0, 0, 0, 0}};
1293
1294 progname = strdup(argv[0]);
1295 if (progname == NULL) {
1296 fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
1297 exit(1);
1298 }
1299
1300 while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts,
1301 NULL)) != -1) {
1302 switch (ch) {
1303 case 'h':
1304 usage();
1305 break;
1306
1307 case 'V':
1308 show_version();
1309 break;
1310
1311 case 'o':
1312 opts = optarg;
1313 break;
1314
1315 case 'u':
1316 unmount = 1;
1317 break;
1318
1319 case 'z':
1320 lazy = 1;
1321 break;
1322
1323 case 'q':
1324 quiet = 1;
1325 break;
1326
1327 default:
1328 exit(1);
1329 }
1330 }
1331
1332 if (lazy && !unmount) {
1333 fprintf(stderr, "%s: -z can only be used with -u\n", progname);
1334 exit(1);
1335 }
1336
1337 if (optind >= argc) {
1338 fprintf(stderr, "%s: missing mountpoint argument\n", progname);
1339 exit(1);
1340 } else if (argc > optind + 1) {
1341 fprintf(stderr, "%s: extra arguments after the mountpoint\n",
1342 progname);
1343 exit(1);
1344 }
1345
1346 origmnt = argv[optind];
1347
1348 drop_privs();
1349 mnt = fuse_mnt_resolve_path(progname, origmnt);
1350 if (mnt != NULL) {
1351 res = chdir("/");
1352 if (res == -1) {
1353 fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1354 goto err_out;
1355 }
1356 }
1357 restore_privs();
1358 if (mnt == NULL)
1359 exit(1);
1360
1361 umask(033);
1362 if (unmount)
1363 goto do_unmount;
1364
1365 commfd = getenv(FUSE_COMMFD_ENV);
1366 if (commfd == NULL) {
1367 fprintf(stderr, "%s: old style mounting not supported\n",
1368 progname);
1369 goto err_out;
1370 }
1371
1372 fd = mount_fuse(mnt, opts, &type);
1373 if (fd == -1)
1374 goto err_out;
1375
1376 cfd = atoi(commfd);
1377 res = send_fd(cfd, fd);
1378 if (res == -1)
1379 goto err_out;
1380 close(fd);
1381
1382 if (!auto_unmount) {
1383 free(mnt);
1384 return 0;
1385 }
1386
1387 /* Become a daemon and wait for the parent to exit or die.
1388 ie For the control socket to get closed.
1389 btw We don't want to use daemon() function here because
1390 it forks and messes with the file descriptors. */
1391 setsid();
1392 res = chdir("/");
1393 if (res == -1) {
1394 fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1395 goto err_out;
1396 }
1397
1398 sigfillset(&sigset);
1399 sigprocmask(SIG_BLOCK, &sigset, NULL);
1400
1401 lazy = 1;
1402 quiet = 1;
1403
1404 while (1) {
1405 unsigned char buf[16];
1406 int n = recv(cfd, buf, sizeof(buf), 0);
1407 if (!n)
1408 break;
1409
1410 if (n < 0) {
1411 if (errno == EINTR)
1412 continue;
1413 break;
1414 }
1415 }
1416
1417 if (!should_auto_unmount(mnt, type)) {
1418 goto success_out;
1419 }
1420
1421 do_unmount:
1422 if (geteuid() == 0)
1423 res = unmount_fuse(mnt, quiet, lazy);
1424 else {
1425 res = umount2(mnt, lazy ? UMOUNT_DETACH : 0);
1426 if (res == -1 && !quiet)
1427 fprintf(stderr,
1428 "%s: failed to unmount %s: %s\n",
1429 progname, mnt, strerror(errno));
1430 }
1431 if (res == -1)
1432 goto err_out;
1433
1434 success_out:
1435 free(mnt);
1436 return 0;
1437
1438 err_out:
1439 free(mnt);
1440 exit(1);
1441 }