From patchwork Wed Mar 5 17:46:32 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Whitcroft X-Patchwork-Id: 327095 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) by ozlabs.org (Postfix) with ESMTP id 845202C00C2 for ; Thu, 6 Mar 2014 04:46:51 +1100 (EST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1WLFu3-00077a-Qk; Wed, 05 Mar 2014 17:46:47 +0000 Received: from mail-we0-f176.google.com ([74.125.82.176]) by huckleberry.canonical.com with esmtp (Exim 4.76) (envelope-from ) id 1WLFtv-00075p-UW for kernel-team@lists.ubuntu.com; Wed, 05 Mar 2014 17:46:39 +0000 Received: by mail-we0-f176.google.com with SMTP id x48so1663812wes.35 for ; Wed, 05 Mar 2014 09:46:39 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=wTIxPi/WH+mePRstPOSd/qtuapg6O2lLqDhDSFAl/ZA=; b=dE+ZmWLiotlyrMZHK7tuV8zJ73YPQS7AsOu+deiJeYK+L8MFliDM1575ZcxSyU0C2o EZw10Tbql538RPCAikb6cnIFM/kcAtj5tWjIsrdNF4RTeEL0zkoTFc/sZxj4/UvtmQ6N hH42lSPvm4OKKEgV4T+rQ8xsTzx7Ee11D+dRwWHKM2u8GFLfc75uqtqQoYdDLH/Iwbzn wovSRgZfs35pHdq3LijLLj1h3/Azmwx6SRKyip+hLtFK1P4YtcZ7FiNHVzjgwKzI1uVb r13PRXVvkU4HtC1ytEQbo0rwoTVFblBqfmKDoZjcJEdr5mbEN3tgLG0bXx4rh7I/cfA5 Izyg== X-Gm-Message-State: ALoCoQnurNBN+2cLne2N4IvvXq/IjNWGI+T244b4nvDWSefeaDv1b59nt2miQrz6VtD/19gKTvni X-Received: by 10.194.75.225 with SMTP id f1mr2745778wjw.87.1394041599791; Wed, 05 Mar 2014 09:46:39 -0800 (PST) Received: from localhost ([2001:470:6973:2:221:70ff:fe81:b177]) by mx.google.com with ESMTPSA id uq2sm3429554wjc.5.2014.03.05.09.46.38 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Wed, 05 Mar 2014 09:46:39 -0800 (PST) From: Andy Whitcroft To: Miklos Szeredi , Serge Hallyn Subject: [RFC PATCH 1/1] overlayfs: use kernel service credentials for copy up and xattr manipulations Date: Wed, 5 Mar 2014 17:46:32 +0000 Message-Id: <1394041592-3772-3-git-send-email-apw@canonical.com> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1394041592-3772-1-git-send-email-apw@canonical.com> References: <20140228145514.GD4334@dm> <1394041592-3772-1-git-send-email-apw@canonical.com> Cc: Linux-Fsdevel , Andy Whitcroft , kernel-team@lists.ubuntu.com, =?UTF-8?q?St=C3=A9phane=20Graber?= X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.14 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: kernel-team-bounces@lists.ubuntu.com We need to be priviledged to perform operations such as copy up and xattr manipulations on "trusted.". Use prepare_kernel_cred to obtain the necessary priviledges; from its documentation: "Prepare a set of credentials for a kernel service. This can then be used to override a task's own credentials so that work can be done on behalf of that task that requires a different subjective context." Signed-off-by: Andy Whitcroft Tested-by: Serge E. Hallyn Acked-by: Serge E. Hallyn --- fs/overlayfs/copy_up.c | 14 +------------- fs/overlayfs/dir.c | 35 +++++++++++------------------------ fs/overlayfs/readdir.c | 18 ++---------------- fs/overlayfs/super.c | 4 +--- 4 files changed, 15 insertions(+), 56 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 351c162..c7894de 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -276,24 +276,12 @@ static int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry, } err = -ENOMEM; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) goto out_free_link; override_cred->fsuid = stat->uid; override_cred->fsgid = stat->gid; - /* - * CAP_SYS_ADMIN for copying up extended attributes - * CAP_DAC_OVERRIDE for create - * CAP_FOWNER for chmod, timestamp update - * CAP_FSETID for chmod - * CAP_MKNOD for mknod - */ - 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); - cap_raise(override_cred->cap_effective, CAP_FSETID); - cap_raise(override_cred->cap_effective, CAP_MKNOD); 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..0a7eb4a 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "overlayfs.h" @@ -26,20 +27,16 @@ static int ovl_whiteout(struct dentry *upperdir, struct dentry *dentry) /* FIXME: recheck lower dentry to see if whiteout is really needed */ err = -ENOMEM; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) goto out; - /* - * CAP_SYS_ADMIN 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; old_cred = override_creds(override_cred); newdentry = lookup_one_len(dentry->d_name.name, upperdir, @@ -103,16 +100,10 @@ static struct dentry *ovl_lookup_create(struct dentry *upperdir, goto out_dput; err = -ENOMEM; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) goto out_dput; - /* - * CAP_SYS_ADMIN 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); old_cred = override_creds(override_cred); err = -EEXIST; @@ -205,12 +196,10 @@ static int ovl_set_opaque(struct dentry *upperdentry) const struct cred *old_cred; struct cred *override_cred; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) return -ENOMEM; - /* CAP_SYS_ADMIN for setxattr of "trusted" namespace */ - cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); old_cred = override_creds(override_cred); err = vfs_setxattr(upperdentry, ovl_opaque_xattr, "y", 1, 0); revert_creds(old_cred); @@ -225,12 +214,10 @@ static int ovl_remove_opaque(struct dentry *upperdentry) const struct cred *old_cred; struct cred *override_cred; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) return -ENOMEM; - /* CAP_SYS_ADMIN for removexattr of "trusted" namespace */ - cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); 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..1cc4cbd 100644 --- a/fs/overlayfs/readdir.c +++ b/fs/overlayfs/readdir.c @@ -218,18 +218,12 @@ static int ovl_dir_mark_whiteouts(struct ovl_readdir_data *rdd) const struct cred *old_cred; struct cred *override_cred; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) { ovl_cache_free(rdd->list); return -ENOMEM; } - /* - * CAP_SYS_ADMIN 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); old_cred = override_creds(override_cred); mutex_lock(&rdd->dir->d_inode->i_mutex); @@ -503,18 +497,10 @@ static int ovl_remove_whiteouts(struct dentry *dir, struct list_head *list) ovl_path_upper(dir, &upperpath); upperdir = upperpath.dentry; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) return -ENOMEM; - /* - * CAP_DAC_OVERRIDE for lookup and unlink - * CAP_SYS_ADMIN 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); 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..79288a8 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -304,12 +304,10 @@ static int ovl_do_lookup(struct dentry *dentry) struct cred *override_cred; err = -ENOMEM; - override_cred = prepare_creds(); + override_cred = prepare_kernel_cred(NULL); if (!override_cred) goto out_dput_upper; - /* CAP_SYS_ADMIN needed for getxattr */ - cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); old_cred = override_creds(override_cred); if (ovl_is_opaquedir(upperdentry)) {