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  0x5346414f /* OPENAFS_SUPER_MAGIC */,
1016  0x61756673 /* AUFS_SUPER_MAGIC */,
1017  0x00000187 /* AUTOFS_SUPER_MAGIC */,
1018  0xCA451A4E /* BCACHEFS_STATFS_MAGIC */,
1019  0x9123683E /* BTRFS_SUPER_MAGIC */,
1020  0x00C36400 /* CEPH_SUPER_MAGIC */,
1021  0xFF534D42 /* CIFS_MAGIC_NUMBER */,
1022  0X00004D44 /* MSDOS_SUPER_MAGIC */,
1023  0x0000F15F /* ECRYPTFS_SUPER_MAGIC */,
1024  0x0000EF53 /* EXT[234]_SUPER_MAGIC */,
1025  0xF2F52010 /* F2FS_SUPER_MAGIC */,
1026  0x65735546 /* FUSE_SUPER_MAGIC */,
1027  0x01161970 /* GFS2_MAGIC */,
1028  0x47504653 /* GPFS_SUPER_MAGIC */,
1029  0x3153464A /* JFS_SUPER_MAGIC */,
1030  0x000072B6 /* JFFS2_SUPER_MAGIC */,
1031  0x0BD00BD0 /* LL_SUPER_MAGIC */,
1032  0x0000564C /* NCP_SUPER_MAGIC */,
1033  0x00006969 /* NFS_SUPER_MAGIC */,
1034  0x00003434 /* NILFS_SUPER_MAGIC */,
1035  0x5346544E /* NTFS_SB_MAGIC */,
1036  0x794C7630 /* OVERLAYFS_SUPER_MAGIC */,
1037  0x52654973 /* REISERFS_SUPER_MAGIC */,
1038  0x73717368 /* SQUASHFS_MAGIC */,
1039  0x01021994 /* TMPFS_MAGIC */,
1040  0x24051905 /* UBIFS_SUPER_MAGIC */,
1041  0x58465342 /* XFS_SB_MAGIC */,
1042  0x2FC12FC1 /* ZFS_SUPER_MAGIC */,
1043  0x0000482b /* HFSPLUS_SUPER_MAGIC */,
1044  };
1045  for (i = 0; i < sizeof(f_type_whitelist)/sizeof(f_type_whitelist[0]); i++) {
1046  if (f_type_whitelist[i] == fs_buf.f_type)
1047  return 0;
1048  }
1049 
1050  fprintf(stderr, "%s: mounting over filesystem type %#010lx is forbidden\n",
1051  progname, (unsigned long)fs_buf.f_type);
1052  return -1;
1053 }
1054 
1055 static int try_open(const char *dev, char **devp, int silent)
1056 {
1057  int fd = open(dev, O_RDWR);
1058  if (fd != -1) {
1059  *devp = strdup(dev);
1060  if (*devp == NULL) {
1061  fprintf(stderr, "%s: failed to allocate memory\n",
1062  progname);
1063  close(fd);
1064  fd = -1;
1065  }
1066  } else if (errno == ENODEV ||
1067  errno == ENOENT)/* check for ENOENT too, for the udev case */
1068  return -2;
1069  else if (!silent) {
1070  fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
1071  strerror(errno));
1072  }
1073  return fd;
1074 }
1075 
1076 static int try_open_fuse_device(char **devp)
1077 {
1078  int fd;
1079 
1080  drop_privs();
1081  fd = try_open(FUSE_DEV, devp, 0);
1082  restore_privs();
1083  return fd;
1084 }
1085 
1086 static int open_fuse_device(char **devp)
1087 {
1088  int fd = try_open_fuse_device(devp);
1089  if (fd >= -1)
1090  return fd;
1091 
1092  fprintf(stderr,
1093  "%s: fuse device not found, try 'modprobe fuse' first\n",
1094  progname);
1095 
1096  return -1;
1097 }
1098 
1099 
1100 static int mount_fuse(const char *mnt, const char *opts, const char **type)
1101 {
1102  int res;
1103  int fd;
1104  char *dev;
1105  struct stat stbuf;
1106  char *source = NULL;
1107  char *mnt_opts = NULL;
1108  const char *real_mnt = mnt;
1109  int mountpoint_fd = -1;
1110 
1111  fd = open_fuse_device(&dev);
1112  if (fd == -1)
1113  return -1;
1114 
1115  drop_privs();
1116  read_conf();
1117 
1118  if (getuid() != 0 && mount_max != -1) {
1119  int mount_count = count_fuse_fs();
1120  if (mount_count >= mount_max) {
1121  fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in %s\n", progname, FUSE_CONF);
1122  goto fail_close_fd;
1123  }
1124  }
1125 
1126  res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
1127  restore_privs();
1128  if (res != -1)
1129  res = do_mount(real_mnt, type, stbuf.st_mode & S_IFMT,
1130  fd, opts, dev, &source, &mnt_opts);
1131 
1132  if (mountpoint_fd != -1)
1133  close(mountpoint_fd);
1134 
1135  if (res == -1)
1136  goto fail_close_fd;
1137 
1138  res = chdir("/");
1139  if (res == -1) {
1140  fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1141  goto fail_close_fd;
1142  }
1143 
1144  if (geteuid() == 0) {
1145  res = add_mount(source, mnt, *type, mnt_opts);
1146  if (res == -1) {
1147  /* Can't clean up mount in a non-racy way */
1148  goto fail_close_fd;
1149  }
1150  }
1151 
1152 out_free:
1153  free(source);
1154  free(mnt_opts);
1155  free(dev);
1156 
1157  return fd;
1158 
1159 fail_close_fd:
1160  close(fd);
1161  fd = -1;
1162  goto out_free;
1163 }
1164 
1165 static int send_fd(int sock_fd, int fd)
1166 {
1167  int retval;
1168  struct msghdr msg;
1169  struct cmsghdr *p_cmsg;
1170  struct iovec vec;
1171  size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
1172  int *p_fds;
1173  char sendchar = 0;
1174 
1175  msg.msg_control = cmsgbuf;
1176  msg.msg_controllen = sizeof(cmsgbuf);
1177  p_cmsg = CMSG_FIRSTHDR(&msg);
1178  p_cmsg->cmsg_level = SOL_SOCKET;
1179  p_cmsg->cmsg_type = SCM_RIGHTS;
1180  p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
1181  p_fds = (int *) CMSG_DATA(p_cmsg);
1182  *p_fds = fd;
1183  msg.msg_controllen = p_cmsg->cmsg_len;
1184  msg.msg_name = NULL;
1185  msg.msg_namelen = 0;
1186  msg.msg_iov = &vec;
1187  msg.msg_iovlen = 1;
1188  msg.msg_flags = 0;
1189  /* "To pass file descriptors or credentials you need to send/read at
1190  * least one byte" (man 7 unix) */
1191  vec.iov_base = &sendchar;
1192  vec.iov_len = sizeof(sendchar);
1193  while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
1194  if (retval != 1) {
1195  perror("sending file descriptor");
1196  return -1;
1197  }
1198  return 0;
1199 }
1200 
1201 /* The parent fuse process has died: decide whether to auto_unmount.
1202  *
1203  * In the normal case (umount or fusermount -u), the filesystem
1204  * has already been unmounted. If we simply unmount again we can
1205  * cause problems with stacked mounts (e.g. autofs).
1206  *
1207  * So we unmount here only in abnormal case where fuse process has
1208  * died without unmount happening. To detect this, we first look in
1209  * the mount table to make sure the mountpoint is still mounted and
1210  * has proper type. If so, we then see if opening the mount dir is
1211  * returning 'Transport endpoint is not connected'.
1212  *
1213  * The order of these is important, because if autofs is in use,
1214  * opening the dir to check for ENOTCONN will cause a new mount
1215  * in the normal case where filesystem has been unmounted cleanly.
1216  */
1217 static int should_auto_unmount(const char *mnt, const char *type)
1218 {
1219  char *copy;
1220  const char *last;
1221  int result = 0;
1222  int fd;
1223 
1224  copy = strdup(mnt);
1225  if (copy == NULL) {
1226  fprintf(stderr, "%s: failed to allocate memory\n", progname);
1227  return 0;
1228  }
1229 
1230  if (chdir_to_parent(copy, &last) == -1)
1231  goto out;
1232  if (check_is_mount(last, mnt, type) == -1)
1233  goto out;
1234 
1235  fd = open(mnt, O_RDONLY);
1236  if (fd != -1) {
1237  close(fd);
1238  } else {
1239  result = errno == ENOTCONN;
1240  }
1241 out:
1242  free(copy);
1243  return result;
1244 }
1245 
1246 static void usage(void)
1247 {
1248  printf("%s: [options] mountpoint\n"
1249  "Options:\n"
1250  " -h print help\n"
1251  " -V print version\n"
1252  " -o opt[,opt...] mount options\n"
1253  " -u unmount\n"
1254  " -q quiet\n"
1255  " -z lazy unmount\n",
1256  progname);
1257  exit(1);
1258 }
1259 
1260 static void show_version(void)
1261 {
1262  printf("fusermount3 version: %s\n", PACKAGE_VERSION);
1263  exit(0);
1264 }
1265 
1266 int main(int argc, char *argv[])
1267 {
1268  sigset_t sigset;
1269  int ch;
1270  int fd;
1271  int res;
1272  char *origmnt;
1273  char *mnt;
1274  static int unmount = 0;
1275  static int lazy = 0;
1276  static int quiet = 0;
1277  char *commfd;
1278  int cfd;
1279  const char *opts = "";
1280  const char *type = NULL;
1281 
1282  static const struct option long_opts[] = {
1283  {"unmount", no_argument, NULL, 'u'},
1284  {"lazy", no_argument, NULL, 'z'},
1285  {"quiet", no_argument, NULL, 'q'},
1286  {"help", no_argument, NULL, 'h'},
1287  {"version", no_argument, NULL, 'V'},
1288  {0, 0, 0, 0}};
1289 
1290  progname = strdup(argv[0]);
1291  if (progname == NULL) {
1292  fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
1293  exit(1);
1294  }
1295 
1296  while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts,
1297  NULL)) != -1) {
1298  switch (ch) {
1299  case 'h':
1300  usage();
1301  break;
1302 
1303  case 'V':
1304  show_version();
1305  break;
1306 
1307  case 'o':
1308  opts = optarg;
1309  break;
1310 
1311  case 'u':
1312  unmount = 1;
1313  break;
1314 
1315  case 'z':
1316  lazy = 1;
1317  break;
1318 
1319  case 'q':
1320  quiet = 1;
1321  break;
1322 
1323  default:
1324  exit(1);
1325  }
1326  }
1327 
1328  if (lazy && !unmount) {
1329  fprintf(stderr, "%s: -z can only be used with -u\n", progname);
1330  exit(1);
1331  }
1332 
1333  if (optind >= argc) {
1334  fprintf(stderr, "%s: missing mountpoint argument\n", progname);
1335  exit(1);
1336  } else if (argc > optind + 1) {
1337  fprintf(stderr, "%s: extra arguments after the mountpoint\n",
1338  progname);
1339  exit(1);
1340  }
1341 
1342  origmnt = argv[optind];
1343 
1344  drop_privs();
1345  mnt = fuse_mnt_resolve_path(progname, origmnt);
1346  if (mnt != NULL) {
1347  res = chdir("/");
1348  if (res == -1) {
1349  fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1350  goto err_out;
1351  }
1352  }
1353  restore_privs();
1354  if (mnt == NULL)
1355  exit(1);
1356 
1357  umask(033);
1358  if (unmount)
1359  goto do_unmount;
1360 
1361  commfd = getenv(FUSE_COMMFD_ENV);
1362  if (commfd == NULL) {
1363  fprintf(stderr, "%s: old style mounting not supported\n",
1364  progname);
1365  goto err_out;
1366  }
1367 
1368  fd = mount_fuse(mnt, opts, &type);
1369  if (fd == -1)
1370  goto err_out;
1371 
1372  cfd = atoi(commfd);
1373  res = send_fd(cfd, fd);
1374  if (res == -1)
1375  goto err_out;
1376  close(fd);
1377 
1378  if (!auto_unmount) {
1379  free(mnt);
1380  return 0;
1381  }
1382 
1383  /* Become a daemon and wait for the parent to exit or die.
1384  ie For the control socket to get closed.
1385  btw We don't want to use daemon() function here because
1386  it forks and messes with the file descriptors. */
1387  setsid();
1388  res = chdir("/");
1389  if (res == -1) {
1390  fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1391  goto err_out;
1392  }
1393 
1394  sigfillset(&sigset);
1395  sigprocmask(SIG_BLOCK, &sigset, NULL);
1396 
1397  lazy = 1;
1398  quiet = 1;
1399 
1400  while (1) {
1401  unsigned char buf[16];
1402  int n = recv(cfd, buf, sizeof(buf), 0);
1403  if (!n)
1404  break;
1405 
1406  if (n < 0) {
1407  if (errno == EINTR)
1408  continue;
1409  break;
1410  }
1411  }
1412 
1413  if (!should_auto_unmount(mnt, type)) {
1414  goto success_out;
1415  }
1416 
1417 do_unmount:
1418  if (geteuid() == 0)
1419  res = unmount_fuse(mnt, quiet, lazy);
1420  else {
1421  res = umount2(mnt, lazy ? UMOUNT_DETACH : 0);
1422  if (res == -1 && !quiet)
1423  fprintf(stderr,
1424  "%s: failed to unmount %s: %s\n",
1425  progname, mnt, strerror(errno));
1426  }
1427  if (res == -1)
1428  goto err_out;
1429 
1430 success_out:
1431  free(mnt);
1432  return 0;
1433 
1434 err_out:
1435  free(mnt);
1436  exit(1);
1437 }