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