diff options
| -rw-r--r-- | fs/fuse/acl.c | 4 | ||||
| -rw-r--r-- | fs/fuse/cuse.c | 7 | ||||
| -rw-r--r-- | fs/fuse/dev.c | 8 | ||||
| -rw-r--r-- | fs/fuse/dir.c | 14 | ||||
| -rw-r--r-- | fs/fuse/fuse_i.h | 6 | ||||
| -rw-r--r-- | fs/fuse/inode.c | 31 |
6 files changed, 43 insertions, 27 deletions
diff --git a/fs/fuse/acl.c b/fs/fuse/acl.c index ec85765502f1..5a48cee6d7d3 100644 --- a/fs/fuse/acl.c +++ b/fs/fuse/acl.c | |||
| @@ -34,7 +34,7 @@ struct posix_acl *fuse_get_acl(struct inode *inode, int type) | |||
| 34 | return ERR_PTR(-ENOMEM); | 34 | return ERR_PTR(-ENOMEM); |
| 35 | size = fuse_getxattr(inode, name, value, PAGE_SIZE); | 35 | size = fuse_getxattr(inode, name, value, PAGE_SIZE); |
| 36 | if (size > 0) | 36 | if (size > 0) |
| 37 | acl = posix_acl_from_xattr(&init_user_ns, value, size); | 37 | acl = posix_acl_from_xattr(fc->user_ns, value, size); |
| 38 | else if ((size == 0) || (size == -ENODATA) || | 38 | else if ((size == 0) || (size == -ENODATA) || |
| 39 | (size == -EOPNOTSUPP && fc->no_getxattr)) | 39 | (size == -EOPNOTSUPP && fc->no_getxattr)) |
| 40 | acl = NULL; | 40 | acl = NULL; |
| @@ -81,7 +81,7 @@ int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type) | |||
| 81 | if (!value) | 81 | if (!value) |
| 82 | return -ENOMEM; | 82 | return -ENOMEM; |
| 83 | 83 | ||
| 84 | ret = posix_acl_to_xattr(&init_user_ns, acl, value, size); | 84 | ret = posix_acl_to_xattr(fc->user_ns, acl, value, size); |
| 85 | if (ret < 0) { | 85 | if (ret < 0) { |
| 86 | kfree(value); | 86 | kfree(value); |
| 87 | return ret; | 87 | return ret; |
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 31d33b69957f..8f68181256c0 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/stat.h> | 48 | #include <linux/stat.h> |
| 49 | #include <linux/module.h> | 49 | #include <linux/module.h> |
| 50 | #include <linux/uio.h> | 50 | #include <linux/uio.h> |
| 51 | #include <linux/user_namespace.h> | ||
| 51 | 52 | ||
| 52 | #include "fuse_i.h" | 53 | #include "fuse_i.h" |
| 53 | 54 | ||
| @@ -498,7 +499,11 @@ static int cuse_channel_open(struct inode *inode, struct file *file) | |||
| 498 | if (!cc) | 499 | if (!cc) |
| 499 | return -ENOMEM; | 500 | return -ENOMEM; |
| 500 | 501 | ||
| 501 | fuse_conn_init(&cc->fc); | 502 | /* |
| 503 | * Limit the cuse channel to requests that can | ||
| 504 | * be represented in file->f_cred->user_ns. | ||
| 505 | */ | ||
| 506 | fuse_conn_init(&cc->fc, file->f_cred->user_ns); | ||
| 502 | 507 | ||
| 503 | fud = fuse_dev_alloc(&cc->fc); | 508 | fud = fuse_dev_alloc(&cc->fc); |
| 504 | if (!fud) { | 509 | if (!fud) { |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 4852f8803156..686631f12001 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
| @@ -156,8 +156,8 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages, | |||
| 156 | goto out; | 156 | goto out; |
| 157 | } | 157 | } |
| 158 | 158 | ||
| 159 | req->in.h.uid = from_kuid(&init_user_ns, current_fsuid()); | 159 | req->in.h.uid = from_kuid(fc->user_ns, current_fsuid()); |
| 160 | req->in.h.gid = from_kgid(&init_user_ns, current_fsgid()); | 160 | req->in.h.gid = from_kgid(fc->user_ns, current_fsgid()); |
| 161 | req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); | 161 | req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); |
| 162 | 162 | ||
| 163 | __set_bit(FR_WAITING, &req->flags); | 163 | __set_bit(FR_WAITING, &req->flags); |
| @@ -257,8 +257,8 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, | |||
| 257 | if (!req) | 257 | if (!req) |
| 258 | req = get_reserved_req(fc, file); | 258 | req = get_reserved_req(fc, file); |
| 259 | 259 | ||
| 260 | req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid()); | 260 | req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid()); |
| 261 | req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid()); | 261 | req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid()); |
| 262 | req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); | 262 | req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); |
| 263 | 263 | ||
| 264 | __set_bit(FR_WAITING, &req->flags); | 264 | __set_bit(FR_WAITING, &req->flags); |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 7a980b4462d9..cf8a1cd7a62e 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
| @@ -858,8 +858,8 @@ static void fuse_fillattr(struct inode *inode, struct fuse_attr *attr, | |||
| 858 | stat->ino = attr->ino; | 858 | stat->ino = attr->ino; |
| 859 | stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); | 859 | stat->mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); |
| 860 | stat->nlink = attr->nlink; | 860 | stat->nlink = attr->nlink; |
| 861 | stat->uid = make_kuid(&init_user_ns, attr->uid); | 861 | stat->uid = make_kuid(fc->user_ns, attr->uid); |
| 862 | stat->gid = make_kgid(&init_user_ns, attr->gid); | 862 | stat->gid = make_kgid(fc->user_ns, attr->gid); |
| 863 | stat->rdev = inode->i_rdev; | 863 | stat->rdev = inode->i_rdev; |
| 864 | stat->atime.tv_sec = attr->atime; | 864 | stat->atime.tv_sec = attr->atime; |
| 865 | stat->atime.tv_nsec = attr->atimensec; | 865 | stat->atime.tv_nsec = attr->atimensec; |
| @@ -1475,17 +1475,17 @@ static bool update_mtime(unsigned ivalid, bool trust_local_mtime) | |||
| 1475 | return true; | 1475 | return true; |
| 1476 | } | 1476 | } |
| 1477 | 1477 | ||
| 1478 | static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg, | 1478 | static void iattr_to_fattr(struct fuse_conn *fc, struct iattr *iattr, |
| 1479 | bool trust_local_cmtime) | 1479 | struct fuse_setattr_in *arg, bool trust_local_cmtime) |
| 1480 | { | 1480 | { |
| 1481 | unsigned ivalid = iattr->ia_valid; | 1481 | unsigned ivalid = iattr->ia_valid; |
| 1482 | 1482 | ||
| 1483 | if (ivalid & ATTR_MODE) | 1483 | if (ivalid & ATTR_MODE) |
| 1484 | arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; | 1484 | arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; |
| 1485 | if (ivalid & ATTR_UID) | 1485 | if (ivalid & ATTR_UID) |
| 1486 | arg->valid |= FATTR_UID, arg->uid = from_kuid(&init_user_ns, iattr->ia_uid); | 1486 | arg->valid |= FATTR_UID, arg->uid = from_kuid(fc->user_ns, iattr->ia_uid); |
| 1487 | if (ivalid & ATTR_GID) | 1487 | if (ivalid & ATTR_GID) |
| 1488 | arg->valid |= FATTR_GID, arg->gid = from_kgid(&init_user_ns, iattr->ia_gid); | 1488 | arg->valid |= FATTR_GID, arg->gid = from_kgid(fc->user_ns, iattr->ia_gid); |
| 1489 | if (ivalid & ATTR_SIZE) | 1489 | if (ivalid & ATTR_SIZE) |
| 1490 | arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; | 1490 | arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; |
| 1491 | if (ivalid & ATTR_ATIME) { | 1491 | if (ivalid & ATTR_ATIME) { |
| @@ -1657,7 +1657,7 @@ int fuse_do_setattr(struct dentry *dentry, struct iattr *attr, | |||
| 1657 | 1657 | ||
| 1658 | memset(&inarg, 0, sizeof(inarg)); | 1658 | memset(&inarg, 0, sizeof(inarg)); |
| 1659 | memset(&outarg, 0, sizeof(outarg)); | 1659 | memset(&outarg, 0, sizeof(outarg)); |
| 1660 | iattr_to_fattr(attr, &inarg, trust_local_cmtime); | 1660 | iattr_to_fattr(fc, attr, &inarg, trust_local_cmtime); |
| 1661 | if (file) { | 1661 | if (file) { |
| 1662 | struct fuse_file *ff = file->private_data; | 1662 | struct fuse_file *ff = file->private_data; |
| 1663 | inarg.valid |= FATTR_FH; | 1663 | inarg.valid |= FATTR_FH; |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 7d2e7deea64b..f630951df8dc 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/xattr.h> | 26 | #include <linux/xattr.h> |
| 27 | #include <linux/pid_namespace.h> | 27 | #include <linux/pid_namespace.h> |
| 28 | #include <linux/refcount.h> | 28 | #include <linux/refcount.h> |
| 29 | #include <linux/user_namespace.h> | ||
| 29 | 30 | ||
| 30 | /** Max number of pages that can be used in a single read request */ | 31 | /** Max number of pages that can be used in a single read request */ |
| 31 | #define FUSE_MAX_PAGES_PER_REQ 32 | 32 | #define FUSE_MAX_PAGES_PER_REQ 32 |
| @@ -466,6 +467,9 @@ struct fuse_conn { | |||
| 466 | /** The pid namespace for this mount */ | 467 | /** The pid namespace for this mount */ |
| 467 | struct pid_namespace *pid_ns; | 468 | struct pid_namespace *pid_ns; |
| 468 | 469 | ||
| 470 | /** The user namespace for this mount */ | ||
| 471 | struct user_namespace *user_ns; | ||
| 472 | |||
| 469 | /** Maximum read size */ | 473 | /** Maximum read size */ |
| 470 | unsigned max_read; | 474 | unsigned max_read; |
| 471 | 475 | ||
| @@ -876,7 +880,7 @@ struct fuse_conn *fuse_conn_get(struct fuse_conn *fc); | |||
| 876 | /** | 880 | /** |
| 877 | * Initialize fuse_conn | 881 | * Initialize fuse_conn |
| 878 | */ | 882 | */ |
| 879 | void fuse_conn_init(struct fuse_conn *fc); | 883 | void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns); |
| 880 | 884 | ||
| 881 | /** | 885 | /** |
| 882 | * Release reference to fuse_conn | 886 | * Release reference to fuse_conn |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 3c9b675d99da..1643043d4fe5 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
| @@ -171,8 +171,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, | |||
| 171 | inode->i_ino = fuse_squash_ino(attr->ino); | 171 | inode->i_ino = fuse_squash_ino(attr->ino); |
| 172 | inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); | 172 | inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); |
| 173 | set_nlink(inode, attr->nlink); | 173 | set_nlink(inode, attr->nlink); |
| 174 | inode->i_uid = make_kuid(&init_user_ns, attr->uid); | 174 | inode->i_uid = make_kuid(fc->user_ns, attr->uid); |
| 175 | inode->i_gid = make_kgid(&init_user_ns, attr->gid); | 175 | inode->i_gid = make_kgid(fc->user_ns, attr->gid); |
| 176 | inode->i_blocks = attr->blocks; | 176 | inode->i_blocks = attr->blocks; |
| 177 | inode->i_atime.tv_sec = attr->atime; | 177 | inode->i_atime.tv_sec = attr->atime; |
| 178 | inode->i_atime.tv_nsec = attr->atimensec; | 178 | inode->i_atime.tv_nsec = attr->atimensec; |
| @@ -477,7 +477,8 @@ static int fuse_match_uint(substring_t *s, unsigned int *res) | |||
| 477 | return err; | 477 | return err; |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) | 480 | static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev, |
| 481 | struct user_namespace *user_ns) | ||
| 481 | { | 482 | { |
| 482 | char *p; | 483 | char *p; |
| 483 | memset(d, 0, sizeof(struct fuse_mount_data)); | 484 | memset(d, 0, sizeof(struct fuse_mount_data)); |
| @@ -513,7 +514,7 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) | |||
| 513 | case OPT_USER_ID: | 514 | case OPT_USER_ID: |
| 514 | if (fuse_match_uint(&args[0], &uv)) | 515 | if (fuse_match_uint(&args[0], &uv)) |
| 515 | return 0; | 516 | return 0; |
| 516 | d->user_id = make_kuid(current_user_ns(), uv); | 517 | d->user_id = make_kuid(user_ns, uv); |
| 517 | if (!uid_valid(d->user_id)) | 518 | if (!uid_valid(d->user_id)) |
| 518 | return 0; | 519 | return 0; |
| 519 | d->user_id_present = 1; | 520 | d->user_id_present = 1; |
| @@ -522,7 +523,7 @@ static int parse_fuse_opt(char *opt, struct fuse_mount_data *d, int is_bdev) | |||
