libfuse: fuse-3.10.3/util/fusermount.c Source File

libfuse

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