From patchwork Wed Nov 29 21:50:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473544 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 245D761661; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CkpGCKdr" Received: by smtp.kernel.org (Postfix) with ESMTPS id A86E8C433C9; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294657; bh=8hyIqObGCNM7OndECY6ik1cyygtFav0NlxWDW3pdIrY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CkpGCKdrKgvgw3LXn9ipOahA2+M19iR2U9o3O3o5Fk+3nPTiY2Za0d6297yIEPj6n LLA9YQB/5ldnlPFWxRXazF6Dc/HFN7U068ajVdMwIykXLC2YKLFgzPg+jZHD9UHhn8 nxTyrVDxCeWSG3gthIxE7wwgSAKSJlMFbt8woLU00OM3TMwXCQMyIeDGrJ8zb+g0pa fjOd8/Ps2V8RHNeefdeLnEhPE4KmA6oRg52+xOUpcRnctB72Ttu0AngNzRESFpBxDq jcK3tXTpyWAi1Nf9YBgumpPSOfJzgBnDcfZol5f4CQ94T4MFgSaL6dVFZcGdJ/rnGC uHjuC6Ke+zqjA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 934E6C4167B; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:19 -0600 Subject: [PATCH 01/16] mnt_idmapping: split out core vfs[ug]id_t definitions into vfsid.h Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-1-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=5492; i=sforshee@kernel.org; h=from:subject:message-id; bh=8hyIqObGCNM7OndECY6ik1cyygtFav0NlxWDW3pdIrY=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7IypVCG7IPii3Bv/9IWC//wj?= =?utf-8?q?bIJFZxmwWtk15il_2eLSfdSJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyMgAKCRBTA5mu5fQxyeIuB/_98tcQpOL+ArlkKRsUG2863oU+nR4ASsCNyB?= =?utf-8?q?0teYwg1zHPGKgvQpVQ6sTEKVATR8UU8BHodZ/NrW+9z_SCWPGhpCWCOuLMyLQKoaV?= =?utf-8?q?jacW1v7mfAHytfLH7W7PA8Uv2l+4YauHotUx6ViIJMiurXpu3am9mMctL_xwiDiJc?= =?utf-8?q?7e88bSAWeqRim6qWEUQV6Qft733XXUOwHo7XQGF6nw2owmvyUnQpPrruZCWfrnL4c?= =?utf-8?q?LSouL+_aZm0cLpA6I4BzvGdPncMfkqSFtylQN+mgbWnX5UZEgzr4akhSvywqhfUii?= =?utf-8?q?cwxB1ZNz38qY07ce0fmk?= pXiqKWJ91c4rFBldMqTgeDb6+B4Jfe X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 The rootid member of cpu_vfs_cap_data is a kuid_t, but it should be a vfsuid_t as the id stored there is mapped into the mount idmapping. It's currently impossible to use vfsuid_t within cred.h though as it is defined in mnt_idmapping.h, which uses definitions from cred.h. Split out the core vfsid type definitions into a separate file which can be included from cred.h. Signed-off-by: Seth Forshee (DigitalOcean) --- MAINTAINERS | 1 + include/linux/mnt_idmapping.h | 66 +------------------------------------- include/linux/vfsid.h | 74 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 65 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 012df8ccf34e..8c73081d3dcc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10260,6 +10260,7 @@ S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping.git F: Documentation/filesystems/idmappings.rst F: include/linux/mnt_idmapping.* +F: include/linux/vfsid.h F: tools/testing/selftests/mount_setattr/ IDT VersaClock 5 CLOCK DRIVER diff --git a/include/linux/mnt_idmapping.h b/include/linux/mnt_idmapping.h index b8da2db4ecd2..8b5e00ee6472 100644 --- a/include/linux/mnt_idmapping.h +++ b/include/linux/mnt_idmapping.h @@ -4,6 +4,7 @@ #include #include +#include struct mnt_idmap; struct user_namespace; @@ -11,61 +12,6 @@ struct user_namespace; extern struct mnt_idmap nop_mnt_idmap; extern struct user_namespace init_user_ns; -typedef struct { - uid_t val; -} vfsuid_t; - -typedef struct { - gid_t val; -} vfsgid_t; - -static_assert(sizeof(vfsuid_t) == sizeof(kuid_t)); -static_assert(sizeof(vfsgid_t) == sizeof(kgid_t)); -static_assert(offsetof(vfsuid_t, val) == offsetof(kuid_t, val)); -static_assert(offsetof(vfsgid_t, val) == offsetof(kgid_t, val)); - -#ifdef CONFIG_MULTIUSER -static inline uid_t __vfsuid_val(vfsuid_t uid) -{ - return uid.val; -} - -static inline gid_t __vfsgid_val(vfsgid_t gid) -{ - return gid.val; -} -#else -static inline uid_t __vfsuid_val(vfsuid_t uid) -{ - return 0; -} - -static inline gid_t __vfsgid_val(vfsgid_t gid) -{ - return 0; -} -#endif - -static inline bool vfsuid_valid(vfsuid_t uid) -{ - return __vfsuid_val(uid) != (uid_t)-1; -} - -static inline bool vfsgid_valid(vfsgid_t gid) -{ - return __vfsgid_val(gid) != (gid_t)-1; -} - -static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right) -{ - return vfsuid_valid(left) && __vfsuid_val(left) == __vfsuid_val(right); -} - -static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right) -{ - return vfsgid_valid(left) && __vfsgid_val(left) == __vfsgid_val(right); -} - /** * vfsuid_eq_kuid - check whether kuid and vfsuid have the same value * @vfsuid: the vfsuid to compare @@ -96,16 +42,6 @@ static inline bool vfsgid_eq_kgid(vfsgid_t vfsgid, kgid_t kgid) return vfsgid_valid(vfsgid) && __vfsgid_val(vfsgid) == __kgid_val(kgid); } -/* - * vfs{g,u}ids are created from k{g,u}ids. - * We don't allow them to be created from regular {u,g}id. - */ -#define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) } -#define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) } - -#define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID) -#define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID) - /* * Allow a vfs{g,u}id to be used as a k{g,u}id where we want to compare * whether the mapped value is identical to value of a k{g,u}id. diff --git a/include/linux/vfsid.h b/include/linux/vfsid.h new file mode 100644 index 000000000000..90262944b042 --- /dev/null +++ b/include/linux/vfsid.h @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_MNT_VFSID_H +#define _LINUX_MNT_VFSID_H + +#include +#include +#include + +typedef struct { + uid_t val; +} vfsuid_t; + +typedef struct { + gid_t val; +} vfsgid_t; + +static_assert(sizeof(vfsuid_t) == sizeof(kuid_t)); +static_assert(sizeof(vfsgid_t) == sizeof(kgid_t)); +static_assert(offsetof(vfsuid_t, val) == offsetof(kuid_t, val)); +static_assert(offsetof(vfsgid_t, val) == offsetof(kgid_t, val)); + +#ifdef CONFIG_MULTIUSER +static inline uid_t __vfsuid_val(vfsuid_t uid) +{ + return uid.val; +} + +static inline gid_t __vfsgid_val(vfsgid_t gid) +{ + return gid.val; +} +#else +static inline uid_t __vfsuid_val(vfsuid_t uid) +{ + return 0; +} + +static inline gid_t __vfsgid_val(vfsgid_t gid) +{ + return 0; +} +#endif + +static inline bool vfsuid_valid(vfsuid_t uid) +{ + return __vfsuid_val(uid) != (uid_t)-1; +} + +static inline bool vfsgid_valid(vfsgid_t gid) +{ + return __vfsgid_val(gid) != (gid_t)-1; +} + +static inline bool vfsuid_eq(vfsuid_t left, vfsuid_t right) +{ + return vfsuid_valid(left) && __vfsuid_val(left) == __vfsuid_val(right); +} + +static inline bool vfsgid_eq(vfsgid_t left, vfsgid_t right) +{ + return vfsgid_valid(left) && __vfsgid_val(left) == __vfsgid_val(right); +} + +/* + * vfs{g,u}ids are created from k{g,u}ids. + * We don't allow them to be created from regular {u,g}id. + */ +#define VFSUIDT_INIT(val) (vfsuid_t){ __kuid_val(val) } +#define VFSGIDT_INIT(val) (vfsgid_t){ __kgid_val(val) } + +#define INVALID_VFSUID VFSUIDT_INIT(INVALID_UID) +#define INVALID_VFSGID VFSGIDT_INIT(INVALID_GID) + +#endif /* _LINUX_MNT_VFSID_H */ From patchwork Wed Nov 29 21:50:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473547 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2466861686; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="CNpv4DHs" Received: by smtp.kernel.org (Postfix) with ESMTPS id B3A36C433CB; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294657; bh=kBYMx/ct1DJWmWZZrfAgu5rv/aqJOd49LOYKeJgW/mY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CNpv4DHstKF3PxggnUX4FHrJcqYePxrMZsptqwwZiD3jYC0EtBc4FKCErOk8x0Nma 089hRb3I+KOjo+2Ret3FHt772sG1ChgiBtUkr3F3Mcc2Tapxt74XpXPuFtOyO8/yW8 R17MS2K9P9TBhLZ7qiibZ+mz/kv1bGxkQ0A1jzi/RtvdD2B2XiJQpZZe2dsddNCvNK wBRPLgYsbplXea35qt4vXD0S68urjWegwAAhc6hOal/Db6K7w24LqcqV5mMkacjiyK aWv26FyeF+jG0yhW/SOYwhrqwOXgNDtRQHS52vYv7X9f1D+EvVrgy1TsrnnWtKYRrd 5MBC0PQ5/ypSQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9C8DAC46CA0; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:20 -0600 Subject: [PATCH 02/16] mnt_idmapping: include cred.h Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-2-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=615; i=sforshee@kernel.org; h=from:subject:message-id; bh=kBYMx/ct1DJWmWZZrfAgu5rv/aqJOd49LOYKeJgW/mY=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7IzazfoDYxcriweVPsbLfsCP?= =?utf-8?q?Xs/YDZSjasrRYGN_eexJIWaJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyMwAKCRBTA5mu5fQxySJiB/_9HkMVbp8BLl9a8xkc+YIMjsDXeUD/DHctJI?= =?utf-8?q?ej9o90WQvjfYFOqnp97oRSL05awrVwXaUy4ay7+yCJS_h+TxM3omvveG14tjLJ3wC?= =?utf-8?q?yk3SZ5mQum5AyAut1Dx7GvAH+aKzPhZyyQZtT0nPq9vJ494NfMFXjQ5yJ_3S4b0Kc?= =?utf-8?q?fPnTHEeSpenRnG/gVjMR15wLsSE07DAnXfndDrwZ25uR9RNVxxoQ2/oIyPGlW9O4K?= =?utf-8?q?Zj8s0y_ApyXfbn7vle/qhUTdd10Mt0GITrja5wk0lSvSicVeS2eB1a7VlOSSCIz6P?= =?utf-8?q?Qhg2BEDCONPD+NTd0khr?= zlm1ANoVLdZpKoEkqw0ZUzJrM5jm8Z X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 mnt_idmapping.h uses declarations from cred.h, so it should include that file directly. Signed-off-by: Seth Forshee (DigitalOcean) --- include/linux/mnt_idmapping.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/mnt_idmapping.h b/include/linux/mnt_idmapping.h index 8b5e00ee6472..65e5d0c32fde 100644 --- a/include/linux/mnt_idmapping.h +++ b/include/linux/mnt_idmapping.h @@ -5,6 +5,7 @@ #include #include #include +#include struct mnt_idmap; struct user_namespace; From patchwork Wed Nov 29 21:50:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473560 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4EA393B1BE; Wed, 29 Nov 2023 21:50:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="fQIMu9V0" Received: by smtp.kernel.org (Postfix) with ESMTPS id BCC2EC433CC; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=TIgQ5CbkliqAVMldXf5Py2rYlW1ruP/xbtTpoJwKMY8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=fQIMu9V0oT8xUK0GL+HsYCv1d6LOK+fR4jAaYG8Do89RGP+xAS7dBjCHFKKlCb+9C lezD6IPNQGoRz+LXbUElA8DxWqLKijC0oA3S4flAeQAILZVmC4E+4i6aR4tPWvP8Yd 199/qQn8/qv0DO4UKHiGYgs8YDavd/NKnQCC+Y5Gn4Va2T44He7/pvBvafz38/2Lca tV7UWIJ0J87nZiWdQyi5ofbpPMxWL9VL6Q3cYoxQYbUUPtnCOUgJUA6MfrTtuU2p9Z 6rQlVXJe5XKOJHHk4sx4wYcgzIilxUqryDHbNXdas4D+z9VYj3B1gMvu/MMGV72ue/ 0E41N/P3bGGeg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5D51C10DC2; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:21 -0600 Subject: [PATCH 03/16] capability: rename cpu_vfs_cap_data to vfs_caps Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-3-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=3448; i=sforshee@kernel.org; h=from:subject:message-id; bh=TIgQ5CbkliqAVMldXf5Py2rYlW1ruP/xbtTpoJwKMY8=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I0nwuW1xpac3xkFjSxN46Ko?= =?utf-8?q?GJvViTQQr5z+iz5_Wk9fgqyJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyNAAKCRBTA5mu5fQxyaNwB/_9pyZQEBnedvrvYiYrFWuw3BEQLrhwzPeP+j?= =?utf-8?q?XU2KRZgr6vrzRbFlDtNuNLFIBATPoVujyOCLkUK7H+f_88lE3d/IbtjndsgxfUqO4?= =?utf-8?q?TK/qiimK2hWIqmPKh2moxUobyRKRFeZqZyjXt3tN73mRM6/6ip9yTWhXi_w9Tagm/?= =?utf-8?q?A2MzQBmlYG/S003GXBPgisL/bWyg0XaQMqt6pSFNEzG6a/OmHE+fIxUWKIQmNvfVn?= =?utf-8?q?XfwqH3_4xF2MKBcZI5Mi3fIVSJlEUD/7vjTTKelJa9ZqUYbjF+AL28JxwDjvHdvF0?= =?utf-8?q?VE5Rdweg/uJpBt9jyE1v?= 0o/JdYEKaL3Qh3x94fc5HOxAJ3GcBV X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 vfs_caps is a more generic name which is better suited to the broader use this struct will see in subsequent commits. Signed-off-by: Seth Forshee (DigitalOcean) Reviewed-by: Christian Brauner Acked-by: Paul Moore (Audit,LSM) --- include/linux/capability.h | 4 ++-- kernel/auditsc.c | 4 ++-- security/commoncap.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index 0c356a517991..c24477e660fc 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -24,7 +24,7 @@ extern int file_caps_enabled; typedef struct { u64 val; } kernel_cap_t; /* same as vfs_ns_cap_data but in cpu endian and always filled completely */ -struct cpu_vfs_cap_data { +struct vfs_caps { __u32 magic_etc; kuid_t rootid; kernel_cap_t permitted; @@ -211,7 +211,7 @@ static inline bool checkpoint_restore_ns_capable(struct user_namespace *ns) /* audit system wants to get cap info from files as well */ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, const struct dentry *dentry, - struct cpu_vfs_cap_data *cpu_caps); + struct vfs_caps *cpu_caps); int cap_convert_nscap(struct mnt_idmap *idmap, struct dentry *dentry, const void **ivalue, size_t size); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 6f0d6fb6523f..783d0bf69ca5 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2247,7 +2247,7 @@ void __audit_getname(struct filename *name) static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry) { - struct cpu_vfs_cap_data caps; + struct vfs_caps caps; int rc; if (!dentry) @@ -2800,7 +2800,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, { struct audit_aux_data_bprm_fcaps *ax; struct audit_context *context = audit_context(); - struct cpu_vfs_cap_data vcaps; + struct vfs_caps vcaps; ax = kmalloc(sizeof(*ax), GFP_KERNEL); if (!ax) diff --git a/security/commoncap.c b/security/commoncap.c index 8e8c630ce204..cf130d81b8b4 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -583,7 +583,7 @@ int cap_convert_nscap(struct mnt_idmap *idmap, struct dentry *dentry, * Calculate the new process capability sets from the capability sets attached * to a file. */ -static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, +static inline int bprm_caps_from_vfs_caps(struct vfs_caps *caps, struct linux_binprm *bprm, bool *effective, bool *has_fcap) @@ -634,7 +634,7 @@ static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps, */ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, const struct dentry *dentry, - struct cpu_vfs_cap_data *cpu_caps) + struct vfs_caps *cpu_caps) { struct inode *inode = d_backing_inode(dentry); __u32 magic_etc; @@ -645,7 +645,7 @@ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, vfsuid_t rootvfsuid; struct user_namespace *fs_ns; - memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); + memset(cpu_caps, 0, sizeof(struct vfs_caps)); if (!inode) return -ENODATA; @@ -724,7 +724,7 @@ static int get_file_caps(struct linux_binprm *bprm, const struct file *file, bool *effective, bool *has_fcap) { int rc = 0; - struct cpu_vfs_cap_data vcaps; + struct vfs_caps vcaps; cap_clear(bprm->cred->cap_permitted); From patchwork Wed Nov 29 21:50:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473546 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3115661688; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="co0OX5ej" Received: by smtp.kernel.org (Postfix) with ESMTPS id C45EEC433CA; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294657; bh=pshpKEfVriw6XfSjr2t+lrLZ+CyfWDF9L4xfhlBHrcs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=co0OX5ejSAjxdjCRGV053V24U5RgKX2l/Io7Vacy5dpOOz9UAwVIxRY1Pwi9qrSlO CUYKbNPcHTDCvKK8U1OMeLu9xt27bRtI9bLmGQ0GSjSX3CHoUVVho6/Lw4tNx1uELb JpZN+Fzg4axO3P5GFGGBXiBFhjM9o8rSxaSd6U8kJChzHLapD8trde+hTp+POUSeZX wUozMWHsXZFrZA/d5IuJaNirfQnsXY6138dKZvAlo0gNyODwmNAlD6sz3HVDu4UwYc X92xKVmx6eZa58uxzSUCBQtq1LNL9PeMvCjwR27WqpIOrGQz+NP0uiVzRB7RdLnUR4 WXzv8VJsDIPPg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id AE91BC46CA3; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:22 -0600 Subject: [PATCH 04/16] capability: use vfsuid_t for vfs_caps rootids Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-4-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=2769; i=sforshee@kernel.org; h=from:subject:message-id; bh=pshpKEfVriw6XfSjr2t+lrLZ+CyfWDF9L4xfhlBHrcs=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I1iMJZHgv5KLLN6DNVYz1Vf?= =?utf-8?q?vJSI5vw8+yI5Cgd_aAZEAPOJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyNQAKCRBTA5mu5fQxyQDFB/_9RqEyCcUph8c316tvppHNjQ/llSAMODIXsN?= =?utf-8?q?mSqJwy2aZcJXvBbUuIv4/NOLvqxn+j55KG7FdjvArP6_c28uf+EKMJh7cJKxKtKEy?= =?utf-8?q?zRdd4va3XJnkesTaNAJHo9zcx5lvZkMOBm6ZCiA29WXKAxqzadC/Vy+98_ztZZA0m?= =?utf-8?q?1c90VhmCi+uMTrJTwT6jdc1a43GfX/jcKBtSS/HL2EyRZdayOURPL8gQVezzv60r8?= =?utf-8?q?766ssp_4TLrCTABo8230NrJ7xA4Kg7tvAs7mtrvnBv2Q08sS71+xjhIXoYLYqGtmT?= =?utf-8?q?+k0Q0p8nB9TlHk06W9aH?= 6B7k5FVQmj3qXUOjyE3FbILXAuBOru X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 The rootid is a kuid_t, but it contains an id which maped into a mount idmapping, so it is really a vfsuid. This is confusing and creates potential for misuse of the value, so change it to vfsuid_t. Signed-off-by: Seth Forshee (DigitalOcean) Acked-by: Paul Moore (Audit,LSM) --- include/linux/capability.h | 3 ++- kernel/auditsc.c | 5 +++-- security/commoncap.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index c24477e660fc..eb46d346bbbc 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -16,6 +16,7 @@ #include #include #include +#include #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3 @@ -26,7 +27,7 @@ typedef struct { u64 val; } kernel_cap_t; /* same as vfs_ns_cap_data but in cpu endian and always filled completely */ struct vfs_caps { __u32 magic_etc; - kuid_t rootid; + vfsuid_t rootid; kernel_cap_t permitted; kernel_cap_t inheritable; }; diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 783d0bf69ca5..65691450b080 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -65,6 +65,7 @@ #include #include // struct open_how #include +#include #include "audit.h" @@ -2260,7 +2261,7 @@ static inline int audit_copy_fcaps(struct audit_names *name, name->fcap.permitted = caps.permitted; name->fcap.inheritable = caps.inheritable; name->fcap.fE = !!(caps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); - name->fcap.rootid = caps.rootid; + name->fcap.rootid = AS_KUIDT(caps.rootid); name->fcap_ver = (caps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; @@ -2816,7 +2817,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, ax->fcap.permitted = vcaps.permitted; ax->fcap.inheritable = vcaps.inheritable; ax->fcap.fE = !!(vcaps.magic_etc & VFS_CAP_FLAGS_EFFECTIVE); - ax->fcap.rootid = vcaps.rootid; + ax->fcap.rootid = AS_KUIDT(vcaps.rootid); ax->fcap_ver = (vcaps.magic_etc & VFS_CAP_REVISION_MASK) >> VFS_CAP_REVISION_SHIFT; ax->old_pcap.permitted = old->cap_permitted; diff --git a/security/commoncap.c b/security/commoncap.c index cf130d81b8b4..3d045d377e5e 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -710,7 +710,7 @@ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, cpu_caps->permitted.val &= CAP_VALID_MASK; cpu_caps->inheritable.val &= CAP_VALID_MASK; - cpu_caps->rootid = vfsuid_into_kuid(rootvfsuid); + cpu_caps->rootid = rootvfsuid; return 0; } From patchwork Wed Nov 29 21:50:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473548 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 311AB61690; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NmIQSuTT" Received: by smtp.kernel.org (Postfix) with ESMTPS id CE134C433D9; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294657; bh=rEZM0PVp6B4xr9cFfrir9S9tivQgwae/87tx7pQYtPw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NmIQSuTT5QABW/JM9mk4Y6P9IqsRbh1AzC7TDHw2ap1Ou9R3cR9btT4RkPSjIOuuy EJMOJeha2WSab01lzikLwTKIVVIbrOxsSyVfi2ur68DhB3sSRyS/HAQmSlyzwiV65X p7AN5s2GE9dGLp2Nm0lCgo3MIqtQAI9lF2TsyLmf8mQ4ryMla/LevCTcK/yCdzB/R4 52n1gBtMURFqRZu2S2pJGYlPDQEiZfVdKz6jnw4pQT8Te7g9OMkVGHyqgol7yCPamX cXNUriKk3mYwKcewEN+L6Yu7ZHluNhOqkIPCrj+sIM266M72LtGk/BVXNQBL7qjJ7X N453KCPlIjztg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B84B3C10DC1; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:23 -0600 Subject: [PATCH 05/16] capability: provide helpers for converting between xattrs and vfs_caps Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-5-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=11589; i=sforshee@kernel.org; h=from:subject:message-id; bh=rEZM0PVp6B4xr9cFfrir9S9tivQgwae/87tx7pQYtPw=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I1iss3rNLVl2UZBM57RVYLa?= =?utf-8?q?Y48HKiyLX7CxZzC_xrTaalGJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyNQAKCRBTA5mu5fQxyeN1B/_0V9hhGaEvf4zWw2QJxFgY9ooSXwAyqgF8q7?= =?utf-8?q?u/0pP1qeCQToOH5MCP+9GL/9or9GClN+MDte6u08N6b_ft/myKObUapwocQYB/j5W?= =?utf-8?q?LYhffMKM3uHmVSVg5NsjaMQSc6PUnOTdWTYGzzfdce3HspbTuOR7EncQI_xeaRiKU?= =?utf-8?q?m83jdh/6WfaZVRvhylVfFK1AhPjJ/ILEq7t3pbhsa/OJIK+SghFrw7dTieLooJCYw?= =?utf-8?q?REG1Fn_/veLK5ITbx2TnRQG2K1uzym3p++6IqBPatvdOxg1wdTMOANEF4aQ16rBRc?= =?utf-8?q?IGyr9j07GzOZK/aULGng?= 58hy3tcQeMYdFmBqVt8swRhcncbobk X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 To pass around vfs_caps instead of raw xattr data we will need to convert between the two representations near userspace and disk boundaries. We already convert xattrs from disks to vfs_caps, so move that code into a helper, and change get_vfs_caps_from_disk() to use the helper. When converting vfs_caps to xattrs we have different considerations depending on the destination of the xattr data. For xattrs which will be written to disk we need to reject the xattr if the rootid does not map into the filesystem's user namespace, whereas xattrs read by userspace may need to undergo a conversion from v3 to v2 format when the rootid does not map. So this helper is split into an internal and an external interface. The internal interface does not return an error if the rootid has no mapping in the target user namespace and will be used for conversions targeting userspace. The external interface returns EOVERFLOW if the rootid has no mapping and will be used for all other conversions. Signed-off-by: Seth Forshee (DigitalOcean) --- include/linux/capability.h | 10 ++ security/commoncap.c | 227 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 186 insertions(+), 51 deletions(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index eb46d346bbbc..cdd7d2d8855e 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -209,6 +209,16 @@ static inline bool checkpoint_restore_ns_capable(struct user_namespace *ns) ns_capable(ns, CAP_SYS_ADMIN); } +/* helpers to convert between xattr and in-kernel representations */ +int vfs_caps_from_xattr(struct mnt_idmap *idmap, + struct user_namespace *src_userns, + struct vfs_caps *vfs_caps, + const void *data, int size); +int vfs_caps_to_xattr(struct mnt_idmap *idmap, + struct user_namespace *dest_userns, + const struct vfs_caps *vfs_caps, + void *data, int size); + /* audit system wants to get cap info from files as well */ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, const struct dentry *dentry, diff --git a/security/commoncap.c b/security/commoncap.c index 3d045d377e5e..ef37966f3522 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -618,54 +618,41 @@ static inline int bprm_caps_from_vfs_caps(struct vfs_caps *caps, } /** - * get_vfs_caps_from_disk - retrieve vfs caps from disk + * vfs_caps_from_xattr - convert raw caps xattr data to vfs_caps * - * @idmap: idmap of the mount the inode was found from - * @dentry: dentry from which @inode is retrieved - * @cpu_caps: vfs capabilities + * @idmap: idmap of the mount the inode was found from + * @src_userns: user namespace for ids in xattr data + * @vfs_caps: destination buffer for vfs_caps data + * @data: rax xattr caps data + * @size: size of xattr data * - * Extract the on-exec-apply capability sets for an executable file. + * Converts a raw security.capability xattr into the kernel-internal + * capabilities format. * - * If the inode has been found through an idmapped mount the idmap of - * the vfsmount must be passed through @idmap. This function will then - * take care to map the inode according to @idmap before checking - * permissions. On non-idmapped mounts or if permission checking is to be - * performed on the raw inode simply pass @nop_mnt_idmap. + * If the xattr is being read or written through an idmapped mount the + * idmap of the vfsmount must be passed through @idmap. This function + * will then take care to map the rootid according to @idmap. + * + * Return: On success, return 0; on error, return < 0. */ -int get_vfs_caps_from_disk(struct mnt_idmap *idmap, - const struct dentry *dentry, - struct vfs_caps *cpu_caps) +int vfs_caps_from_xattr(struct mnt_idmap *idmap, + struct user_namespace *src_userns, + struct vfs_caps *vfs_caps, + const void *data, int size) { - struct inode *inode = d_backing_inode(dentry); __u32 magic_etc; - int size; - struct vfs_ns_cap_data data, *nscaps = &data; - struct vfs_cap_data *caps = (struct vfs_cap_data *) &data; + const struct vfs_ns_cap_data *ns_caps = data; + struct vfs_cap_data *caps = (struct vfs_cap_data *)ns_caps; kuid_t rootkuid; - vfsuid_t rootvfsuid; - struct user_namespace *fs_ns; - - memset(cpu_caps, 0, sizeof(struct vfs_caps)); - - if (!inode) - return -ENODATA; - fs_ns = inode->i_sb->s_user_ns; - size = __vfs_getxattr((struct dentry *)dentry, inode, - XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ); - if (size == -ENODATA || size == -EOPNOTSUPP) - /* no data, that's ok */ - return -ENODATA; - - if (size < 0) - return size; + memset(vfs_caps, 0, sizeof(*vfs_caps)); if (size < sizeof(magic_etc)) return -EINVAL; - cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps->magic_etc); + vfs_caps->magic_etc = magic_etc = le32_to_cpu(caps->magic_etc); - rootkuid = make_kuid(fs_ns, 0); + rootkuid = make_kuid(src_userns, 0); switch (magic_etc & VFS_CAP_REVISION_MASK) { case VFS_CAP_REVISION_1: if (size != XATTR_CAPS_SZ_1) @@ -678,39 +665,177 @@ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, case VFS_CAP_REVISION_3: if (size != XATTR_CAPS_SZ_3) return -EINVAL; - rootkuid = make_kuid(fs_ns, le32_to_cpu(nscaps->rootid)); + rootkuid = make_kuid(src_userns, le32_to_cpu(ns_caps->rootid)); break; default: return -EINVAL; } - rootvfsuid = make_vfsuid(idmap, fs_ns, rootkuid); - if (!vfsuid_valid(rootvfsuid)) - return -ENODATA; + vfs_caps->rootid = make_vfsuid(idmap, src_userns, rootkuid); + if (!vfsuid_valid(vfs_caps->rootid)) + return -EOVERFLOW; - /* Limit the caps to the mounter of the filesystem - * or the more limited uid specified in the xattr. + vfs_caps->permitted.val = le32_to_cpu(caps->data[0].permitted); + vfs_caps->inheritable.val = le32_to_cpu(caps->data[0].inheritable); + + /* + * Rev1 had just a single 32-bit word, later expanded + * to a second one for the high bits */ - if (!rootid_owns_currentns(rootvfsuid)) - return -ENODATA; + if ((magic_etc & VFS_CAP_REVISION_MASK) != VFS_CAP_REVISION_1) { + vfs_caps->permitted.val += (u64)le32_to_cpu(caps->data[1].permitted) << 32; + vfs_caps->inheritable.val += (u64)le32_to_cpu(caps->data[1].inheritable) << 32; + } + + vfs_caps->permitted.val &= CAP_VALID_MASK; + vfs_caps->inheritable.val &= CAP_VALID_MASK; + + return 0; +} + +/* + * Inner implementation of vfs_caps_to_xattr() which does not return an + * error if the rootid does not map into @dest_userns. + */ +static int __vfs_caps_to_xattr(struct mnt_idmap *idmap, + struct user_namespace *dest_userns, + const struct vfs_caps *vfs_caps, + void *data, int size) +{ + struct vfs_ns_cap_data *ns_caps = data; + struct vfs_cap_data *caps = (struct vfs_cap_data *)ns_caps; + kuid_t rootkuid; + uid_t rootid; + + memset(ns_caps, 0, size); + + rootid = 0; + switch (vfs_caps->magic_etc & VFS_CAP_REVISION_MASK) { + case VFS_CAP_REVISION_1: + if (size < XATTR_CAPS_SZ_1) + return -EINVAL; + size = XATTR_CAPS_SZ_1; + break; + case VFS_CAP_REVISION_2: + if (size < XATTR_CAPS_SZ_2) + return -EINVAL; + size = XATTR_CAPS_SZ_2; + break; + case VFS_CAP_REVISION_3: + if (size < XATTR_CAPS_SZ_3) + return -EINVAL; + size = XATTR_CAPS_SZ_3; + rootkuid = from_vfsuid(idmap, dest_userns, vfs_caps->rootid); + rootid = from_kuid(dest_userns, rootkuid); + ns_caps->rootid = cpu_to_le32(rootid); + break; - cpu_caps->permitted.val = le32_to_cpu(caps->data[0].permitted); - cpu_caps->inheritable.val = le32_to_cpu(caps->data[0].inheritable); + default: + return -EINVAL; + } + + caps->magic_etc = cpu_to_le32(vfs_caps->magic_etc); + + caps->data[0].permitted = cpu_to_le32(lower_32_bits(vfs_caps->permitted.val)); + caps->data[0].inheritable = cpu_to_le32(lower_32_bits(vfs_caps->inheritable.val)); /* * Rev1 had just a single 32-bit word, later expanded * to a second one for the high bits */ - if ((magic_etc & VFS_CAP_REVISION_MASK) != VFS_CAP_REVISION_1) { - cpu_caps->permitted.val += (u64)le32_to_cpu(caps->data[1].permitted) << 32; - cpu_caps->inheritable.val += (u64)le32_to_cpu(caps->data[1].inheritable) << 32; + if ((vfs_caps->magic_etc & VFS_CAP_REVISION_MASK) != VFS_CAP_REVISION_1) { + caps->data[1].permitted = + cpu_to_le32(upper_32_bits(vfs_caps->permitted.val)); + caps->data[1].inheritable = + cpu_to_le32(upper_32_bits(vfs_caps->inheritable.val)); } - cpu_caps->permitted.val &= CAP_VALID_MASK; - cpu_caps->inheritable.val &= CAP_VALID_MASK; + return size; +} + + +/** + * vfs_caps_to_xattr - convert vfs_caps to raw caps xattr data + * + * @idmap: idmap of the mount the inode was found from + * @dest_userns: user namespace for ids in xattr data + * @vfs_caps: source vfs_caps data + * @data: destination buffer for rax xattr caps data + * @size: size of the @data buffer + * + * Converts a kernel-interrnal capability into the raw security.capability + * xattr format. + * + * If the xattr is being read or written through an idmapped mount the + * idmap of the vfsmount must be passed through @idmap. This function + * will then take care to map the rootid according to @idmap. + * + * Return: On success, return 0; on error, return < 0. + */ +int vfs_caps_to_xattr(struct mnt_idmap *idmap, + struct user_namespace *dest_userns, + const struct vfs_caps *vfs_caps, + void *data, int size) +{ + struct vfs_ns_cap_data *caps = data; + int ret; + + ret = __vfs_caps_to_xattr(idmap, dest_userns, vfs_caps, data, size); + if (ret > 0 && + (vfs_caps->magic_etc & VFS_CAP_REVISION_MASK) == VFS_CAP_REVISION_3 && + le32_to_cpu(caps->rootid) == (uid_t)-1) + return -EOVERFLOW; + return ret; +} + +/** + * get_vfs_caps_from_disk - retrieve vfs caps from disk + * + * @idmap: idmap of the mount the inode was found from + * @dentry: dentry from which @inode is retrieved + * @cpu_caps: vfs capabilities + * + * Extract the on-exec-apply capability sets for an executable file. + * + * If the inode has been found through an idmapped mount the idmap of + * the vfsmount must be passed through @idmap. This function will then + * take care to map the inode according to @idmap before checking + * permissions. On non-idmapped mounts or if permission checking is to be + * performed on the raw inode simply pass @nop_mnt_idmap. + */ +int get_vfs_caps_from_disk(struct mnt_idmap *idmap, + const struct dentry *dentry, + struct vfs_caps *cpu_caps) +{ + struct inode *inode = d_backing_inode(dentry); + int size, ret; + struct vfs_ns_cap_data data, *nscaps = &data; + + if (!inode) + return -ENODATA; - cpu_caps->rootid = rootvfsuid; + size = __vfs_getxattr((struct dentry *)dentry, inode, + XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ); + if (size == -ENODATA || size == -EOPNOTSUPP) + /* no data, that's ok */ + return -ENODATA; + + if (size < 0) + return size; + + ret = vfs_caps_from_xattr(idmap, inode->i_sb->s_user_ns, + cpu_caps, nscaps, size); + if (ret == -EOVERFLOW) + return -ENODATA; + if (ret) + return ret; + + /* Limit the caps to the mounter of the filesystem + * or the more limited uid specified in the xattr. + */ + if (!rootid_owns_currentns(cpu_caps->rootid)) + return -ENODATA; return 0; } From patchwork Wed Nov 29 21:50:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473550 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D87761FB5; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MQlYzNKm" Received: by smtp.kernel.org (Postfix) with ESMTPS id D4985C43397; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294657; bh=rQN1xLGeld4j4IW55z8ld7WdVy/2BRoKQW9LSljn2x0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=MQlYzNKmwllaE+g7Kiw69evrBe9kNjK/CFcpROSwzp+Xfc4dVrwcJXdbUE4rGhXeH jjr2KAwWQBZuDhTQkr6VU3G3xzjHSquVC4gEpLt+3uoJ9G7g4S3Yo+PkRPPdEg5kJZ FPbWRnnRwIEHGMJlnMNMpiSb6DzULhg4U5j5PNrGJIeEaOowYLgjK1R6+bWD0L/FjD d5fEZuaiAoQhcK5PaSvLnqV3JK/tfCRM3/BW9QQOsXdAJaTBLJAJ18+k9N6RE8nIIY c2cG3cPzEFv7ONmYwlQTEjLTQbMltr1Da/eENDa2ApaicEVp7H7lGEjmqKHmxrfvgy yInCUeH8TZr3w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C11B6C07CB1; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:24 -0600 Subject: [PATCH 06/16] capability: provide a helper for converting vfs_caps to xattr for userspace Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-6-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=4302; i=sforshee@kernel.org; h=from:subject:message-id; bh=rQN1xLGeld4j4IW55z8ld7WdVy/2BRoKQW9LSljn2x0=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I2DU3K3tsTu4Nh8wDOr9uJU?= =?utf-8?q?4ZS6gYIJ3xT83+V_4MHJNZuJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyNgAKCRBTA5mu5fQxyYcPB/_oCnDaCsGtlI83YM/2/wsWTJyD+0FVcqwnJX?= =?utf-8?q?JNLK440u0oY9qYSciy1oqdWpmygdZisDX+oEpTIOJlA_52I9g7hW/k6g9hGzYDRJU?= =?utf-8?q?VL5z6MsXIuwFz2jRII3hPjri3Rg5X6dgmQW4+HS0g00Gvj66S0WCBY4C1_BYZK9uo?= =?utf-8?q?Y4vkbYHxH6wTyU9BwZtLIIqKedD9n9HB7CM9eWan/UXNjK4Dm8ULZsgbVLp/06oU+?= =?utf-8?q?UfBaYt_a2HVuGd1xWx1kbMJqiFhZ1Gu61AOG2ByjQ4YwRvaNwUKzQcYjYKSuCGWaa?= =?utf-8?q?nqvqsXumbDoNi6naMlwM?= DC44ra2po4L1NPdaT9HLGdiUjQS6Aj X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 cap_inode_getsecurity() implements a handful of policies for capability xattrs read by userspace: - It returns EINVAL if the on-disk capability is in v1 format. - It masks off all bits in magic_etc except for the version and VFS_CAP_FLAGS_EFFECTIVE. - v3 capabilities are converted to v2 format if the rootid returned to userspace would be 0 or if the rootid corresponds to root in an ancestor user namespace. - It returns EOVERFLOW for a v3 capability whose rootid does not map to a valid id in current_user_ns() or to root in an ancestor namespace. These policies must be maintained when converting vfs_caps to an xattr for userspace. Provide a vfs_caps_to_user_xattr() helper which will enforce these policies. Signed-off-by: Seth Forshee (DigitalOcean) --- include/linux/capability.h | 4 +++ security/commoncap.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/include/linux/capability.h b/include/linux/capability.h index cdd7d2d8855e..c0bd9447685b 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -218,6 +218,10 @@ int vfs_caps_to_xattr(struct mnt_idmap *idmap, struct user_namespace *dest_userns, const struct vfs_caps *vfs_caps, void *data, int size); +int vfs_caps_to_user_xattr(struct mnt_idmap *idmap, + struct user_namespace *dest_userns, + const struct vfs_caps *vfs_caps, + void *data, int size); /* audit system wants to get cap info from files as well */ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, diff --git a/security/commoncap.c b/security/commoncap.c index ef37966f3522..c645330f83a0 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -789,6 +789,74 @@ int vfs_caps_to_xattr(struct mnt_idmap *idmap, return ret; } +/** + * vfs_caps_to_user_xattr - convert vfs_caps to caps xattr for userspace + * + * @idmap: idmap of the mount the inode was found from + * @dest_userns: user namespace for ids in xattr data + * @vfs_caps: source vfs_caps data + * @data: destination buffer for rax xattr caps data + * @size: size of the @data buffer + * + * Converts a kernel-interrnal capability into the raw security.capability + * xattr format. Includes permission checking and v2->v3 conversion as + * appropriate. + * + * If the xattr is being read or written through an idmapped mount the + * idmap of the vfsmount must be passed through @idmap. This function + * will then take care to map the rootid according to @idmap. + * + * Return: On success, return 0; on error, return < 0. + */ +int vfs_caps_to_user_xattr(struct mnt_idmap *idmap, + struct user_namespace *dest_userns, + const struct vfs_caps *vfs_caps, + void *data, int size) +{ + struct vfs_ns_cap_data *ns_caps = data; + bool is_v3; + u32 magic; + + /* Preserve previous behavior of returning EINVAL for v1 caps */ + if ((vfs_caps->magic_etc & VFS_CAP_REVISION_MASK) == VFS_CAP_REVISION_1) + return -EINVAL; + + size = __vfs_caps_to_xattr(idmap, dest_userns, vfs_caps, data, size); + if (size < 0) + return size; + + magic = vfs_caps->magic_etc & + (VFS_CAP_REVISION_MASK | VFS_CAP_FLAGS_EFFECTIVE); + ns_caps->magic_etc = cpu_to_le32(magic); + + /* + * If this is a v3 capability with a valid, non-zero rootid, return + * the v3 capability to userspace. A v3 capability with a rootid of + * 0 will be converted to a v2 capability below for compatibility + * with old userspace. + */ + is_v3 = (vfs_caps->magic_etc & VFS_CAP_REVISION_MASK) == VFS_CAP_REVISION_3; + if (is_v3) { + uid_t rootid = le32_to_cpu(ns_caps->rootid); + if (rootid != (uid_t)-1 && rootid != (uid_t)0) + return size; + } + + if (!rootid_owns_currentns(vfs_caps->rootid)) + return -EOVERFLOW; + + /* This comes from a parent namespace. Return as a v2 capability. */ + if (is_v3) { + magic = VFS_CAP_REVISION_2 | + (vfs_caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE); + ns_caps->magic_etc = cpu_to_le32(magic); + ns_caps->rootid = cpu_to_le32(0); + size = XATTR_CAPS_SZ_2; + } + + return size; +} + /** * get_vfs_caps_from_disk - retrieve vfs caps from disk * From patchwork Wed Nov 29 21:50:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473551 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5A96E61FA8; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="JhBEZ/6P" Received: by smtp.kernel.org (Postfix) with ESMTPS id DF7E4C433AB; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294657; bh=a3Y6lynq44wXodnU5zT/TB2mw/YUwehyzd+izLi+710=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JhBEZ/6PLgihMSRnoKSzznrVZA5XVGhQYgyCRimavQ0hBFN2pHRljsvYLtD0vX49I 5V4HYEB1+nw1uUY6tiwEa/cnwsD655UJLuIzjnqj5e3l/BTx8FGYNdEiwdh5UfdkSb 4fdzq1KkO+m8kvgVnsJUtYfg/eoocSNFQ5HBKSVAn3ut19I16C0+HNzjheoxXa9oaV YNS+lso1WXhSIdz4V5Q3C5NCzXa/liYZo7tJpHSeHQP0Ilc0WTZy38w9nClxz+pzlA y/o6/RhcvQ14o+kdoXv/ozlhhbT7XvuSacub39Ld9CU8Yb+NMZTGb81AWKO5UFxBFw rqfJTCYEnM5VA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB2D8C4167B; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:25 -0600 Subject: [PATCH 07/16] fs: add inode operations to get/set/remove fscaps Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-7-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=1071; i=sforshee@kernel.org; h=from:subject:message-id; bh=a3Y6lynq44wXodnU5zT/TB2mw/YUwehyzd+izLi+710=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I3jkGX0ENxe+x6fg9biSGvz?= =?utf-8?q?faFH0+OzJVRhGL1_4G7+T7mJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyNwAKCRBTA5mu5fQxyeKuB/_9fSGpP5pXSOyn3UkRq6j9l/2nr77wJO5nHS?= =?utf-8?q?UPVLP5ZWjfcO8vezbperL5n23B6ppF7zSRWMWMK8nc5_RyyQRhW+2y60KxF7sGRyY?= =?utf-8?q?hAI434prSE8W5pSf7yj0IjuslabYuvpSVW+1aVPcpLrgHoOlZv0fINTDT_aB0X2HD?= =?utf-8?q?zovSJwmMjrbaV8xmVzw6wxyxc+ag8dHIAe+9FYPtEAJc6orS+tYRHGIVwsIgR682Z?= =?utf-8?q?djQ5TQ_Rb5zjFwxxkGdTu/udnpVVQb4YujdB+Ds6VuSdPXJOtS8eiLFpJX9NWsGs5?= =?utf-8?q?pUJ8RMEjmOBT9Ds0S0uR?= 41HDfP0hKQ7rUTwY1jLx6IQL3V59Sf X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Add inode operations for getting, setting and removing filesystem capabilities rather than passing around raw xattr data. This provides better type safety for ids contained within xattrs. Signed-off-by: Seth Forshee (DigitalOcean) Reviewed-by: Christian Brauner --- include/linux/fs.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index 98b7a7a8c42e..a0a77f67b999 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2002,6 +2002,11 @@ struct inode_operations { int); int (*set_acl)(struct mnt_idmap *, struct dentry *, struct posix_acl *, int); + int (*get_fscaps)(struct mnt_idmap *, struct dentry *, + struct vfs_caps *); + int (*set_fscaps)(struct mnt_idmap *, struct dentry *, + const struct vfs_caps *, int flags); + int (*remove_fscaps)(struct mnt_idmap *, struct dentry *); int (*fileattr_set)(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa); int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa); From patchwork Wed Nov 29 21:50:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473552 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7C8A761FB4; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="ZCKANpzA" Received: by smtp.kernel.org (Postfix) with ESMTPS id E4CFEC433A9; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294657; bh=+rNu+aEJtyNDKr3Mz+sg00VpaKJj7LN1+EUYKCn22bc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ZCKANpzAjVN+iZhP0a6dpqp1xM6AJIp2C/3VFbXbPYlklUhPNfzkn7v5VbXxJQC6K tG9adpxF0Ec+kk2XBpQKlvQ8nOZM8jViq/EUplejF8Ou74+FGM8NfvmloHfXpcJWyK PEUQuZHqvIGBnfWoR5GC9oEFQT/S8Db+3lCwLHiWRA7O75lHulk+06FP0AAG6ps/W4 LFnbaTUFtdTWirRytgxK7jlaOPlsU4ZjJScsstI8DQzYfzilT/jO/Nbir0wlEHQiOg gWdY5zqroFCJ85q5h1BLBB+tC9Htz3qr+N/JSJBmoFz0UBeXD9nKePkkkoNIOEXgaW 7Fn8kko3KkrXA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4AABC10DC3; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:26 -0600 Subject: [PATCH 08/16] fs: add vfs_get_fscaps() Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-8-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=3647; i=sforshee@kernel.org; h=from:subject:message-id; bh=+rNu+aEJtyNDKr3Mz+sg00VpaKJj7LN1+EUYKCn22bc=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I4/avu6/WjMpQysJRD4e086?= =?utf-8?q?dAG/Cwb8KohO3Og_fd3i1iGJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyOAAKCRBTA5mu5fQxyUF1B/_9oQr2DVGypJwRSipJa6KV9qSjXlv20xo0hN?= =?utf-8?q?hsSFvuH9Ach0ImZwoiRJyWGJTQ1qBcQPq7seTQQ+7B+_S2dK266E1ICJEoRmy+cIe?= =?utf-8?q?8P+BJme5M6yUAyFiSPqel1NPeKIbMFIGG6LST8fWtudf6UinqfhFZKyvd_qE1ALWh?= =?utf-8?q?6jQ12XE2xqlEPn0/tDpmo8eT7EU0F0z5LdbBiLGrQIQwMQpHnldwMwrCZkrjFnViq?= =?utf-8?q?2fZbAj_wzu2f79hmFumu4lFZ7Y4Gtb7CrOmipp/+6R4MsVmbtiaiiDpWIn3MrIlDO?= =?utf-8?q?0ivXbVWESxV66lWPdbWZ?= CcbdRRuAOliiqvt4XyKPp1qO4gEpFI X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Provide a type-safe interface for retrieving filesystem capabilities and a generic implementation suitable for most filesystems. Also add an internal interface, __vfs_get_fscaps(), which skips security checks for later use from the capability code. Signed-off-by: Seth Forshee (DigitalOcean) --- fs/xattr.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 4 ++++ 2 files changed, 70 insertions(+) diff --git a/fs/xattr.c b/fs/xattr.c index 09d927603433..3abaf9bef0a5 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -181,6 +181,72 @@ xattr_supports_user_prefix(struct inode *inode) } EXPORT_SYMBOL(xattr_supports_user_prefix); +static int generic_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + struct vfs_caps *caps) +{ + struct inode *inode = d_inode(dentry); + struct vfs_ns_cap_data *nscaps = NULL; + int ret; + + ret = (int)vfs_getxattr_alloc(idmap, dentry, XATTR_NAME_CAPS, + (char **)&nscaps, 0, GFP_NOFS); + + if (ret >= 0) + ret = vfs_caps_from_xattr(idmap, i_user_ns(inode), caps, nscaps, ret); + + kfree(nscaps); + return ret; +} + +/** + * __vfs_get_fscaps - get filesystem capabilities without security checks + * @idmap: idmap of the mount the inode was found from + * @dentry: the dentry from which to get filesystem capabilities + * @caps: storage in which to return the filesystem capabilities + * + * This function gets the filesystem capabilities for the dentry and returns + * them in @caps. It does not perform security checks. + * + * Return: 0 on success, a negative errno on error. + */ +int __vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + struct vfs_caps *caps) +{ + struct inode *inode = d_inode(dentry); + + if (inode->i_op->get_fscaps) + return inode->i_op->get_fscaps(idmap, dentry, caps); + return generic_get_fscaps(idmap, dentry, caps); +} + +/** + * vfs_get_fscaps - get filesystem capabilities + * @idmap: idmap of the mount the inode was found from + * @dentry: the dentry from which to get filesystem capabilities + * @caps: storage in which to return the filesystem capabilities + * + * This function gets the filesystem capabilities for the dentry and returns + * them in @caps. + * + * Return: 0 on success, a negative errno on error. + */ +int vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + struct vfs_caps *caps) +{ + int error; + + /* + * The VFS has no restrictions on reading security.* xattrs, so + * xattr_permission() isn't needed. Only LSMs get a say. + */ + error = security_inode_getxattr(dentry, XATTR_NAME_CAPS); + if (error) + return error; + + return __vfs_get_fscaps(idmap, dentry, caps); +} +EXPORT_SYMBOL(vfs_get_fscaps); + int __vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, struct inode *inode, const char *name, const void *value, diff --git a/include/linux/fs.h b/include/linux/fs.h index a0a77f67b999..e25b39e4017a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2055,6 +2055,10 @@ extern int vfs_dedupe_file_range(struct file *file, extern loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, struct file *dst_file, loff_t dst_pos, loff_t len, unsigned int remap_flags); +extern int __vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + struct vfs_caps *caps); +extern int vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + struct vfs_caps *caps); enum freeze_holder { FREEZE_HOLDER_KERNEL = (1U << 0), From patchwork Wed Nov 29 21:50:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473549 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6064061FAA; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IQYgSQK0" Received: by smtp.kernel.org (Postfix) with ESMTPS id EF221C433B7; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=9l5fqS0lfJcyX9vw4KCwkH1iHUQkPeV3R9q3VUBroWs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IQYgSQK0pjlDeUfAOU+8q6ndpXVAyYjkBW/EBI9sJFhWeFw9Tvj3jwNKBDjHQyWnA VXcMrksi0rZtOClt3p6ZcHM9/pBXOFY8xerzuDT23qhUPFua+G/eVu/2i0QNmXKdug gx/8poeaFAh5nE3fw7VBptk32UWFhScfBLo+BDtQ+v8MMQu4eiCSe0TDahbpaTQ9rc /LiWbySBCR/5nMjUcU6i7PQbs7dlqgVrA+7D/iu2Z6lIfvv9NwqYwLn/607xp8WYei f+oQRLAbwIAzJaoEVRGD+H1r55Veg+aNejGYE4iIfxYFxOAQPe1fNWcDP5/zIOXDBy ngOwgB/FrO02g== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE140C10DCE; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:27 -0600 Subject: [PATCH 09/16] fs: add vfs_set_fscaps() Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-9-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=3947; i=sforshee@kernel.org; h=from:subject:message-id; bh=9l5fqS0lfJcyX9vw4KCwkH1iHUQkPeV3R9q3VUBroWs=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I5R91Ab7BjTptx2E/V9ecRY?= =?utf-8?q?anz35z2BVyB57QQ_pm6SV2CJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyOQAKCRBTA5mu5fQxyfZwB/_45NtsnoK+BQ3Ly7m1AOvL3fWkADguQcZ36J?= =?utf-8?q?nrA/kmjz3u4R5+qB6Yfz1HQjo9g8MKR2mZh7D9itHuQ_J9jpu/t0jdnNDwSedgG6j?= =?utf-8?q?1ZHUfOoVKnmbpy4xKtahohtVRS9xaQ4ziaxHBG81RRmuc2MXeVApFQN5c_wFrL74w?= =?utf-8?q?gMl1inxRy4/s59AR/BlT6QYXtatl6m5zLBDAOxUwlbvU5rp1tLUiHl4C4B8gbor1E?= =?utf-8?q?TNEome_MyjCTJLeAZrx1p7mnXZR6XWf9/qYQZOz2VSqIq48NsMSLPxTl1svnt64tZ?= =?utf-8?q?1qAm91QCQkjx8eBPjRIC?= Qkx/iwFGKwS+YSpydOUNvpJY2tdx/L X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Provide a type-safe interface for setting filesystem capabilities and a generic implementation suitable for most filesystems. Signed-off-by: Seth Forshee (DigitalOcean) --- fs/xattr.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 ++ 2 files changed, 89 insertions(+) diff --git a/fs/xattr.c b/fs/xattr.c index 3abaf9bef0a5..03cc824e4f87 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -247,6 +247,93 @@ int vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, } EXPORT_SYMBOL(vfs_get_fscaps); +static int generic_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + const struct vfs_caps *caps, int flags) +{ + struct inode *inode = d_inode(dentry); + struct vfs_ns_cap_data nscaps; + int size; + + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, + &nscaps, sizeof(nscaps)); + if (size < 0) + return size; + + return __vfs_setxattr_noperm(idmap, dentry, XATTR_NAME_CAPS, + &nscaps, size, flags); +} + +/** + * vfs_set_fscaps - set filesystem capabilities + * @idmap: idmap of the mount the inode was found from + * @dentry: the dentry on which to set filesystem capabilities + * @caps: the filesystem capabilities to be written + * @flags: setxattr flags to use when writing the capabilities xattr + * + * This function writes the supplied filesystem capabilities to the dentry. + * + * Return: 0 on success, a negative errno on error. + */ +int vfs_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + const struct vfs_caps *caps, int flags) +{ + struct inode *inode = d_inode(dentry); + struct inode *delegated_inode = NULL; + struct vfs_ns_cap_data nscaps; + int size, error; + + /* + * Unfortunately EVM wants to have the raw xattr value to compare to + * the on-disk version, so we need to pass the raw xattr to the + * security hooks. But we also want to do security checks before + * breaking leases, so that means a conversion to the raw xattr here + * which will usually be reduntant with the conversion we do for + * writing the xattr to disk. + */ + size = vfs_caps_to_xattr(idmap, i_user_ns(inode), caps, &nscaps, + sizeof(nscaps)); + if (size < 0) + return size; + +retry_deleg: + inode_lock(inode); + + error = xattr_permission(idmap, inode, XATTR_NAME_CAPS, MAY_WRITE); + if (error) + goto out_inode_unlock; + error = security_inode_setxattr(idmap, dentry, XATTR_NAME_CAPS, &nscaps, + size, flags); + if (error) + goto out_inode_unlock; + + error = try_break_deleg(inode, &delegated_inode); + if (error) + goto out_inode_unlock; + + if (inode->i_opflags & IOP_XATTR) { + if (inode->i_op->set_fscaps) + error = inode->i_op->set_fscaps(idmap, dentry, caps, flags); + else + error = generic_set_fscaps(idmap, dentry, caps, flags); + } else if (unlikely(is_bad_inode(inode))) { + error = -EIO; + } else { + error = -EOPNOTSUPP; + } + +out_inode_unlock: + inode_unlock(inode); + + if (delegated_inode) { + error = break_deleg_wait(&delegated_inode); + if (!error) + goto retry_deleg; + } + + return error; +} +EXPORT_SYMBOL(vfs_set_fscaps); + int __vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, struct inode *inode, const char *name, const void *value, diff --git a/include/linux/fs.h b/include/linux/fs.h index e25b39e4017a..80992e210b83 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2059,6 +2059,8 @@ extern int __vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, struct vfs_caps *caps); extern int vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, struct vfs_caps *caps); +extern int vfs_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + const struct vfs_caps *caps, int flags); enum freeze_holder { FREEZE_HOLDER_KERNEL = (1U << 0), From patchwork Wed Nov 29 21:50:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473557 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8896361FC2; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="kmCkgtjR" Received: by smtp.kernel.org (Postfix) with ESMTPS id 033B2C433BA; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=RKuTcbYgZvHVKggTHC2zuvdJ26QENxjmgCweIZ3eegk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kmCkgtjRpxDsMEC0ScFiG7Rywqww7dZDZdR+Pvl32kQYeYkBhGbMSQ5A15W+uVQAp zIU/dIEFszza21uQmGoWrZTNZOwdsKbhCNSWZEkfc/gNsaPlyBQiFbcyyQLvkIECRG O2tXZprWsHPVckIsbdUyITzR4EIteUYDgn4DqMFwCawFTVm3RDkU8Lr+sNYYhs2lCf JN0dIJ0OIL/kLZy3QYqigqL3elHHlVqRoeBjGiU3O/BUOZLcYzmLdWpTpFHGHg+hoF gPc/oBvA+YOpi1ZYy+wbesrPM9mwGAGCu1dsm217JRrW67zGDbe7G7UZdsMhJk9m+X /OfUFmXZuGZYg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6CDEC10F04; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:28 -0600 Subject: [PATCH 10/16] fs: add vfs_remove_fscaps() Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-10-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=3668; i=sforshee@kernel.org; h=from:subject:message-id; bh=RKuTcbYgZvHVKggTHC2zuvdJ26QENxjmgCweIZ3eegk=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I64UBhX2GGFexH+bBTTpHN+?= =?utf-8?q?1ZZSs/s9GteH5Ya_Ao5bAXqJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyOgAKCRBTA5mu5fQxyZvhB/_9/0OH7uhQCHOgqtW6u1AsBk1GTbo0kK20Cn?= =?utf-8?q?bD4KJ5wbBLk1DZBgcWkKnbOEwoDBTbsYps5A36R5VNO_+3Jq2pg5sBcXDPdXt43p2?= =?utf-8?q?/gfipt41G5bIASpTWS8pnm/RFRtLvNURjT8VLyGrEcrY9H85teLbZ2qyC_PHy7qr5?= =?utf-8?q?+BlZwhbvKU3JmBQSjSS4CAP2nzCOumOJGM3t2SeYGZK15fNVExtZSKfg+ueOdR9Bc?= =?utf-8?q?eWrP2U_3Vp+H5E9v+M/1Sl3vEwEAdBaicRWTe69HeZD0cn0is1XhMgEf3iu940R8R?= =?utf-8?q?LLSo97mWrtbmWNopBk91?= XzbOBlAStUH2Ld9boVsTifWqMzAAuI X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Provide a type-safe interface for removing filesystem capabilities and a generic implementation suitable for most filesystems. Also add an internal interface, __vfs_remove_fscaps(), which is called with the inode lock held and skips security checks for later use from the capability code. Signed-off-by: Seth Forshee (DigitalOcean) --- fs/xattr.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 2 ++ 2 files changed, 79 insertions(+) diff --git a/fs/xattr.c b/fs/xattr.c index 03cc824e4f87..f60ef2a79dfa 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -334,6 +334,83 @@ int vfs_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, } EXPORT_SYMBOL(vfs_set_fscaps); +static int generic_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry) +{ + return __vfs_removexattr(idmap, dentry, XATTR_NAME_CAPS); +} + +/** + * __vfs_remove_fscaps - remove filesystem capabilities without security checks + * @idmap: idmap of the mount the inode was found from + * @dentry: the dentry from which to remove filesystem capabilities + * + * This function removes any filesystem capabilities from the specified + * dentry. Does not perform any security checks, and callers must hold the + * inode lock. + * + * Return: 0 on success, a negative errno on error. + */ +int __vfs_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + int error; + + if (inode->i_op->remove_fscaps) + error = inode->i_op->remove_fscaps(idmap, dentry); + else + error = generic_remove_fscaps(idmap, dentry); + + return error; +} + +/** + * vfs_remove_fscaps - remove filesystem capabilities + * @idmap: idmap of the mount the inode was found from + * @dentry: the dentry from which to remove filesystem capabilities + * + * This function removes any filesystem capabilities from the specified + * dentry. + * + * Return: 0 on success, a negative errno on error. + */ +int vfs_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct inode *delegated_inode = NULL; + int error; + +retry_deleg: + inode_lock(inode); + + error = xattr_permission(idmap, inode, XATTR_NAME_CAPS, MAY_WRITE); + if (error) + goto out_inode_unlock; + + error = security_inode_removexattr(idmap, dentry, XATTR_NAME_CAPS); + if (error) + goto out_inode_unlock; + + error = try_break_deleg(inode, &delegated_inode); + if (error) + goto out_inode_unlock; + + error = __vfs_remove_fscaps(idmap, dentry); + if (!error) + fsnotify_xattr(dentry); + +out_inode_unlock: + inode_unlock(inode); + + if (delegated_inode) { + error = break_deleg_wait(&delegated_inode); + if (!error) + goto retry_deleg; + } + + return error; +} +EXPORT_SYMBOL(vfs_remove_fscaps); + int __vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, struct inode *inode, const char *name, const void *value, diff --git a/include/linux/fs.h b/include/linux/fs.h index 80992e210b83..057bad11a4e6 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2061,6 +2061,8 @@ extern int vfs_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, struct vfs_caps *caps); extern int vfs_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, const struct vfs_caps *caps, int flags); +extern int __vfs_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry); +extern int vfs_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry); enum freeze_holder { FREEZE_HOLDER_KERNEL = (1U << 0), From patchwork Wed Nov 29 21:50:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473556 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 88A2361FC3; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="f3MAsD0z" Received: by smtp.kernel.org (Postfix) with ESMTPS id 10634C433BD; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=BwiWRhULdTol/9WEQmsxas2IytUWyM/ogSTWu44qpJw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=f3MAsD0zheGFbZNJ+GXDyZ7/ou//Kjnf7ivaXYr+ehAMn9o19Ts4BPD7C5nQjAjRm xoUUTmsi4G3MXY6ZUDXhTgHAKOUGkO5D0Y9MuyCSgsJXdLvlCzD/h9Yzhv+ADSgnBB XIKVqx0Zna/zq4WrvG1GGu5tmskyUvwpyAy6x2BjoSo5w15DsKjs5kjY2jPKnWz6OC WKel1lFqjSZvRLQv9du9h9nz+8BYGcfyMbBkJ5RrrhNCfmEEUKoDvShArk0sJkbwBm Af0brTePkJDCFabnM45bg1InXhMQRV93z62+e2w2ojzuWVhv2U3qBMJd5vC48vlhth jgAc+wJK4jyJw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2E2BC10DC1; Wed, 29 Nov 2023 21:50:57 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:29 -0600 Subject: [PATCH 11/16] ovl: add fscaps handlers Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-11-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=4821; i=sforshee@kernel.org; h=from:subject:message-id; bh=BwiWRhULdTol/9WEQmsxas2IytUWyM/ogSTWu44qpJw=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I6iAocplR2q2+fuSg1ko4e7?= =?utf-8?q?Kz+2lEulIyGRTZ8_n3DgHXeJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyOgAKCRBTA5mu5fQxyUobB/_9cVA5ptITHzeEzm+RIQcQADfXChKCFVQKeA?= =?utf-8?q?6bHZok/18cgOkQk/26rzwsL5XdFD7fnv2bCrU9vRIRb_30Z1oMUu1lq4adrgGuw0I?= =?utf-8?q?hCsLbdY3Sh8o4KKBSqJXlYhMK3FpLMpV1C7ioFShEFLmIXLlIrUxmRNLe_aWKQH7K?= =?utf-8?q?7PUIzB16F2PxRmUkS99ZyafUJO2rx2rxh+BZR5gM+ieFJYTKZsy+oY3A4QTMzDaCY?= =?utf-8?q?yipAnv_XEXNxJ0jwDOQiQTnsw/M6p4DnzSJqhCQUX8GktpvTwLypNdTJnQkl6W2cf?= =?utf-8?q?nOiTCFwSB/YfzaFa0SYy?= H/nnJe3yZCfkkB3Ngt58xpEwaqw7Il X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Add handlers which read fs caps from the lower or upper filesystem and write/remove fs caps to the upper filesystem, performing copy-up as necessary. While it doesn't make sense to use fscaps on directories, nothing in the kernel actually prevents setting or getting fscaps xattrs for directory inodes. If we omit fscaps handlers in ovl_dir_inode_operations then the generic handlers will be used. These handlers will use the xattr inode operations, bypassing any idmapping on lower mounts, so fscaps handlers are also installed for ovl_dir_inode_operations. Signed-off-by: Seth Forshee (DigitalOcean) --- fs/overlayfs/dir.c | 3 ++ fs/overlayfs/inode.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/overlayfs/overlayfs.h | 6 ++++ 3 files changed, 93 insertions(+) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index aab3f5d93556..d9ab3c9ce10a 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -1303,6 +1303,9 @@ const struct inode_operations ovl_dir_inode_operations = { .get_inode_acl = ovl_get_inode_acl, .get_acl = ovl_get_acl, .set_acl = ovl_set_acl, + .get_fscaps = ovl_get_fscaps, + .set_fscaps = ovl_set_fscaps, + .remove_fscaps = ovl_remove_fscaps, .update_time = ovl_update_time, .fileattr_get = ovl_fileattr_get, .fileattr_set = ovl_fileattr_set, diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index c63b31a460be..82fc6e479d45 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -568,6 +568,87 @@ int ovl_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, } #endif +int ovl_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + struct vfs_caps *caps) +{ + int err; + const struct cred *old_cred; + struct path realpath; + + ovl_path_real(dentry, &realpath); + old_cred = ovl_override_creds(dentry->d_sb); + err = vfs_get_fscaps(mnt_idmap(realpath.mnt), realpath.dentry, caps); + revert_creds(old_cred); + return err; +} + +int ovl_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + const struct vfs_caps *caps, int flags) +{ + int err; + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); + struct dentry *upperdentry = ovl_dentry_upper(dentry); + struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); + const struct cred *old_cred; + + err = ovl_want_write(dentry); + if (err) + goto out; + + if (!upperdentry) { + err = ovl_copy_up(dentry); + if (err) + goto out_drop_write; + + realdentry = ovl_dentry_upper(dentry); + } + + old_cred = ovl_override_creds(dentry->d_sb); + err = vfs_set_fscaps(ovl_upper_mnt_idmap(ofs), realdentry, caps, flags); + revert_creds(old_cred); + + /* copy c/mtime */ + ovl_copyattr(d_inode(dentry)); + +out_drop_write: + ovl_drop_write(dentry); +out: + return err; +} + +int ovl_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry) +{ + int err; + struct ovl_fs *ofs = OVL_FS(dentry->d_sb); + struct dentry *upperdentry = ovl_dentry_upper(dentry); + struct dentry *realdentry = upperdentry ?: ovl_dentry_lower(dentry); + const struct cred *old_cred; + + err = ovl_want_write(dentry); + if (err) + goto out; + + if (!upperdentry) { + err = ovl_copy_up(dentry); + if (err) + goto out_drop_write; + + realdentry = ovl_dentry_upper(dentry); + } + + old_cred = ovl_override_creds(dentry->d_sb); + err = vfs_remove_fscaps(ovl_upper_mnt_idmap(ofs), realdentry); + revert_creds(old_cred); + + /* copy c/mtime */ + ovl_copyattr(d_inode(dentry)); + +out_drop_write: + ovl_drop_write(dentry); +out: + return err; +} + int ovl_update_time(struct inode *inode, int flags) { if (flags & S_ATIME) { @@ -747,6 +828,9 @@ static const struct inode_operations ovl_file_inode_operations = { .get_inode_acl = ovl_get_inode_acl, .get_acl = ovl_get_acl, .set_acl = ovl_set_acl, + .get_fscaps = ovl_get_fscaps, + .set_fscaps = ovl_set_fscaps, + .remove_fscaps = ovl_remove_fscaps, .update_time = ovl_update_time, .fiemap = ovl_fiemap, .fileattr_get = ovl_fileattr_get, diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 05c3dd597fa8..e72ee2374f96 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -764,6 +764,12 @@ static inline struct posix_acl *ovl_get_acl_path(const struct path *path, } #endif +int ovl_get_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + struct vfs_caps *caps); +int ovl_set_fscaps(struct mnt_idmap *idmap, struct dentry *dentry, + const struct vfs_caps *caps, int flags); +int ovl_remove_fscaps(struct mnt_idmap *idmap, struct dentry *dentry); + int ovl_update_time(struct inode *inode, int flags); bool ovl_is_private_xattr(struct super_block *sb, const char *name); From patchwork Wed Nov 29 21:50:30 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473555 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8EF8161FC4; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="u8qp9bnx" Received: by smtp.kernel.org (Postfix) with ESMTPS id 184BAC4166B; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=sdaoEg9ciUZftk2H34h2y651gj0bEkfe58vTpkMB1yM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=u8qp9bnx716v5Vigy7mjHUsLCuMP8nLpRUBvItevXMcTOsgzUh/C15VxsDAxnHLnl bQ/sevGtoOzwHAK/P6s1Zo18UovQyWcEFbX4W76SZ8q1P0JyTEMu+xmk04h5oRQsLK 06M8qxJdHM4mde8Q6t2YQNgR9nAKjPfaB6DSpXKDonVoDRjJq/sx1Gv+d8WEOkdpWW VXg97Wqp3HWq5G0Xo2/Bm+N6G9GP7uibWBcYYDa/vf4CnGyXnXB78uoWIqTZD3uveb K19pyeiRxf6KprihD3McCPOWmlf2ePuYGIzQfzSjw6Ga7CdcMCWHF9fGJWv2mFzxcG 3wjNU9f6+udRQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 09728C4167B; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:30 -0600 Subject: [PATCH 12/16] ovl: use vfs_{get,set}_fscaps() for copy-up Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-12-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=4000; i=sforshee@kernel.org; h=from:subject:message-id; bh=sdaoEg9ciUZftk2H34h2y651gj0bEkfe58vTpkMB1yM=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I7nj2pDM1Swf1xxfWdnQF14?= =?utf-8?q?2gaU0cjaKHbr9wa_IfaLDx2JATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyOwAKCRBTA5mu5fQxyagzB/_9p+FECwvuMkt4XpREQZadycge188mmaG0Bd?= =?utf-8?q?TCbVb2BetQ3LKBPtUkg4sx9fWHrGjDqMTmYASWswk8w_ZxaDGEGJ4Hu1GJI6t42C5?= =?utf-8?q?f0v6yLIm3xXZa54SVpbW6saMAY4YcZBAHtg+Lq5zJqjHxSy/WWSI3lNco_7/L9wXs?= =?utf-8?q?aUPMpHWuiy8v7p4EhXAxCjGiNTCHLkM/2FnayolmIwXVgBMiQ7PSU+KwElFmf/JHB?= =?utf-8?q?mc/CXJ_qy3Ibx41A7h81JLGZSY+rnHq7KdXnC0tbY7F1bbXdlD5Sr0pkfDOA7r7Rp?= =?utf-8?q?laqTUtg48HD5m1hJ7hp5?= YxnKnn+lyAuSXl8IlHlrpCCrEeLE8U X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Using vfs_{get,set}xattr() for fscaps will be blocked in a future commit, so convert ovl to use the new interfaces. Also remove the now unused ovl_getxattr_value(). Signed-off-by: Seth Forshee (DigitalOcean) Reviewed-by: Amir Goldstein --- fs/overlayfs/copy_up.c | 72 ++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 35 deletions(-) diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index 4382881b0709..b43af5ce4b21 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -73,6 +73,23 @@ static int ovl_copy_acl(struct ovl_fs *ofs, const struct path *path, return err; } +static int ovl_copy_fscaps(struct ovl_fs *ofs, const struct path *oldpath, + struct dentry *new) +{ + struct vfs_caps capability; + int err; + + err = vfs_get_fscaps(mnt_idmap(oldpath->mnt), oldpath->dentry, + &capability); + if (err) { + if (err == -ENODATA || err == -EOPNOTSUPP) + return 0; + return err; + } + + return vfs_set_fscaps(ovl_upper_mnt_idmap(ofs), new, &capability, 0); +} + int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct dentry *new) { struct dentry *old = oldpath->dentry; @@ -130,6 +147,14 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de break; } + if (!strcmp(name, XATTR_NAME_CAPS)) { + error = ovl_copy_fscaps(OVL_FS(sb), oldpath, new); + if (!error) + continue; + /* fs capabilities must be copied */ + break; + } + retry: size = ovl_do_getxattr(oldpath, name, value, value_size); if (size == -ERANGE) @@ -1006,61 +1031,40 @@ static bool ovl_need_meta_copy_up(struct dentry *dentry, umode_t mode, return true; } -static ssize_t ovl_getxattr_value(const struct path *path, char *name, char **value) -{ - ssize_t res; - char *buf; - - res = ovl_do_getxattr(path, name, NULL, 0); - if (res == -ENODATA || res == -EOPNOTSUPP) - res = 0; - - if (res > 0) { - buf = kzalloc(res, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - res = ovl_do_getxattr(path, name, buf, res); - if (res < 0) - kfree(buf); - else - *value = buf; - } - return res; -} - /* Copy up data of an inode which was copied up metadata only in the past. */ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) { struct ovl_fs *ofs = OVL_FS(c->dentry->d_sb); struct path upperpath; int err; - char *capability = NULL; - ssize_t cap_size; + struct vfs_caps capability; + bool has_capability = false; ovl_path_upper(c->dentry, &upperpath); if (WARN_ON(upperpath.dentry == NULL)) return -EIO; if (c->stat.size) { - err = cap_size = ovl_getxattr_value(&upperpath, XATTR_NAME_CAPS, - &capability); - if (cap_size < 0) + err = vfs_get_fscaps(mnt_idmap(upperpath.mnt), upperpath.dentry, + &capability); + if (!err) + has_capability = 1; + else if (err != -ENODATA && err != EOPNOTSUPP) goto out; } err = ovl_copy_up_data(c, &upperpath); if (err) - goto out_free; + goto out; /* * Writing to upper file will clear security.capability xattr. We * don't want that to happen for normal copy-up operation. */ ovl_start_write(c->dentry); - if (capability) { - err = ovl_do_setxattr(ofs, upperpath.dentry, XATTR_NAME_CAPS, - capability, cap_size, 0); + if (has_capability) { + err = vfs_set_fscaps(mnt_idmap(upperpath.mnt), upperpath.dentry, + &capability, 0); } if (!err) { err = ovl_removexattr(ofs, upperpath.dentry, @@ -1068,13 +1072,11 @@ static int ovl_copy_up_meta_inode_data(struct ovl_copy_up_ctx *c) } ovl_end_write(c->dentry); if (err) - goto out_free; + goto out; ovl_clear_flag(OVL_HAS_DIGEST, d_inode(c->dentry)); ovl_clear_flag(OVL_VERIFIED_DIGEST, d_inode(c->dentry)); ovl_set_upperdata(d_inode(c->dentry)); -out_free: - kfree(capability); out: return err; } From patchwork Wed Nov 29 21:50:31 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473558 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 907F261FC9; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="EOaZfNhq" Received: by smtp.kernel.org (Postfix) with ESMTPS id 215A3C433C7; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=2HiADlLvgGW720oIUK6woDmD2V9EI+/r0VTeM20LPPs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EOaZfNhqvhlO8BZ4PLdI0JgXRNglutJeDpDR46JAPYU7frD9BNZA0I4AOCKObzayW GCwsJvfneErUDdYut0s8slvX2MRREyyu7kla6KAGaGpbjp/4vCi25bbnh7t4SAyiLr M+hlrB6h+IS6N+vB1UyUQ/LjxMjwrXk3DMqgp4dx7JXYqrzMoZ6jcaEGVRLJ11ElPv LBPPPqyACX6l0ay8zeu2VL+3fGGWMtaW2tZohzQPmaJKlo2VxdFh/eKRysVqanoiPN sfGTuWmq8HeFfnwr1v3QuplABP1yvb7Gdx/9GYFZY0XV3+Ge7Aa1+88eYIyxvi6xzF qe14FbjluFU4A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13130C07CB1; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:31 -0600 Subject: [PATCH 13/16] fs: use vfs interfaces for capabilities xattrs Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-13-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=8524; i=sforshee@kernel.org; h=from:subject:message-id; bh=2HiADlLvgGW720oIUK6woDmD2V9EI+/r0VTeM20LPPs=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I84eoLP86nEuxsd0EOX/Og5?= =?utf-8?q?0rHT0ZAzT63Z49r_9RiM2oOJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyPAAKCRBTA5mu5fQxyZhyB/_9gYYIbkYFa10api1PrNd0MoEaeKZ/aJybzo?= =?utf-8?q?VQjHKThBmpvtRrAxol4IrKQr4Gruq6rBfw62ZdbflNs_AgQHicVr/QIC6zxyar2Vo?= =?utf-8?q?a6KkLhLKnAajluGF6ghiJG+gkoOd+qRPX6HmmOfUH8ge7hAK+ils71Wdb_emuoGBO?= =?utf-8?q?u7J4L1641adZs1rEEfEBzVhPAT/2lPD2rvpco0QupuBPFU9ty3XyQdtRF6Gb3vuxF?= =?utf-8?q?UnGWzm_rkoNeZCp6VhQkcEpsCQ6nF8ypGwiTXGUsf6+aJy1+LK/gsgNSq519SdLiQ?= =?utf-8?q?0i5VlzDTtQOb4qIHrm6/?= QazLsgiYauqobTgzmjki+Qj658voFS X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Now that all the plumbing is in place, switch over to using the new inode operations to get/set fs caps. This pushes all mapping of ids into the caller's user ns to above the vfs_*() level, making this consistent with other vfs_*() interfaces. cap_convert_nscap() is updated to return vfs_caps and moved to be called from the new code path for setting fscaps. This means that use of vfs_setxattr() will no longer remap ids in fscap xattrs, but all code which used vfs_setxattr() for fscaps xattrs has been converted to the new interfaces. Removing the mapping of fscaps rootids from vfs_getxattr() is more invovled and will be addressed in a later commit. Signed-off-by: Seth Forshee (DigitalOcean) --- fs/xattr.c | 49 ++++++++++++++++++++++++---- include/linux/capability.h | 2 +- security/commoncap.c | 79 +++++++++++++++------------------------------- 3 files changed, 69 insertions(+), 61 deletions(-) diff --git a/fs/xattr.c b/fs/xattr.c index f60ef2a79dfa..372644b15457 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -540,13 +540,6 @@ vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const void *orig_value = value; int error; - if (size && strcmp(name, XATTR_NAME_CAPS) == 0) { - error = cap_convert_nscap(idmap, dentry, &value, size); - if (error < 0) - return error; - size = error; - } - retry_deleg: inode_lock(inode); error = __vfs_setxattr_locked(idmap, dentry, name, value, size, @@ -857,6 +850,24 @@ int do_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, return do_set_acl(idmap, dentry, ctx->kname->name, ctx->kvalue, ctx->size); + if (strcmp(ctx->kname->name, XATTR_NAME_CAPS) == 0) { + struct vfs_caps caps; + int ret; + + /* + * rootid is already in the mount idmap, so pass nop_mnt_idmap + * so that it won't be mapped. + */ + ret = vfs_caps_from_xattr(&nop_mnt_idmap, current_user_ns(), + &caps, ctx->kvalue, ctx->size); + if (ret) + return ret; + ret = cap_convert_nscap(idmap, dentry, &caps); + if (ret) + return ret; + return vfs_set_fscaps(idmap, dentry, &caps, ctx->flags); + } + return vfs_setxattr(idmap, dentry, ctx->kname->name, ctx->kvalue, ctx->size, ctx->flags); } @@ -955,6 +966,27 @@ do_getxattr(struct mnt_idmap *idmap, struct dentry *d, ssize_t error; char *kname = ctx->kname->name; + if (strcmp(kname, XATTR_NAME_CAPS) == 0) { + struct vfs_caps caps; + struct vfs_ns_cap_data data; + int ret; + + ret = vfs_get_fscaps(idmap, d, &caps); + if (ret) + return ret; + /* + * rootid is already in the mount idmap, so pass nop_mnt_idmap + * so that it won't be mapped. + */ + ret = vfs_caps_to_user_xattr(&nop_mnt_idmap, current_user_ns(), + &caps, &data, ctx->size); + if (ret < 0) + return ret; + if (ctx->size && copy_to_user(ctx->value, &data, ret)) + return -EFAULT; + return ret; + } + if (ctx->size) { if (ctx->size > XATTR_SIZE_MAX) ctx->size = XATTR_SIZE_MAX; @@ -1145,6 +1177,9 @@ removexattr(struct mnt_idmap *idmap, struct dentry *d, if (is_posix_acl_xattr(kname)) return vfs_remove_acl(idmap, d, kname); + if (strcmp(kname, XATTR_NAME_CAPS) == 0) + return vfs_remove_fscaps(idmap, d); + return vfs_removexattr(idmap, d, kname); } diff --git a/include/linux/capability.h b/include/linux/capability.h index c0bd9447685b..563f084e9453 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -229,6 +229,6 @@ int get_vfs_caps_from_disk(struct mnt_idmap *idmap, struct vfs_caps *cpu_caps); int cap_convert_nscap(struct mnt_idmap *idmap, struct dentry *dentry, - const void **ivalue, size_t size); + struct vfs_caps *caps); #endif /* !_LINUX_CAPABILITY_H */ diff --git a/security/commoncap.c b/security/commoncap.c index c645330f83a0..bd95b806af2f 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -484,27 +484,21 @@ int cap_inode_getsecurity(struct mnt_idmap *idmap, } /** - * rootid_from_xattr - translate root uid of vfs caps + * rootid_from_vfs_caps - translate root uid of vfs caps * - * @value: vfs caps value which may be modified by this function - * @size: size of @ivalue + * @caps: vfs caps value which may be modified by this function * @task_ns: user namespace of the caller + * + * Return the rootid from a v3 fs cap, or the id of root in the task's user + * namespace for v1 and v2 fs caps. */ -static vfsuid_t rootid_from_xattr(const void *value, size_t size, - struct user_namespace *task_ns) +static vfsuid_t rootid_from_vfs_caps(const struct vfs_caps *caps, + struct user_namespace *task_ns) { - const struct vfs_ns_cap_data *nscap = value; - uid_t rootid = 0; - - if (size == XATTR_CAPS_SZ_3) - rootid = le32_to_cpu(nscap->rootid); - - return VFSUIDT_INIT(make_kuid(task_ns, rootid)); -} + if ((caps->magic_etc & VFS_CAP_REVISION_MASK) == VFS_CAP_REVISION_3) + return caps->rootid; -static bool validheader(size_t size, const struct vfs_cap_data *cap) -{ - return is_v2header(size, cap) || is_v3header(size, cap); + return VFSUIDT_INIT(make_kuid(task_ns, 0)); } /** @@ -512,11 +506,10 @@ static bool validheader(size_t size, const struct vfs_cap_data *cap) * * @idmap: idmap of the mount the inode was found from * @dentry: used to retrieve inode to check permissions on - * @ivalue: vfs caps value which may be modified by this function - * @size: size of @ivalue + * @caps: vfs caps which may be modified by this function * - * User requested a write of security.capability. If needed, update the - * xattr to change from v2 to v3, or to fixup the v3 rootid. + * User requested a write of security.capability. Check permissions, and if + * needed, update the xattr to change from v2 to v3. * * If the inode has been found through an idmapped mount the idmap of * the vfsmount must be passed through @idmap. This function will then @@ -524,59 +517,39 @@ static bool validheader(size_t size, const struct vfs_cap_data *cap) * permissions. On non-idmapped mounts or if permission checking is to be * performed on the raw inode simply pass @nop_mnt_idmap. * - * Return: On success, return the new size; on error, return < 0. + * Return: On success, return 0; on error, return < 0. */ int cap_convert_nscap(struct mnt_idmap *idmap, struct dentry *dentry, - const void **ivalue, size_t size) + struct vfs_caps *caps) { - struct vfs_ns_cap_data *nscap; - uid_t nsrootid; - const struct vfs_cap_data *cap = *ivalue; - __u32 magic, nsmagic; struct inode *inode = d_backing_inode(dentry); struct user_namespace *task_ns = current_user_ns(), *fs_ns = inode->i_sb->s_user_ns; - kuid_t rootid; vfsuid_t vfsrootid; - size_t newsize; + __u32 revision; - if (!*ivalue) - return -EINVAL; - if (!validheader(size, cap)) + revision = sansflags(caps->magic_etc); + if (revision != VFS_CAP_REVISION_2 && revision != VFS_CAP_REVISION_3) return -EINVAL; if (!capable_wrt_inode_uidgid(idmap, inode, CAP_SETFCAP)) return -EPERM; - if (size == XATTR_CAPS_SZ_2 && (idmap == &nop_mnt_idmap)) + if (revision == VFS_CAP_REVISION_2 && (idmap == &nop_mnt_idmap)) if (ns_capable(inode->i_sb->s_user_ns, CAP_SETFCAP)) /* user is privileged, just write the v2 */ - return size; + return 0; - vfsrootid = rootid_from_xattr(*ivalue, size, task_ns); + vfsrootid = rootid_from_vfs_caps(caps, task_ns); if (!vfsuid_valid(vfsrootid)) return -EINVAL; - rootid = from_vfsuid(idmap, fs_ns, vfsrootid); - if (!uid_valid(rootid)) + if (!vfsuid_has_fsmapping(idmap, fs_ns, vfsrootid)) return -EINVAL; - nsrootid = from_kuid(fs_ns, rootid); - if (nsrootid == -1) - return -EINVAL; + caps->rootid = vfsrootid; + caps->magic_etc = VFS_CAP_REVISION_3 | + (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE); - newsize = sizeof(struct vfs_ns_cap_data); - nscap = kmalloc(newsize, GFP_ATOMIC); - if (!nscap) - return -ENOMEM; - nscap->rootid = cpu_to_le32(nsrootid); - nsmagic = VFS_CAP_REVISION_3; - magic = le32_to_cpu(cap->magic_etc); - if (magic & VFS_CAP_FLAGS_EFFECTIVE) - nsmagic |= VFS_CAP_FLAGS_EFFECTIVE; - nscap->magic_etc = cpu_to_le32(nsmagic); - memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32); - - *ivalue = nscap; - return newsize; + return 0; } /* From patchwork Wed Nov 29 21:50:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473553 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 828F361FB8; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="MunA49Sv" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2F0A2C116D7; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=uFzoiVjJtbvck1BcdPMgWuiZkFJlPHwpLqYlbNGQAXY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=MunA49SvgqILlcyTsUtk7fgy+OkvtA+Oj81PUI4cdPRthbZnHrxydq95+EQTiu8nv lZLlNKfon5pIQDKEVKEucmEooVF1fW7E1r38rqyQ2KeH4zRznD9piWgMnn6C6SS47H Fd+LUFm87XLhUD6BAqzpjzZZVvkC9RoQHGtAepgtdoAtVdTLTouOpWYiKDPpDMPGdv gHrSl8y4+o/JTMhxGWhewuEjfY2BsK7xfpKV/fPsGwMdIh2rY4Vetk9mmxjd24/CLE EJD3OPVZc34RSV9eAGFfR2P9Q0A2wWqdF0lV2lqJiftJYJigxxBsm5LDE8OjsYaXX1 OXzssEsnYb9rA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E745C10DC3; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:32 -0600 Subject: [PATCH 14/16] commoncap: remove cap_inode_getsecurity() Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-14-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=6309; i=sforshee@kernel.org; h=from:subject:message-id; bh=uFzoiVjJtbvck1BcdPMgWuiZkFJlPHwpLqYlbNGQAXY=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I9Ry+ru3s9jQPglbV78Ohwi?= =?utf-8?q?5Zi3ZtxSMaZDa/z_LC4reqGJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyPQAKCRBTA5mu5fQxyXyDCA_CUQfFirgZg5wY4TmnfPxiTW/np4Xp05OLEQ?= =?utf-8?q?CBV7W1rWsmbDsYrGiA8d6TwhoVMbfXJA8KKOfWZDKjO_RSNVd4r2NRO29XJ7hbMny?= =?utf-8?q?I/1f8/4QBaldLAPtkvwxfzRQRQexpHRnNDImwIy7G7e2Z2XKqknELBOFg_K5jhQQ7?= =?utf-8?q?TFQiPSoTXaDk7VJ79pNZPSkldpxmJkFtIZHrvTXmjLRtgjNu/GMpORILf4Bgba/fv?= =?utf-8?q?2U4AdQ_CAMjnlEHxu6uvvU4AmvaUCropVe3elJFm74aNI9DM+IBSmMH3WWs7BmP5R?= =?utf-8?q?wwLn6VV/S16RWb5cgj6c?= bxPoIwdeFE8xzAui/554ryvi2XtD/U X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Reading of fscaps xattrs is now done via vfs_get_fscaps(), so there is no longer any need to do it from security_inode_getsecurity(). Remove cap_inode_getsecurity() and its associated helpers which are now unused. We don't allow reading capabilities xattrs this way anyomre, so remove the handler and associated helpers. Signed-off-by: Seth Forshee (DigitalOcean) Acked-by: Paul Moore (LSM) --- include/linux/security.h | 5 +- security/commoncap.c | 132 ----------------------------------------------- 2 files changed, 1 insertion(+), 136 deletions(-) diff --git a/include/linux/security.h b/include/linux/security.h index 1d1df326c881..784b85816907 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -158,9 +158,6 @@ int cap_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name); int cap_inode_need_killpriv(struct dentry *dentry); int cap_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry); -int cap_inode_getsecurity(struct mnt_idmap *idmap, - struct inode *inode, const char *name, void **buffer, - bool alloc); extern int cap_mmap_addr(unsigned long addr); extern int cap_mmap_file(struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags); @@ -934,7 +931,7 @@ static inline int security_inode_getsecurity(struct mnt_idmap *idmap, const char *name, void **buffer, bool alloc) { - return cap_inode_getsecurity(idmap, inode, name, buffer, alloc); + return -EOPNOTSUPP; } static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) diff --git a/security/commoncap.c b/security/commoncap.c index bd95b806af2f..ced7a3c9685f 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -352,137 +352,6 @@ static __u32 sansflags(__u32 m) return m & ~VFS_CAP_FLAGS_EFFECTIVE; } -static bool is_v2header(int size, const struct vfs_cap_data *cap) -{ - if (size != XATTR_CAPS_SZ_2) - return false; - return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_2; -} - -static bool is_v3header(int size, const struct vfs_cap_data *cap) -{ - if (size != XATTR_CAPS_SZ_3) - return false; - return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_3; -} - -/* - * getsecurity: We are called for security.* before any attempt to read the - * xattr from the inode itself. - * - * This gives us a chance to read the on-disk value and convert it. If we - * return -EOPNOTSUPP, then vfs_getxattr() will call the i_op handler. - * - * Note we are not called by vfs_getxattr_alloc(), but that is only called - * by the integrity subsystem, which really wants the unconverted values - - * so that's good. - */ -int cap_inode_getsecurity(struct mnt_idmap *idmap, - struct inode *inode, const char *name, void **buffer, - bool alloc) -{ - int size; - kuid_t kroot; - vfsuid_t vfsroot; - u32 nsmagic, magic; - uid_t root, mappedroot; - char *tmpbuf = NULL; - struct vfs_cap_data *cap; - struct vfs_ns_cap_data *nscap = NULL; - struct dentry *dentry; - struct user_namespace *fs_ns; - - if (strcmp(name, "capability") != 0) - return -EOPNOTSUPP; - - dentry = d_find_any_alias(inode); - if (!dentry) - return -EINVAL; - size = vfs_getxattr_alloc(idmap, dentry, XATTR_NAME_CAPS, &tmpbuf, - sizeof(struct vfs_ns_cap_data), GFP_NOFS); - dput(dentry); - /* gcc11 complains if we don't check for !tmpbuf */ - if (size < 0 || !tmpbuf) - goto out_free; - - fs_ns = inode->i_sb->s_user_ns; - cap = (struct vfs_cap_data *) tmpbuf; - if (is_v2header(size, cap)) { - root = 0; - } else if (is_v3header(size, cap)) { - nscap = (struct vfs_ns_cap_data *) tmpbuf; - root = le32_to_cpu(nscap->rootid); - } else { - size = -EINVAL; - goto out_free; - } - - kroot = make_kuid(fs_ns, root); - - /* If this is an idmapped mount shift the kuid. */ - vfsroot = make_vfsuid(idmap, fs_ns, kroot); - - /* If the root kuid maps to a valid uid in current ns, then return - * this as a nscap. */ - mappedroot = from_kuid(current_user_ns(), vfsuid_into_kuid(vfsroot)); - if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) { - size = sizeof(struct vfs_ns_cap_data); - if (alloc) { - if (!nscap) { - /* v2 -> v3 conversion */ - nscap = kzalloc(size, GFP_ATOMIC); - if (!nscap) { - size = -ENOMEM; - goto out_free; - } - nsmagic = VFS_CAP_REVISION_3; - magic = le32_to_cpu(cap->magic_etc); - if (magic & VFS_CAP_FLAGS_EFFECTIVE) - nsmagic |= VFS_CAP_FLAGS_EFFECTIVE; - memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32); - nscap->magic_etc = cpu_to_le32(nsmagic); - } else { - /* use allocated v3 buffer */ - tmpbuf = NULL; - } - nscap->rootid = cpu_to_le32(mappedroot); - *buffer = nscap; - } - goto out_free; - } - - if (!rootid_owns_currentns(vfsroot)) { - size = -EOVERFLOW; - goto out_free; - } - - /* This comes from a parent namespace. Return as a v2 capability */ - size = sizeof(struct vfs_cap_data); - if (alloc) { - if (nscap) { - /* v3 -> v2 conversion */ - cap = kzalloc(size, GFP_ATOMIC); - if (!cap) { - size = -ENOMEM; - goto out_free; - } - magic = VFS_CAP_REVISION_2; - nsmagic = le32_to_cpu(nscap->magic_etc); - if (nsmagic & VFS_CAP_FLAGS_EFFECTIVE) - magic |= VFS_CAP_FLAGS_EFFECTIVE; - memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32); - cap->magic_etc = cpu_to_le32(magic); - } else { - /* use unconverted v2 */ - tmpbuf = NULL; - } - *buffer = cap; - } -out_free: - kfree(tmpbuf); - return size; -} - /** * rootid_from_vfs_caps - translate root uid of vfs caps * @@ -1616,7 +1485,6 @@ static struct security_hook_list capability_hooks[] __ro_after_init = { LSM_HOOK_INIT(bprm_creds_from_file, cap_bprm_creds_from_file), LSM_HOOK_INIT(inode_need_killpriv, cap_inode_need_killpriv), LSM_HOOK_INIT(inode_killpriv, cap_inode_killpriv), - LSM_HOOK_INIT(inode_getsecurity, cap_inode_getsecurity), LSM_HOOK_INIT(mmap_addr, cap_mmap_addr), LSM_HOOK_INIT(mmap_file, cap_mmap_file), LSM_HOOK_INIT(task_fix_setuid, cap_task_fix_setuid), From patchwork Wed Nov 29 21:50:33 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473559 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9F8E461FD4; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="bAcI0tbP" Received: by smtp.kernel.org (Postfix) with ESMTPS id 3B13AC4AF5C; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=FWlHUtx1il/2WmiearZx3LNeV83xpbRFd1g6e9syKsA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bAcI0tbPjMNanqFp6BahN4cGnqvFSgWqISkhobG33OIwOhGJPetz//8/MOO7EHgQu UcyStUo6qyxEqn4ml/4hm9r2vRvry1p5F1awMPhl4HV9wG2prG6wEhWzt4JgJUiIcK KNXfUMMbtP6Bbb6aejIpouOKBsW2lxMxv+OlBR6zluHjJ8PdJVokhJeuACkKWEIzwD 9idToiv8SeabdHCJLwIk5bsnsesbLGE4+HyEno3SvAeyzS2y5taXd2f6HOSQ/D4sDZ FyIJMZfj9zvLjxU5sOdVl/4jkUVemKRXmcBbPYg/Jzge8DNfvTJ3wM3gVmsh6v1zjQ QB3fZltHLvmbQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2910AC10DC1; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:33 -0600 Subject: [PATCH 15/16] commoncap: use vfs fscaps interfaces for killpriv checks Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-15-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=1080; i=sforshee@kernel.org; h=from:subject:message-id; bh=FWlHUtx1il/2WmiearZx3LNeV83xpbRFd1g6e9syKsA=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I+qo1rIY3IOTiiUwRAxi2OM?= =?utf-8?q?NSepIYyq0YWIbCA_KDVnYlCJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyPgAKCRBTA5mu5fQxyQptCA_CBRf/0K9qKrdU9ZyL7OUgLfoKpWZ3Y5Xvo2?= =?utf-8?q?/RWzXlmQ2DXKoq/UH+loOnYsDaqePGfdWVh5uyo58d5_tr4QxdG4SYWTf0aojF8Nv?= =?utf-8?q?/Ap+jz0JAT1fkv5J5wNpK8VYaurr5U74/r2olZuglS8yOIpiotQf/sS7m_FPb8lsc?= =?utf-8?q?649YKHNU1fc+t9qPO3v3pygCKP9+bJJ2r6HSyaZw6SPYHtvKOlS1chbYH20mqdKLa?= =?utf-8?q?40NzU3_WzZnkXBYpChnZM7Wx7072VG8CmqZ/WS7DNSeX8HZx14OF7c4clq4hsIZ16?= =?utf-8?q?P0bYtxnGjcdxJfekad8I?= TE9Ua9977cqAsf27gse9g5nBZH9JZX X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Signed-off-by: Seth Forshee (DigitalOcean) --- security/commoncap.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/security/commoncap.c b/security/commoncap.c index ced7a3c9685f..15344c86c759 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -295,11 +295,12 @@ int cap_capset(struct cred *new, */ int cap_inode_need_killpriv(struct dentry *dentry) { - struct inode *inode = d_backing_inode(dentry); + struct vfs_caps caps; int error; - error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0); - return error > 0; + /* Use nop_mnt_idmap for no mapping here as mapping is unimportant */ + error= __vfs_get_fscaps(&nop_mnt_idmap, dentry, &caps); + return error == 0; } /** @@ -322,7 +323,7 @@ int cap_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry) { int error; - error = __vfs_removexattr(idmap, dentry, XATTR_NAME_CAPS); + error = __vfs_remove_fscaps(idmap, dentry); if (error == -EOPNOTSUPP) error = 0; return error; From patchwork Wed Nov 29 21:50:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Seth Forshee (DigitalOcean)" X-Patchwork-Id: 13473554 X-Patchwork-Delegate: paul@paul-moore.com Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8544661FBC; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IB53PCzW" Received: by smtp.kernel.org (Postfix) with ESMTPS id 41392C2BCFE; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1701294658; bh=fGkhj5/NF9UPawvhqYtWeLh70xVuDREL8YeiOyAcAQA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IB53PCzW++dHYvwKAxy9kOqiyPyUek3biP1aF4qO+xxCiRDBxWIsvoQgfusBoAUhC yPGQL94ljCFqKIBx4pBRDlJDGJJC8pzejcgg7fwE7cYMmyR5VIO6kgDA8G0tKWFDaE bbFuPFjpreoMnn5mME0Y8Tuqs20jJ+Hd35oXKkVxID942x3Q4rW2JEJbO7adRrm0Ls cGcoDHR3+4Zo/1+djNBX8tcKchb8aotvtqjnkt3ZYxbRVbtRpmndCnwzlAsXB7pY99 MZytrt3cW9mz5QqWcWmbRIJeZo89PVPFo/z8rRENvBWkvZteNZ/dyBKmFDFXxqH8Ov 6EW1MI9msi4YQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32624C4167B; Wed, 29 Nov 2023 21:50:58 +0000 (UTC) From: "Seth Forshee (DigitalOcean)" Date: Wed, 29 Nov 2023 15:50:34 -0600 Subject: [PATCH 16/16] vfs: return -EOPNOTSUPP for fscaps from vfs_*xattr() Precedence: bulk X-Mailing-List: linux-security-module@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20231129-idmap-fscap-refactor-v1-16-da5a26058a5b@kernel.org> References: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> In-Reply-To: <20231129-idmap-fscap-refactor-v1-0-da5a26058a5b@kernel.org> To: Christian Brauner , Serge Hallyn , Paul Moore , Eric Paris , James Morris , Alexander Viro , Miklos Szeredi , Amir Goldstein Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-security-module@vger.kernel.org, audit@vger.kernel.org, linux-unionfs@vger.kernel.org, "Seth Forshee (DigitalOcean)" X-Mailer: b4 0.12.4 X-Developer-Signature: v=1; a=openpgp-sha256; l=1541; i=sforshee@kernel.org; h=from:subject:message-id; bh=fGkhj5/NF9UPawvhqYtWeLh70xVuDREL8YeiOyAcAQA=; =?utf-8?q?b=3DowEBbQGS/pANAwAKAVMDma7l9DHJAcsmYgBlZ7I+wlKgt++JWupSZaBp9QGfd?= =?utf-8?q?Bkmz7IEI8ioxj4s_f1+aQbyJATMEAAEKAB0WIQSQnt+rKAvnETy4Hc9TA5mu5fQxy?= =?utf-8?q?QUCZWeyPgAKCRBTA5mu5fQxyTvfB/_9YWexz1iQXD9/hl9qna/DWzl4zGo/SAzZV9?= =?utf-8?q?yU+WAg1lMJqq4GFg0sAtqm2p8er4jQP8TEmJ1gfT+Rp_OwnKnhV4uu4HWyEr7dNuR?= =?utf-8?q?ZPmxzAryHGI1rMeQqZmBuQ6oItUJeIE00YEKRTgMVm18qFcraMmUQVYcD_o8vPfg2?= =?utf-8?q?zw4i4XaDyCATxBE4yxIWmTjTHvJxdui3jxNCN1DDq9wMrXGKX2OZsyeCDw9VhgdNL?= =?utf-8?q?6EYyF2_xIHyfPKGASENkIpB05s2Aq3zudSepjo7YMWyfxSC3ghhvdqjksN1MMdM8J?= =?utf-8?q?Ff8oAsfPKxEyobr3TadT?= DOjWk90F22+U7CvJPhBxhcP09S5qxG X-Developer-Key: i=sforshee@kernel.org; a=openpgp; fpr=2ABCA7498D83E1D32D51D3B5AB4800A62DB9F73A X-Endpoint-Received: by B4 Relay for sforshee@kernel.org/default with auth_id=103 Now that the new vfs-level interfaces are fully supported and all code has been converted to use them, stop permitting use of the top-level vfs xattr interfaces for capabilities xattrs. Unlike with ACLs we still need to be able to work with fscaps xattrs using lower-level interfaces in a handful of places, so only use of the top-level xattr interfaces is restricted. Signed-off-by: Seth Forshee (DigitalOcean) --- fs/xattr.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/xattr.c b/fs/xattr.c index 372644b15457..4b779779ad8c 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -540,6 +540,9 @@ vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const void *orig_value = value; int error; + if (!strcmp(name, XATTR_NAME_CAPS)) + return -EOPNOTSUPP; + retry_deleg: inode_lock(inode); error = __vfs_setxattr_locked(idmap, dentry, name, value, size, @@ -655,6 +658,9 @@ vfs_getxattr(struct mnt_idmap *idmap, struct dentry *dentry, struct inode *inode = dentry->d_inode; int error; + if (!strcmp(name, XATTR_NAME_CAPS)) + return -EOPNOTSUPP; + error = xattr_permission(idmap, inode, name, MAY_READ); if (error) return error; @@ -794,6 +800,9 @@ vfs_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, struct inode *delegated_inode = NULL; int error; + if (!strcmp(name, XATTR_NAME_CAPS)) + return -EOPNOTSUPP; + retry_deleg: inode_lock(inode); error = __vfs_removexattr_locked(idmap, dentry,