diff options
Diffstat (limited to 'contrib/fuse-lib')
| -rw-r--r-- | contrib/fuse-lib/misc.c | 3 | ||||
| -rw-r--r-- | contrib/fuse-lib/mount-common.c | 22 | ||||
| -rw-r--r-- | contrib/fuse-lib/mount-gluster-compat.h | 48 | ||||
| -rw-r--r-- | contrib/fuse-lib/mount.c | 174 |
4 files changed, 217 insertions, 30 deletions
diff --git a/contrib/fuse-lib/misc.c b/contrib/fuse-lib/misc.c index 0c41b1a1917..1a9b418e511 100644 --- a/contrib/fuse-lib/misc.c +++ b/contrib/fuse-lib/misc.c @@ -10,7 +10,7 @@ #include <string.h> #include <limits.h> #include <fcntl.h> -#include "glusterfs.h" +#include "glusterfs/glusterfs.h" #include "fuse_kernel.h" #include "fuse-misc.h" @@ -41,7 +41,6 @@ void convert_fuse_file_lock (struct fuse_file_lock *fl, struct gf_flock *flock, uint64_t lk_owner) { - memset (flock, 0, sizeof (struct flock)); flock->l_type = fl->type; flock->l_whence = SEEK_SET; flock->l_start = fl->start; diff --git a/contrib/fuse-lib/mount-common.c b/contrib/fuse-lib/mount-common.c index c436cb16a5c..cffd4c01ed5 100644 --- a/contrib/fuse-lib/mount-common.c +++ b/contrib/fuse-lib/mount-common.c @@ -32,7 +32,7 @@ mtab_needs_update (const char *mnt) struct stat stbuf; /* If mtab is within new mount, don't touch it */ - if (strncmp (mnt, _PATH_MOUNTED, strlen (mnt)) == 0 && + if (strncmp (mnt, _PATH_MOUNTED, sizeof (_PATH_MOUNTED) - 1) == 0 && _PATH_MOUNTED[strlen (mnt)] == '/') return 0; @@ -105,7 +105,11 @@ fuse_mnt_add_mount (const char *progname, const char *fsname, char *tmp; sigprocmask (SIG_SETMASK, &oldmask, NULL); - setuid (geteuid ()); + res = setuid (geteuid ()); + if (res != 0) { + GFFUSE_LOGERR ("%s: setuid: %s", progname, strerror (errno)); + exit (1); + } /* * hide in a directory, where mount isn't able to resolve @@ -245,18 +249,22 @@ fuse_mnt_umount (const char *progname, const char *abs_mnt, } if (res == 0) { sigprocmask (SIG_SETMASK, &oldmask, NULL); - setuid (geteuid ()); + res = setuid (geteuid ()); + if (res != 0) { + GFFUSE_LOGERR ("%s: setuid: %s", progname, strerror (errno)); + exit (1); + } #ifdef GF_LINUX_HOST_OS - execl ("/bin/umount", "/bin/umount", "-i", rel_mnt, + execl ("umount", "umount", "-i", rel_mnt, lazy ? "-l" : NULL, NULL); - GFFUSE_LOGERR ("%s: failed to execute /bin/umount: %s", + GFFUSE_LOGERR ("%s: failed to execute umount: %s", progname, strerror (errno)); #elif __NetBSD__ /* exitting the filesystem causes the umount */ exit (0); #else - execl ("/sbin/umount", "/sbin/umount", "-f", rel_mnt, NULL); - GFFUSE_LOGERR ("%s: failed to execute /sbin/umount: %s", + execl ("umount", "umount", "-f", rel_mnt, NULL); + GFFUSE_LOGERR ("%s: failed to execute umount: %s", progname, strerror (errno)); #endif /* GF_LINUX_HOST_OS */ exit (1); diff --git a/contrib/fuse-lib/mount-gluster-compat.h b/contrib/fuse-lib/mount-gluster-compat.h index 562f089dd1f..d3646d08d8e 100644 --- a/contrib/fuse-lib/mount-gluster-compat.h +++ b/contrib/fuse-lib/mount-gluster-compat.h @@ -30,17 +30,59 @@ #include <sys/wait.h> #include <sys/mount.h> +#ifdef GF_LINUX_HOST_OS +typedef unsigned long mount_flag_t; +#endif + #if defined(__NetBSD__) #include <perfuse.h> #define umount2(dir, flags) unmount(dir, ((flags) != 0) ? MNT_FORCE : 0) #define MS_RDONLY MNT_RDONLY +#define MS_NOSUID MNT_NOSUID +#define MS_NODEV MNT_NODEV +#define MS_NOATIME MNT_NOATIME +#define MS_NOEXEC MNT_NOEXEC +typedef int mount_flag_t; #endif #if defined(GF_DARWIN_HOST_OS) || defined(__FreeBSD__) #include <sys/param.h> #include <sys/mount.h> #define umount2(dir, flags) unmount(dir, ((flags) != 0) ? MNT_FORCE : 0) +#endif + +#if defined(__FreeBSD__) #define MS_RDONLY MNT_RDONLY +#define MS_NOSUID MNT_NOSUID +/* "nodev"/MNT_NODEV was removed from FreBSD, as it became unneeded because "As + * of FreeBSD 6.0 device nodes may be created in regular file systems but such + * nodes cannot be used to access devices." (See + * https://freebsd.org/cgi/man.cgi?query=mknod&sektion=8 . + * Also see: + * - https://github.com/freebsd/freebsd/commit/266790a + * - https://github.com/freebsd/freebsd/commit/a5e716d + * - 700008 in + * https://www.freebsd.org/doc/en/books/porters-handbook/versions-7.html .) + */ +#if __FreeBSD_version < 700008 +#define MS_NODEV MNT_NODEV +#else +#define MS_NODEV 0 +#endif +#define MS_NOATIME MNT_NOATIME +#define MS_NOEXEC MNT_NOEXEC +#if __FreeBSD_version < 1000715 +typedef int mount_flag_t; +#else +/* __FreeBSD_version was not bumped for this type change. Anyway, see + * https://github.com/freebsd/freebsd/commit/e8d76f8 + * and respective __FreeBSD_version: + * https://github.com/freebsd/freebsd/blob/e8d76f8/sys/sys/param.h#L61 . + * We use the subsequent value, 1000715, to switch. (Also see: + * https://www.freebsd.org/doc/en/books/porters-handbook/versions-10.html .) + */ +typedef long long mount_flag_t; +#endif #endif #ifdef GF_LINUX_HOST_OS @@ -54,9 +96,9 @@ #define FREE(ptr) free (ptr) #define GFFUSE_LOGERR(...) fprintf (stderr, ## __VA_ARGS__) #else /* FUSE_UTIL */ -#include "glusterfs.h" -#include "logging.h" -#include "common-utils.h" +#include "glusterfs/glusterfs.h" +#include "glusterfs/logging.h" +#include "glusterfs/common-utils.h" #define GFFUSE_LOGERR(...) \ gf_log ("glusterfs-fuse", GF_LOG_ERROR, ## __VA_ARGS__) diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c index 1edde86014a..06ff191f542 100644 --- a/contrib/fuse-lib/mount.c +++ b/contrib/fuse-lib/mount.c @@ -52,12 +52,16 @@ gf_fuse_unmount (const char *mountpoint, int fd) if (geteuid () == 0) { fuse_mnt_umount ("fuse", mountpoint, mountpoint, 1); return; + } else { + GFFUSE_LOGERR ("fuse: Effective-uid: %d", geteuid()); } res = umount2 (mountpoint, 2); if (res == 0) return; + GFFUSE_LOGERR ("fuse: failed to unmount %s: %s", + mountpoint, strerror (errno)); pid = fork (); if (pid == -1) return; @@ -67,6 +71,8 @@ gf_fuse_unmount (const char *mountpoint, int fd) "--", mountpoint, NULL }; execvp (FUSERMOUNT_PROG, (char **)argv); + GFFUSE_LOGERR ("fuse: failed to execute fuserumount: %s", + strerror (errno)); _exit (1); } waitpid (pid, NULL, 0); @@ -75,6 +81,54 @@ gf_fuse_unmount (const char *mountpoint, int fd) /* gluster-specific routines */ +/* Unmounting in a daemon that lurks 'till main process exits */ +int +gf_fuse_unmount_daemon (const char *mountpoint, int fd) +{ + int ret = -1; + pid_t pid = -1; + + if (fd == -1) + return -1; + + int ump[2] = {0,}; + + ret = pipe(ump); + if (ret == -1) { + close (fd); + return -1; + } + + pid = fork (); + switch (pid) { + case 0: + { + char c = 0; + sigset_t sigset; + + close_fds_except (ump, 1); + + setsid(); + (void)chdir("/"); + sigfillset(&sigset); + sigprocmask(SIG_BLOCK, &sigset, NULL); + + read (ump[0], &c, 1); + + gf_fuse_unmount (mountpoint, fd); + exit (0); + } + case -1: + close (fd); + fd = -1; + ret = -1; + close (ump[1]); + } + close (ump[0]); + + return ret; +} + static char * escape (char *s) { @@ -106,8 +160,7 @@ escape (char *s) static int fuse_mount_fusermount (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, - int fd) + char *mnt_param, int fd) { int pid = -1; int res = 0; @@ -130,8 +183,7 @@ fuse_mount_fusermount (const char *mountpoint, char *fsname, return -1; } ret = asprintf (&fm_mnt_params, - "%s%s,fsname=%s,nonempty,subtype=glusterfs", - (mountflags & MS_RDONLY) ? "ro," : "", + "%s,fsname=%s,nonempty,subtype=glusterfs", mnt_param, efsname); FREE (efsname); if (ret == -1) { @@ -224,19 +276,101 @@ build_iovec_argf(struct iovec **iov, int *iovlen, const char *name, } #endif /* __FreeBSD__ */ +struct mount_flags { + const char *opt; + mount_flag_t flag; + int on; +} mount_flags[] = { + /* We provide best effort cross platform support for mount flags by + * defining the ones which are commonly used in Unix-like OS-es. + */ + {"ro", MS_RDONLY, 1}, + {"nosuid", MS_NOSUID, 1}, + {"nodev", MS_NODEV, 1}, + {"noatime", MS_NOATIME, 1}, + {"noexec", MS_NOEXEC, 1}, +#ifdef GF_LINUX_HOST_OS + {"rw", MS_RDONLY, 0}, + {"suid", MS_NOSUID, 0}, + {"dev", MS_NODEV, 0}, + {"exec", MS_NOEXEC, 0}, + {"async", MS_SYNCHRONOUS, 0}, + {"sync", MS_SYNCHRONOUS, 1}, + {"atime", MS_NOATIME, 0}, + {"dirsync", MS_DIRSYNC, 1}, +#endif + {NULL, 0, 0} +}; + +static int +mount_param_to_flag (char *mnt_param, mount_flag_t *mntflags, + char **mnt_param_new) +{ + gf_boolean_t found = _gf_false; + struct mount_flags *flag = NULL; + char *param_tok = NULL; + token_iter_t tit = {0,}; + gf_boolean_t iter_end = _gf_false; + + /* Allocate a buffer that will hold the mount parameters remaining + * after the ones corresponding to mount flags are processed and + * removed.The length of the original params are a good upper bound + * of the size needed. + */ + *mnt_param_new = strdup (mnt_param); + if (!*mnt_param_new) + return -1; + + for (param_tok = token_iter_init (*mnt_param_new, ',', &tit) ;;) { + iter_end = next_token (¶m_tok, &tit); + + found = _gf_false; + for (flag = mount_flags; flag->opt; flag++) { + /* Compare the mount flag name to the param + * name at hand. + */ + if (strcmp (flag->opt, param_tok) == 0) { + /* If there is a match, adjust mntflags + * accordingly and break. + */ + if (flag->on) { + *mntflags |= flag->flag; + } else { + *mntflags &= ~flag->flag; + } + found = _gf_true; + break; + } + } + /* Exclude flag names from new parameter list. */ + if (found) + drop_token (param_tok, &tit); + + if (iter_end) + break; + } + + return 0; +} + static int fuse_mount_sys (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, int fd) + char *mnt_param, int fd) { int ret = -1; unsigned mounted = 0; char *mnt_param_mnt = NULL; char *fstype = "fuse.glusterfs"; char *source = fsname; - - ret = asprintf (&mnt_param_mnt, - "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i", - mnt_param, fd, S_IFDIR, getuid (), getgid ()); + mount_flag_t mountflags = 0; + char *mnt_param_new = NULL; + + ret = mount_param_to_flag (mnt_param, &mountflags, &mnt_param_new); + if (ret == 0) + ret = asprintf (&mnt_param_mnt, + "%s,fd=%i,rootmode=%o,user_id=%i,group_id=%i", + mnt_param_new, fd, S_IFDIR, getuid (), + getgid ()); if (ret == -1) { GFFUSE_LOGERR ("Out of memory"); @@ -256,6 +390,7 @@ fuse_mount_sys (const char *mountpoint, char *fsname, build_iovec (&iov, &iovlen, "from", "/dev/fuse", -1); build_iovec (&iov, &iovlen, "volname", source, -1); build_iovec (&iov, &iovlen, "fd", fdstr, -1); + build_iovec (&iov, &iovlen, "allow_other", NULL, -1); ret = nmount (iov, iovlen, mountflags); #else ret = mount (source, mountpoint, fstype, mountflags, @@ -295,7 +430,7 @@ fuse_mount_sys (const char *mountpoint, char *fsname, ret = asprintf (&mnt_param_mtab, "%s%s", mountflags & MS_RDONLY ? "ro," : "", - mnt_param); + mnt_param_new); if (ret == -1) GFFUSE_LOGERR ("Out of memory"); else { @@ -320,6 +455,7 @@ out: umount2 (mountpoint, 2); /* lazy umount */ } FREE (mnt_param_mnt); + FREE (mnt_param_new); if (source != fsname) FREE (source); @@ -328,8 +464,7 @@ out: int gf_fuse_mount (const char *mountpoint, char *fsname, - unsigned long mountflags, char *mnt_param, - pid_t *mnt_pid, int status_fd) + char *mnt_param, pid_t *mnt_pid, int status_fd) { int fd = -1; pid_t pid = -1; @@ -356,16 +491,19 @@ gf_fuse_mount (const char *mountpoint, char *fsname, exit (pid == -1 ? 1 : 0); } - ret = fuse_mount_sys (mountpoint, fsname, mountflags, mnt_param, - fd); + ret = fuse_mount_sys (mountpoint, fsname, mnt_param, fd); if (ret == -1) { gf_log ("glusterfs-fuse", GF_LOG_INFO, - "direct mount failed (%s) errno %d, " - "retry to mount via fusermount", + "direct mount failed (%s) errno %d", strerror (errno), errno); - ret = fuse_mount_fusermount (mountpoint, fsname, - mountflags, mnt_param, fd); + if (errno == EPERM) { + gf_log ("glusterfs-fuse", GF_LOG_INFO, + "retry to mount via fusermount"); + + ret = fuse_mount_fusermount (mountpoint, fsname, + mnt_param, fd); + } } if (ret == -1) |
