Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 8259
b: refs/heads/master
c: 87729a5
h: refs/heads/master
i:
  8257: 7bfb570
  8255: b7201ac
v: v3
  • Loading branch information
Miklos Szeredi authored and Linus Torvalds committed Sep 9, 2005
1 parent 95d2f53 commit 1416c5c
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 7 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: db50b96c0f28a21c5a4a19ecaba12d0972aab06a
refs/heads/master: 87729a5514e855ce2c71e3e33833a106b8caf2ae
40 changes: 34 additions & 6 deletions trunk/fs/fuse/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,17 +411,45 @@ int fuse_do_getattr(struct inode *inode)
return err;
}

/*
* Calling into a user-controlled filesystem gives the filesystem
* daemon ptrace-like capabilities over the requester process. This
* means, that the filesystem daemon is able to record the exact
* filesystem operations performed, and can also control the behavior
* of the requester process in otherwise impossible ways. For example
* it can delay the operation for arbitrary length of time allowing
* DoS against the requester.
*
* For this reason only those processes can call into the filesystem,
* for which the owner of the mount has ptrace privilege. This
* excludes processes started by other users, suid or sgid processes.
*/
static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
{
if (fc->flags & FUSE_ALLOW_OTHER)
return 1;

if (task->euid == fc->user_id &&
task->suid == fc->user_id &&
task->uid == fc->user_id &&
task->egid == fc->group_id &&
task->sgid == fc->group_id &&
task->gid == fc->group_id)
return 1;

return 0;
}

static int fuse_revalidate(struct dentry *entry)
{
struct inode *inode = entry->d_inode;
struct fuse_inode *fi = get_fuse_inode(inode);
struct fuse_conn *fc = get_fuse_conn(inode);

if (get_node_id(inode) == FUSE_ROOT_ID) {
if (!(fc->flags & FUSE_ALLOW_OTHER) &&
current->fsuid != fc->user_id)
return -EACCES;
} else if (time_before_eq(jiffies, fi->i_time))
if (!fuse_allow_task(fc, current))
return -EACCES;
if (get_node_id(inode) != FUSE_ROOT_ID &&
time_before_eq(jiffies, fi->i_time))
return 0;

return fuse_do_getattr(inode);
Expand All @@ -431,7 +459,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
{
struct fuse_conn *fc = get_fuse_conn(inode);

if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->user_id)
if (!fuse_allow_task(fc, current))
return -EACCES;
else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
int err = generic_permission(inode, mask, NULL);
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/fuse/fuse_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ struct fuse_conn {
/** The user id for this mount */
uid_t user_id;

/** The group id for this mount */
gid_t group_id;

/** The fuse mount flags for this mount */
unsigned flags;

Expand Down
12 changes: 12 additions & 0 deletions trunk/fs/fuse/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct fuse_mount_data {
int fd;
unsigned rootmode;
unsigned user_id;
unsigned group_id;
unsigned flags;
unsigned max_read;
};
Expand Down Expand Up @@ -199,6 +200,7 @@ static void fuse_put_super(struct super_block *sb)
spin_lock(&fuse_lock);
fc->mounted = 0;
fc->user_id = 0;
fc->group_id = 0;
fc->flags = 0;
/* Flush all readers on this fs */
wake_up_all(&fc->waitq);
Expand Down Expand Up @@ -248,6 +250,7 @@ enum {
OPT_FD,
OPT_ROOTMODE,
OPT_USER_ID,
OPT_GROUP_ID,
OPT_DEFAULT_PERMISSIONS,
OPT_ALLOW_OTHER,
OPT_KERNEL_CACHE,
Expand All @@ -259,6 +262,7 @@ static match_table_t tokens = {
{OPT_FD, "fd=%u"},
{OPT_ROOTMODE, "rootmode=%o"},
{OPT_USER_ID, "user_id=%u"},
{OPT_GROUP_ID, "group_id=%u"},
{OPT_DEFAULT_PERMISSIONS, "default_permissions"},
{OPT_ALLOW_OTHER, "allow_other"},
{OPT_KERNEL_CACHE, "kernel_cache"},
Expand Down Expand Up @@ -300,6 +304,12 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
d->user_id = value;
break;

case OPT_GROUP_ID:
if (match_int(&args[0], &value))
return 0;
d->group_id = value;
break;

case OPT_DEFAULT_PERMISSIONS:
d->flags |= FUSE_DEFAULT_PERMISSIONS;
break;
Expand Down Expand Up @@ -333,6 +343,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb);

seq_printf(m, ",user_id=%u", fc->user_id);
seq_printf(m, ",group_id=%u", fc->group_id);
if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
seq_puts(m, ",default_permissions");
if (fc->flags & FUSE_ALLOW_OTHER)
Expand Down Expand Up @@ -465,6 +476,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)

fc->flags = d.flags;
fc->user_id = d.user_id;
fc->group_id = d.group_id;
fc->max_read = d.max_read;
if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;
Expand Down

0 comments on commit 1416c5c

Please sign in to comment.