11#include "fuse_config.h" 
   12#include "mount_util.h" 
   30#include "fuse_mount_compat.h" 
   33#include <sys/socket.h> 
   34#include <sys/utsname.h> 
   39#ifdef HAVE_LINUX_CLOSE_RANGE_H 
   40#include <linux/close_range.h> 
   43#define FUSE_COMMFD_ENV         "_FUSE_COMMFD" 
   45#define FUSE_DEV "/dev/fuse" 
   47static const char *progname;
 
   49static int user_allow_other = 0;
 
   50static int mount_max = 1000;
 
   52static int auto_unmount = 0;
 
   54#ifdef GETMNTENT_NEEDS_UNESCAPING 
   59static void unescape(
char *buf) {
 
   63                char *next_src = strchrnul(src, 
'\\');
 
   64                int offset = next_src - src;
 
   65                memmove(dest, src, offset);
 
   75                if(
'0' <= src[0] && src[0] < 
'2' &&
 
   76                   '0' <= src[1] && src[1] < 
'8' &&
 
   77                   '0' <= src[2] && src[2] < 
'8') {
 
   78                        *dest++ = (src[0] - 
'0') << 6
 
   80                                | (src[2] - 
'0') << 0;
 
   82                } 
else if (src[0] == 
'\\') {
 
   91static struct mntent *GETMNTENT(FILE *stream)
 
   93        struct mntent *entp = getmntent(stream);
 
   95                unescape(entp->mnt_fsname);
 
   96                unescape(entp->mnt_dir);
 
   97                unescape(entp->mnt_type);
 
   98                unescape(entp->mnt_opts);
 
  103#define GETMNTENT getmntent 
  109static int extract_x_options(
const char *original, 
char **non_x_opts,
 
  113        const char *opt, *opt_end;
 
  115        orig_len = strlen(original) + 1;
 
  117        *non_x_opts = calloc(1, orig_len);
 
  118        *x_opts    = calloc(1, orig_len);
 
  120        size_t non_x_opts_len = orig_len;
 
  121        size_t x_opts_len = orig_len;
 
  123        if (*non_x_opts == NULL || *x_opts == NULL) {
 
  124                fprintf(stderr, 
"%s: Failed to allocate %zuB.\n",
 
  129        for (opt = original; opt < original + orig_len; opt = opt_end + 1) {
 
  132                opt_end = strchr(opt, 
',');
 
  134                        opt_end = original + orig_len;
 
  136                size_t opt_len = opt_end - opt;
 
  137                size_t opt_len_left = orig_len - (opt - original);
 
  141                if (strncmp(opt, 
"x-", MIN(2, opt_len_left)) == 0) {
 
  142                        buf_len = x_opts_len;
 
  146                        buf_len = non_x_opts_len;
 
  148                        opt_buf = *non_x_opts;
 
  151                if (buf_len < orig_len) {
 
  152                        strncat(opt_buf, 
",", 2);
 
  157                if ((ssize_t)(buf_len - opt_len) < 0) {
 
  159                        fprintf(stderr, 
"%s: no buf space left in copy, orig='%s'\n",
 
  164                strncat(opt_buf, opt, opt_end - opt);
 
  168                        x_opts_len = buf_len;
 
  170                        non_x_opts_len = buf_len;
 
  176static const char *get_user_name(
void)
 
  178        struct passwd *pw = getpwuid(getuid());
 
  179        if (pw != NULL && pw->pw_name != NULL)
 
  182                fprintf(stderr, 
"%s: could not determine username\n", progname);
 
  187static uid_t oldfsuid;
 
  188static gid_t oldfsgid;
 
  190static void drop_privs(
void)
 
  193                oldfsuid = setfsuid(getuid());
 
  194                oldfsgid = setfsgid(getgid());
 
  198static void restore_privs(
void)
 
  210static int lock_umount(
void)
 
  212        const char *mtab_lock = _PATH_MOUNTED 
".fuselock";
 
  215        struct stat mtab_stat;
 
  218        if (lstat(_PATH_MOUNTED, &mtab_stat) == 0 && S_ISLNK(mtab_stat.st_mode))
 
  221        mtablock = open(mtab_lock, O_RDWR | O_CREAT, 0600);
 
  222        if (mtablock == -1) {
 
  223                fprintf(stderr, 
"%s: unable to open fuse lock file: %s\n",
 
  224                        progname, strerror(errno));
 
  227        res = lockf(mtablock, F_LOCK, 0);
 
  229                fprintf(stderr, 
"%s: error getting lock: %s\n", progname,
 
  238static void unlock_umount(
int mtablock)
 
  243                res = lockf(mtablock, F_ULOCK, 0);
 
  245                        fprintf(stderr, 
"%s: error releasing lock: %s\n",
 
  246                                progname, strerror(errno));
 
  252static int add_mount(
const char *source, 
const char *mnt, 
const char *type,
 
  255        return fuse_mnt_add_mount(progname, source, mnt, type, opts);
 
  258static int may_unmount(
const char *mnt, 
int quiet)
 
  262        const char *user = NULL;
 
  266        const char *mtab = _PATH_MOUNTED;
 
  268        user = get_user_name();
 
  272        fp = setmntent(mtab, 
"r");
 
  274                fprintf(stderr, 
"%s: failed to open %s: %s\n", progname, mtab,
 
  279        uidlen = sprintf(uidstr, 
"%u", getuid());
 
  282        while ((entp = GETMNTENT(fp)) != NULL) {
 
  283                if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
 
  284                    (strcmp(entp->mnt_type, 
"fuse") == 0 ||
 
  285                     strcmp(entp->mnt_type, 
"fuseblk") == 0 ||
 
  286                     strncmp(entp->mnt_type, 
"fuse.", 5) == 0 ||
 
  287                     strncmp(entp->mnt_type, 
"fuseblk.", 8) == 0)) {
 
  288                        char *p = strstr(entp->mnt_opts, 
"user=");
 
  290                            (p == entp->mnt_opts || *(p-1) == 
',') &&
 
  291                            strcmp(p + 5, user) == 0) {
 
  298                                  strstr(entp->mnt_opts, 
"user_id=")) &&
 
  299                                 (p == entp->mnt_opts ||
 
  301                                 strncmp(p + 8, uidstr, uidlen) == 0 &&
 
  302                                 (*(p+8+uidlen) == 
',' ||
 
  303                                  *(p+8+uidlen) == 
'\0')) {
 
  314                                "%s: entry for %s not found in %s\n",
 
  315                                progname, mnt, mtab);
 
  346static int check_is_mount_child(
void *p)
 
  349        const char *last = a[0];
 
  350        const char *mnt = a[1];
 
  351        const char *type = a[2];
 
  353        const char *procmounts = 
"/proc/mounts";
 
  359        res = mount(
"", 
"/", 
"", MS_PRIVATE | MS_REC, NULL);
 
  361                fprintf(stderr, 
"%s: failed to mark mounts private: %s\n",
 
  362                        progname, strerror(errno));
 
  366        fp = setmntent(procmounts, 
"r");
 
  368                fprintf(stderr, 
"%s: failed to open %s: %s\n", progname,
 
  369                        procmounts, strerror(errno));
 
  374        while (GETMNTENT(fp) != NULL)
 
  378        fp = setmntent(procmounts, 
"r");
 
  380                fprintf(stderr, 
"%s: failed to open %s: %s\n", progname,
 
  381                        procmounts, strerror(errno));
 
  385        res = mount(
".", 
"/", 
"", MS_BIND | MS_REC, NULL);
 
  387                fprintf(stderr, 
"%s: failed to bind parent to /: %s\n",
 
  388                        progname, strerror(errno));
 
  393        while ((entp = GETMNTENT(fp)) != NULL) {
 
  398                if (entp->mnt_dir[0] == 
'/' &&
 
  399                    strcmp(entp->mnt_dir + 1, last) == 0 &&
 
  400                    (!type || strcmp(entp->mnt_type, type) == 0)) {
 
  408                fprintf(stderr, 
"%s: %s not mounted\n", progname, mnt);
 
  415static pid_t clone_newns(
void *a)
 
  418        char *stack = buf + (
sizeof(buf) / 2 - ((
size_t) buf & 15));
 
  421        extern int __clone2(
int (*fn)(
void *),
 
  422                            void *child_stack_base, 
size_t stack_size,
 
  423                            int flags, 
void *arg, pid_t *ptid,
 
  424                            void *tls, pid_t *ctid);
 
  426        return __clone2(check_is_mount_child, stack, 
sizeof(buf) / 2,
 
  427                        CLONE_NEWNS, a, NULL, NULL, NULL);
 
  429        return clone(check_is_mount_child, stack, CLONE_NEWNS, a);
 
  433static int check_is_mount(
const char *last, 
const char *mnt, 
const char *type)
 
  437        const char *a[3] = { last, mnt, type };
 
  439        pid = clone_newns((
void *) a);
 
  440        if (pid == (pid_t) -1) {
 
  441                fprintf(stderr, 
"%s: failed to clone namespace: %s\n",
 
  442                        progname, strerror(errno));
 
  445        p = waitpid(pid, &status, __WCLONE);
 
  446        if (p == (pid_t) -1) {
 
  447                fprintf(stderr, 
"%s: waitpid failed: %s\n",
 
  448                        progname, strerror(errno));
 
  451        if (!WIFEXITED(status)) {
 
  452                fprintf(stderr, 
"%s: child terminated abnormally (status %i)\n",
 
  456        if (WEXITSTATUS(status) != 0)
 
  462static int chdir_to_parent(
char *copy, 
const char **lastp)
 
  469        tmp = strrchr(copy, 
'/');
 
  470        if (tmp == NULL || tmp[1] == 
'\0') {
 
  471                fprintf(stderr, 
"%s: internal error: invalid abs path: <%s>\n",
 
  479        } 
else if (tmp[1] != 
'\0') {
 
  489                fprintf(stderr, 
"%s: failed to chdir to %s: %s\n",
 
  490                        progname, parent, strerror(errno));
 
  494        if (getcwd(buf, 
sizeof(buf)) == NULL) {
 
  495                fprintf(stderr, 
"%s: failed to obtain current directory: %s\n",
 
  496                        progname, strerror(errno));
 
  499        if (strcmp(buf, parent) != 0) {
 
  500                fprintf(stderr, 
"%s: mountpoint moved (%s -> %s)\n", progname,
 
  510static int unmount_fuse_locked(
const char *mnt, 
int quiet, 
int lazy)
 
  515        int umount_flags = (lazy ? UMOUNT_DETACH : 0) | UMOUNT_NOFOLLOW;
 
  518                res = may_unmount(mnt, quiet);
 
  525                fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
 
  530        res = chdir_to_parent(copy, &last);
 
  536        res = umount2(last, umount_flags);
 
  538        if (res == -1 && !quiet) {
 
  539                fprintf(stderr, 
"%s: failed to unmount %s: %s\n",
 
  540                        progname, mnt, strerror(errno));
 
  550                fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
 
  554        return fuse_mnt_remove_mount(progname, mnt);
 
  557static int unmount_fuse(
const char *mnt, 
int quiet, 
int lazy)
 
  560        int mtablock = lock_umount();
 
  562        res = unmount_fuse_locked(mnt, quiet, lazy);
 
  563        unlock_umount(mtablock);
 
  568static int count_fuse_fs(
void)
 
  572        const char *mtab = _PATH_MOUNTED;
 
  573        FILE *fp = setmntent(mtab, 
"r");
 
  575                fprintf(stderr, 
"%s: failed to open %s: %s\n", progname, mtab,
 
  579        while ((entp = GETMNTENT(fp)) != NULL) {
 
  580                if (strcmp(entp->mnt_type, 
"fuse") == 0 ||
 
  581                    strncmp(entp->mnt_type, 
"fuse.", 5) == 0)
 
  590static int count_fuse_fs(
void)
 
  595static int add_mount(
const char *source, 
const char *mnt, 
const char *type,
 
  605static int unmount_fuse(
const char *mnt, 
int quiet, 
int lazy)
 
  608        return fuse_mnt_umount(progname, mnt, mnt, lazy);
 
  612static void strip_line(
char *line)
 
  614        char *s = strchr(line, 
'#');
 
  617        for (s = line + strlen(line) - 1;
 
  618             s >= line && isspace((
unsigned char) *s); s--);
 
  620        for (s = line; isspace((
unsigned char) *s); s++);
 
  622                memmove(line, s, strlen(s)+1);
 
  625static void parse_line(
char *line, 
int linenum)
 
  628        if (strcmp(line, 
"user_allow_other") == 0)
 
  629                user_allow_other = 1;
 
  630        else if (sscanf(line, 
"mount_max = %i", &tmp) == 1)
 
  634                        "%s: unknown parameter in %s at line %i: '%s'\n",
 
  635                        progname, FUSE_CONF, linenum, line);
 
  638static void read_conf(
void)
 
  640        FILE *fp = fopen(FUSE_CONF, 
"r");
 
  645                while (fgets(line, 
sizeof(line), fp) != NULL) {
 
  647                                if (line[strlen(line)-1] == 
'\n') {
 
  649                                        parse_line(line, linenum);
 
  653                        } 
else if(line[strlen(line)-1] == 
'\n') {
 
  654                                fprintf(stderr, 
"%s: reading %s: line %i too long\n", progname, FUSE_CONF, linenum);
 
  662                        fprintf(stderr, 
"%s: reading %s: missing newline at end of file\n", progname, FUSE_CONF);
 
  666                        fprintf(stderr, 
"%s: reading %s: read failed\n", progname, FUSE_CONF);
 
  670        } 
else if (errno != ENOENT) {
 
  671                bool fatal = (errno != EACCES && errno != ELOOP &&
 
  672                              errno != ENAMETOOLONG && errno != ENOTDIR &&
 
  674                fprintf(stderr, 
"%s: failed to open %s: %s\n",
 
  675                        progname, FUSE_CONF, strerror(errno));
 
  681static int begins_with(
const char *s, 
const char *beg)
 
  683        if (strncmp(s, beg, strlen(beg)) == 0)
 
  696static struct mount_flags mount_flags[] = {
 
  697        {
"rw",      MS_RDONLY,      0, 1},
 
  698        {
"ro",      MS_RDONLY,      1, 1},
 
  699        {
"suid",    MS_NOSUID,      0, 0},
 
  700        {
"nosuid",  MS_NOSUID,      1, 1},
 
  701        {
"dev",     MS_NODEV,       0, 0},
 
  702        {
"nodev",   MS_NODEV,       1, 1},
 
  703        {
"exec",    MS_NOEXEC,      0, 1},
 
  704        {
"noexec",  MS_NOEXEC,      1, 1},
 
  705        {
"async",   MS_SYNCHRONOUS, 0, 1},
 
  706        {
"sync",    MS_SYNCHRONOUS, 1, 1},
 
  707        {
"atime",   MS_NOATIME,     0, 1},
 
  708        {
"noatime", MS_NOATIME,     1, 1},
 
  709        {
"diratime",        MS_NODIRATIME,  0, 1},
 
  710        {
"nodiratime",      MS_NODIRATIME,  1, 1},
 
  711        {
"lazytime",        MS_LAZYTIME,    1, 1},
 
  712        {
"nolazytime",      MS_LAZYTIME,    0, 1},
 
  713        {
"relatime",        MS_RELATIME,    1, 1},
 
  714        {
"norelatime",      MS_RELATIME,    0, 1},
 
  715        {
"strictatime",     MS_STRICTATIME, 1, 1},
 
  716        {
"nostrictatime",   MS_STRICTATIME, 0, 1},
 
  717        {
"dirsync", MS_DIRSYNC,     1, 1},
 
  718        {
"symfollow",       MS_NOSYMFOLLOW, 0, 1},
 
  719        {
"nosymfollow",     MS_NOSYMFOLLOW, 1, 1},
 
  723static int find_mount_flag(
const char *s, 
unsigned len, 
int *on, 
int *flag)
 
  727        for (i = 0; mount_flags[i].opt != NULL; i++) {
 
  728                const char *opt = mount_flags[i].opt;
 
  729                if (strlen(opt) == len && strncmp(opt, s, len) == 0) {
 
  730                        *on = mount_flags[i].on;
 
  731                        *flag = mount_flags[i].flag;
 
  732                        if (!mount_flags[i].safe && getuid() != 0) {
 
  735                                        "%s: unsafe option %s ignored\n",
 
  744static int add_option(
char **optsp, 
const char *opt, 
unsigned expand)
 
  748                newopts = strdup(opt);
 
  750                unsigned oldsize = strlen(*optsp);
 
  751                unsigned newsize = oldsize + 1 + strlen(opt) + expand + 1;
 
  752                newopts = (
char *) realloc(*optsp, newsize);
 
  754                        sprintf(newopts + oldsize, 
",%s", opt);
 
  756        if (newopts == NULL) {
 
  757                fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
 
  764static int get_mnt_opts(
int flags, 
char *opts, 
char **mnt_optsp)
 
  769        if (!(flags & MS_RDONLY) && add_option(mnt_optsp, 
"rw", 0) == -1)
 
  772        for (i = 0; mount_flags[i].opt != NULL; i++) {
 
  773                if (mount_flags[i].on && (flags & mount_flags[i].flag) &&
 
  774                    add_option(mnt_optsp, mount_flags[i].opt, 0) == -1)
 
  778        if (add_option(mnt_optsp, opts, 0) == -1)
 
  781        l = strlen(*mnt_optsp);
 
  782        if ((*mnt_optsp)[l-1] == 
',')
 
  783                (*mnt_optsp)[l-1] = 
'\0';
 
  785                const char *user = get_user_name();
 
  789                if (add_option(mnt_optsp, 
"user=", strlen(user)) == -1)
 
  791                strcat(*mnt_optsp, user);
 
  796static int opt_eq(
const char *s, 
unsigned len, 
const char *opt)
 
  798        if(strlen(opt) == len && strncmp(s, opt, len) == 0)
 
  804static int get_string_opt(
const char *s, 
unsigned len, 
const char *opt,
 
  808        unsigned opt_len = strlen(opt);
 
  813        *val = (
char *) malloc(len - opt_len + 1);
 
  815                fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
 
  822        for (i = 0; i < len; i++) {
 
  823                if (s[i] == 
'\\' && i + 1 < len)
 
  836static int mount_notrunc(
const char *source, 
const char *target,
 
  837                         const char *filesystemtype, 
unsigned long mountflags,
 
  839        if (strlen(data) > sysconf(_SC_PAGESIZE) - 1) {
 
  840                fprintf(stderr, 
"%s: mount options too long\n", progname);
 
  844        return mount(source, target, filesystemtype, mountflags, data);
 
  848static int do_mount(
const char *mnt, 
const char **typep, mode_t rootmode,
 
  849                    int fd, 
const char *opts, 
const char *dev, 
char **sourcep,
 
  853        int flags = MS_NOSUID | MS_NODEV;
 
  855        char *mnt_opts = NULL;
 
  859        char *subtype = NULL;
 
  864        optbuf = (
char *) malloc(strlen(opts) + 128);
 
  866                fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
 
  870        for (s = opts, d = optbuf; *s;) {
 
  872                const char *fsname_str = 
"fsname=";
 
  873                const char *subtype_str = 
"subtype=";
 
  874                bool escape_ok = begins_with(s, fsname_str) ||
 
  875                                 begins_with(s, subtype_str);
 
  876                for (len = 0; s[len]; len++) {
 
  877                        if (escape_ok && s[len] == 
'\\' && s[len + 1])
 
  879                        else if (s[len] == 
',')
 
  882                if (begins_with(s, fsname_str)) {
 
  883                        if (!get_string_opt(s, len, fsname_str, &fsname))
 
  885                } 
else if (begins_with(s, subtype_str)) {
 
  886                        if (!get_string_opt(s, len, subtype_str, &subtype))
 
  888                } 
else if (opt_eq(s, len, 
"blkdev")) {
 
  891                                        "%s: option blkdev is privileged\n",
 
  896                } 
else if (opt_eq(s, len, 
"auto_unmount")) {
 
  898                } 
else if (!opt_eq(s, len, 
"nonempty") &&
 
  899                           !begins_with(s, 
"fd=") &&
 
  900                           !begins_with(s, 
"rootmode=") &&
 
  901                           !begins_with(s, 
"user_id=") &&
 
  902                           !begins_with(s, 
"group_id=")) {
 
  906                        if (opt_eq(s, len, 
"large_read")) {
 
  907                                struct utsname utsname;
 
  909                                res = uname(&utsname);
 
  911                                    sscanf(utsname.release, 
"%u.%u",
 
  912                                           &kmaj, &kmin) == 2 &&
 
  913                                    (kmaj > 2 || (kmaj == 2 && kmin > 4))) {
 
  914                                        fprintf(stderr, 
"%s: note: 'large_read' mount option is deprecated for %i.%i kernels\n", progname, kmaj, kmin);
 
  918                        if (getuid() != 0 && !user_allow_other &&
 
  919                            (opt_eq(s, len, 
"allow_other") ||
 
  920                             opt_eq(s, len, 
"allow_root"))) {
 
  921                                fprintf(stderr, 
"%s: option %.*s only allowed if 'user_allow_other' is set in %s\n", progname, len, s, FUSE_CONF);
 
  925                                if (find_mount_flag(s, len, &on, &flag)) {
 
  930                                } 
else if (opt_eq(s, len, 
"default_permissions") ||
 
  931                                           opt_eq(s, len, 
"allow_other") ||
 
  932                                           begins_with(s, 
"max_read=") ||
 
  933                                           begins_with(s, 
"blksize=")) {
 
  938                                        fprintf(stderr, 
"%s: unknown option '%.*s'\n", progname, len, s);
 
  948        res = get_mnt_opts(flags, optbuf, &mnt_opts);
 
  952        sprintf(d, 
"fd=%i,rootmode=%o,user_id=%u,group_id=%u",
 
  953                fd, rootmode, getuid(), getgid());
 
  955        source = malloc((fsname ? strlen(fsname) : 0) +
 
  956                        (subtype ? strlen(subtype) : 0) + strlen(dev) + 32);
 
  958        type = malloc((subtype ? strlen(subtype) : 0) + 32);
 
  959        if (!type || !source) {
 
  960                fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
 
  965                sprintf(type, 
"%s.%s", blkdev ? 
"fuseblk" : 
"fuse", subtype);
 
  967                strcpy(type, blkdev ? 
"fuseblk" : 
"fuse");
 
  970                strcpy(source, fsname);
 
  972                strcpy(source, subtype ? subtype : dev);
 
  974        res = mount_notrunc(source, mnt, type, flags, optbuf);
 
  975        if (res == -1 && errno == ENODEV && subtype) {
 
  977                strcpy(type, blkdev ? 
"fuseblk" : 
"fuse");
 
  980                                sprintf(source, 
"%s#%s", subtype, fsname);
 
  982                        strcpy(source, type);
 
  985                res = mount_notrunc(source, mnt, type, flags, optbuf);
 
  987        if (res == -1 && errno == EINVAL) {
 
  989                sprintf(d, 
"fd=%i,rootmode=%o,user_id=%u",
 
  990                        fd, rootmode, getuid());
 
  991                res = mount_notrunc(source, mnt, type, flags, optbuf);
 
  994                int errno_save = errno;
 
  995                if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
 
  996                        fprintf(stderr, 
"%s: 'fuseblk' support missing\n",
 
  999                        fprintf(stderr, 
"%s: mount failed: %s\n", progname,
 
 1000                                strerror(errno_save));
 
 1005        *mnt_optsp = mnt_opts;
 
 1021static int check_perm(
const char **mntp, 
struct stat *stbuf, 
int *mountpoint_fd)
 
 1024        const char *mnt = *mntp;
 
 1025        const char *origmnt = mnt;
 
 1026        struct statfs fs_buf;
 
 1029        res = lstat(mnt, stbuf);
 
 1031                fprintf(stderr, 
"%s: failed to access mountpoint %s: %s\n",
 
 1032                        progname, mnt, strerror(errno));
 
 1040        if (S_ISDIR(stbuf->st_mode)) {
 
 1044                                "%s: failed to chdir to mountpoint: %s\n",
 
 1045                                progname, strerror(errno));
 
 1049                res = lstat(mnt, stbuf);
 
 1052                                "%s: failed to access mountpoint %s: %s\n",
 
 1053                                progname, origmnt, strerror(errno));
 
 1057                if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) {
 
 1058                        fprintf(stderr, 
"%s: mountpoint %s not owned by user\n",
 
 1063                res = access(mnt, W_OK);
 
 1065                        fprintf(stderr, 
"%s: user has no write access to mountpoint %s\n",
 
 1069        } 
else if (S_ISREG(stbuf->st_mode)) {
 
 1070                static char procfile[256];
 
 1071                *mountpoint_fd = open(mnt, O_WRONLY);
 
 1072                if (*mountpoint_fd == -1) {
 
 1073                        fprintf(stderr, 
"%s: failed to open %s: %s\n",
 
 1074                                progname, mnt, strerror(errno));
 
 1077                res = fstat(*mountpoint_fd, stbuf);
 
 1080                                "%s: failed to access mountpoint %s: %s\n",
 
 1081                                progname, mnt, strerror(errno));
 
 1084                if (!S_ISREG(stbuf->st_mode)) {
 
 1086                                "%s: mountpoint %s is no longer a regular file\n",
 
 1091                sprintf(procfile, 
"/proc/self/fd/%i", *mountpoint_fd);
 
 1095                        "%s: mountpoint %s is not a directory or a regular file\n",
 
 1106        if (statfs(*mntp, &fs_buf)) {
 
 1107                fprintf(stderr, 
"%s: failed to access mountpoint %s: %s\n",
 
 1108                        progname, mnt, strerror(errno));
 
 1117        typeof(fs_buf.f_type) f_type_whitelist[] = {
 
 1149#if __SIZEOF_LONG__ > 4 
 1150                0x736675005346544e ,
 
 1156        for (i = 0; i < 
sizeof(f_type_whitelist)/
sizeof(f_type_whitelist[0]); i++) {
 
 1157                if (f_type_whitelist[i] == fs_buf.f_type)
 
 1161        fprintf(stderr, 
"%s: mounting over filesystem type %#010lx is forbidden\n",
 
 1162                progname, (
unsigned long)fs_buf.f_type);
 
 1166static int try_open(
const char *dev, 
char **devp, 
int silent)
 
 1168        int fd = open(dev, O_RDWR);
 
 1170                *devp = strdup(dev);
 
 1171                if (*devp == NULL) {
 
 1172                        fprintf(stderr, 
"%s: failed to allocate memory\n",
 
 1177        } 
else if (errno == ENODEV ||
 
 1181                fprintf(stderr, 
"%s: failed to open %s: %s\n", progname, dev,
 
 1187static int try_open_fuse_device(
char **devp)
 
 1192        fd = try_open(FUSE_DEV, devp, 0);
 
 1197static int open_fuse_device(
char **devp)
 
 1199        int fd = try_open_fuse_device(devp);
 
 1204                "%s: fuse device not found, try 'modprobe fuse' first\n",
 
 1211static int mount_fuse(
const char *mnt, 
const char *opts, 
const char **type)
 
 1217        char *source = NULL;
 
 1218        char *mnt_opts = NULL;
 
 1219        const char *real_mnt = mnt;
 
 1220        int mountpoint_fd = -1;
 
 1221        char *do_mount_opts = NULL;
 
 1222        char *x_opts = NULL;
 
 1224        fd = open_fuse_device(&dev);
 
 1231        if (getuid() != 0 && mount_max != -1) {
 
 1232                int mount_count = count_fuse_fs();
 
 1233                if (mount_count >= mount_max) {
 
 1234                        fprintf(stderr, 
"%s: too many FUSE filesystems mounted; mount_max=N can be set in %s\n", progname, FUSE_CONF);
 
 1240        res= extract_x_options(opts, &do_mount_opts, &x_opts);
 
 1244        res = check_perm(&real_mnt, &stbuf, &mountpoint_fd);
 
 1247                res = do_mount(real_mnt, type, stbuf.st_mode & S_IFMT,
 
 1248                               fd, do_mount_opts, dev, &source, &mnt_opts);
 
 1250        if (mountpoint_fd != -1)
 
 1251                close(mountpoint_fd);
 
 1258                fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
 
 1262        if (geteuid() == 0) {
 
 1263                if (x_opts && strlen(x_opts) > 0) {
 
 1268                        size_t mnt_opts_len = strlen(mnt_opts);
 
 1269                        size_t x_mnt_opts_len =  mnt_opts_len+
 
 1271                        char *x_mnt_opts = calloc(1, x_mnt_opts_len);
 
 1274                                strcpy(x_mnt_opts, mnt_opts);
 
 1275                                strncat(x_mnt_opts, 
",", 2);
 
 1278                        strncat(x_mnt_opts, x_opts,
 
 1279                                x_mnt_opts_len - mnt_opts_len - 2);
 
 1282                        mnt_opts = x_mnt_opts;
 
 1285                res = add_mount(source, mnt, *type, mnt_opts);
 
 1297        free(do_mount_opts);
 
 1307static int send_fd(
int sock_fd, 
int fd)
 
 1311        struct cmsghdr *p_cmsg;
 
 1313        size_t cmsgbuf[CMSG_SPACE(
sizeof(fd)) / 
sizeof(size_t)];
 
 1317        msg.msg_control = cmsgbuf;
 
 1318        msg.msg_controllen = 
sizeof(cmsgbuf);
 
 1319        p_cmsg = CMSG_FIRSTHDR(&msg);
 
 1320        p_cmsg->cmsg_level = SOL_SOCKET;
 
 1321        p_cmsg->cmsg_type = SCM_RIGHTS;
 
 1322        p_cmsg->cmsg_len = CMSG_LEN(
sizeof(fd));
 
 1323        p_fds = (
int *) CMSG_DATA(p_cmsg);
 
 1325        msg.msg_controllen = p_cmsg->cmsg_len;
 
 1326        msg.msg_name = NULL;
 
 1327        msg.msg_namelen = 0;
 
 1333        vec.iov_base = &sendchar;
 
 1334        vec.iov_len = 
sizeof(sendchar);
 
 1335        while ((retval = sendmsg(sock_fd, &msg, 0)) == -1 && errno == EINTR);
 
 1337                perror(
"sending file descriptor");
 
 1349static int recheck_ENOTCONN_as_owner(
const char *mnt)
 
 1353                perror(
"fuse: recheck_ENOTCONN_as_owner can't fork");
 
 1354                _exit(EXIT_FAILURE);
 
 1355        } 
else if(pid == 0) {
 
 1356                uid_t uid = getuid();
 
 1357                gid_t gid = getgid();
 
 1358                if(setresgid(gid, gid, gid) == -1) {
 
 1359                        perror(
"fuse: can't set resgid");
 
 1360                        _exit(EXIT_FAILURE);
 
 1362                if(setresuid(uid, uid, uid) == -1) {
 
 1363                        perror(
"fuse: can't set resuid");
 
 1364                        _exit(EXIT_FAILURE);
 
 1367                int fd = open(mnt, O_RDONLY);
 
 1368                if(fd == -1 && errno == ENOTCONN)
 
 1369                        _exit(EXIT_SUCCESS);
 
 1371                        _exit(EXIT_FAILURE);
 
 1374                int res = waitpid(pid, &status, 0);
 
 1376                        perror(
"fuse: waiting for child failed");
 
 1377                        _exit(EXIT_FAILURE);
 
 1379                return WIFEXITED(status) && WEXITSTATUS(status) == EXIT_SUCCESS;
 
 1399static int should_auto_unmount(
const char *mnt, 
const char *type)
 
 1408        fprintf(stderr, 
"%s: failed to allocate memory\n", progname);
 
 1412        if (chdir_to_parent(copy, &last) == -1)
 
 1414        if (check_is_mount(last, mnt, type) == -1)
 
 1417        fd = open(mnt, O_RDONLY);
 
 1427                        result = recheck_ENOTCONN_as_owner(mnt);
 
 1439static void usage(
void)
 
 1441        printf(
"%s: [options] mountpoint\n" 
 1444               " -V                 print version\n" 
 1445               " -o opt[,opt...]    mount options\n" 
 1448               " -z                 lazy unmount\n",
 
 1453static void show_version(
void)
 
 1455        printf(
"fusermount3 version: %s\n", PACKAGE_VERSION);
 
 1459static void close_range_loop(
int min_fd, 
int max_fd, 
int cfd)
 
 1461        for (
int fd = min_fd; fd <= max_fd; fd++)
 
 1471static int close_inherited_fds(
int cfd)
 
 1477        if (cfd <= STDERR_FILENO)
 
 1480#ifdef HAVE_LINUX_CLOSE_RANGE_H 
 1481        if (cfd < STDERR_FILENO + 2) {
 
 1482                close_range_loop(STDERR_FILENO + 1, cfd - 1, cfd);
 
 1484                rc = close_range(STDERR_FILENO + 1, cfd - 1, 0);
 
 1490        rc = close_range(cfd + 1, ~0U, 0);
 
 1497                int max_fd = sysconf(_SC_OPEN_MAX) - 1;
 
 1499                close_range_loop(STDERR_FILENO + 1, max_fd, cfd);
 
 1502        nullfd = open(
"/dev/null", O_RDWR);
 
 1504                perror(
"fusermount: cannot open /dev/null");
 
 1509        dup2(nullfd, STDIN_FILENO);
 
 1510        dup2(nullfd, STDOUT_FILENO);
 
 1511        dup2(nullfd, STDERR_FILENO);
 
 1512        if (nullfd > STDERR_FILENO)
 
 1518int main(
int argc, 
char *argv[])
 
 1526        static int unmount = 0;
 
 1527        static int lazy = 0;
 
 1528        static int quiet = 0;
 
 1529        char *commfd = NULL;
 
 1531        const char *opts = 
"";
 
 1532        const char *type = NULL;
 
 1533        int setup_auto_unmount_only = 0;
 
 1535        static const struct option long_opts[] = {
 
 1536                {
"unmount", no_argument, NULL, 
'u'},
 
 1537                {
"lazy",    no_argument, NULL, 
'z'},
 
 1538                {
"quiet",   no_argument, NULL, 
'q'},
 
 1539                {
"help",    no_argument, NULL, 
'h'},
 
 1540                {
"version", no_argument, NULL, 
'V'},
 
 1541                {
"options", required_argument, NULL, 
'o'},
 
 1544                {
"auto-unmount", no_argument, NULL, 
'U'},
 
 1545                {
"comm-fd", required_argument, NULL, 
'c'},
 
 1548        progname = strdup(argc > 0 ? argv[0] : 
"fusermount");
 
 1549        if (progname == NULL) {
 
 1550                fprintf(stderr, 
"%s: failed to allocate memory\n", argv[0]);
 
 1554        while ((ch = getopt_long(argc, argv, 
"hVo:uzq", long_opts,
 
 1575                        setup_auto_unmount_only = 1;
 
 1593        if (lazy && !unmount) {
 
 1594                fprintf(stderr, 
"%s: -z can only be used with -u\n", progname);
 
 1598        if (optind >= argc) {
 
 1599                fprintf(stderr, 
"%s: missing mountpoint argument\n", progname);
 
 1601        } 
else if (argc > optind + 1) {
 
 1602                fprintf(stderr, 
"%s: extra arguments after the mountpoint\n",
 
 1607        origmnt = argv[optind];
 
 1610        mnt = fuse_mnt_resolve_path(progname, origmnt);
 
 1614                        fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
 
 1623        if (!setup_auto_unmount_only && unmount)
 
 1627                commfd = getenv(FUSE_COMMFD_ENV);
 
 1628        if (commfd == NULL) {
 
 1629                fprintf(stderr, 
"%s: old style mounting not supported\n",
 
 1634        res = libfuse_strtol(commfd, &cfd);
 
 1637                        "%s: invalid _FUSE_COMMFD: %s\n",
 
 1644                struct stat statbuf;
 
 1645                fstat(cfd, &statbuf);
 
 1646                if(!S_ISSOCK(statbuf.st_mode)) {
 
 1648                                "%s: file descriptor %li is not a socket, can't send fuse fd\n",
 
 1654        if (setup_auto_unmount_only)
 
 1655                goto wait_for_auto_unmount;
 
 1657        fd = mount_fuse(mnt, opts, &type);
 
 1661        res = send_fd(cfd, fd);
 
 1663                umount2(mnt, MNT_DETACH); 
 
 1668        if (!auto_unmount) {
 
 1674wait_for_auto_unmount:
 
 1680        res = close_inherited_fds(cfd);
 
 1687                fprintf(stderr, 
"%s: failed to chdir to '/'\n", progname);
 
 1691        sigfillset(&sigset);
 
 1692        sigprocmask(SIG_BLOCK, &sigset, NULL);
 
 1698                unsigned char buf[16];
 
 1699                int n = recv(cfd, buf, 
sizeof(buf), 0);
 
 1710        if (!should_auto_unmount(mnt, type)) {
 
 1716                res = unmount_fuse(mnt, quiet, lazy);
 
 1718                res = umount2(mnt, lazy ? UMOUNT_DETACH : 0);
 
 1719                if (res == -1 && !quiet)
 
 1721                                "%s: failed to unmount %s: %s\n",
 
 1722                                progname, mnt, strerror(errno));