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