Skip to content
Permalink
Browse files

* 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.
  • Loading branch information...
szmi committed Dec 23, 2009
1 parent e61b775 commit 4c3d9b19576c228e1a3c6eab9a6942d9431f6ce4
Showing with 116 additions and 14 deletions.
  1. +9 −0 ChangeLog
  2. +107 −14 lib/mount_util.c
@@ -1,3 +1,12 @@
2009-12-17 Miklos Szeredi <miklos@szeredi.hu>

* 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 <miklos@szeredi.hu>

* Released 2.8.1
@@ -13,6 +13,7 @@
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <mntent.h>
#include <sys/stat.h>
@@ -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)

0 comments on commit 4c3d9b1

Please sign in to comment.
You can’t perform that action at this time.