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 }