aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/fuse/dir.c40
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/fuse/inode.c12
3 files changed, 49 insertions, 6 deletions
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index f127625543b4..65da6e1b6de5 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -411,17 +411,45 @@ int fuse_do_getattr(struct inode *inode)
411 return err; 411 return err;
412} 412}
413 413
414/*
415 * Calling into a user-controlled filesystem gives the filesystem
416 * daemon ptrace-like capabilities over the requester process. This
417 * means, that the filesystem daemon is able to record the exact
418 * filesystem operations performed, and can also control the behavior
419 * of the requester process in otherwise impossible ways. For example
420 * it can delay the operation for arbitrary length of time allowing
421 * DoS against the requester.
422 *
423 * For this reason only those processes can call into the filesystem,
424 * for which the owner of the mount has ptrace privilege. This
425 * excludes processes started by other users, suid or sgid processes.
426 */
427static int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task)
428{
429 if (fc->flags & FUSE_ALLOW_OTHER)
430 return 1;
431
432 if (task->euid == fc->user_id &&
433 task->suid == fc->user_id &&
434 task->uid == fc->user_id &&
435 task->egid == fc->group_id &&
436 task->sgid == fc->group_id &&
437 task->gid == fc->group_id)
438 return 1;
439
440 return 0;
441}
442
414static int fuse_revalidate(struct dentry *entry) 443static int fuse_revalidate(struct dentry *entry)
415{ 444{
416 struct inode *inode = entry->d_inode; 445 struct inode *inode = entry->d_inode;
417 struct fuse_inode *fi = get_fuse_inode(inode); 446 struct fuse_inode *fi = get_fuse_inode(inode);
418 struct fuse_conn *fc = get_fuse_conn(inode); 447 struct fuse_conn *fc = get_fuse_conn(inode);
419 448
420 if (get_node_id(inode) == FUSE_ROOT_ID) { 449 if (!fuse_allow_task(fc, current))
421 if (!(fc->flags & FUSE_ALLOW_OTHER) && 450 return -EACCES;
422 current->fsuid != fc->user_id) 451 if (get_node_id(inode) != FUSE_ROOT_ID &&
423 return -EACCES; 452 time_before_eq(jiffies, fi->i_time))
424 } else if (time_before_eq(jiffies, fi->i_time))
425 return 0; 453 return 0;
426 454
427 return fuse_do_getattr(inode); 455 return fuse_do_getattr(inode);
@@ -431,7 +459,7 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd)
431{ 459{
432 struct fuse_conn *fc = get_fuse_conn(inode); 460 struct fuse_conn *fc = get_fuse_conn(inode);
433 461
434 if (!(fc->flags & FUSE_ALLOW_OTHER) && current->fsuid != fc->user_id) 462 if (!fuse_allow_task(fc, current))
435 return -EACCES; 463 return -EACCES;
436 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) { 464 else if (fc->flags & FUSE_DEFAULT_PERMISSIONS) {
437 int err = generic_permission(inode, mask, NULL); 465 int err = generic_permission(inode, mask, NULL);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index aff3a01ea02b..3ec2aff3fdb5 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -198,6 +198,9 @@ struct fuse_conn {
198 /** The user id for this mount */ 198 /** The user id for this mount */
199 uid_t user_id; 199 uid_t user_id;
200 200
201 /** The group id for this mount */
202 gid_t group_id;
203
201 /** The fuse mount flags for this mount */ 204 /** The fuse mount flags for this mount */
202 unsigned flags; 205 unsigned flags;
203 206
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 0b75c73386e9..c8e54c0658f1 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -31,6 +31,7 @@ struct fuse_mount_data {
31 int fd; 31 int fd;
32 unsigned rootmode; 32 unsigned rootmode;
33 unsigned user_id; 33 unsigned user_id;
34 unsigned group_id;
34 unsigned flags; 35 unsigned flags;
35 unsigned max_read; 36 unsigned max_read;
36}; 37};
@@ -199,6 +200,7 @@ static void fuse_put_super(struct super_block *sb)
199 spin_lock(&fuse_lock); 200 spin_lock(&fuse_lock);
200 fc->mounted = 0; 201 fc->mounted = 0;
201 fc->user_id = 0; 202 fc->user_id = 0;
203 fc->group_id = 0;
202 fc->flags = 0; 204 fc->flags = 0;
203 /* Flush all readers on this fs */ 205 /* Flush all readers on this fs */
204 wake_up_all(&fc->waitq); 206 wake_up_all(&fc->waitq);
@@ -248,6 +250,7 @@ enum {
248 OPT_FD, 250 OPT_FD,
249 OPT_ROOTMODE, 251 OPT_ROOTMODE,
250 OPT_USER_ID, 252 OPT_USER_ID,
253 OPT_GROUP_ID,
251 OPT_DEFAULT_PERMISSIONS, 254 OPT_DEFAULT_PERMISSIONS,
252 OPT_ALLOW_OTHER, 255 OPT_ALLOW_OTHER,
253 OPT_KERNEL_CACHE, 256 OPT_KERNEL_CACHE,
@@ -259,6 +262,7 @@ static match_table_t tokens = {
259 {OPT_FD, "fd=%u"}, 262 {OPT_FD, "fd=%u"},
260 {OPT_ROOTMODE, "rootmode=%o"}, 263 {OPT_ROOTMODE, "rootmode=%o"},
261 {OPT_USER_ID, "user_id=%u"}, 264 {OPT_USER_ID, "user_id=%u"},
265 {OPT_GROUP_ID, "group_id=%u"},
262 {OPT_DEFAULT_PERMISSIONS, "default_permissions"}, 266 {OPT_DEFAULT_PERMISSIONS, "default_permissions"},
263 {OPT_ALLOW_OTHER, "allow_other"}, 267 {OPT_ALLOW_OTHER, "allow_other"},
264 {OPT_KERNEL_CACHE, "kernel_cache"}, 268 {OPT_KERNEL_CACHE, "kernel_cache"},
@@ -300,6 +304,12 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d)
300 d->user_id = value; 304 d->user_id = value;
301 break; 305 break;
302 306
307 case OPT_GROUP_ID:
308 if (match_int(&args[0], &value))
309 return 0;
310 d->group_id = value;
311 break;
312
303 case OPT_DEFAULT_PERMISSIONS: 313 case OPT_DEFAULT_PERMISSIONS:
304 d->flags |= FUSE_DEFAULT_PERMISSIONS; 314 d->flags |= FUSE_DEFAULT_PERMISSIONS;
305 break; 315 break;
@@ -333,6 +343,7 @@ static int fuse_show_options(struct seq_file *m, struct vfsmount *mnt)
333 struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb); 343 struct fuse_conn *fc = get_fuse_conn_super(mnt->mnt_sb);
334 344
335 seq_printf(m, ",user_id=%u", fc->user_id); 345 seq_printf(m, ",user_id=%u", fc->user_id);
346 seq_printf(m, ",group_id=%u", fc->group_id);
336 if (fc->flags & FUSE_DEFAULT_PERMISSIONS) 347 if (fc->flags & FUSE_DEFAULT_PERMISSIONS)
337 seq_puts(m, ",default_permissions"); 348 seq_puts(m, ",default_permissions");
338 if (fc->flags & FUSE_ALLOW_OTHER) 349 if (fc->flags & FUSE_ALLOW_OTHER)
@@ -465,6 +476,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
465 476
466 fc->flags = d.flags; 477 fc->flags = d.flags;
467 fc->user_id = d.user_id; 478 fc->user_id = d.user_id;
479 fc->group_id = d.group_id;
468 fc->max_read = d.max_read; 480 fc->max_read = d.max_read;
469 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages) 481 if (fc->max_read / PAGE_CACHE_SIZE < fc->bdi.ra_pages)
470 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE; 482 fc->bdi.ra_pages = fc->max_read / PAGE_CACHE_SIZE;