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