]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
UBUNTU: SAUCE: (namespace) fuse: Add support for pid namespaces
authorSeth Forshee <seth.forshee@canonical.com>
Wed, 2 Jul 2014 21:29:19 +0000 (16:29 -0500)
committerTim Gardner <tim.gardner@canonical.com>
Mon, 20 Feb 2017 03:57:58 +0000 (20:57 -0700)
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.

Acked-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c

index f11792672977d2280ec7fc301f81e9b1b1ba7741..e0a6a4f8dcf0022903f3892ea41a60a74ec88c02 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/swap.h>
 #include <linux/splice.h>
+#include <linux/sched.h>
 
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
 MODULE_ALIAS("devname:fuse");
@@ -111,11 +112,11 @@ static void __fuse_put_request(struct fuse_req *req)
        atomic_dec(&req->count);
 }
 
-static void fuse_req_init_context(struct fuse_req *req)
+static void fuse_req_init_context(struct fuse_conn *fc, struct fuse_req *req)
 {
        req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
        req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
-       req->in.h.pid = current->pid;
+       req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
 }
 
 void fuse_set_initialized(struct fuse_conn *fc)
@@ -162,7 +163,7 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
                goto out;
        }
 
-       fuse_req_init_context(req);
+       fuse_req_init_context(fc, req);
        __set_bit(FR_WAITING, &req->flags);
        if (for_background)
                __set_bit(FR_BACKGROUND, &req->flags);
@@ -255,7 +256,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
        if (!req)
                req = get_reserved_req(fc, file);
 
-       fuse_req_init_context(req);
+       fuse_req_init_context(fc, req);
        __set_bit(FR_WAITING, &req->flags);
        __clear_bit(FR_BACKGROUND, &req->flags);
        return req;
@@ -1222,6 +1223,9 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        struct fuse_in *in;
        unsigned reqsize;
 
+       if (task_active_pid_ns(current) != fc->pid_ns)
+               return -EIO;
+
  restart:
        spin_lock(&fiq->waitq.lock);
        err = -EAGAIN;
@@ -1820,6 +1824,9 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
        struct fuse_req *req;
        struct fuse_out_header oh;
 
+       if (task_active_pid_ns(current) != fc->pid_ns)
+               return -EIO;
+
        if (nbytes < sizeof(struct fuse_out_header))
                return -EINVAL;
 
index 2401c5dabb2a227b6511be01b1589ffa5180e636..c25bef3ed0f0d75fbec01f1a4b2b4549866ad3b0 100644 (file)
@@ -2087,7 +2087,8 @@ static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
        return generic_file_mmap(file, vma);
 }
 
-static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
+static int convert_fuse_file_lock(struct fuse_conn *fc,
+                                 const struct fuse_file_lock *ffl,
                                  struct file_lock *fl)
 {
        switch (ffl->type) {
@@ -2102,7 +2103,14 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
 
                fl->fl_start = ffl->start;
                fl->fl_end = ffl->end;
-               fl->fl_pid = ffl->pid;
+
+               /*
+                * Convert pid into the caller's pid namespace. If the pid
+                * does not map into the namespace fl_pid will get set to 0.
+                */
+               rcu_read_lock();
+               fl->fl_pid = pid_vnr(find_pid_ns(ffl->pid, fc->pid_ns));
+               rcu_read_unlock();
                break;
 
        default:
@@ -2151,7 +2159,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
        args.out.args[0].value = &outarg;
        err = fuse_simple_request(fc, &args);
        if (!err)
-               err = convert_fuse_file_lock(&outarg.lk, fl);
+               err = convert_fuse_file_lock(fc, &outarg.lk, fl);
 
        return err;
 }
@@ -2163,7 +2171,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
        FUSE_ARGS(args);
        struct fuse_lk_in inarg;
        int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
-       pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
+       struct pid *pid = fl->fl_type != F_UNLCK ? task_tgid(current) : NULL;
+       pid_t pid_nr = pid_nr_ns(pid, fc->pid_ns);
        int err;
 
        if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
@@ -2175,7 +2184,10 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
        if (fl->fl_flags & FL_CLOSE)
                return 0;
 
-       fuse_lk_fill(&args, file, fl, opcode, pid, flock, &inarg);
+       if (pid && pid_nr == 0)
+               return -EOVERFLOW;
+
+       fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
        err = fuse_simple_request(fc, &args);
 
        /* locking is restartable */
index 91307940c8ac5e921b08133a04ca0b65283fd308..2760cc92dc554d70ab3d0bd13816b333f802853d 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/workqueue.h>
 #include <linux/kref.h>
 #include <linux/xattr.h>
+#include <linux/pid_namespace.h>
 
 /** Max number of pages that can be used in a single read request */
 #define FUSE_MAX_PAGES_PER_REQ 32
@@ -461,6 +462,9 @@ struct fuse_conn {
        /** The group id for this mount */
        kgid_t group_id;
 
+       /** The pid namespace for this mount */
+       struct pid_namespace *pid_ns;
+
        /** Maximum read size */
        unsigned max_read;
 
index 6fe6a88ecb4afd9eaaad1b0c75fe961108efc64a..5b97ad598dc5898c9b486d161823b334c154dc32 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/sched.h>
 #include <linux/exportfs.h>
 #include <linux/posix_acl.h>
+#include <linux/pid_namespace.h>
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -626,6 +627,7 @@ void fuse_conn_init(struct fuse_conn *fc)
        fc->connected = 1;
        fc->attr_version = 1;
        get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
+       fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
 }
 EXPORT_SYMBOL_GPL(fuse_conn_init);
 
@@ -634,6 +636,7 @@ void fuse_conn_put(struct fuse_conn *fc)
        if (atomic_dec_and_test(&fc->count)) {
                if (fc->destroy_req)
                        fuse_request_free(fc->destroy_req);
+               put_pid_ns(fc->pid_ns);
                fc->release(fc);
        }
 }