lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 22 May 2015 09:47:02 -0500
From:	Seth Forshee <seth.forshee@...onical.com>
To:	Miklos Szeredi <miklos@...redi.hu>
Cc:	alexey@...nosov.spb.ru, Andy Lutomirski <luto@...capital.net>,
	"Eric W. Biederman" <ebiederm@...ssion.com>,
	Serge Hallyn <serge.hallyn@...ntu.com>,
	fuse-devel <fuse-devel@...ts.sourceforge.net>,
	Linux-Fsdevel <linux-fsdevel@...r.kernel.org>,
	Kernel Mailing List <linux-kernel@...r.kernel.org>
Subject: Re: [fuse-devel] fuse_get_context() and namespaces

On Fri, May 22, 2015 at 04:23:55PM +0200, Miklos Szeredi wrote:
> On Sat, May 2, 2015 at 5:56 PM,  <alexey@...nosov.spb.ru> wrote:
> >
> > 3.10.0-229 form Scientific Linux and native 4.0.1-1 (from elrepo).
> > SL 7.1 on the host and SL 6.6 on the LXC guest. At least in 3.10
> > the 499dcf2024092e5cce41d05599a5b51d1f92031a is present.
> > Steps to reproduce:
> >
> > On first console:
> > [root@...test ~]# lxc-start  -n test-2 /bin/su -
> > [root@...t-2 ~]# diff -u  hello.py /usr/share/doc/fuse-python-0.2.1/example/hello.py
> > --- hello.py    2015-05-02 11:12:13.963093580 -0400
> > +++ /usr/share/doc/fuse-python-0.2.1/example/hello.py   2010-04-14 18:29:21.000000000 -0400
> > @@ -41,8 +41,6 @@
> >  class HelloFS(Fuse):
> >
> >      def getattr(self, path):
> > -        dic = Fuse.GetContext(self)
> > -        print dic
> >          st = MyStat()
> >          if path == '/':
> >              st.st_mode = stat.S_IFDIR | 0755
> > [root@...t-2 ~]# python hello.py -f  /mnt/
> >
> > On second console:
> > [root@...t-2 ~]# echo $$
> > 41
> > [root@...t-2 ~]# ls /mnt/
> > hello
> >
> > Output of first console:
> > {'gid': 0, 'pid': 12083, 'uid': 0}
> 
> Thanks.
> 
> Digging in mailbox...  There was a thread last year about adding
> support for running fuse daemon in a container:
> 
>   http://thread.gmane.org/gmane.linux.kernel/1811658
> 
> Not sure what happened, but no updated patches have been posted or
> maybe I just missed them.

I haven't sent updated patches in a while. I still intend to, but I
shifted focus to first getting general support for mounts from user
namespaces into the vfs (which will give a clearer direction for some of
the concerns raised about the fuse patches).

All of this code is available in the userns-mounts branch of
git://kernel.ubuntu.com/sforshee/linux.git, and I don't think the fuse
patches actually depend on any of the stuff that precedes them. I'm
planning to start submitting some of the earlier patches from that
branch soon, and eventually get back to resubmitting the fuse patches.

This is about pid namespaces though, and the fuse pid namespace patch
from that series (see below) should be more or less independent of the
rest of the patches. Potentially that could be merged separately from
the user namespae stuff.

Seth

---

>From 8f49164266e85103a6e95759644c6c343266eb9e Mon Sep 17 00:00:00 2001
From: Seth Forshee <seth.forshee@...onical.com>
Date: Wed, 2 Jul 2014 16:29:19 -0500
Subject: [PATCH] fuse: Add support for pid namespaces

If the userspace process servicing fuse requests is running in
a pid namespace then pids passed via the fuse fd need to be
translated relative to that namespace. Capture the pid namespace
in use when the filesystem is mounted and use this for pid
translation.

As with user namespaces, since no use case currently exists for
changing namespaces so all translations are done relative to the
pid namespace in use when /dev/fuse is opened. Mounting or
/dev/fuse IO from another namespace will return errors. This
restriction can be relaxed at a later time if needed.

File locking changes based on previous work done by Eric
Biederman.

Signed-off-by: Seth Forshee <seth.forshee@...onical.com>
---
 fs/fuse/dev.c    | 15 ++++++++++-----
 fs/fuse/file.c   | 23 ++++++++++++++++++-----
 fs/fuse/fuse_i.h |  4 ++++
 fs/fuse/inode.c  |  3 +++
 4 files changed, 35 insertions(+), 10 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 2ee0a7376e0e..627cbdbc63a3 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -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");
@@ -127,7 +128,7 @@ static void fuse_req_init_context(struct fuse_conn *fc, struct fuse_req *req)
 {
 	req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid());
 	req->in.h.gid = from_kgid_munged(fc->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)
@@ -1124,7 +1125,8 @@ __releases(fc->lock)
 	arg.unique = req->in.h.unique;
 
 	spin_unlock(&fc->lock);
-	if (fc->user_ns != current_user_ns())
+	if (fc->user_ns != current_user_ns() ||
+	    fc->pid_ns != task_active_pid_ns(current))
 		return -EIO;
 	if (nbytes < reqsize)
 		return -EINVAL;
@@ -1178,7 +1180,8 @@ __releases(fc->lock)
 
 	spin_unlock(&fc->lock);
 	kfree(forget);
-	if (fc->user_ns != current_user_ns())
+	if (fc->user_ns != current_user_ns() ||
+	    fc->pid_ns != task_active_pid_ns(current))
 		return -EIO;
 	if (nbytes < ih.len)
 		return -EINVAL;
@@ -1218,7 +1221,8 @@ __releases(fc->lock)
 	head = dequeue_forget(fc, max_forgets, &count);
 	spin_unlock(&fc->lock);
 
-	if (fc->user_ns != current_user_ns())
+	if (fc->user_ns != current_user_ns() ||
+	    fc->pid_ns != task_active_pid_ns(current))
 		return -EIO;
 
 	arg.count = count;
@@ -1306,7 +1310,8 @@ static ssize_t fuse_dev_do_read(struct fuse_conn *fc, struct file *file,
 	req->state = FUSE_REQ_READING;
 	list_move(&req->list, &fc->io);
 
-	if (fc->user_ns != current_user_ns()) {
+	if (fc->user_ns != current_user_ns() ||
+	    fc->pid_ns != task_active_pid_ns(current)) {
 		req->out.h.error = -EIO;
 		request_end(fc, req);
 		return -EPERM;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 5ef05b5c4cff..126b1568dc4c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2061,7 +2061,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) {
@@ -2076,7 +2077,15 @@ 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 connection'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:
@@ -2125,7 +2134,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;
 }
@@ -2137,7 +2146,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) {
@@ -2149,7 +2159,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 */
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index f6eddd8a2e06..3b7a301c0999 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -23,6 +23,7 @@
 #include <linux/poll.h>
 #include <linux/workqueue.h>
 #include <linux/user_namespace.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
@@ -406,6 +407,9 @@ struct fuse_conn {
 	/** The user namespace for this mount */
 	struct user_namespace *user_ns;
 
+	/** The pid namespace for this mount */
+	struct pid_namespace *pid_ns;
+
 	/** The fuse mount flags for this mount */
 	unsigned flags;
 
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 0e2a35507f1a..d190ce2c9d8f 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -20,6 +20,7 @@
 #include <linux/random.h>
 #include <linux/sched.h>
 #include <linux/exportfs.h>
+#include <linux/pid_namespace.h>
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@...redi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -627,6 +628,7 @@ void fuse_conn_init(struct fuse_conn *fc)
 	fc->attr_version = 1;
 	get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
 	fc->user_ns = get_user_ns(current_user_ns());
+	fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
 }
 EXPORT_SYMBOL_GPL(fuse_conn_init);
 
@@ -636,6 +638,7 @@ void fuse_conn_put(struct fuse_conn *fc)
 		if (fc->destroy_req)
 			fuse_request_free(fc->destroy_req);
 		put_user_ns(fc->user_ns);
+		put_pid_ns(fc->pid_ns);
 		fc->release(fc);
 	}
 }

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists