From 4c3d9b19576c228e1a3c6eab9a6942d9431f6ce4 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 23 Dec 2009 12:51:40 +0000 Subject: [PATCH] * Use '--no-canonicalize' option of mount(8) (available in util-linux-ng version 2.17 or greater) to avoid calling readling(2) on the newly mounted filesystem before the mount procedure is finished. This has caused a deadlock if audit was enabled in the kernel. Also use '--no-canonicalize' for umount to avoid touching the mounted filesystem. --- ChangeLog | 9 ++++ lib/mount_util.c | 121 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 116 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1711026..47e6100 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-12-17 Miklos Szeredi + + * Use '--no-canonicalize' option of mount(8) (available in + util-linux-ng version 2.17 or greater) to avoid calling + readling(2) on the newly mounted filesystem before the mount + procedure is finished. This has caused a deadlock if "audit" was + enabled in the kernel. Also use '--no-canonicalize' for umount to + avoid touching the mounted filesystem. + 2009-09-11 Miklos Szeredi * Released 2.8.1 diff --git a/lib/mount_util.c b/lib/mount_util.c index e78b482..3b6e771 100644 --- a/lib/mount_util.c +++ b/lib/mount_util.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -53,17 +54,14 @@ static int mtab_needs_update(const char *mnt) return 1; } -int fuse_mnt_add_mount(const char *progname, const char *fsname, - const char *mnt, const char *type, const char *opts) +static int add_mount_legacy(const char *progname, const char *fsname, + const char *mnt, const char *type, const char *opts) { int res; int status; sigset_t blockmask; sigset_t oldmask; - if (!mtab_needs_update(mnt)) - return 0; - sigemptyset(&blockmask); sigaddset(&blockmask, SIGCHLD); res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask); @@ -116,23 +114,83 @@ int fuse_mnt_add_mount(const char *progname, const char *fsname, out_restore: sigprocmask(SIG_SETMASK, &oldmask, NULL); + return res; } -int fuse_mnt_umount(const char *progname, const char *mnt, int lazy) +static int add_mount(const char *progname, const char *fsname, + const char *mnt, const char *type, const char *opts) { int res; int status; sigset_t blockmask; sigset_t oldmask; - if (!mtab_needs_update(mnt)) { - res = umount2(mnt, lazy ? 2 : 0); - if (res == -1) - fprintf(stderr, "%s: failed to unmount %s: %s\n", - progname, mnt, strerror(errno)); - return res; + sigemptyset(&blockmask); + sigaddset(&blockmask, SIGCHLD); + res = sigprocmask(SIG_BLOCK, &blockmask, &oldmask); + if (res == -1) { + fprintf(stderr, "%s: sigprocmask: %s\n", progname, strerror(errno)); + return -1; + } + + res = fork(); + if (res == -1) { + fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno)); + goto out_restore; } + if (res == 0) { + /* + * Hide output, because old versions don't support + * --no-canonicalize + */ + int fd = open("/dev/null", O_RDONLY); + dup2(fd, 1); + dup2(fd, 2); + + sigprocmask(SIG_SETMASK, &oldmask, NULL); + setuid(geteuid()); + execl("/bin/mount", "/bin/mount", "--no-canonicalize", "-i", + "-f", "-t", type, "-o", opts, fsname, mnt, NULL); + fprintf(stderr, "%s: failed to execute /bin/mount: %s\n", + progname, strerror(errno)); + exit(1); + } + res = waitpid(res, &status, 0); + if (res == -1) + fprintf(stderr, "%s: waitpid: %s\n", progname, strerror(errno)); + + if (status != 0) + res = -1; + + out_restore: + sigprocmask(SIG_SETMASK, &oldmask, NULL); + + return res; +} + +int fuse_mnt_add_mount(const char *progname, const char *fsname, + const char *mnt, const char *type, const char *opts) +{ + int res; + + if (!mtab_needs_update(mnt)) + return 0; + + res = add_mount(progname, fsname, mnt, type, opts); + if (res == -1) + res = add_mount_legacy(progname, fsname, mnt, type, opts); + + return res; +} + +static int exec_umount(const char *progname, const char *mnt, int lazy, + int legacy) +{ + int res; + int status; + sigset_t blockmask; + sigset_t oldmask; sigemptyset(&blockmask); sigaddset(&blockmask, SIGCHLD); @@ -148,10 +206,25 @@ int fuse_mnt_umount(const char *progname, const char *mnt, int lazy) goto out_restore; } if (res == 0) { + /* + * Hide output, because old versions don't support + * --no-canonicalize + */ + if (!legacy) { + int fd = open("/dev/null", O_RDONLY); + dup2(fd, 1); + dup2(fd, 2); + } + sigprocmask(SIG_SETMASK, &oldmask, NULL); setuid(geteuid()); - execl("/bin/umount", "/bin/umount", "-i", mnt, - lazy ? "-l" : NULL, NULL); + if (legacy) { + execl("/bin/umount", "/bin/umount", "-i", mnt, + lazy ? "-l" : NULL, NULL); + } else { + execl("/bin/umount", "/bin/umount", "--no-canonicalize", + "-i", mnt, lazy ? "-l" : NULL, NULL); + } fprintf(stderr, "%s: failed to execute /bin/umount: %s\n", progname, strerror(errno)); exit(1); @@ -166,6 +239,26 @@ int fuse_mnt_umount(const char *progname, const char *mnt, int lazy) out_restore: sigprocmask(SIG_SETMASK, &oldmask, NULL); return res; + +} + +int fuse_mnt_umount(const char *progname, const char *mnt, int lazy) +{ + int res; + + if (!mtab_needs_update(mnt)) { + res = umount2(mnt, lazy ? 2 : 0); + if (res == -1) + fprintf(stderr, "%s: failed to unmount %s: %s\n", + progname, mnt, strerror(errno)); + return res; + } + + res = exec_umount(progname, mnt, lazy, 0); + if (res == -1) + res = exec_umount(progname, mnt, lazy, 1); + + return res; } char *fuse_mnt_resolve_path(const char *progname, const char *orig) -- 2.30.2