diff options
author | Miklos Szeredi <miklos@szeredi.hu> | 2005-06-08 10:41:36 +0000 |
---|---|---|
committer | Miklos Szeredi <miklos@szeredi.hu> | 2005-06-08 10:41:36 +0000 |
commit | daa690e56e56e01b9fb4cffa6ae3d57907c21515 (patch) | |
tree | 85a8e7d676cdcf9db5100566bc514c7bfdfb8938 | |
parent | ec12fad28d7dc7d50f9bb591ed68ccc6ab411c78 (diff) |
fix
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | util/fusermount.c | 119 |
2 files changed, 77 insertions, 45 deletions
@@ -3,6 +3,9 @@ * Enable the auto-loading of the module via access to the corresponding device file. Patch by Takashi Iwai. + * Allow mounting a regular file (over a regular file) for + unprivleged users. + 2005-06-02 Miklos Szeredi <miklos@szeredi.hu> * Released 2.3.0 diff --git a/util/fusermount.c b/util/fusermount.c index 93a44e2..dbd46cc 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -622,11 +622,12 @@ static int check_version(const char *dev) return 0; } -static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd) +static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd, + int *mountpoint_fd) { int res; const char *mnt = *mntp; - const char *origmnt; + const char *origmnt = mnt; res = lstat(mnt, stbuf); if (res == -1) { @@ -639,45 +640,68 @@ static int check_perm(const char **mntp, struct stat *stbuf, int *currdir_fd) if (getuid() == 0) return 0; - if (!S_ISDIR(stbuf->st_mode)) { - fprintf(stderr, "%s: mountpoint %s is not a directory\n", - progname, mnt); - return -1; - } - - *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, "%s: failed to chdir to mountpoint: %s\n", - progname, strerror(errno)); - return -1; - } - origmnt = mnt; - mnt = *mntp = "."; - res = lstat(mnt, stbuf); - if (res == -1) { - fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", - progname, origmnt, strerror(errno)); - return -1; - } + 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, "%s: failed to chdir to mountpoint: %s\n", + progname, strerror(errno)); + return -1; + } + mnt = *mntp = "."; + res = lstat(mnt, stbuf); + if (res == -1) { + fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", + progname, origmnt, strerror(errno)); + return -1; + } + + if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) { + fprintf(stderr, "%s: mountpoint %s not owned by user\n", + progname, origmnt); + return -1; + } + + res = access(mnt, W_OK); + if (res == -1) { + fprintf(stderr, "%s: user has no write access to mountpoint %s\n", + progname, origmnt); + return -1; + } + } else if (S_ISREG(stbuf->st_mode)) { + static char procfile[256]; + *mountpoint_fd = open(mnt, O_WRONLY); + if (*mountpoint_fd == -1) { + fprintf(stderr, "%s: failed to open %s: %s\n", progname, mnt, + strerror(errno)); + return -1; + } + res = fstat(*mountpoint_fd, stbuf); + if (res == -1) { + fprintf(stderr, "%s: failed to access mountpoint %s: %s\n", + progname, mnt, strerror(errno)); + return -1; + } + if (!S_ISREG(stbuf->st_mode)) { + fprintf(stderr, "%s: mountpoint %s is no longer a regular file\n", + progname, mnt); + return -1; + } - if ((stbuf->st_mode & S_ISVTX) && stbuf->st_uid != getuid()) { - fprintf(stderr, "%s: mountpoint %s not owned by user\n", - progname, origmnt); + sprintf(procfile, "/proc/self/fd/%i", *mountpoint_fd); + *mntp = procfile; + } else { + fprintf(stderr, + "%s: mountpoint %s is not a directory or a regular file\n", + progname, mnt); return -1; } - res = access(mnt, W_OK); - if (res == -1) { - fprintf(stderr, "%s: user has no write access to mountpoint %s\n", - progname, origmnt); - return -1; - } return 0; } @@ -799,6 +823,7 @@ static int mount_fuse(const char *mnt, const char *opts) char *mnt_opts; const char *real_mnt = mnt; int currdir_fd = -1; + int mountpoint_fd = -1; int mtablock = -1; fd = open_fuse_device(&dev); @@ -836,14 +861,23 @@ static int mount_fuse(const char *mnt, const char *opts) res = check_version(dev); if (res != -1) { - res = check_perm(&real_mnt, &stbuf, &currdir_fd); + res = check_perm(&real_mnt, &stbuf, &currdir_fd, &mountpoint_fd); + if (getuid() != 0) + restore_privs(); if (res != -1) res = do_mount(real_mnt, type, stbuf.st_mode & S_IFMT, fd, opts, dev, &fsname, &mnt_opts); + } else { + if (getuid() != 0) + restore_privs(); } - if (getuid() != 0) - restore_privs(); + if (currdir_fd != -1) { + fchdir(currdir_fd); + close(currdir_fd); + } + if (mountpoint_fd != -1) + close(mountpoint_fd); if (res == -1) { close(fd); @@ -851,11 +885,6 @@ static int mount_fuse(const char *mnt, const char *opts) return -1; } - if (currdir_fd != -1) { - fchdir(currdir_fd); - close(currdir_fd); - } - if (geteuid() == 0) { res = add_mount(fsname, mnt, type, mnt_opts); unlock_mtab(mtablock); |