From patchwork Sat Jan 14 18:02:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mateusz Guzik X-Patchwork-Id: 13102081 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 750FEC6379F for ; Sat, 14 Jan 2023 18:02:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230343AbjANSCp (ORCPT ); Sat, 14 Jan 2023 13:02:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230231AbjANSCo (ORCPT ); Sat, 14 Jan 2023 13:02:44 -0500 Received: from mail-ed1-x536.google.com (mail-ed1-x536.google.com [IPv6:2a00:1450:4864:20::536]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89088BBA3; Sat, 14 Jan 2023 10:02:43 -0800 (PST) Received: by mail-ed1-x536.google.com with SMTP id v10so34232897edi.8; Sat, 14 Jan 2023 10:02:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=t6N7J2F7vZrkh1mREUzr3Uhb6M7WIvjgHrSlVsDZzcw=; b=ADIUZhCDGwtjc8id6hSSs006LIW01fTkLA7qDjjWvNb/XOV8bzMbSndCye++Bulk/E M4XvfL2Xl23aCvItGnL/eRYVDX0E1L93zYjB1XMlcBMhwuKjb91SxOPMrxoGs0EbBl8O FL3c1tBUHcdZpmNTFESAWkUgAA096Q9uwMkckxhYiDuQrUmbSSXhGOAtNvGf06fTALIA GJMHHAcitXaux2mWlnrqcdEU9/Dq7yOdZ42S4XzJd/zoVx79kOw84T63GIXAWU7NJ1Q9 v6m0S06ymhRKmMU1MTXgrWHKVacHsBhc5kw/YbFIdU7eYEQJQe+mcdLMwhMcWOTj3ooa fpTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=t6N7J2F7vZrkh1mREUzr3Uhb6M7WIvjgHrSlVsDZzcw=; b=WXiJKmtm47MFbXtklcGjoqc39zWMwUXHoPDLdLRo3787WzxhxMuUbvfltlgv8FheN6 z+aL0kAszChvx9JJUm/Mr7UUgPPH1HBLp61miL4Ygq4qrCfamhdqSAmH/phhYmr489/C 3r8khWvtKQ3Gv20T9jZ52Dt4H3560QQ/lPKKiSKVQnDRKFqGfJ2rik17X4aQDJzRJdGH n93yAdtblEu0yZY/adz4QBEAbzU3h769vHMK5KopkDj5eektOHfpoiGQ9iAkXvb6QZpz suqdZ9ckHA3oBauXhI3kHBpySWr4kXqUSUor8zj573OjLxXTVLtqF5L5yl4oCa3jzh5P SN0A== X-Gm-Message-State: AFqh2kpjY+8t68D8VvB/JzOCdyAZ6jkpgUeeu9C5Sr5DD81tBRwlgCEW 22nOctwCPVBj0j5TPxHA1U5qrTYcI+YSwg== X-Google-Smtp-Source: AMrXdXt4I50W/aoCUj/+8khUmGwAPDrxlvImYlI3YLhe5z/06Iv/bo4RMdGoLE+iWHrsHTFenLGnXg== X-Received: by 2002:a05:6402:b55:b0:49d:d8ec:cbd3 with SMTP id bx21-20020a0564020b5500b0049dd8eccbd3mr2165859edb.16.1673719362094; Sat, 14 Jan 2023 10:02:42 -0800 (PST) Received: from f.. (cst-prg-72-175.cust.vodafone.cz. [46.135.72.175]) by smtp.gmail.com with ESMTPSA id eg49-20020a05640228b100b00488117821ffsm9623220edb.31.2023.01.14.10.02.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Jan 2023 10:02:41 -0800 (PST) From: Mateusz Guzik To: viro@zeniv.linux.org.uk Cc: serge@hallyn.com, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, Mateusz Guzik Subject: [PATCH 1/2] capability: add cap_isidentical Date: Sat, 14 Jan 2023 19:02:23 +0100 Message-Id: <20230114180224.1777699-1-mjguzik@gmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org Signed-off-by: Mateusz Guzik Reviewed-by: Serge Hallyn --- 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" From patchwork Sat Jan 14 18:02:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mateusz Guzik X-Patchwork-Id: 13102082 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 047EEC3DA78 for ; Sat, 14 Jan 2023 18:02:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230364AbjANSCu (ORCPT ); Sat, 14 Jan 2023 13:02:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230231AbjANSCs (ORCPT ); Sat, 14 Jan 2023 13:02:48 -0500 Received: from mail-ej1-x634.google.com (mail-ej1-x634.google.com [IPv6:2a00:1450:4864:20::634]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ACB4CBBAC; Sat, 14 Jan 2023 10:02:46 -0800 (PST) Received: by mail-ej1-x634.google.com with SMTP id u19so59137626ejm.8; Sat, 14 Jan 2023 10:02:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DiozvCaMITGYcphAARs79W4NXPgo9KLi6rj9QC8zgn0=; b=MQ0GgH52Jyj5zgcCIKehozrBZUZmbh25poVp6JSmLbjNCBXko2KXRfE2tBAbzXvBHm ZLRh924mbrfN5cOPknP1rGaVdJe8hVMchF6KKzbQ8rqNlZ5osuFg+xyUgZ8yp3DSEeho Hmvq7UftpHgmXri1QZ14UEjZwaU+US+YtQAxytMSuJHwgKj9kz8OWG+Vr6dvXEpAJOGh hc5ulqUcWgHfNzlTG+YDIysgFZvgAZCRrUPKdXdLzq7gTAlmr3yApDj3uS99J5p0RC7g E1yIXrPgn3mBLd6QopWJFUyq5wGJ/0ZGUmQg06PLt82JTPeHubfvMH1H5/Kh9jL8CsMv PZOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DiozvCaMITGYcphAARs79W4NXPgo9KLi6rj9QC8zgn0=; b=gCzsj9nOAdSOp3bUJLKpH3kcgA9ceb0RsGHQ3nH8JOCD8kVqPyrA/Vmd5Zz6/12Wlx gXqFNJjMj0tP5dLgroS6erGXsndNA2++JZPaS4/9cG2kJe5yoCeO42nJTM3ebhsTCyYq LWQXEKwgWlAKuh1nAJ37Esww5V3C7jVI63IxFCCVOJ1rqsxyzjp96zdp2+Hnsby0Acru 6itGklF0XbBjrlSDwyJurzxPHIEDkRkkxDDYtwPpO/OjeClBJQbjXqc0c/1gMaSUtiBJ 3iW5dUHV3/7JMKXlr44QhnPpgKbRzb89PFWIRIpJOfUv6lL+XloL/nasQK3AVlcnCMTq 1pAg== X-Gm-Message-State: AFqh2kr2pEU2To/wxe8F7aDoFUhyMUIZpP2MiqqboxvGIfBlRokbNUZW QJoGgWHQrbyRWf1q/pzxjwDTKJFSwcU8cg== X-Google-Smtp-Source: AMrXdXvxblpBKmoNatgiUxhFRIC67gOWDs1S1NoDlVjEM36jINCaabw638IbXCrDRlwdQPn5E7yZ6A== X-Received: by 2002:a17:907:6e16:b0:7c1:b64:e290 with SMTP id sd22-20020a1709076e1600b007c10b64e290mr126029725ejc.45.1673719365211; Sat, 14 Jan 2023 10:02:45 -0800 (PST) Received: from f.. (cst-prg-72-175.cust.vodafone.cz. [46.135.72.175]) by smtp.gmail.com with ESMTPSA id eg49-20020a05640228b100b00488117821ffsm9623220edb.31.2023.01.14.10.02.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 14 Jan 2023 10:02:44 -0800 (PST) From: Mateusz Guzik To: viro@zeniv.linux.org.uk Cc: serge@hallyn.com, torvalds@linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, Mateusz Guzik Subject: [PATCH 2/2] vfs: avoid duplicating creds in faccessat if possible Date: Sat, 14 Jan 2023 19:02:24 +0100 Message-Id: <20230114180224.1777699-2-mjguzik@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230114180224.1777699-1-mjguzik@gmail.com> References: <20230114180224.1777699-1-mjguzik@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org 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 --- 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;