aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorSeth Forshee <seth.forshee@canonical.com>2014-07-02 17:29:19 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2017-04-18 10:58:38 -0400
commit0b6e9ea041e6c932f5b3a86fae2d60cbcfad4dd2 (patch)
treecd3865a34605be80a272a920713b11df7efcb35b /fs/fuse
parent095fc40ace5ffccd306f39fdd1a40b4faa41b8a0 (diff)
fuse: Add support for pid namespaces
When the userspace process servicing fuse requests is running in a pid namespace then pids passed via the fuse fd are not being translated into that process' namespace. Translation is necessary for the pid to be useful to that process. Since no use case currently exists for changing namespaces all translations can be done relative to the pid namespace in use when fuse_conn_init() is called. For fuse this translates to mount time, and for cuse this is when /dev/cuse is opened. IO for this connection from another namespace will return errors. Requests from processes whose pid cannot be translated into the target namespace will have a value of 0 for in.h.pid. File locking changes based on previous work done by Eric Biederman. Signed-off-by: Seth Forshee <seth.forshee@canonical.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c15
-rw-r--r--fs/fuse/file.c22
-rw-r--r--fs/fuse/fuse_i.h4
-rw-r--r--fs/fuse/inode.c3
4 files changed, 35 insertions, 9 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5e815072be1b..f95682115bc2 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -20,6 +20,7 @@
20#include <linux/pipe_fs_i.h> 20#include <linux/pipe_fs_i.h>
21#include <linux/swap.h> 21#include <linux/swap.h>
22#include <linux/splice.h> 22#include <linux/splice.h>
23#include <linux/sched.h>
23 24
24MODULE_ALIAS_MISCDEV(FUSE_MINOR); 25MODULE_ALIAS_MISCDEV(FUSE_MINOR);
25MODULE_ALIAS("devname:fuse"); 26MODULE_ALIAS("devname:fuse");
@@ -111,11 +112,11 @@ static void __fuse_put_request(struct fuse_req *req)
111 refcount_dec(&req->count); 112 refcount_dec(&req->count);
112} 113}
113 114
114static void fuse_req_init_context(struct fuse_req *req) 115static void fuse_req_init_context(struct fuse_conn *fc, struct fuse_req *req)
115{ 116{
116 req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid()); 117 req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
117 req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid()); 118 req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
118 req->in.h.pid = current->pid; 119 req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
119} 120}
120 121
121void fuse_set_initialized(struct fuse_conn *fc) 122void fuse_set_initialized(struct fuse_conn *fc)
@@ -162,7 +163,7 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
162 goto out; 163 goto out;
163 } 164 }
164 165
165 fuse_req_init_context(req); 166 fuse_req_init_context(fc, req);
166 __set_bit(FR_WAITING, &req->flags); 167 __set_bit(FR_WAITING, &req->flags);
167 if (for_background) 168 if (for_background)
168 __set_bit(FR_BACKGROUND, &req->flags); 169 __set_bit(FR_BACKGROUND, &req->flags);
@@ -255,7 +256,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
255 if (!req) 256 if (!req)
256 req = get_reserved_req(fc, file); 257 req = get_reserved_req(fc, file);
257 258
258 fuse_req_init_context(req); 259 fuse_req_init_context(fc, req);
259 __set_bit(FR_WAITING, &req->flags); 260 __set_bit(FR_WAITING, &req->flags);
260 __clear_bit(FR_BACKGROUND, &req->flags); 261 __clear_bit(FR_BACKGROUND, &req->flags);
261 return req; 262 return req;
@@ -1222,6 +1223,9 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
1222 struct fuse_in *in; 1223 struct fuse_in *in;
1223 unsigned reqsize; 1224 unsigned reqsize;
1224 1225
1226 if (task_active_pid_ns(current) != fc->pid_ns)
1227 return -EIO;
1228
1225 restart: 1229 restart:
1226 spin_lock(&fiq->waitq.lock); 1230 spin_lock(&fiq->waitq.lock);
1227 err = -EAGAIN; 1231 err = -EAGAIN;
@@ -1820,6 +1824,9 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
1820 struct fuse_req *req; 1824 struct fuse_req *req;
1821 struct fuse_out_header oh; 1825 struct fuse_out_header oh;
1822 1826
1827 if (task_active_pid_ns(current) != fc->pid_ns)
1828 return -EIO;
1829
1823 if (nbytes < sizeof(struct fuse_out_header)) 1830 if (nbytes < sizeof(struct fuse_out_header))
1824 return -EINVAL; 1831 return -EINVAL;
1825 1832
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 70770a0db734..aa93f09ae6e6 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2083,7 +2083,8 @@ static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
2083 return generic_file_mmap(file, vma); 2083 return generic_file_mmap(file, vma);
2084} 2084}
2085 2085
2086static int convert_fuse_file_lock(const struct fuse_file_lock *ffl, 2086static int convert_fuse_file_lock(struct fuse_conn *fc,
2087 const struct fuse_file_lock *ffl,
2087 struct file_lock *fl) 2088 struct file_lock *fl)
2088{ 2089{
2089 switch (ffl->type) { 2090 switch (ffl->type) {
@@ -2098,7 +2099,14 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
2098 2099
2099 fl->fl_start = ffl->start; 2100 fl->fl_start = ffl->start;
2100 fl->fl_end = ffl->end; 2101 fl->fl_end = ffl->end;
2101 fl->fl_pid = ffl->pid; 2102
2103 /*
2104 * Convert pid into the caller's pid namespace. If the pid
2105 * does not map into the namespace fl_pid will get set to 0.
2106 */
2107 rcu_read_lock();
2108 fl->fl_pid = pid_vnr(find_pid_ns(ffl->pid, fc->pid_ns));
2109 rcu_read_unlock();
2102 break; 2110 break;
2103 2111
2104 default: 2112 default:
@@ -2147,7 +2155,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
2147 args.out.args[0].value = &outarg; 2155 args.out.args[0].value = &outarg;
2148 err = fuse_simple_request(fc, &args); 2156 err = fuse_simple_request(fc, &args);
2149 if (!err) 2157 if (!err)
2150 err = convert_fuse_file_lock(&outarg.lk, fl); 2158 err = convert_fuse_file_lock(fc, &outarg.lk, fl);
2151 2159
2152 return err; 2160 return err;
2153} 2161}
@@ -2159,7 +2167,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
2159 FUSE_ARGS(args); 2167 FUSE_ARGS(args);
2160 struct fuse_lk_in inarg; 2168 struct fuse_lk_in inarg;
2161 int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK; 2169 int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
2162 pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; 2170 struct pid *pid = fl->fl_type != F_UNLCK ? task_tgid(current) : NULL;
2171 pid_t pid_nr = pid_nr_ns(pid, fc->pid_ns);
2163 int err; 2172 int err;
2164 2173
2165 if (fl->fl_lmops && fl->fl_lmops->lm_grant) { 2174 if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
@@ -2171,7 +2180,10 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
2171 if (fl->fl_flags & FL_CLOSE) 2180 if (fl->fl_flags & FL_CLOSE)
2172 return 0; 2181 return 0;
2173 2182
2174 fuse_lk_fill(&args, file, fl, opcode, pid, flock, &inarg); 2183 if (pid && pid_nr == 0)
2184 return -EOVERFLOW;
2185
2186 fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
2175 err = fuse_simple_request(fc, &args); 2187 err = fuse_simple_request(fc, &args);
2176 2188
2177 /* locking is restartable */ 2189 /* locking is restartable */
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 6c649f0c58f9..041521d29d33 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -24,6 +24,7 @@
24#include <linux/workqueue.h> 24#include <linux/workqueue.h>
25#include <linux/kref.h> 25#include <linux/kref.h>
26#include <linux/xattr.h> 26#include <linux/xattr.h>
27#include <linux/pid_namespace.h>
27#include <linux/refcount.h> 28#include <linux/refcount.h>
28 29
29/** Max number of pages that can be used in a single read request */ 30/** Max number of pages that can be used in a single read request */
@@ -462,6 +463,9 @@ struct fuse_conn {
462 /** The group id for this mount */ 463 /** The group id for this mount */
463 kgid_t group_id; 464 kgid_t group_id;
464 465
466 /** The pid namespace for this mount */
467 struct pid_namespace *pid_ns;
468
465 /** Maximum read size */ 469 /** Maximum read size */
466 unsigned max_read; 470 unsigned max_read;
467 471
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 3961c5f886be..a137f1c99a33 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -21,6 +21,7 @@
21#include <linux/sched.h> 21#include <linux/sched.h>
22#include <linux/exportfs.h> 22#include <linux/exportfs.h>
23#include <linux/posix_acl.h> 23#include <linux/posix_acl.h>
24#include <linux/pid_namespace.h>
24 25
25MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>"); 26MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
26MODULE_DESCRIPTION("Filesystem in Userspace"); 27MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -626,6 +627,7 @@ void fuse_conn_init(struct fuse_conn *fc)
626 fc->connected = 1; 627 fc->connected = 1;
627 fc->attr_version = 1; 628 fc->attr_version = 1;
628 get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); 629 get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
630 fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
629} 631}
630EXPORT_SYMBOL_GPL(fuse_conn_init); 632EXPORT_SYMBOL_GPL(fuse_conn_init);
631 633
@@ -634,6 +636,7 @@ void fuse_conn_put(struct fuse_conn *fc)
634 if (refcount_dec_and_test(&fc->count)) { 636 if (refcount_dec_and_test(&fc->count)) {
635 if (fc->destroy_req) 637 if (fc->destroy_req)
636 fuse_request_free(fc->destroy_req); 638 fuse_request_free(fc->destroy_req);
639 put_pid_ns(fc->pid_ns);
637 fc->release(fc); 640 fc->release(fc);
638 } 641 }
639} 642}