linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] orangefs: fix namespace handling
@ 2016-06-24 23:51 Jann Horn
  2016-06-25  4:29 ` Eric W. Biederman
  0 siblings, 1 reply; 3+ messages in thread
From: Jann Horn @ 2016-06-24 23:51 UTC (permalink / raw)
  To: Mike Marshall
  Cc: linux-kernel, Eric Biederman, Alexander Viro, linux-fsdevel,
	jann, Jann Horn

In orangefs_inode_getxattr(), an fsuid is written to dmesg. The kuid is
converted to a userspace uid via from_kuid(current_user_ns(), [...]), but
since dmesg is global, init_user_ns should be used here instead.

In copy_attributes_from_inode(), op_alloc() and fill_default_sys_attrs(),
upcall structures are populated with uids/gids that have been mapped into
the caller's namespace. However, those upcall structures are read by
another process (the userspace filesystem driver), and that process might
be running in another namespace. This effectively lets any user spoof its
uid and gid as seen by the userspace filesystem driver.

To fix the second issue, I just construct the opcall structures with
init_user_ns uids/gids and require the filesystem server to run in the
init namespace. Since orangefs is full of global state anyway (as the error
message in DUMP_DEVICE_ERROR explains, there can only be one userspace
orangefs filesystem driver at once), that shouldn't be a problem.

[
Why does orangefs even exist in the kernel if everything does upcalls into
userspace? What does orangefs do that couldn't be done with the FUSE
interface? If there is no good answer to those questions, I'd prefer to see
orangefs kicked out of the kernel. Can that be done for something that
shipped in a release?

According to commit f7ab093f74bf ("Orangefs: kernel client part 1"), they
even already have a FUSE daemon, and the only rational reason (apart from
"but most of our users report preferring to use our kernel module instead")
given for not wanting to use FUSE is one "in-the-works" feature that could
probably be integated into FUSE instead.
]

This patch has been compile-tested.

Signed-off-by: Jann Horn <jannh@google.com>
---
 fs/orangefs/devorangefs-req.c | 7 +++++++
 fs/orangefs/orangefs-cache.c  | 4 ++--
 fs/orangefs/orangefs-kernel.h | 4 ++--
 fs/orangefs/orangefs-utils.c  | 4 ++--
 fs/orangefs/xattr.c           | 4 ++--
 5 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
index db170be..a287a66 100644
--- a/fs/orangefs/devorangefs-req.c
+++ b/fs/orangefs/devorangefs-req.c
@@ -116,6 +116,13 @@ static int orangefs_devreq_open(struct inode *inode, struct file *file)
 {
 	int ret = -EINVAL;
 
+	/* in order to ensure that the filesystem driver sees correct UIDs */
+	if (file->f_cred->user_ns != &init_user_ns) {
+		gossip_err("%s: device cannot be opened outside init_user_ns\n",
+			   __func__);
+		goto out;
+	}
+
 	if (!(file->f_flags & O_NONBLOCK)) {
 		gossip_err("%s: device cannot be opened in blocking mode\n",
 			   __func__);
diff --git a/fs/orangefs/orangefs-cache.c b/fs/orangefs/orangefs-cache.c
index 900a2e3..b6edbe9 100644
--- a/fs/orangefs/orangefs-cache.c
+++ b/fs/orangefs/orangefs-cache.c
@@ -136,10 +136,10 @@ struct orangefs_kernel_op_s *op_alloc(__s32 type)
 			     llu(new_op->tag),
 			     get_opname_string(new_op));
 
-		new_op->upcall.uid = from_kuid(current_user_ns(),
+		new_op->upcall.uid = from_kuid(&init_user_ns,
 					       current_fsuid());
 
-		new_op->upcall.gid = from_kgid(current_user_ns(),
+		new_op->upcall.gid = from_kgid(&init_user_ns,
 					       current_fsgid());
 	} else {
 		gossip_err("op_alloc: kmem_cache_zalloc failed!\n");
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 2281882..a6834d4 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -600,8 +600,8 @@ int service_operation(struct orangefs_kernel_op_s *op,
 
 #define fill_default_sys_attrs(sys_attr, type, mode)			\
 do {									\
-	sys_attr.owner = from_kuid(current_user_ns(), current_fsuid()); \
-	sys_attr.group = from_kgid(current_user_ns(), current_fsgid()); \
+	sys_attr.owner = from_kuid(&init_user_ns, current_fsuid()); \
+	sys_attr.group = from_kgid(&init_user_ns, current_fsgid()); \
 	sys_attr.perms = ORANGEFS_util_translate_mode(mode);		\
 	sys_attr.mtime = 0;						\
 	sys_attr.atime = 0;						\
diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c
index 2d129b5..c5fbc62 100644
--- a/fs/orangefs/orangefs-utils.c
+++ b/fs/orangefs/orangefs-utils.c
@@ -153,12 +153,12 @@ static inline int copy_attributes_from_inode(struct inode *inode,
 	 */
 	attrs->mask = 0;
 	if (iattr->ia_valid & ATTR_UID) {
-		attrs->owner = from_kuid(current_user_ns(), iattr->ia_uid);
+		attrs->owner = from_kuid(&init_user_ns, iattr->ia_uid);
 		attrs->mask |= ORANGEFS_ATTR_SYS_UID;
 		gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner);
 	}
 	if (iattr->ia_valid & ATTR_GID) {
-		attrs->group = from_kgid(current_user_ns(), iattr->ia_gid);
+		attrs->group = from_kgid(&init_user_ns, iattr->ia_gid);
 		attrs->mask |= ORANGEFS_ATTR_SYS_GID;
 		gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group);
 	}
diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c
index 5893ddd..e4a070f 100644
--- a/fs/orangefs/xattr.c
+++ b/fs/orangefs/xattr.c
@@ -79,8 +79,8 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *prefix,
 		return -EINVAL;
 	}
 
-	fsuid = from_kuid(current_user_ns(), current_fsuid());
-	fsgid = from_kgid(current_user_ns(), current_fsgid());
+	fsuid = from_kuid(&init_user_ns, current_fsuid());
+	fsgid = from_kgid(&init_user_ns, current_fsgid());
 
 	gossip_debug(GOSSIP_XATTR_DEBUG,
 		     "getxattr on inode %pU, name %s "
-- 
2.8.0.rc3.226.g39d4020

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] orangefs: fix namespace handling
  2016-06-24 23:51 [PATCH] orangefs: fix namespace handling Jann Horn
@ 2016-06-25  4:29 ` Eric W. Biederman
  2016-06-25 23:03   ` Mike Marshall
  0 siblings, 1 reply; 3+ messages in thread
From: Eric W. Biederman @ 2016-06-25  4:29 UTC (permalink / raw)
  To: Jann Horn
  Cc: Mike Marshall, linux-kernel, Alexander Viro, linux-fsdevel, jann

Jann Horn <jannh@google.com> writes:

> diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
> index db170be..a287a66 100644
> --- a/fs/orangefs/devorangefs-req.c
> +++ b/fs/orangefs/devorangefs-req.c
> @@ -116,6 +116,13 @@ static int orangefs_devreq_open(struct inode *inode, struct file *file)
>  {
>  	int ret = -EINVAL;
>  
> +	/* in order to ensure that the filesystem driver sees correct UIDs */
> +	if (file->f_cred->user_ns != &init_user_ns) {
> +		gossip_err("%s: device cannot be opened outside init_user_ns\n",
> +			   __func__);
> +		goto out;
> +	}
> +

Not necessarily in this patch but the code should also verify that the
opener is also in the initial pid namespace as pids are transferred in
the upcalls as well.

>  	if (!(file->f_flags & O_NONBLOCK)) {
>  		gossip_err("%s: device cannot be opened in blocking mode\n",
>  			   __func__);

Eric

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] orangefs: fix namespace handling
  2016-06-25  4:29 ` Eric W. Biederman
@ 2016-06-25 23:03   ` Mike Marshall
  0 siblings, 0 replies; 3+ messages in thread
From: Mike Marshall @ 2016-06-25 23:03 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: Jann Horn, LKML, Alexander Viro, linux-fsdevel, jann

Your suggestions make sense to me, especially after looking
at how other filesystems use init_user_ns...

As far as kicking us out of the Kernel, good grief, I hope not, it
was hard getting into the kernel!

-Mike

On Sat, Jun 25, 2016 at 12:29 AM, Eric W. Biederman
<ebiederm@xmission.com> wrote:
> Jann Horn <jannh@google.com> writes:
>
>> diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
>> index db170be..a287a66 100644
>> --- a/fs/orangefs/devorangefs-req.c
>> +++ b/fs/orangefs/devorangefs-req.c
>> @@ -116,6 +116,13 @@ static int orangefs_devreq_open(struct inode *inode, struct file *file)
>>  {
>>       int ret = -EINVAL;
>>
>> +     /* in order to ensure that the filesystem driver sees correct UIDs */
>> +     if (file->f_cred->user_ns != &init_user_ns) {
>> +             gossip_err("%s: device cannot be opened outside init_user_ns\n",
>> +                        __func__);
>> +             goto out;
>> +     }
>> +
>
> Not necessarily in this patch but the code should also verify that the
> opener is also in the initial pid namespace as pids are transferred in
> the upcalls as well.
>
>>       if (!(file->f_flags & O_NONBLOCK)) {
>>               gossip_err("%s: device cannot be opened in blocking mode\n",
>>                          __func__);
>
> Eric

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-06-25 23:03 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-24 23:51 [PATCH] orangefs: fix namespace handling Jann Horn
2016-06-25  4:29 ` Eric W. Biederman
2016-06-25 23:03   ` Mike Marshall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).