From ce6dc515e13fad593458dab942712f9068420fd2 Mon Sep 17 00:00:00 2001 From: Csaba Henk Date: Tue, 15 May 2012 21:24:43 +0530 Subject: fuse: sync with upstream Cherry-picked following commits from git://fuse.git.sourceforge.net/gitroot/fuse/fuse form 555d6b50..acc5c79d interval: commit 1193a39c0869a3608f22472735bcffdcccb6b2a5 Author: Reuben Hawkins cleaning up warnings commit dba9185999dfa35161d4c810735df0ab3fde5104 Author: Laszlo Papp Check the 'mtablock' for negative value commit e63a9d8ee6529c9d15a87745276f45c9bdad3961 Author: Miklos Szeredi fusermount: clean up do_mount() function commit 81fee822a098a3e26969401fc486f136465f96f0 Author: Laszlo Papp Eliminate the unused value commit 60eb44ee5eb2756465610b215968f176f4aaac6e Author: Laszlo Papp Fix resource leaks in fusermount commit d6bec4020fddd4dd67248789a1af600580f2cbda Author: Miklos Szeredi In case of failure to add to /etc/mtab don't umount. commit 1e7607ff89c65b005f69e27aeb1649d624099873 Author: Miklos Szeredi fusermount: chdir to / before performing mount/umount commit 2fcbc2a5a94983813c533c015134c6974f8ee636 Author: Miklos Szeredi fusermount: don't save/restore cwd commit bd99f9cf24e16643752b02fb4fa7b48f2124ab4e Author: Miklos Szeredi Fix check for read-only fs in mtab update Nb.: - not picked changes that implement and enforce mount/umount mechanisms based on newer util-linux features (umount --fake and --no-canonicalize) - not picked fusermount "auto-unmount" feature Change-Id: Ib9498516184336e77ec047e5414125332d0a4292 BUG: 762389 Signed-off-by: Csaba Henk Reviewed-on: http://review.gluster.com/3343 Tested-by: Gluster Build System Reviewed-by: Anand Avati --- contrib/fuse-lib/mount-common.c | 22 ++++++++++- contrib/fuse-lib/mount.c | 1 + contrib/fuse-util/fusermount.c | 87 +++++++++++++++++++---------------------- 3 files changed, 62 insertions(+), 48 deletions(-) (limited to 'contrib') diff --git a/contrib/fuse-lib/mount-common.c b/contrib/fuse-lib/mount-common.c index 7411e56c..fd6cce44 100644 --- a/contrib/fuse-lib/mount-common.c +++ b/contrib/fuse-lib/mount-common.c @@ -20,10 +20,11 @@ * - there are some other minor things * * For changes that were made later and syncs with upstream, - * see the commit log. + * see the commit log and per-function comments. */ #ifndef __NetBSD__ +/* FUSE: cherry-picked bd99f9cf */ static int mtab_needs_update (const char *mnt) { @@ -47,11 +48,22 @@ mtab_needs_update (const char *mnt) if (errno == ENOENT) return 0; } else { + uid_t ruid; + int err; + if (S_ISLNK (stbuf.st_mode)) return 0; + ruid = getuid (); + if (ruid != 0) + setreuid (0, -1); + res = access (_PATH_MOUNTED, W_OK); - if (res == -1 && errno == EROFS) + err = (res == -1) ? errno : 0; + if (ruid != 0) + setreuid (ruid, -1); + + if (err == EROFS) return 0; } @@ -61,6 +73,7 @@ mtab_needs_update (const char *mnt) #define mtab_needs_update(x) 1 #endif /* __NetBSD__ */ +/* FUSE: called add_mount_legacy(); R.I.P. as of cbd3a2a8 */ int fuse_mnt_add_mount (const char *progname, const char *fsname, const char *mnt, const char *type, const char *opts) @@ -194,6 +207,11 @@ fuse_mnt_resolve_path (const char *progname, const char *orig) return dst; } +/* FUSE: to support some changes that were reverted since + * then, it was split in two (fuse_mnt_umount() and + * exec_umount()); however the actual code is same as here + * since 0197ce40 + */ int fuse_mnt_umount (const char *progname, const char *abs_mnt, const char *rel_mnt, int lazy) diff --git a/contrib/fuse-lib/mount.c b/contrib/fuse-lib/mount.c index 8787064f..f02a835b 100644 --- a/contrib/fuse-lib/mount.c +++ b/contrib/fuse-lib/mount.c @@ -18,6 +18,7 @@ #define FUSE_DEVFD_ENV "_FUSE_DEVFD" +/* FUSE: function is called fuse_kern_unmount() */ void gf_fuse_unmount (const char *mountpoint, int fd) { diff --git a/contrib/fuse-util/fusermount.c b/contrib/fuse-util/fusermount.c index 4e7e4f95..9a895257 100644 --- a/contrib/fuse-util/fusermount.c +++ b/contrib/fuse-util/fusermount.c @@ -116,8 +116,16 @@ static int lock_umount(void) static void unlock_umount(int mtablock) { - lockf(mtablock, F_ULOCK, 0); - close(mtablock); + if (mtablock >= 0) { + int res; + + res = lockf(mtablock, F_ULOCK, 0); + if (res < 0) { + fprintf(stderr, "%s: error releasing lock: %s\n", + progname, strerror(errno)); + } + close(mtablock); + } } static int add_mount(const char *source, const char *mnt, const char *type, @@ -240,7 +248,7 @@ static int check_is_mount_child(void *p) } count = 0; - while ((entp = getmntent(fp)) != NULL) + while (getmntent(fp) != NULL) count++; endmntent(fp); @@ -327,7 +335,7 @@ static int check_is_mount(const char *last, const char *mnt) return 0; } -static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) +static int chdir_to_parent(char *copy, const char **lastp) { char *tmp; const char *parent; @@ -352,14 +360,6 @@ static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) parent = "/"; } - *currdir_fd = open(".", O_RDONLY); - if (*currdir_fd == -1) { - fprintf(stderr, - "%s: failed to open current directory: %s\n", - progname, strerror(errno)); - return -1; - } - res = chdir(parent); if (res == -1) { fprintf(stderr, "%s: failed to chdir to %s: %s\n", @@ -384,7 +384,6 @@ static int chdir_to_parent(char *copy, const char **lastp, int *currdir_fd) static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) { - int currdir_fd = -1; char *copy; const char *last; int res; @@ -401,7 +400,7 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) return -1; } - res = chdir_to_parent(copy, &last, &currdir_fd); + res = chdir_to_parent(copy, &last); if (res == -1) goto out; @@ -413,10 +412,6 @@ static int unmount_fuse_locked(const char *mnt, int quiet, int lazy) out: free(copy); - if (currdir_fd != -1) { - fchdir(currdir_fd); - close(currdir_fd); - } return res; } @@ -825,15 +820,14 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode, fprintf(stderr, "%s: mount failed: %s\n", progname, strerror(errno_save)); goto err; - } else { - *sourcep = source; - *typep = type; - *mnt_optsp = mnt_opts; } + *sourcep = source; + *typep = type; + *mnt_optsp = mnt_opts; free(fsname); free(optbuf); - return res; + return 0; err: free(fsname); @@ -876,8 +870,7 @@ static int check_version(const char *dev) return 0; } -static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd, - int *mountpoint_fd) +static int check_perm(const char **mntp, struct stat *stbuf, int *mountpoint_fd) { int res; const char *mnt = *mntp; @@ -895,13 +888,6 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd, return 0; if (S_ISDIR(stbuf->st_mode)) { - *currdir_fd = open(".", O_RDONLY); - if (*currdir_fd == -1) { - fprintf(stderr, - "%s: failed to open current directory: %s\n", - progname, strerror(errno)); - return -1; - } res = chdir(mnt); if (res == -1) { fprintf(stderr, @@ -1057,7 +1043,6 @@ static int mount_fuse(const char *mnt, const char *opts, char *devfd) char *source = NULL; char *mnt_opts = NULL; const char *real_mnt = mnt; - int currdir_fd = -1; int mountpoint_fd = -1; fd = devfd ? check_fuse_device(devfd, &dev) : open_fuse_device(&dev); @@ -1071,15 +1056,13 @@ static int mount_fuse(const char *mnt, const char *opts, char *devfd) int mount_count = count_fuse_fs(); if (mount_count >= mount_max) { fprintf(stderr, "%s: too many FUSE filesystems mounted; mount_max=N can be set in /etc/fuse.conf\n", progname); - close(fd); - return -1; + goto fail_close_fd; } } res = check_version(dev); if (res != -1) { - res = check_perm(&real_mnt, &stbuf, &currdir_fd, - &mountpoint_fd); + res = check_perm(&real_mnt, &stbuf, &mountpoint_fd); restore_privs(); if (res != -1) res = do_mount(real_mnt, &type, stbuf.st_mode & S_IFMT, @@ -1088,33 +1071,38 @@ static int mount_fuse(const char *mnt, const char *opts, char *devfd) } else restore_privs(); - if (currdir_fd != -1) { - fchdir(currdir_fd); - close(currdir_fd); - } if (mountpoint_fd != -1) close(mountpoint_fd); + if (res == -1) + goto fail_close_fd; + + res = chdir("/"); if (res == -1) { - close(fd); - return -1; + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + goto fail_close_fd; } if (geteuid() == 0) { res = add_mount(source, mnt, type, mnt_opts); if (res == -1) { - umount2(mnt, 2); /* lazy umount */ - close(fd); - return -1; + /* Can't clean up mount in a non-racy way */ + goto fail_close_fd; } } +out_free: free(source); free(type); free(mnt_opts); free(dev); return fd; + +fail_close_fd: + close(fd); + fd = -1; + goto out_free; } static int send_fd(int sock_fd, int fd) @@ -1253,6 +1241,13 @@ int main(int argc, char *argv[]) drop_privs(); mnt = fuse_mnt_resolve_path(progname, origmnt); + if (mnt != NULL) { + res = chdir("/"); + if (res == -1) { + fprintf(stderr, "%s: failed to chdir to '/'\n", progname); + exit(1); + } + } restore_privs(); if (mnt == NULL) exit(1); -- cgit