* [PATCH 1/2] capability: add cap_isidentical
@ 2023-01-14 18:02 Mateusz Guzik
2023-01-14 18:02 ` [PATCH 2/2] vfs: avoid duplicating creds in faccessat if possible Mateusz Guzik
2023-01-14 19:33 ` [PATCH 1/2] capability: add cap_isidentical Serge E. Hallyn
0 siblings, 2 replies; 3+ messages in thread
From: Mateusz Guzik @ 2023-01-14 18:02 UTC (permalink / raw)
To: viro
Cc: serge, torvalds, linux-fsdevel, linux-kernel,
linux-security-module, Mateusz Guzik
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
---
include/linux/capability.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 65efb74c3585..736a973c677a 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -156,6 +156,16 @@ static inline bool cap_isclear(const kernel_cap_t a)
return true;
}
+static inline bool cap_isidentical(const kernel_cap_t a, const kernel_cap_t b)
+{
+ unsigned __capi;
+ CAP_FOR_EACH_U32(__capi) {
+ if (a.cap[__capi] != b.cap[__capi])
+ return false;
+ }
+ return true;
+}
+
/*
* Check if "a" is a subset of "set".
* return true if ALL of the capabilities in "a" are also in "set"
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] vfs: avoid duplicating creds in faccessat if possible
2023-01-14 18:02 [PATCH 1/2] capability: add cap_isidentical Mateusz Guzik
@ 2023-01-14 18:02 ` Mateusz Guzik
2023-01-14 19:33 ` [PATCH 1/2] capability: add cap_isidentical Serge E. Hallyn
1 sibling, 0 replies; 3+ messages in thread
From: Mateusz Guzik @ 2023-01-14 18:02 UTC (permalink / raw)
To: viro
Cc: serge, torvalds, linux-fsdevel, linux-kernel,
linux-security-module, Mateusz Guzik
access(2) remains commonly used, for example on exec:
access("/etc/ld.so.preload", R_OK)
or when running gcc: strace -c gcc empty.c
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
0.00 0.000000 0 42 26 access
It falls down to do_faccessat without the AT_EACCESS flag, which in turn
results in allocation of new creds in order to modify fsuid/fsgid and
caps. This is a very expensive process single-threaded and most notably
multi-threaded, with numerous structures getting refed and unrefed on
imminent new cred destruction.
Turns out for typical consumers the resulting creds would be identical
and this can be checked upfront, avoiding the hard work.
An access benchmark plugged into will-it-scale running on Cascade Lake
shows:
test proc before after
access1 1 1310582 2908735 (+121%) # distinct files
access1 24 4716491 63822173 (+1353%) # distinct files
access2 24 2378041 5370335 (+125%) # same file
The above benchmarks are not integrated into will-it-scale, but can be
found in a pull request:
https://github.com/antonblanchard/will-it-scale/pull/36/files
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
---
fs/open.c | 32 +++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)
diff --git a/fs/open.c b/fs/open.c
index 82c1a28b3308..c5bfc4e3df94 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -367,7 +367,37 @@ COMPAT_SYSCALL_DEFINE6(fallocate, int, fd, int, mode, compat_arg_u64_dual(offset
* access() needs to use the real uid/gid, not the effective uid/gid.
* We do this by temporarily clearing all FS-related capabilities and
* switching the fsuid/fsgid around to the real ones.
+ *
+ * Creating new credentials is expensive, so we try to skip doing it,
+ * which we can if the result would match what we already got.
*/
+static bool access_need_override_creds(int flags)
+{
+ const struct cred *cred;
+
+ if (flags & AT_EACCESS)
+ return false;
+
+ cred = current->cred;
+ if (!uid_eq(cred->fsuid, cred->uid) ||
+ !gid_eq(cred->fsgid, cred->gid))
+ return true;
+
+ if (!issecure(SECURE_NO_SETUID_FIXUP)) {
+ kuid_t root_uid = make_kuid(cred->user_ns, 0);
+ if (!uid_eq(cred->uid, root_uid)) {
+ if (!cap_isclear(cred->cap_effective))
+ return true;
+ } else {
+ if (!cap_isidentical(cred->cap_effective,
+ cred->cap_permitted))
+ return true;
+ }
+ }
+
+ return false;
+}
+
static const struct cred *access_override_creds(void)
{
const struct cred *old_cred;
@@ -436,7 +466,7 @@ static long do_faccessat(int dfd, const char __user *filename, int mode, int fla
if (flags & AT_EMPTY_PATH)
lookup_flags |= LOOKUP_EMPTY;
- if (!(flags & AT_EACCESS)) {
+ if (access_need_override_creds(flags)) {
old_cred = access_override_creds();
if (!old_cred)
return -ENOMEM;
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] capability: add cap_isidentical
2023-01-14 18:02 [PATCH 1/2] capability: add cap_isidentical Mateusz Guzik
2023-01-14 18:02 ` [PATCH 2/2] vfs: avoid duplicating creds in faccessat if possible Mateusz Guzik
@ 2023-01-14 19:33 ` Serge E. Hallyn
1 sibling, 0 replies; 3+ messages in thread
From: Serge E. Hallyn @ 2023-01-14 19:33 UTC (permalink / raw)
To: Mateusz Guzik
Cc: viro, serge, torvalds, linux-fsdevel, linux-kernel,
linux-security-module
On Sat, Jan 14, 2023 at 07:02:23PM +0100, Mateusz Guzik wrote:
> Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
> ---
> include/linux/capability.h | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/include/linux/capability.h b/include/linux/capability.h
> index 65efb74c3585..736a973c677a 100644
> --- a/include/linux/capability.h
> +++ b/include/linux/capability.h
> @@ -156,6 +156,16 @@ static inline bool cap_isclear(const kernel_cap_t a)
> return true;
> }
>
> +static inline bool cap_isidentical(const kernel_cap_t a, const kernel_cap_t b)
> +{
> + unsigned __capi;
> + CAP_FOR_EACH_U32(__capi) {
> + if (a.cap[__capi] != b.cap[__capi])
> + return false;
> + }
> + return true;
> +}
> +
> /*
> * Check if "a" is a subset of "set".
> * return true if ALL of the capabilities in "a" are also in "set"
> --
> 2.34.1
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2023-01-14 19:33 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-14 18:02 [PATCH 1/2] capability: add cap_isidentical Mateusz Guzik
2023-01-14 18:02 ` [PATCH 2/2] vfs: avoid duplicating creds in faccessat if possible Mateusz Guzik
2023-01-14 19:33 ` [PATCH 1/2] capability: add cap_isidentical Serge E. Hallyn
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).