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