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 
33 #define FUSE_COMMFD_ENV "_FUSE_COMMFD"
34 
35 #define FUSE_DEV "/dev/fuse"
36 #define FUSE_CONF "/etc/fuse.conf"
37 
38 #ifndef MS_DIRSYNC
39 #define MS_DIRSYNC 128
40 #endif
41 #ifndef MS_REC
42 #define MS_REC 16384
43 #endif
44 #ifndef MS_PRIVATE
45 #define MS_PRIVATE (1<<18)
46 #endif
47 
48 #ifndef UMOUNT_DETACH
49 #define UMOUNT_DETACH 0x00000002 /* Just detach from the tree */
50 #endif
51 #ifndef UMOUNT_NOFOLLOW
52 #define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
53 #endif
54 #ifndef UMOUNT_UNUSED
55 #define UMOUNT_UNUSED 0x80000000 /* Flag guaranteed to be unused */
56 #endif
57 
58 static const char *progname;
59 
60 static int user_allow_other = 0;
61 static int mount_max = 1000;
62 
63 static int auto_unmount = 0;
64 
65 static const char *get_user_name(void)
66 {
67  struct passwd *pw = getpwuid(getuid());
68  if (pw != NULL && pw->pw_name != NULL)
69  return pw->pw_name;
70  else {
71  fprintf(stderr, "%s: could not determine username\n", progname);
72  return NULL;
73  }
74 }
75 
76 static uid_t oldfsuid;
77 static gid_t oldfsgid;
78 
79 static void drop_privs(void)
80 {
81  if (getuid() != 0) {
82  oldfsuid = setfsuid(getuid());
83  oldfsgid = setfsgid(getgid());
84  }
85 }
86 
87 static void restore_privs(void)
88 {
89  if (getuid() != 0) {
90  setfsuid(oldfsuid);
91  setfsgid(oldfsgid);
92  }
93 }
94 
95 #ifndef IGNORE_MTAB
96 /*
97  * Make sure that /etc/mtab is checked and updated atomically
98  */
99 static int lock_umount(void)
100 {
101  const char *mtab_lock = _PATH_MOUNTED ".fuselock";
102  int mtablock;
103  int res;
104  struct stat mtab_stat;
105 
106  /* /etc/mtab could be a symlink to /proc/mounts */
107  if (lstat(_PATH_MOUNTED, &mtab_stat) == 0 && S_ISLNK(mtab_stat.st_mode))
108  return -1;
109 
110  mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
111  if (mtablock == -1) {
112  fprintf(stderr, "%s: unable to open fuse lock file: %s\n",
113  progname, strerror(errno));
114  return -1;
115  }
116  res = lockf(mtablock, F_LOCK, 0);
117  if (res < 0) {
118  fprintf(stderr, "%s: error getting lock: %s\n", progname,
119  strerror(errno));
120  close(mtablock);
121  return -1;
122  }
123 
124  return mtablock;
125 }
126 
127 static void unlock_umount(int mtablock)
128 {
129  if (mtablock >= 0) {
130  int res;
131 
132  res = lockf(mtablock, F_ULOCK, 0);
133  if (res < 0) {
134  fprintf(stderr, "%s: error releasing lock: %s\n",
135  progname, strerror(errno));
136  }
137  close(mtablock);
138  }
139 }
140 
141 static int add_mount(const char *source, const char *mnt, const char *type,
142  const char *opts)
143 {
144  return fuse_mnt_add_mount(progname, source, mnt, type, opts);
145 }
146 
147 static int may_unmount(const char *mnt, int quiet)
148 {
149  struct mntent *entp;
150  FILE *fp;
151  const char *user = NULL;
152  char uidstr[32];
153  unsigned uidlen = 0;
154  int found;
155  const char *mtab = _PATH_MOUNTED;
156 
157  user = get_user_name();
158  if (user == NULL)
159  return -1;
160 
161  fp = setmntent(mtab, "r");
162  if (fp == NULL) {
163  fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
164  strerror(errno));
165  return -1;
166  }
167 
168  uidlen = sprintf(uidstr, "%u", getuid());
169 
170  found = 0;
171  while ((entp = getmntent(fp)) != NULL) {
172  if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
173  (strcmp(entp->mnt_type, "fuse") == 0 ||
174  strcmp(entp->mnt_type, "fuseblk") == 0 ||
175  strncmp(entp->mnt_type, "fuse.", 5) == 0 ||
176  strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) {
177  char *p = strstr(entp->mnt_opts, "user=");
178  if (p &&
179  (p == entp->mnt_opts || *(p-1) == ',') &&
180  strcmp(p + 5, user) == 0) {
181  found = 1;
182  break;
183  }
184  /* /etc/mtab is a link pointing to
185  /proc/mounts: */
186  else if ((p =
187  strstr(entp->mnt_opts, "user_id=")) &&
188  (p == entp->mnt_opts ||
189  *(p-1) == ',') &&
190  strncmp(p + 8, uidstr, uidlen) == 0 &&
191  (*(p+8+uidlen) == ',' ||
192  *(p+8+uidlen) == '\0')) {
193  found = 1;
194  break;
195  }
196  }
197  }
198  endmntent(fp);
199 
200  if (!found) {
201  if (!quiet)
202  fprintf(stderr,
203  "%s: entry for %s not found in %s\n",
204  progname, mnt, mtab);
205  return -1;
206  }
207 
208  return 0;
209 }
210 
211 /*
212  * Check whether the file specified in "fusermount3 -u" is really a
213  * mountpoint and not a symlink. This is necessary otherwise the user
214  * could move the mountpoint away and replace it with a symlink
215  * pointing to an arbitrary mount, thereby tricking fusermount3 into
216  * unmounting that (umount(2) will follow symlinks).
217  *
218  * This is the child process running in a separate mount namespace, so
219  * we don't mess with the global namespace and if the process is
220  * killed for any reason, mounts are automatically cleaned up.
221  *
222  * First make sure nothing is propagated back into the parent
223  * namespace by marking all mounts "private".
224  *
225  * Then bind mount parent onto a stable base where the user can't move
226  * it around.
227  *
228  * Finally check /proc/mounts for an entry matching the requested
229  * mountpoint. If it's found then we are OK, and the user can't move
230  * it around within the parent directory as rename() will return
231  * EBUSY. Be careful to ignore any mounts that existed before the
232  * bind.
233  */
234 static int check_is_mount_child(void *p)
235 {
236  const char **a = p;
237  const char *last = a[0];
238  const char *mnt = a[1];
239  int res;
240  const char *procmounts = "/proc/mounts";
241  int found;
242  FILE *fp;
243  struct mntent *entp;
244  int count;
245 
246  res = mount("", "/", "", MS_PRIVATE | MS_REC, NULL);
247  if (res == -1) {
248  fprintf(stderr, "%s: failed to mark mounts private: %s\n",
249  progname, strerror(errno));
250  return 1;
251  }
252 
253  fp = setmntent(procmounts, "r");
254  if (fp == NULL) {
255  fprintf(stderr, "%s: failed to open %s: %s\n", progname,
256  procmounts, strerror(errno));
257  return 1;
258  }
259 
260  count = 0;
261  while (getmntent(fp) != NULL)
262  count++;
263  endmntent(fp);
264 
265  fp = setmntent(procmounts, "r");
266  if (fp == NULL) {
267  fprintf(stderr, "%s: failed to open %s: %s\n", progname,
268  procmounts, strerror(errno));
269  return 1;
270  }
271 
272  res = mount(".", "/", "", MS_BIND | MS_REC, NULL);
273  if (res == -1) {
274  fprintf(stderr, "%s: failed to bind parent to /: %s\n",
275  progname, strerror(errno));
276  return 1;
277  }
278 
279  found = 0;
280  while ((entp = getmntent(fp)) != NULL) {
281  if (count > 0) {
282  count--;
283  continue;
284  }
285  if (entp->mnt_dir[0] == '/' &&
286  strcmp(entp->mnt_dir + 1, last) == 0) {
287  found = 1;
288  break;
289  }
290  }
291  endmntent(fp);
292 
293  if (!found) {
294  fprintf(stderr, "%s: %s not mounted\n", progname, mnt);
295  return 1;
296  }
297 
298  return 0;
299 }
300 
301 static pid_t clone_newns(void *a)
302 {
303  char buf[131072];
304  char *stack = buf + (sizeof(buf) / 2 - ((size_t) buf & 15));
305 
306 #ifdef __ia64__
307  extern int __clone2(int (*fn)(void *),
308  void *child_stack_base, size_t stack_size,
309  int flags, void *arg, pid_t *ptid,
310  void *tls, pid_t *ctid);
311 
312  return __clone2(check_is_mount_child, stack, sizeof(buf) / 2,
313  CLONE_NEWNS, a, NULL, NULL, NULL);
314 #else
315  return clone(check_is_mount_child, stack, CLONE_NEWNS, a);
316 #endif
317 }
318 
319 static int check_is_mount(const char *last, const char *mnt)
320 {
321  pid_t pid, p;
322  int status;
323  const char *a[2] = { last, mnt };
324 
325  pid = clone_newns((void *) a);
326  if (pid == (pid_t) -1) {
327  fprintf(stderr, "%s: failed to clone namespace: %s\n",
328  progname, strerror(errno));
329  return -1;
330  }
331  p = waitpid(pid, &status, __WCLONE);
332  if (p == (pid_t) -1) {
333  fprintf(stderr, "%s: waitpid failed: %s\n",
334  progname, strerror(errno));
335  return -1;
336  }
337  if (!WIFEXITED(status)) {
338  fprintf(stderr, "%s: child terminated abnormally (status %i)\n",
339  progname, status);
340  return -1;
341  }
342  if (WEXITSTATUS(status) != 0)
343  return -1;
344 
345  return 0;
346 }
347 
348 static int chdir_to_parent(char *copy, const char **lastp)
349 {
350  char *tmp;
351  const char *parent;
352  char buf[65536];
353  int res;
354 
355  tmp = strrchr(copy, '/');
356  if (tmp == NULL || tmp[1] == '\0') {
357  fprintf(stderr, "%s: internal error: invalid abs path: <%s>\n",
358  progname, copy);
359  return -1;
360  }
361  if (tmp != copy) {
362  *tmp = '\0';
363  parent = copy;
364  *lastp = tmp + 1;
365  } else if (tmp[1] != '\0') {
366  *lastp = tmp + 1;
367  parent = "/";
368  } else {
369  *lastp = ".";
370  parent = "/";
371  }
372 
373  res = chdir(parent);
374  if (res == -1) {
375  fprintf(stderr, "%s: failed to chdir to %s: %s\n",
376  progname, parent, strerror(errno));
377  return -1;
378  }
379 
380  if (getcwd(buf, sizeof(buf)) == NULL) {
381  fprintf(stderr, "%s: failed to obtain current directory: %s\n",
382  progname, strerror(errno));
383  return -1;
384  }
385  if (strcmp(buf, parent) != 0) {
386  fprintf(stderr, "%s: mountpoint moved (%s -> %s)\n", progname,
387  parent, buf);
388  return -1;
389 
390  }
391 
392  return 0;
393 }
394 
395 /* Check whether the kernel supports UMOUNT_NOFOLLOW flag */
396 static int umount_nofollow_support(void)
397 {
398  int res = umount2("", UMOUNT_UNUSED);
399  if (res != -1 || errno != EINVAL)
400  return 0;
401 
402  res = umount2("", UMOUNT_NOFOLLOW);
403  if (res != -1 || errno != ENOENT)
404  return 0;
405 
406  return 1;
407 }
408 
409 static int unmount_fuse_locked(const char *mnt, int quiet, int lazy)
410 {
411  int res;
412  char *copy;
413  const char *last;
414  int umount_flags = lazy ? UMOUNT_DETACH : 0;
415 
416  if (getuid() != 0) {
417  res = may_unmount(mnt, quiet);
418  if (res == -1)
419  return -1;
420  }
421 
422  copy = strdup(mnt);
423  if (copy == NULL) {
424  fprintf(stderr, "%s: failed to allocate memory\n", progname);
425  return -1;
426  }
427 
428  res = chdir_to_parent(copy, &last);
429  if (res == -1)
430  goto out;
431 
432  if (umount_nofollow_support()) {
433  umount_flags |= UMOUNT_NOFOLLOW;
434  } else {
435  res = check_is_mount(last, mnt);
436  if (res == -1)
437  goto out;
438  }
439 
440  res = umount2(last, umount_flags);
441  if (res == -1 && !quiet) {
442  fprintf(stderr, "%s: failed to unmount %s: %s\n",
443  progname, mnt, strerror(errno));
444  }
445 
446 out:
447  if (res == -1)
448  return -1;
449 
450  res = chdir("/");
451  if (res == -1) {
452  fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
453  return -1;
454  }
455 
456  return fuse_mnt_remove_mount(progname, mnt);
457 }
458 
459 static int unmount_fuse(const char *mnt, int quiet, int lazy)
460 {
461  int res;
462  int mtablock = lock_umount();
463 
464  res = unmount_fuse_locked(mnt, quiet, lazy);
465  unlock_umount(mtablock);
466 
467  return res;
468 }
469 
470 static int count_fuse_fs(void)
471 {
472  struct mntent *entp;
473  int count = 0;
474  const char *mtab = _PATH_MOUNTED;
475  FILE *fp = setmntent(mtab, "r");
476  if (fp == NULL) {
477  fprintf(stderr, "%s: failed to open %s: %s\n", progname, mtab,
478  strerror(errno));
479  return -1;
480  }
481  while ((entp = getmntent(fp)) != NULL) {
482  if (strcmp(entp->mnt_type, "fuse") == 0 ||
483  strncmp(entp->mnt_type, "fuse.", 5) == 0)
484  count ++;
485  }
486  endmntent(fp);
487  return count;
488 }
489 
490 
491 #else /* IGNORE_MTAB */
492 static int count_fuse_fs()
493 {
494  return 0;
495 }
496 
497 static int add_mount(const char *source, const char *mnt, const char *type,
498  const char *opts)
499 {
500  (void) source;
501  (void) mnt;
502  (void) type;
503  (void) opts;
504  return 0;
505 }
506 
507 static int unmount_fuse(const char *mnt, int quiet, int lazy)
508 {
509  return fuse_mnt_umount(progname, mnt, mnt, lazy);
510 }
511 #endif /* IGNORE_MTAB */
512 
513 static void strip_line(char *line)
514 {
515  char *s = strchr(line, '#');
516  if (s != NULL)
517  s[0] = '\0';
518  for (s = line + strlen(line) - 1;
519  s >= line && isspace((unsigned char) *s); s--);
520  s[1] = '\0';
521  for (s = line; isspace((unsigned char) *s); s++);
522  if (s != line)
523  memmove(line, s, strlen(s)+1);
524 }
525 
526 static void parse_line(char *line, int linenum)
527 {
528  int tmp;
529  if (strcmp(line, "user_allow_other") == 0)
530  user_allow_other = 1;
531  else if (sscanf(line, "mount_max = %i", &tmp) == 1)
532  mount_max = tmp;
533  else if(line[0])
534  fprintf(stderr,
535  "%s: unknown parameter in %s at line %i: '%s'\n",
536  progname, FUSE_CONF, linenum, line);
537 }
538 
539 static void read_conf(void)
540 {
541  FILE *fp = fopen(FUSE_CONF, "r");
542  if (fp != NULL) {
543  int linenum = 1;
544  char line[256];
545  int isnewline = 1;
546  while (fgets(line, sizeof(line), fp) != NULL) {
547  if (isnewline) {
548  if (line[strlen(line)-1] == '\n') {
549  strip_line(line);
550  parse_line(line, linenum);
551  } else {
552  isnewline = 0;
553  }
554  } else if(line[strlen(line)-1] == '\n') {
555  fprintf(stderr, "%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum);
556 
557  isnewline = 1;
558  }
559  if (isnewline)
560  linenum ++;
561  }
562  if (!isnewline) {
563  fprintf(stderr, "%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF);
564 
565  }
566  fclose(fp);
567  } else if (errno != ENOENT) {
568  fprintf(stderr, "%s: failed to open %s: %s\n",
569  progname, FUSE_CONF, strerror(errno));
570  }
571 }
572 
573 static int begins_with(const char *s, const char *beg)
574 {
575  if (strncmp(s, beg, strlen(beg)) == 0)
576  return 1;
577  else
578  return 0;
579 }
580 
581 struct mount_flags {
582  const char *opt;
583  unsigned long flag;
584  int on;
585  int safe;
586 };
587 
588 static struct mount_flags mount_flags[] = {
589  {"rw", MS_RDONLY, 0, 1},
590  {"ro", MS_RDONLY, 1, 1},
591  {"suid", MS_NOSUID, 0, 0},
592  {"nosuid", MS_NOSUID, 1, 1},
593  {"dev", MS_NODEV, 0, 0},
594  {"nodev", MS_NODEV, 1, 1},
595  {"exec", MS_NOEXEC, 0, 1},
596  {"noexec", MS_NOEXEC, 1, 1},
597  {"async", MS_SYNCHRONOUS, 0, 1},
598  {"sync", MS_SYNCHRONOUS, 1, 1},
599  {"atime", MS_NOATIME, 0, 1},
600  {"noatime", MS_NOATIME, 1, 1},
601  {"dirsync", MS_DIRSYNC, 1, 1},
602  {NULL, 0, 0, 0}
603 };
604 
605 static int find_mount_flag(const char *s, unsigned len, int *on, int *flag)
606 {
607  int i;
608 
609  for (i = 0; mount_flags[i].opt != NULL; i++) {
610  const char *opt = mount_flags[i].opt;
611  if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
612  *on = mount_flags[i].on;
613  *flag = mount_flags[i].flag;
614  if (!mount_flags[i].safe && getuid() != 0) {
615  *flag = 0;
616  fprintf(stderr,
617  "%s: unsafe option %s ignored\n",
618  progname, opt);
619  }
620  return 1;
621  }
622  }
623  return 0;
624 }
625 
626 static int add_option(char **optsp, const char *opt, unsigned expand)
627 {
628  char *newopts;
629  if (*optsp == NULL)
630  newopts = strdup(opt);
631  else {
632  unsigned oldsize = strlen(*optsp);
633  unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
634  newopts = (char *) realloc(*optsp, newsize);
635  if (newopts)
636  sprintf(newopts + oldsize, ",%s", opt);
637  }
638  if (newopts == NULL) {
639  fprintf(stderr, "%s: failed to allocate memory\n", progname);
640  return -1;
641  }
642  *optsp = newopts;
643  return 0;
644 }
645 
646 static int get_mnt_opts(int flags, char *opts, char **mnt_optsp)
647 {
648  int i;
649  int l;
650 
651  if (!(flags & MS_RDONLY) && add_option(mnt_optsp, "rw", 0) == -1)
652  return -1;
653 
654  for (i = 0; mount_flags[i].opt != NULL; i++) {
655  if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
656  add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
657  return -1;
658  }
659 
660  if (add_option(mnt_optsp, opts, 0) == -1)
661  return -1;
662  /* remove comma from end of opts*/
663  l = strlen(*mnt_optsp);
664  if ((*mnt_optsp)[l-1] == ',')
665  (*mnt_optsp)[l-1] = '\0';
666  if (getuid() != 0) {
667  const char *user = get_user_name();
668  if (user == NULL)
669  return -1;
670 
671  if (add_option(mnt_optsp, "user=", strlen(user)) == -1)
672  return -1;
673  strcat(*mnt_optsp, user);
674  }
675  return 0;
676 }
677 
678 static int opt_eq(const char *s, unsigned len, const char *opt)
679 {
680  if(strlen(opt) == len && strncmp(s, opt, len) == 0)
681  return 1;
682  else
683  return 0;
684 }
685 
686 static int get_string_opt(const char *s, unsigned len, const char *opt,
687  char **val)
688 {
689  int i;
690  unsigned opt_len = strlen(opt);
691  char *d;
692 
693  if (*val)
694  free(*val);
695  *val = (char *) malloc(len - opt_len + 1);
696  if (!*val) {
697  fprintf(stderr, "%s: failed to allocate memory\n", progname);
698  return 0;
699  }
700 
701  d = *val;
702  s += opt_len;
703  len -= opt_len;
704  for (i = 0; i < len; i++) {
705  if (s[i] == '\\' && i + 1 < len)
706  i++;
707  *d++ = s[i];
708  }
709  *d = '\0';
710  return 1;
711 }
712 
713 static int do_mount(const char *mnt, char **typep, mode_t rootmode,
714  int fd, const char *opts, const char *dev, char **sourcep,
715  char **mnt_optsp)
716 {
717  int res;
718  int flags = MS_NOSUID | MS_NODEV;
719  char *optbuf;
720  char *mnt_opts = NULL;
721  const char *s;
722  char *d;
723  char *fsname = NULL;
724  char *subtype = NULL;
725  char *source = NULL;
726  char *type = NULL;
727  int blkdev = 0;
728 
729  optbuf = (char *) malloc(strlen(opts) + 128);
730  if (!optbuf) {
731  fprintf(stderr, "%s: failed to allocate memory\n", progname);
732  return -1;
733  }
734 
735  for (s = opts, d = optbuf; *s;) {
736  unsigned len;
737  const char *fsname_str = "fsname=";
738  const char *subtype_str = "subtype=";
739  for (len = 0; s[len]; len++) {
740  if (s[len] == '\\' && s[len + 1])
741  len++;
742  else if (s[len] == ',')
743  break;
744  }
745  if (begins_with(s, fsname_str)) {
746  if (!get_string_opt(s, len, fsname_str, &fsname))
747  goto err;
748  } else if (begins_with(s, subtype_str)) {
749  if (!get_string_opt(s, len, subtype_str, &subtype))
750  goto err;
751  } else if (opt_eq(s, len, "blkdev")) {
752  if (getuid() != 0) {
753  fprintf(stderr,
754  "%s: option blkdev is privileged\n",
755  progname);
756  goto err;
757  }
758  blkdev = 1;
759  } else if (opt_eq(s, len, "auto_unmount")) {
760  auto_unmount = 1;
761  } else if (!begins_with(s, "fd=") &&
762  !begins_with(s, "rootmode=") &&
763  !begins_with(s, "user_id=") &&
764  !begins_with(s, "group_id=")) {
765  int on;
766  int flag;
767  int skip_option = 0;
768  if (opt_eq(s, len, "large_read")) {
769  struct utsname utsname;
770  unsigned kmaj, kmin;
771  res = uname(&utsname);
772  if (res == 0 &&
773  sscanf(utsname.release, "%u.%u",
774  &kmaj, &kmin) == 2 &&
775  (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
776  fprintf(stderr, "%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
777  skip_option = 1;
778  }
779  }
780  if (getuid() != 0 && !user_allow_other &&
781  (opt_eq(s, len, "allow_other") ||
782  opt_eq(s, len, "allow_root"))) {
783  fprintf(stderr, "%s: option %.*s only allowed if 'user_allow_other' is set in %s\n", progname, len, s, FUSE_CONF);
784  goto err;
785  }
786  if (!skip_option) {
787  if (find_mount_flag(s, len, &on, &flag)) {
788  if (on)
789  flags |= flag;
790  else
791  flags &= ~flag;
792  } else {
793  memcpy(d, s, len);
794  d += len;
795  *d++ = ',';
796  }
797  }
798  }
799  s += len;
800  if (*s)
801  s++;
802  }
803  *d = '\0';
804  res = get_mnt_opts(flags, optbuf, &mnt_opts);
805  if (res == -1)
806  goto err;
807 
808  sprintf(d, "fd=%i,rootmode=%o,user_id=%u,group_id=%u",
809  fd, rootmode, getuid(), getgid());
810 
811  source = malloc((fsname ? strlen(fsname) : 0) +
812  (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
813 
814  type = malloc((subtype ? strlen(subtype) : 0) + 32);
815  if (!type || !source) {
816  fprintf(stderr, "%s: failed to allocate memory\n", progname);
817  goto err;
818  }
819 
820  if (subtype)
821  sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype);
822  else
823  strcpy(type, blkdev ? "fuseblk" : "fuse");
824 
825  if (fsname)
826  strcpy(source, fsname);
827  else
828  strcpy(source, subtype ? subtype : dev);
829 
830  res = mount(source, mnt, type, flags, optbuf);
831  if (res == -1 && errno == ENODEV && subtype) {
832  /* Probably missing subtype support */
833  strcpy(type, blkdev ? "fuseblk" : "fuse");
834  if (fsname) {
835  if (!blkdev)
836  sprintf(source, "%s#%s", subtype, fsname);
837  } else {
838  strcpy(source, type);
839  }
840 
841  res = mount(source, mnt, type, flags, optbuf);
842  }
843  if (res == -1 && errno == EINVAL) {
844  /* It could be an old version not supporting group_id */
845  sprintf(d, "fd=%i,rootmode=%o,user_id=%u",
846  fd, rootmode, getuid());
847  res = mount(source, mnt, type, flags, optbuf);
848  }
849  if (res == -1) {
850  int errno_save = errno;
851  if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
852  fprintf(stderr, "%s: 'fuseblk' support missing\n",
853  progname);
854  else
855  fprintf(stderr, "%s: mount failed: %s\n", progname,
856  strerror(errno_save));
857  goto err;
858  }
859  *sourcep = source;
860  *typep = type;
861  *mnt_optsp = mnt_opts;
862  free(fsname);
863  free(optbuf);
864 
865  return 0;
866 
867 err:
868  free(fsname);
869  free(subtype);
870  free(source);
871  free(type);
872  free(mnt_opts);
873  free(optbuf);
874  return -1;
875 }
876 
877 static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd)
878 {
879  int res;
880  const char *mnt = *mntp;
881  const char *origmnt = mnt;
882 
883  res = lstat(mnt, stbuf);
884  if (res == -1) {
885  fprintf(stderr, "%s: failed to access mountpoint %s: %s\n",
886  progname, mnt, strerror(errno));
887  return -1;
888  }
889 
890  /* No permission checking is done for root */
891  if (getuid() == 0)
892  return 0;
893 
894  if (S_ISDIR(stbuf->st_mode)) {
895  res = chdir(mnt);
896  if (res == -1) {
897  fprintf(stderr,
898  "%s: failed to chdir to mountpoint: %s\n",
899  progname, strerror(errno));
900  return -1;
901  }
902  mnt = *mntp = ".";
903  res = lstat(mnt, stbuf);
904  if (res == -1) {
905  fprintf(stderr,
906  "%s: failed to access mountpoint %s: %s\n",
907  progname, origmnt, strerror(errno));
908  return -1;
909  }
910 
911  if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
912  fprintf(stderr, "%s: mountpoint %s not owned by user\n",
913  progname, origmnt);
914  return -1;
915  }
916 
917  res = access(mnt, W_OK);
918  if (res == -1) {
919  fprintf(stderr, "%s: user has no write access to mountpoint %s\n",
920  progname, origmnt);
921  return -1;
922  }
923  } else if (S_ISREG(stbuf->st_mode)) {
924  static char procfile[256];
925  *mountpoint_fd = open(mnt, O_WRONLY);
926  if (*mountpoint_fd == -1) {
927  fprintf(stderr, "%s: failed to open %s: %s\n",
928  progname, mnt, strerror(errno));
929  return -1;
930  }
931  res = fstat(*mountpoint_fd, stbuf);
932  if (res == -1) {
933  fprintf(stderr,
934  "%s: failed to access mountpoint %s: %s\n",
935  progname, mnt, strerror(errno));
936  return -1;
937  }
938  if (!S_ISREG(stbuf->st_mode)) {
939  fprintf(stderr,
940  "%s: mountpoint %s is no longer a regular file\n",
941  progname, mnt);
942  return -1;
943  }
944 
945  sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd);
946  *mntp = procfile;
947  } else {
948  fprintf(stderr,
949  "%s: mountpoint %s is not a directory or a regular file\n",
950  progname, mnt);
951  return -1;
952  }
953 
954 
955  return 0;
956 }
957 
958 static int try_open(const char *dev, char **devp, int silent)
959 {
960  int fd = open(dev, O_RDWR);
961  if (fd != -1) {
962  *devp = strdup(dev);
963  if (*devp == NULL) {
964  fprintf(stderr, "%s: failed to allocate memory\n",
965  progname);
966  close(fd);
967  fd = -1;
968  }
969  } else if (errno == ENODEV ||
970  errno == ENOENT)/* check for ENOENT too, for the udev case */
971  return -2;
972  else if (!silent) {
973  fprintf(stderr, "%s: failed to open %s: %s\n", progname, dev,
974  strerror(errno));
975  }
976  return fd;
977 }
978 
979 static int try_open_fuse_device(char **devp)
980 {
981  int fd;
982 
983  drop_privs();
984  fd = try_open(FUSE_DEV, devp, 0);
985  restore_privs();
986  return fd;
987 }
988 
989 static int open_fuse_device(char **devp)
990 {
991  int fd = try_open_fuse_device(devp);
992  if (fd >= -1)
993  return fd;
994 
995  fprintf(stderr,
996  "%s: fuse device not found, try 'modprobe fuse' first\n",
997  progname);
998 
999  return -1;
1000 }
1001 
1002 
1003 static int mount_fuse(const char *mnt, const char *opts)
1004 {
1005  int res;
1006  int fd;
1007  char *dev;
1008  struct stat stbuf;
1009  char *type = NULL;
1010  char *source = NULL;
1011  char *mnt_opts = NULL;
1012  const char *real_mnt = mnt;
1013  int mountpoint_fd = -1;
1014 
1015  fd = open_fuse_device(&dev);
1016  if (fd == -1)
1017  return -1;
1018 
1019  drop_privs();
1020  read_conf();
1021 
1022  if (getuid() != 0 && mount_max != -1) {
1023  int mount_count = count_fuse_fs();
1024  if (mount_count >= mount_max) {
1025  fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in %s\n", progname, FUSE_CONF);
1026  goto fail_close_fd;
1027  }
1028  }
1029 
1030  res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
1031  restore_privs();
1032  if (res != -1)
1033  res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT,
1034  fd, opts, dev, &source, &mnt_opts);
1035 
1036  if (mountpoint_fd != -1)
1037  close(mountpoint_fd);
1038 
1039  if (res == -1)
1040  goto fail_close_fd;
1041 
1042  res = chdir("/");
1043  if (res == -1) {
1044  fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1045  goto fail_close_fd;
1046  }
1047 
1048  if (geteuid() == 0) {
1049  res = add_mount(source, mnt, type, mnt_opts);
1050  if (res == -1) {
1051  /* Can't clean up mount in a non-racy way */
1052  goto fail_close_fd;
1053  }
1054  }
1055 
1056 out_free:
1057  free(source);
1058  free(type);
1059  free(mnt_opts);
1060  free(dev);
1061 
1062  return fd;
1063 
1064 fail_close_fd:
1065  close(fd);
1066  fd = -1;
1067  goto out_free;
1068 }
1069 
1070 static int send_fd(int sock_fd, int fd)
1071 {
1072  int retval;
1073  struct msghdr msg;
1074  struct cmsghdr *p_cmsg;
1075  struct iovec vec;
1076  size_t cmsgbuf[CMSG_SPACE(sizeof(fd)) / sizeof(size_t)];
1077  int *p_fds;
1078  char sendchar = 0;
1079 
1080  msg.msg_control = cmsgbuf;
1081  msg.msg_controllen = sizeof(cmsgbuf);
1082  p_cmsg = CMSG_FIRSTHDR(&msg);
1083  p_cmsg->cmsg_level = SOL_SOCKET;
1084  p_cmsg->cmsg_type = SCM_RIGHTS;
1085  p_cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
1086  p_fds = (int *) CMSG_DATA(p_cmsg);
1087  *p_fds = fd;
1088  msg.msg_controllen = p_cmsg->cmsg_len;
1089  msg.msg_name = NULL;
1090  msg.msg_namelen = 0;
1091  msg.msg_iov = &vec;
1092  msg.msg_iovlen = 1;
1093  msg.msg_flags = 0;
1094  /* "To pass file descriptors or credentials you need to send/read at
1095  * least one byte" (man 7 unix) */
1096  vec.iov_base = &sendchar;
1097  vec.iov_len = sizeof(sendchar);
1098  while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
1099  if (retval != 1) {
1100  perror("sending file descriptor");
1101  return -1;
1102  }
1103  return 0;
1104 }
1105 
1106 static void usage(void)
1107 {
1108  printf("%s: [options] mountpoint\n"
1109  "Options:\n"
1110  " -h print help\n"
1111  " -V print version\n"
1112  " -o opt[,opt...] mount options\n"
1113  " -u unmount\n"
1114  " -q quiet\n"
1115  " -z lazy unmount\n",
1116  progname);
1117  exit(1);
1118 }
1119 
1120 static void show_version(void)
1121 {
1122  printf("fusermount3 version: %s\n", PACKAGE_VERSION);
1123  exit(0);
1124 }
1125 
1126 int main(int argc, char *argv[])
1127 {
1128  sigset_t sigset;
1129  int ch;
1130  int fd;
1131  int res;
1132  char *origmnt;
1133  char *mnt;
1134  static int unmount = 0;
1135  static int lazy = 0;
1136  static int quiet = 0;
1137  char *commfd;
1138  int cfd;
1139  const char *opts = "";
1140 
1141  static const struct option long_opts[] = {
1142  {"unmount", no_argument, NULL, 'u'},
1143  {"lazy", no_argument, NULL, 'z'},
1144  {"quiet", no_argument, NULL, 'q'},
1145  {"help", no_argument, NULL, 'h'},
1146  {"version", no_argument, NULL, 'V'},
1147  {0, 0, 0, 0}};
1148 
1149  progname = strdup(argv[0]);
1150  if (progname == NULL) {
1151  fprintf(stderr, "%s: failed to allocate memory\n", argv[0]);
1152  exit(1);
1153  }
1154 
1155  while ((ch = getopt_long(argc, argv, "hVo:uzq", long_opts,
1156  NULL)) != -1) {
1157  switch (ch) {
1158  case 'h':
1159  usage();
1160  break;
1161 
1162  case 'V':
1163  show_version();
1164  break;
1165 
1166  case 'o':
1167  opts = optarg;
1168  break;
1169 
1170  case 'u':
1171  unmount = 1;
1172  break;
1173 
1174  case 'z':
1175  lazy = 1;
1176  break;
1177 
1178  case 'q':
1179  quiet = 1;
1180  break;
1181 
1182  default:
1183  exit(1);
1184  }
1185  }
1186 
1187  if (lazy && !unmount) {
1188  fprintf(stderr, "%s: -z can only be used with -u\n", progname);
1189  exit(1);
1190  }
1191 
1192  if (optind >= argc) {
1193  fprintf(stderr, "%s: missing mountpoint argument\n", progname);
1194  exit(1);
1195  } else if (argc > optind + 1) {
1196  fprintf(stderr, "%s: extra arguments after the mountpoint\n",
1197  progname);
1198  exit(1);
1199  }
1200 
1201  origmnt = argv[optind];
1202 
1203  drop_privs();
1204  mnt = fuse_mnt_resolve_path(progname, origmnt);
1205  if (mnt != NULL) {
1206  res = chdir("/");
1207  if (res == -1) {
1208  fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1209  goto err_out;
1210  }
1211  }
1212  restore_privs();
1213  if (mnt == NULL)
1214  exit(1);
1215 
1216  umask(033);
1217  if (unmount)
1218  goto do_unmount;
1219 
1220  commfd = getenv(FUSE_COMMFD_ENV);
1221  if (commfd == NULL) {
1222  fprintf(stderr, "%s: old style mounting not supported\n",
1223  progname);
1224  goto err_out;
1225  }
1226 
1227  fd = mount_fuse(mnt, opts);
1228  if (fd == -1)
1229  goto err_out;
1230 
1231  cfd = atoi(commfd);
1232  res = send_fd(cfd, fd);
1233  if (res == -1)
1234  goto err_out;
1235  close(fd);
1236 
1237  if (!auto_unmount) {
1238  free(mnt);
1239  return 0;
1240  }
1241 
1242  /* Become a daemon and wait for the parent to exit or die.
1243  ie For the control socket to get closed.
1244  btw We don't want to use daemon() function here because
1245  it forks and messes with the file descriptors. */
1246  setsid();
1247  res = chdir("/");
1248  if (res == -1) {
1249  fprintf(stderr, "%s: failed to chdir to '/'\n", progname);
1250  goto err_out;
1251  }
1252 
1253  sigfillset(&sigset);
1254  sigprocmask(SIG_BLOCK, &sigset, NULL);
1255 
1256  lazy = 1;
1257  quiet = 1;
1258 
1259  while (1) {
1260  unsigned char buf[16];
1261  int n = recv(cfd, buf, sizeof(buf), 0);
1262  if (!n)
1263  break;
1264 
1265  if (n < 0) {
1266  if (errno == EINTR)
1267  continue;
1268  break;
1269  }
1270  }
1271 
1272 do_unmount:
1273  if (geteuid() == 0)
1274  res = unmount_fuse(mnt, quiet, lazy);
1275  else {
1276  res = umount2(mnt, lazy ? UMOUNT_DETACH : 0);
1277  if (res == -1 && !quiet)
1278  fprintf(stderr,
1279  "%s: failed to unmount %s: %s\n",
1280  progname, mnt, strerror(errno));
1281  }
1282  if (res == -1)
1283  goto err_out;
1284  return 0;
1285 
1286 err_out:
1287  free(mnt);
1288  exit(1);
1289 }