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