aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Miklos Szeredi <miklos@szeredi.hu>2005-06-08 10:41:36 +0000
committerGravatar Miklos Szeredi <miklos@szeredi.hu>2005-06-08 10:41:36 +0000
commitdaa690e56e56e01b9fb4cffa6ae3d57907c21515 (patch)
tree85a8e7d676cdcf9db5100566bc514c7bfdfb8938
parentec12fad28d7dc7d50f9bb591ed68ccc6ab411c78 (diff)
fix
-rw-r--r--ChangeLog3
-rw-r--r--util/fusermount.c119
2 files changed, 77 insertions, 45 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ec8544..ae6fec4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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);