All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andy Whitcroft <apw@canonical.com>
To: Miklos Szeredi <miklos@szeredi.hu>,
	Serge Hallyn <serge.hallyn@ubuntu.com>
Cc: Linux-Fsdevel <linux-fsdevel@vger.kernel.org>,
	"Andy Whitcroft" <apw@canonical.com>,
	kernel-team@lists.ubuntu.com,
	"Stéphane Graber" <stephane.graber@canonical.com>
Subject: [RFC PATCH 1/1] overlayfs: switch to the init user namespace for xattr operations
Date: Wed,  5 Mar 2014 17:46:31 +0000	[thread overview]
Message-ID: <1394041592-3772-2-git-send-email-apw@canonical.com> (raw)
In-Reply-To: <1394041592-3772-1-git-send-email-apw@canonical.com>

We need to do xattr operations with CAP_SYS_ADMIN and as the real root
user.  Temporarily switch user namespaces to init_user_ns for those
operations.

Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
 fs/overlayfs/copy_up.c |  4 ++++
 fs/overlayfs/dir.c     | 23 +++++++++++++++++++----
 fs/overlayfs/readdir.c |  7 +++++++
 fs/overlayfs/super.c   |  5 ++++-
 4 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 351c162..698d460 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -15,6 +15,7 @@
 #include <linux/security.h>
 #include <linux/uaccess.h>
 #include <linux/sched.h>
+#include <linux/user_namespace.h>
 #include "overlayfs.h"
 
 #define OVL_COPY_UP_CHUNK_SIZE (1 << 20)
@@ -284,6 +285,7 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
 	override_cred->fsgid = stat->gid;
 	/*
 	 * CAP_SYS_ADMIN for copying up extended attributes
+	 * init_user_ns for copying up extended attributes
 	 * CAP_DAC_OVERRIDE for create
 	 * CAP_FOWNER for chmod, timestamp update
 	 * CAP_FSETID for chmod
@@ -294,6 +296,8 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
 	cap_raise(override_cred->cap_effective, CAP_FOWNER);
 	cap_raise(override_cred->cap_effective, CAP_FSETID);
 	cap_raise(override_cred->cap_effective, CAP_MKNOD);
+	put_user_ns(override_cred->user_ns);
+	override_cred->user_ns = get_user_ns(&init_user_ns);
 	old_cred = override_creds(override_cred);
 
 	mutex_lock_nested(&upperdir->d_inode->i_mutex, I_MUTEX_PARENT);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index a209409..96baba9 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -12,6 +12,7 @@
 #include <linux/xattr.h>
 #include <linux/security.h>
 #include <linux/cred.h>
+#include <linux/user_namespace.h>
 #include "overlayfs.h"
 
 static const char *ovl_whiteout_symlink = "(overlay-whiteout)";
@@ -32,14 +33,21 @@ static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry)
 
 	/*
 	 * CAP_SYS_ADMIN for setxattr
+	 * init_user_ns for setxattr
 	 * CAP_DAC_OVERRIDE for symlink creation
 	 * CAP_FOWNER for unlink in sticky directory
 	 */
 	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
 	cap_raise(override_cred->cap_effective, CAP_FOWNER);
-	override_cred->fsuid = GLOBAL_ROOT_UID;
-	override_cred->fsgid = GLOBAL_ROOT_GID;
+	override_cred->fsuid = make_kuid(current_user_ns(), 0);
+	if (!uid_valid(override_cred->fsuid))
+		override_cred->fsuid = GLOBAL_ROOT_UID;
+	override_cred->fsgid = make_kgid(current_user_ns(), 0);
+	if (!gid_valid(override_cred->fsgid))
+		override_cred->fsgid = GLOBAL_ROOT_GID;
+	put_user_ns(override_cred->user_ns);
+	override_cred->user_ns = get_user_ns(&init_user_ns);
 	old_cred = override_creds(override_cred);
 
 	newdentry = lookup_one_len(dentry->d_name.name, upperdir,
@@ -109,10 +117,13 @@ static struct dentry *ovl_lookup_create(struct dentry *upperdir,
 
 		/*
 		 * CAP_SYS_ADMIN for getxattr
+		 * init_user_ns for getxattr
 		 * CAP_FOWNER for unlink in sticky directory
 		 */
 		cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 		cap_raise(override_cred->cap_effective, CAP_FOWNER);
+		put_user_ns(override_cred->user_ns);
+		override_cred->user_ns = get_user_ns(&init_user_ns);
 		old_cred = override_creds(override_cred);
 
 		err = -EEXIST;
@@ -209,8 +220,10 @@ static int ovl_set_opaque(struct dentry *upperdentry)
 	if (!override_cred)
 		return -ENOMEM;
 
-	/* CAP_SYS_ADMIN for setxattr of "trusted" namespace */
+	/* CAP_SYS_ADMIN, init_user_ns for setxattr of "trusted" namespace */
 	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	put_user_ns(override_cred->user_ns);
+	override_cred->user_ns = get_user_ns(&init_user_ns);
 	old_cred = override_creds(override_cred);
 	err = vfs_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0);
 	revert_creds(old_cred);
@@ -229,8 +242,10 @@ static int ovl_remove_opaque(struct dentry *upperdentry)
 	if (!override_cred)
 		return -ENOMEM;
 
-	/* CAP_SYS_ADMIN for removexattr of "trusted" namespace */
+	/* CAP_SYS_ADMIN, init_user_ns for removexattr of "trusted" namespace */
 	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+	put_user_ns(override_cred->user_ns);
+	override_cred->user_ns = get_user_ns(&init_user_ns);
 	old_cred = override_creds(override_cred);
 	err = vfs_removexattr(upperdentry, ovl_opaque_xattr);
 	revert_creds(old_cred);
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 9c6f08f..5419454 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -15,6 +15,7 @@
 #include <linux/rbtree.h>
 #include <linux/security.h>
 #include <linux/cred.h>
+#include <linux/user_namespace.h>
 #include "overlayfs.h"
 
 struct ovl_cache_entry {
@@ -226,10 +227,13 @@ static int ovl_dir_mark_whiteouts(struct ovl_readdir_data *rdd)
 
 	/*
 	 * CAP_SYS_ADMIN for getxattr
+	 * init_user_ns for getxattr
 	 * CAP_DAC_OVERRIDE for lookup
 	 */
 	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
+	put_user_ns(override_cred->user_ns);
+	override_cred->user_ns = get_user_ns(&init_user_ns);
 	old_cred = override_creds(override_cred);
 
 	mutex_lock(&rdd->dir->d_inode->i_mutex);
@@ -510,11 +514,14 @@ static int ovl_remove_whiteouts(struct dentry *dir, struct list_head *list)
 	/*
 	 * CAP_DAC_OVERRIDE for lookup and unlink
 	 * CAP_SYS_ADMIN for setxattr of "trusted" namespace
+	 * init_user_ns for setxattr of "trusted" namespace
 	 * CAP_FOWNER for unlink in sticky directory
 	 */
 	cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
 	cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
 	cap_raise(override_cred->cap_effective, CAP_FOWNER);
+	put_user_ns(override_cred->user_ns);
+	override_cred->user_ns = get_user_ns(&init_user_ns);
 	old_cred = override_creds(override_cred);
 
 	err = vfs_setxattr(upperdir, ovl_opaque_xattr, "y", 1, 0);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 50890c2..2889818 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/statfs.h>
 #include <linux/seq_file.h>
+#include <linux/user_namespace.h>
 #include "overlayfs.h"
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
@@ -308,8 +309,10 @@ static int ovl_do_lookup(struct dentry *dentry)
 			if (!override_cred)
 				goto out_dput_upper;
 
-			/* CAP_SYS_ADMIN needed for getxattr */
+			/* CAP_SYS_ADMIN, init_user_ns needed for getxattr */
 			cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
+			put_user_ns(override_cred->user_ns);
+			override_cred->user_ns = get_user_ns(&init_user_ns);
 			old_cred = override_creds(override_cred);
 
 			if (ovl_is_opaquedir(upperdentry)) {
-- 
1.9.0

  reply	other threads:[~2014-03-05 17:46 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-25 17:31 [PATCH RFC] overlayfs,xattr: allow unprivileged users to whiteout Serge Hallyn
2014-02-28 14:15 ` Miklos Szeredi
2014-02-28 14:55   ` Andy Whitcroft
2014-02-28 16:23     ` Serge Hallyn
2014-03-05 17:46     ` [RFC] overlayfs priviledge escalation handling under user namespaces Andy Whitcroft
2014-03-05 17:46       ` Andy Whitcroft [this message]
2014-03-05 17:46       ` [RFC PATCH 1/1] overlayfs: use kernel service credentials for copy up and xattr manipulations Andy Whitcroft
2014-03-05 20:01         ` Serge Hallyn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1394041592-3772-2-git-send-email-apw@canonical.com \
    --to=apw@canonical.com \
    --cc=kernel-team@lists.ubuntu.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=serge.hallyn@ubuntu.com \
    --cc=stephane.graber@canonical.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.