From patchwork Fri Sep 4 16:05:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292046 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2D59AC2D0A8 for ; Fri, 4 Sep 2020 16:07:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0388620796 for ; Fri, 4 Sep 2020 16:07:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235647; bh=sobu7xDFkZQz7KqnZh/wH8XJsv7HJQlIH+zyiccpZxs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=W5mkud3RU94EoRDjxEC7/0e5vO89NjL4Fn6SyTm2JRANd0EgG02Yp15S1M3f+VbP6 ArZAjcG0S2zNzR/Ck6K1HRjQWFGsIKuvH1kfmx/XPU7EX9b8En9ML2ypyDKbwJ5L5l hYDY+kfWEUuFAPkhBKblXBccLnIf98hgF7SqDrIU= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727907AbgIDQFq (ORCPT ); Fri, 4 Sep 2020 12:05:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:51274 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726290AbgIDQFm (ORCPT ); Fri, 4 Sep 2020 12:05:42 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 589A920796; Fri, 4 Sep 2020 16:05:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235541; bh=sobu7xDFkZQz7KqnZh/wH8XJsv7HJQlIH+zyiccpZxs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EivLGo3n5tIfxDfgklPGFg6ULETyqygWKwRKt/SAk228b+awKR6ZufBV5NyPoQz/r h5tEjzb7NoSOsxyhJb4VnqKAZNQkiRGdWQCCQU06Kg+1mBRJHWHq4JDOzxt3qcFoRO 1oq7PXvx6puRZPPfdauOkRcYtvDIHKdHBs5hrhNc= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 01/18] vfs: export new_inode_pseudo Date: Fri, 4 Sep 2020 12:05:20 -0400 Message-Id: <20200904160537.76663-2-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Ceph needs to be able to allocate inodes ahead of a create that might involve a fscrypt-encrypted inode. new_inode() almost fits the bill, but it puts the inode on the sb->s_inodes list, and we don't want to do that until we're ready to insert it into the hash. Signed-off-by: Jeff Layton --- fs/inode.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/inode.c b/fs/inode.c index 72c4c347afb7..61554c2477ab 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -935,6 +935,7 @@ struct inode *new_inode_pseudo(struct super_block *sb) } return inode; } +EXPORT_SYMBOL(new_inode_pseudo); /** * new_inode - obtain an inode From patchwork Fri Sep 4 16:05:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292050 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B6F74C433E2 for ; Fri, 4 Sep 2020 16:06:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8CB732074D for ; Fri, 4 Sep 2020 16:06:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235615; bh=S7Q7gkC4y/mbKVLHfu6ItAlaHGFIa0yb/5QJj11p7O4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=yOe1+T1V/OJT7voNoR8G41TcXxgfTxil+q0NBQQwrkcJcTuYdv+qUZnXPoi6EwUjB rKgYV1tYIHdN8AI4sqi+SWdnJ+HOr8FSh+XoHv3PeH6CcSx7agWPP56sThBaziGNSq cFltyBU92XaJUW8GAUjEREofZx0lNbD7PdVysPFQ= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727944AbgIDQFv (ORCPT ); Fri, 4 Sep 2020 12:05:51 -0400 Received: from mail.kernel.org ([198.145.29.99]:51286 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726133AbgIDQFo (ORCPT ); Fri, 4 Sep 2020 12:05:44 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DB81720829; Fri, 4 Sep 2020 16:05:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235543; bh=S7Q7gkC4y/mbKVLHfu6ItAlaHGFIa0yb/5QJj11p7O4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sF1KHYIOBOk45vkSwYkgisnkVju59uD1dVu+2SDJs1fhTM0AIndCw2vFh5Be5cFKt 4C3bz/69k0FNsefEWbAzSTMGM4IW7RIuFFUXIcQRd9aMGHhPwQutWWQGZoT1MOv5Aj pzdV+XbNDpv2dOYLm/+2lT4UXZSDi9nKQcVDyW/0= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 03/18] fscrypt: export fscrypt_d_revalidate Date: Fri, 4 Sep 2020 12:05:22 -0400 Message-Id: <20200904160537.76663-4-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org ceph already has its own d_revalidate op so we can't rely on fscrypt using that directly. Export this symbol so filesystems can call it from their own d_revalidate op. Signed-off-by: Jeff Layton --- fs/crypto/fname.c | 3 ++- include/linux/fscrypt.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 47bcfddb278b..9440a44e24ac 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -538,7 +538,7 @@ EXPORT_SYMBOL_GPL(fscrypt_fname_siphash); * Validate dentries in encrypted directories to make sure we aren't potentially * caching stale dentries after a key has been added. */ -static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) +int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) { struct dentry *dir; int err; @@ -577,6 +577,7 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) return valid; } +EXPORT_SYMBOL_GPL(fscrypt_d_revalidate); const struct dentry_operations fscrypt_d_ops = { .d_revalidate = fscrypt_d_revalidate, diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 81d6ded24328..16d673c50448 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -208,6 +208,7 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, bool fscrypt_match_name(const struct fscrypt_name *fname, const u8 *de_name, u32 de_name_len); u64 fscrypt_fname_siphash(const struct inode *dir, const struct qstr *name); +int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags); /* bio.c */ void fscrypt_decrypt_bio(struct bio *bio); From patchwork Fri Sep 4 16:05:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292045 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DE357C2D0E2 for ; Fri, 4 Sep 2020 16:07:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id AB571207EA for ; Fri, 4 Sep 2020 16:07:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235654; bh=maObR0k26i6l3VCpSdPMc8EVkXArEVCA/NN/0sCTNA0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=LSqNc/E9xnUf7kR8iXuVSUuQaLI/dbcAFp+WFQGwIqjb6uEyytPCJoFu7LJDcoQip naHYnrR7WDpxRShZf6y4Ig6RhoaVlpOi7Ut55e735e5MgcawjIVryjduZXmP2ucdNZ T1xEtGJsdgKK80bWWN3cfb4tHVDkXb0qzg5x+l/g= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728108AbgIDQHd (ORCPT ); Fri, 4 Sep 2020 12:07:33 -0400 Received: from mail.kernel.org ([198.145.29.99]:51296 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727847AbgIDQFo (ORCPT ); Fri, 4 Sep 2020 12:05:44 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 92E512083B; Fri, 4 Sep 2020 16:05:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235544; bh=maObR0k26i6l3VCpSdPMc8EVkXArEVCA/NN/0sCTNA0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pg9ij8vOQRPizxmWVnptpV6RM0q4rhKsZ+wnI/bN/C9Zh/oLjAjBRCsBA6Ipq1VKr fw7x7feDUr4vsdgZJJHr1q0kuUNdf/4JsgTGXl7/na1HMHhErgSyCH1Zmrb1B9L7qr 9cuwfWAW1HE56YHPlmMY3qT35TsvIIHZmIxLOwIo= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 04/18] fscrypt: add fscrypt_new_context_from_inode Date: Fri, 4 Sep 2020 12:05:23 -0400 Message-Id: <20200904160537.76663-5-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org CephFS will need to be able to generate a context for a new "prepared" inode. Add a new routine for getting the context out of an in-core inode. Signed-off-by: Jeff Layton --- fs/crypto/policy.c | 20 ++++++++++++++++++++ include/linux/fscrypt.h | 1 + 2 files changed, 21 insertions(+) diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index c56ad886f7d7..10eddd113a21 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -670,6 +670,26 @@ int fscrypt_set_context(struct inode *inode, void *fs_data) } EXPORT_SYMBOL_GPL(fscrypt_set_context); +/** + * fscrypt_context_from_inode() - fetch the encryption context out of in-core inode + * @ctx: where context should be written + * @inode: inode from which to fetch context + * + * Given an in-core prepared, but not-necessarily fully-instantiated inode, + * generate an encryption context from its policy and write it to ctx. + * + * Returns size of the context. + */ +int fscrypt_new_context_from_inode(union fscrypt_context *ctx, struct inode *inode) +{ + struct fscrypt_info *ci = inode->i_crypt_info; + + BUILD_BUG_ON(sizeof(*ctx) != FSCRYPT_SET_CONTEXT_MAX_SIZE); + + return fscrypt_new_context_from_policy(ctx, &ci->ci_policy, ci->ci_nonce); +} +EXPORT_SYMBOL_GPL(fscrypt_new_context_from_inode); + /** * fscrypt_set_test_dummy_encryption() - handle '-o test_dummy_encryption' * @sb: the filesystem on which test_dummy_encryption is being specified diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 16d673c50448..0ddbd27a2e58 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -157,6 +157,7 @@ int fscrypt_ioctl_get_policy_ex(struct file *filp, void __user *arg); int fscrypt_ioctl_get_nonce(struct file *filp, void __user *arg); int fscrypt_has_permitted_context(struct inode *parent, struct inode *child); int fscrypt_set_context(struct inode *inode, void *fs_data); +int fscrypt_new_context_from_inode(union fscrypt_context *ctx, struct inode *inode); struct fscrypt_dummy_context { const union fscrypt_context *ctx; From patchwork Fri Sep 4 16:05:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292047 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1D94FC433E2 for ; Fri, 4 Sep 2020 16:07:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D560A20772 for ; Fri, 4 Sep 2020 16:07:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235638; bh=3MYNF7bBsJX+WWzvNJzDftLayX5rr+SPepr6lTi27zA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=ciOA2wIhM6b/XzkcRl41GbIKrXWkrRuhFrA+Qe5lq2JPgliVRMpkCzwkcwy+LVxag rrabVKoKhgfxLKSAmUf9LUr2qLkjZv+7udLlpzJu3Vjhru0aQSD9aSgXow02bc98Hs bosn5xmKFnwrTmLFK7NslbHy0pRWIrN6ZkpcbVqE= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728091AbgIDQHQ (ORCPT ); Fri, 4 Sep 2020 12:07:16 -0400 Received: from mail.kernel.org ([198.145.29.99]:51296 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726290AbgIDQFq (ORCPT ); Fri, 4 Sep 2020 12:05:46 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A2A7120796; Fri, 4 Sep 2020 16:05:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235546; bh=3MYNF7bBsJX+WWzvNJzDftLayX5rr+SPepr6lTi27zA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CHKuSZBgVxvHLb1Zl1piBkAmgeaYcow+WbwN9BfDFRRof/urxpSufQBwb9ugCHqxm qH4VoFa2z228iW9+IWP5mWyj8Lf0iav+4EYU6+Vh1WTZGXzfBJQPRPB2tokUDyOIHE z2a3TRzkUzDzFi+n9Fy7Jae2TgrEcCWhUp5Pap/o= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 07/18] lib: lift fscrypt base64 conversion into lib/ Date: Fri, 4 Sep 2020 12:05:26 -0400 Message-Id: <20200904160537.76663-8-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Once we allow encrypted filenames on ceph we'll end up with names that may have illegal characters in them (embedded '\0' or '/'), or characters that aren't printable. It will be safer to use strings that are printable. It turns out that the MDS doesn't really care about the length of filenames, so we can just base64 encode and decode filenames before writing and reading them. Lift the base64 implementation that's in fscrypt into lib/. Make fscrypt select it when it's enabled. Signed-off-by: Jeff Layton --- fs/crypto/Kconfig | 1 + fs/crypto/fname.c | 64 ++------------------------------ include/linux/base64_fname.h | 11 ++++++ lib/Kconfig | 3 ++ lib/Makefile | 1 + lib/base64_fname.c | 71 ++++++++++++++++++++++++++++++++++++ 6 files changed, 90 insertions(+), 61 deletions(-) create mode 100644 include/linux/base64_fname.h create mode 100644 lib/base64_fname.c diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index a5f5c30368a2..6b27d105420c 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -6,6 +6,7 @@ config FS_ENCRYPTION select CRYPTO_SKCIPHER select CRYPTO_LIB_SHA256 select KEYS + select BASE64_FNAME help Enable encryption of files and directories. This feature is similar to ecryptfs, but it is more memory diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 09f09def87fc..89e26e923547 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -11,6 +11,7 @@ * This has not yet undergone a rigorous security audit. */ +#include #include #include #include @@ -184,64 +185,6 @@ static int fname_decrypt(const struct inode *inode, return 0; } -static const char lookup_table[65] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; - -#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) - -/** - * base64_encode() - base64-encode some bytes - * @src: the bytes to encode - * @len: number of bytes to encode - * @dst: (output) the base64-encoded string. Not NUL-terminated. - * - * Encodes the input string using characters from the set [A-Za-z0-9+,]. - * The encoded string is roughly 4/3 times the size of the input string. - * - * Return: length of the encoded string - */ -static int base64_encode(const u8 *src, int len, char *dst) -{ - int i, bits = 0, ac = 0; - char *cp = dst; - - for (i = 0; i < len; i++) { - ac += src[i] << bits; - bits += 8; - do { - *cp++ = lookup_table[ac & 0x3f]; - ac >>= 6; - bits -= 6; - } while (bits >= 6); - } - if (bits) - *cp++ = lookup_table[ac & 0x3f]; - return cp - dst; -} - -static int base64_decode(const char *src, int len, u8 *dst) -{ - int i, bits = 0, ac = 0; - const char *p; - u8 *cp = dst; - - for (i = 0; i < len; i++) { - p = strchr(lookup_table, src[i]); - if (p == NULL || src[i] == 0) - return -2; - ac += (p - lookup_table) << bits; - bits += 6; - if (bits >= 8) { - *cp++ = ac & 0xff; - ac >>= 8; - bits -= 8; - } - } - if (ac) - return -1; - return cp - dst; -} - bool fscrypt_fname_encrypted_size(const struct inode *inode, u32 orig_len, u32 max_len, u32 *encrypted_len_ret) { @@ -335,7 +278,7 @@ void fscrypt_encode_nokey_name(u32 hash, u32 minor_hash, nokey_name.sha256); size = FSCRYPT_NOKEY_NAME_MAX; } - oname->len = base64_encode((const u8 *)&nokey_name, size, oname->name); + oname->len = base64_encode_fname((const u8 *)&nokey_name, size, oname->name); } EXPORT_SYMBOL(fscrypt_encode_nokey_name); @@ -380,7 +323,6 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, if (fscrypt_has_encryption_key(inode)) return fname_decrypt(inode, iname, oname); - fscrypt_encode_nokey_name(hash, minor_hash, iname, oname); return 0; } EXPORT_SYMBOL(fscrypt_fname_disk_to_usr); @@ -460,7 +402,7 @@ int fscrypt_setup_filename(struct inode *dir, const struct qstr *iname, if (fname->crypto_buf.name == NULL) return -ENOMEM; - ret = base64_decode(iname->name, iname->len, fname->crypto_buf.name); + ret = base64_decode_fname(iname->name, iname->len, fname->crypto_buf.name); if (ret < (int)offsetof(struct fscrypt_nokey_name, bytes[1]) || (ret > offsetof(struct fscrypt_nokey_name, sha256) && ret != FSCRYPT_NOKEY_NAME_MAX)) { diff --git a/include/linux/base64_fname.h b/include/linux/base64_fname.h new file mode 100644 index 000000000000..d98d79b4c95c --- /dev/null +++ b/include/linux/base64_fname.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef _LIB_BASE64_FNAME_H +#define _LIB_BASE64_FNAME_H +#include + +#define BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) + +int base64_encode_fname(const u8 *src, int len, char *dst); +int base64_decode_fname(const char *src, int len, u8 *dst); +#endif /* _LIB_BASE64_FNAME_H */ diff --git a/lib/Kconfig b/lib/Kconfig index b4b98a03ff98..94f3939c4cfa 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -684,3 +684,6 @@ config GENERIC_LIB_UCMPDI2 config PLDMFW bool default n + +config BASE64_FNAME + tristate diff --git a/lib/Makefile b/lib/Makefile index a4a4c6864f51..4e77167d6252 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -171,6 +171,7 @@ obj-$(CONFIG_LIBCRC32C) += libcrc32c.o obj-$(CONFIG_CRC8) += crc8.o obj-$(CONFIG_XXHASH) += xxhash.o obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o +obj-$(CONFIG_BASE64_FNAME) += base64_fname.o obj-$(CONFIG_842_COMPRESS) += 842/ obj-$(CONFIG_842_DECOMPRESS) += 842/ diff --git a/lib/base64_fname.c b/lib/base64_fname.c new file mode 100644 index 000000000000..7638c45e4035 --- /dev/null +++ b/lib/base64_fname.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Modified base64 encode/decode functions, suitable for use as filename components. + * + * Originally lifted from fs/crypto/fname.c + * + * Copyright (C) 2015, Jaegeuk Kim + * Copyright (C) 2015, Eric Biggers + */ + +#include +#include +#include + +static const char lookup_table[65] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; + +/** + * base64_encode() - base64-encode some bytes + * @src: the bytes to encode + * @len: number of bytes to encode + * @dst: (output) the base64-encoded string. Not NUL-terminated. + * + * Encodes the input string using characters from the set [A-Za-z0-9+,]. + * The encoded string is roughly 4/3 times the size of the input string. + * + * Return: length of the encoded string + */ +int base64_encode_fname(const u8 *src, int len, char *dst) +{ + int i, bits = 0, ac = 0; + char *cp = dst; + + for (i = 0; i < len; i++) { + ac += src[i] << bits; + bits += 8; + do { + *cp++ = lookup_table[ac & 0x3f]; + ac >>= 6; + bits -= 6; + } while (bits >= 6); + } + if (bits) + *cp++ = lookup_table[ac & 0x3f]; + return cp - dst; +} +EXPORT_SYMBOL(base64_encode_fname); + +int base64_decode_fname(const char *src, int len, u8 *dst) +{ + int i, bits = 0, ac = 0; + const char *p; + u8 *cp = dst; + + for (i = 0; i < len; i++) { + p = strchr(lookup_table, src[i]); + if (p == NULL || src[i] == 0) + return -2; + ac += (p - lookup_table) << bits; + bits += 6; + if (bits >= 8) { + *cp++ = ac & 0xff; + ac >>= 8; + bits -= 8; + } + } + if (ac) + return -1; + return cp - dst; +} +EXPORT_SYMBOL(base64_decode_fname); From patchwork Fri Sep 4 16:05:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292048 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 29C03C2D0A7 for ; Fri, 4 Sep 2020 16:07:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id F100D20772 for ; Fri, 4 Sep 2020 16:07:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235635; bh=wsDcZ4XR+68ZukfnEVYNdgpLxaWJy4Nq3uQQP/TS/+A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=fTgavIsoL+6noKvGHBv4ZxpiCJGpbGYg6KEKge81m+/j4vSfGKkfpIJnwIgvlKSqj 7WSQSxwHh02nua+rXsKaA/BXgjs4Xi/3p16QVdZxVm04fcFd0cu0+Qy4LOIizmTGma xIzO0LY7XMMN7tVHlR2RJ9YWOXc2zT9i4eSCaMVU= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728075AbgIDQHI (ORCPT ); Fri, 4 Sep 2020 12:07:08 -0400 Received: from mail.kernel.org ([198.145.29.99]:51326 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727921AbgIDQFr (ORCPT ); Fri, 4 Sep 2020 12:05:47 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id EBA242084D; Fri, 4 Sep 2020 16:05:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235547; bh=wsDcZ4XR+68ZukfnEVYNdgpLxaWJy4Nq3uQQP/TS/+A=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=f2sBV44zOumafv2ypv0U35LubffPLvzIAmsLVYTLOFa+YlKup0EdNiuDLMNLIFMkf q+7R99BGS9k1/i/1NdVscyMnnt66kMnF9PlmhVCxVBdSy3aaG23pl+ckhNnyTQjEYZ 53OyPc93SVXuXwjrSJFwPGS95ROTYiL760oEAlK4= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 09/18] ceph: crypto context handling for ceph Date: Fri, 4 Sep 2020 12:05:28 -0400 Message-Id: <20200904160537.76663-10-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Store the fscrypt context for an inode as an encryption.ctx xattr. Also add support for "dummy" encryption (useful for testing with automated test harnesses like xfstests). Signed-off-by: Jeff Layton --- fs/ceph/Makefile | 1 + fs/ceph/crypto.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/ceph/crypto.h | 24 +++++++++++++++++ fs/ceph/inode.c | 1 + fs/ceph/super.c | 37 ++++++++++++++++++++++++++ fs/ceph/super.h | 7 ++++- 6 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 fs/ceph/crypto.c create mode 100644 fs/ceph/crypto.h diff --git a/fs/ceph/Makefile b/fs/ceph/Makefile index 50c635dc7f71..1f77ca04c426 100644 --- a/fs/ceph/Makefile +++ b/fs/ceph/Makefile @@ -12,3 +12,4 @@ ceph-y := super.o inode.o dir.o file.o locks.o addr.o ioctl.o \ ceph-$(CONFIG_CEPH_FSCACHE) += cache.o ceph-$(CONFIG_CEPH_FS_POSIX_ACL) += acl.o +ceph-$(CONFIG_FS_ENCRYPTION) += crypto.o diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c new file mode 100644 index 000000000000..22a09d422b72 --- /dev/null +++ b/fs/ceph/crypto.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +#include "super.h" +#include "crypto.h" + +static int ceph_crypt_get_context(struct inode *inode, void *ctx, size_t len) +{ + int ret = __ceph_getxattr(inode, CEPH_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len); + + if (ret > 0) + inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED); + return ret; +} + +static int ceph_crypt_set_context(struct inode *inode, const void *ctx, size_t len, void *fs_data) +{ + int ret; + + WARN_ON_ONCE(fs_data); + ret = __ceph_setxattr(inode, CEPH_XATTR_NAME_ENCRYPTION_CONTEXT, ctx, len, XATTR_CREATE); + if (ret == 0) + inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED); + return ret; +} + +static bool ceph_crypt_empty_dir(struct inode *inode) +{ + struct ceph_inode_info *ci = ceph_inode(inode); + + return ci->i_rsubdirs + ci->i_rfiles == 1; +} + +static const union fscrypt_context * +ceph_get_dummy_context(struct super_block *sb) +{ + return ceph_sb_to_client(sb)->dummy_enc_ctx.ctx; +} + +static struct fscrypt_operations ceph_fscrypt_ops = { + .key_prefix = "ceph:", + .get_context = ceph_crypt_get_context, + .set_context = ceph_crypt_set_context, + .get_dummy_context = ceph_get_dummy_context, + .empty_dir = ceph_crypt_empty_dir, + .max_namelen = NAME_MAX, +}; + +int ceph_fscrypt_set_ops(struct super_block *sb) +{ + struct ceph_fs_client *fsc = sb->s_fs_info; + + fscrypt_set_ops(sb, &ceph_fscrypt_ops); + + if (ceph_test_mount_opt(fsc, TEST_DUMMY_ENC)) { + substring_t arg = { }; + + /* Ewwwwwwww */ + if (fsc->mount_options->test_dummy_encryption) { + arg.from = fsc->mount_options->test_dummy_encryption; + arg.to = arg.from + strlen(arg.from) - 1; + } + + return fscrypt_set_test_dummy_encryption(sb, &arg, &fsc->dummy_enc_ctx); + } + return 0; +} diff --git a/fs/ceph/crypto.h b/fs/ceph/crypto.h new file mode 100644 index 000000000000..af06dca5f5a6 --- /dev/null +++ b/fs/ceph/crypto.h @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Ceph fscrypt functionality + */ + +#ifndef _CEPH_CRYPTO_H +#define _CEPH_CRYPTO_H + +#ifdef CONFIG_FS_ENCRYPTION + +#define CEPH_XATTR_NAME_ENCRYPTION_CONTEXT "encryption.ctx" + +int ceph_fscrypt_set_ops(struct super_block *sb); + +#else /* CONFIG_FS_ENCRYPTION */ + +static inline int ceph_fscrypt_set_ops(struct super_block *sb) +{ + return 0; +} + +#endif /* CONFIG_FS_ENCRYPTION */ + +#endif diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 156b98bda6aa..a527c5dbf93f 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -543,6 +543,7 @@ void ceph_evict_inode(struct inode *inode) dout("evict_inode %p ino %llx.%llx\n", inode, ceph_vinop(inode)); + fscrypt_put_encryption_info(inode); truncate_inode_pages_final(&inode->i_data); clear_inode(inode); diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 7ec0e6d03d10..95f5a7cf60f2 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -20,6 +20,7 @@ #include "super.h" #include "mds_client.h" #include "cache.h" +#include "crypto.h" #include #include @@ -44,6 +45,7 @@ static void ceph_put_super(struct super_block *s) struct ceph_fs_client *fsc = ceph_sb_to_client(s); dout("put_super\n"); + fscrypt_free_dummy_context(&fsc->dummy_enc_ctx); ceph_mdsc_close_sessions(fsc->mdsc); } @@ -159,6 +161,7 @@ enum { Opt_quotadf, Opt_copyfrom, Opt_wsync, + Opt_test_dummy_encryption, }; enum ceph_recover_session_mode { @@ -197,6 +200,8 @@ static const struct fs_parameter_spec ceph_mount_parameters[] = { fsparam_u32 ("rsize", Opt_rsize), fsparam_string ("snapdirname", Opt_snapdirname), fsparam_string ("source", Opt_source), + fsparam_flag_no ("test_dummy_encryption", Opt_test_dummy_encryption), + fsparam_string ("test_dummy_encryption", Opt_test_dummy_encryption), fsparam_u32 ("wsize", Opt_wsize), fsparam_flag_no ("wsync", Opt_wsync), {} @@ -455,6 +460,21 @@ static int ceph_parse_mount_param(struct fs_context *fc, else fsopt->flags |= CEPH_MOUNT_OPT_ASYNC_DIROPS; break; + case Opt_test_dummy_encryption: + kfree(fsopt->test_dummy_encryption); + fsopt->test_dummy_encryption = NULL; + if (!result.negated) { +#ifdef CONFIG_FS_ENCRYPTION + fsopt->test_dummy_encryption = param->string; + param->string = NULL; + fsopt->flags |= CEPH_MOUNT_OPT_TEST_DUMMY_ENC; +#else + return warnfc(fc, "FS encryption not supported: test_dummy_encryption mount option ignored"); +#endif + } else { + fsopt->flags &= ~CEPH_MOUNT_OPT_TEST_DUMMY_ENC; + } + break; default: BUG(); } @@ -474,6 +494,7 @@ static void destroy_mount_options(struct ceph_mount_options *args) kfree(args->mds_namespace); kfree(args->server_path); kfree(args->fscache_uniq); + kfree(args->test_dummy_encryption); kfree(args); } @@ -581,6 +602,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) if (fsopt->flags & CEPH_MOUNT_OPT_ASYNC_DIROPS) seq_puts(m, ",nowsync"); + fscrypt_show_test_dummy_encryption(m, ',', root->d_sb); + if (fsopt->wsize != CEPH_MAX_WRITE_SIZE) seq_printf(m, ",wsize=%u", fsopt->wsize); if (fsopt->rsize != CEPH_MAX_READ_SIZE) @@ -984,7 +1007,12 @@ static int ceph_set_super(struct super_block *s, struct fs_context *fc) s->s_time_min = 0; s->s_time_max = U32_MAX; + ret = ceph_fscrypt_set_ops(s); + if (ret) + goto out; + ret = set_anon_super_fc(s, fc); +out: if (ret != 0) fsc->sb = NULL; return ret; @@ -1140,6 +1168,15 @@ static int ceph_reconfigure_fc(struct fs_context *fc) else ceph_clear_mount_opt(fsc, ASYNC_DIROPS); + /* Don't allow test_dummy_encryption to change on remount */ + if (fsopt->flags & CEPH_MOUNT_OPT_TEST_DUMMY_ENC) { + if (!ceph_test_mount_opt(fsc, TEST_DUMMY_ENC)) + return -EEXIST; + } else { + if (ceph_test_mount_opt(fsc, TEST_DUMMY_ENC)) + return -EEXIST; + } + sync_filesystem(fc->root->d_sb); return 0; } diff --git a/fs/ceph/super.h b/fs/ceph/super.h index b3aa2395b66e..3b8ffa6aee46 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -44,6 +45,7 @@ #define CEPH_MOUNT_OPT_NOQUOTADF (1<<13) /* no root dir quota in statfs */ #define CEPH_MOUNT_OPT_NOCOPYFROM (1<<14) /* don't use RADOS 'copy-from' op */ #define CEPH_MOUNT_OPT_ASYNC_DIROPS (1<<15) /* allow async directory ops */ +#define CEPH_MOUNT_OPT_TEST_DUMMY_ENC (1<<16) /* enable dummy encryption (for testing) */ #define CEPH_MOUNT_OPT_DEFAULT \ (CEPH_MOUNT_OPT_DCACHE | \ @@ -96,6 +98,7 @@ struct ceph_mount_options { char *mds_namespace; /* default NULL */ char *server_path; /* default NULL (means "/") */ char *fscache_uniq; /* default NULL */ + char *test_dummy_encryption; /* default NULL */ }; struct ceph_fs_client { @@ -135,9 +138,11 @@ struct ceph_fs_client { #ifdef CONFIG_CEPH_FSCACHE struct fscache_cookie *fscache; #endif +#ifdef CONFIG_FS_ENCRYPTION + struct fscrypt_dummy_context dummy_enc_ctx; +#endif }; - /* * File i/o capability. This tracks shared state with the metadata * server that allows us to cache or writeback attributes or to read From patchwork Fri Sep 4 16:05:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292054 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B53CFC43461 for ; Fri, 4 Sep 2020 16:05:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7655F20795 for ; Fri, 4 Sep 2020 16:05:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235558; bh=Vm1FyzMQU/O7cTuNSaRa0kNv1PUJicqdpP9d6XlsDd0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=ONC2eq/0hfxLSYzQey7UGxmaaM3zpoByXn2Pbh3Tv1Wm48LW1weKLiojxKD3O5cDE oRKk/AEQkG/IEkMANpYivi4r6iNSzCSP9FDQZ956IjVCv/ZWA6ifs+ushu1Qqs35eA gOTl6j2KTU13nWDGxjC/LuynciTePZbNw8X7xAAU= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727977AbgIDQFz (ORCPT ); Fri, 4 Sep 2020 12:05:55 -0400 Received: from mail.kernel.org ([198.145.29.99]:51362 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727924AbgIDQFt (ORCPT ); Fri, 4 Sep 2020 12:05:49 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id A0CB120772; Fri, 4 Sep 2020 16:05:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235548; bh=Vm1FyzMQU/O7cTuNSaRa0kNv1PUJicqdpP9d6XlsDd0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lw7jeKVdO1aadURhNWlSJGc102/FDJS3X0RpH7p6m08x5X1xUrNuVUPVPx4t8pAJP YOQOzb/3eBY3aBQTADre1TLmui1AwKQ+oyJwpteYDNCpx1IQ1FMX6bLOz10TVa8W1Y 3xE4nBTlrHK9NXXiULw3Kd95uJgyfshvVD67O9KA= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 10/18] ceph: preallocate inode for ops that may create one Date: Fri, 4 Sep 2020 12:05:29 -0400 Message-Id: <20200904160537.76663-11-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org When creating a new inode, we need to determine the crypto context before we can transmit the RPC. The fscrypt API has a routine for getting a crypto context before a create occurs, but it requires an inode. Change the ceph code to preallocate an inode in advance of a create of any sort (open(), mknod(), symlink(), etc). Move the existing code that generates the ACL and SELinux blobs into this routine since that's mostly common across all the different codepaths. In most cases, we just want to allow ceph_fill_trace to use that inode after the reply comes in, so add a new field to the MDS request for it (r_new_inode). The async create codepath is a bit different though. In that case, we want to hash the inode in advance of the RPC so that it can be used before the reply comes in. If the call subsequently fails with -EJUKEBOX, then just put the references and clean up the as_ctx. Note that with this change, we now need to regenerate the as_ctx when this occurs, but it's quite rare for it to happen. Signed-off-by: Jeff Layton --- fs/ceph/dir.c | 49 ++++++++++++++++++-------------- fs/ceph/file.c | 56 +++++++++++++++++++++++-------------- fs/ceph/inode.c | 66 +++++++++++++++++++++++++++++++++++++++----- fs/ceph/mds_client.c | 1 + fs/ceph/mds_client.h | 1 + fs/ceph/super.h | 5 +++- 6 files changed, 130 insertions(+), 48 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 040eaad9d063..b3f2741becdb 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -841,13 +841,6 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, goto out; } - err = ceph_pre_init_acls(dir, &mode, &as_ctx); - if (err < 0) - goto out; - err = ceph_security_init_secctx(dentry, mode, &as_ctx); - if (err < 0) - goto out; - dout("mknod in dir %p dentry %p mode 0%ho rdev %d\n", dir, dentry, mode, rdev); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKNOD, USE_AUTH_MDS); @@ -855,6 +848,14 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, err = PTR_ERR(req); goto out; } + + req->r_new_inode = ceph_new_inode(dir, dentry, &mode, &as_ctx); + if (IS_ERR(req->r_new_inode)) { + err = PTR_ERR(req->r_new_inode); + req->r_new_inode = NULL; + goto out_req; + } + req->r_dentry = dget(dentry); req->r_num_caps = 2; req->r_parent = dir; @@ -870,6 +871,7 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, err = ceph_mdsc_do_request(mdsc, dir, req); if (!err && !req->r_reply_info.head->is_dentry) err = ceph_handle_notrace_create(dir, dentry); +out_req: ceph_mdsc_put_request(req); out: if (!err) @@ -893,6 +895,7 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_mds_request *req; struct ceph_acl_sec_ctx as_ctx = {}; + umode_t mode = S_IFLNK | 0777; int err; if (ceph_snap(dir) != CEPH_NOSNAP) @@ -903,21 +906,24 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, goto out; } - err = ceph_security_init_secctx(dentry, S_IFLNK | 0777, &as_ctx); - if (err < 0) - goto out; - dout("symlink in dir %p dentry %p to '%s'\n", dir, dentry, dest); req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SYMLINK, USE_AUTH_MDS); if (IS_ERR(req)) { err = PTR_ERR(req); goto out; } + + req->r_new_inode = ceph_new_inode(dir, dentry, &mode, &as_ctx); + if (IS_ERR(req->r_new_inode)) { + err = PTR_ERR(req->r_new_inode); + req->r_new_inode = NULL; + goto out_req; + } + req->r_path2 = kstrdup(dest, GFP_KERNEL); if (!req->r_path2) { err = -ENOMEM; - ceph_mdsc_put_request(req); - goto out; + goto out_req; } req->r_parent = dir; set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); @@ -932,6 +938,7 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, err = ceph_mdsc_do_request(mdsc, dir, req); if (!err && !req->r_reply_info.head->is_dentry) err = ceph_handle_notrace_create(dir, dentry); +out_req: ceph_mdsc_put_request(req); out: if (err) @@ -967,13 +974,6 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) goto out; } - mode |= S_IFDIR; - err = ceph_pre_init_acls(dir, &mode, &as_ctx); - if (err < 0) - goto out; - err = ceph_security_init_secctx(dentry, mode, &as_ctx); - if (err < 0) - goto out; req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); if (IS_ERR(req)) { @@ -981,6 +981,14 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) goto out; } + mode |= S_IFDIR; + req->r_new_inode = ceph_new_inode(dir, dentry, &mode, &as_ctx); + if (IS_ERR(req->r_new_inode)) { + err = PTR_ERR(req->r_new_inode); + req->r_new_inode = NULL; + goto out_req; + } + req->r_dentry = dget(dentry); req->r_num_caps = 2; req->r_parent = dir; @@ -997,6 +1005,7 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) !req->r_reply_info.head->is_target && !req->r_reply_info.head->is_dentry) err = ceph_handle_notrace_create(dir, dentry); +out_req: ceph_mdsc_put_request(req); out: if (!err) diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 69dc9516c1f5..e15fa0df92ca 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -566,7 +566,8 @@ static void ceph_async_create_cb(struct ceph_mds_client *mdsc, ceph_mdsc_release_dir_caps(req); } -static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, +static int ceph_finish_async_create(struct inode *dir, struct inode *inode, + struct dentry *dentry, struct file *file, umode_t mode, struct ceph_mds_request *req, struct ceph_acl_sec_ctx *as_ctx, @@ -577,17 +578,12 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, struct ceph_mds_reply_inode in = { }; struct ceph_mds_reply_info_in iinfo = { .in = &in }; struct ceph_inode_info *ci = ceph_inode(dir); - struct inode *inode; struct timespec64 now; struct ceph_vino vino = { .ino = req->r_deleg_ino, .snap = CEPH_NOSNAP }; ktime_get_real_ts64(&now); - inode = ceph_get_inode(dentry->d_sb, vino); - if (IS_ERR(inode)) - return PTR_ERR(inode); - iinfo.inline_version = CEPH_INLINE_NONE; iinfo.change_attr = 1; ceph_encode_timespec64(&iinfo.btime, &now); @@ -623,8 +619,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, ceph_dir_clear_complete(dir); if (!d_unhashed(dentry)) d_drop(dentry); - if (inode->i_state & I_NEW) - discard_new_inode(inode); + discard_new_inode(inode); } else { struct dentry *dn; @@ -664,6 +659,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb); struct ceph_mds_client *mdsc = fsc->mdsc; struct ceph_mds_request *req; + struct inode *new_inode = NULL; struct dentry *dn; struct ceph_acl_sec_ctx as_ctx = {}; bool try_async = ceph_test_mount_opt(fsc, ASYNC_DIROPS); @@ -676,21 +672,21 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, if (dentry->d_name.len > NAME_MAX) return -ENAMETOOLONG; - +retry: if (flags & O_CREAT) { if (ceph_quota_is_max_files_exceeded(dir)) return -EDQUOT; - err = ceph_pre_init_acls(dir, &mode, &as_ctx); - if (err < 0) - return err; - err = ceph_security_init_secctx(dentry, mode, &as_ctx); - if (err < 0) + + new_inode = ceph_new_inode(dir, dentry, &mode, &as_ctx); + if (IS_ERR(new_inode)) { + err = PTR_ERR(new_inode); goto out_ctx; + } } else if (!d_in_lookup(dentry)) { /* If it's not being looked up, it's negative */ return -ENOENT; } -retry: + /* do the open */ req = prepare_open_request(dir->i_sb, flags, mode); if (IS_ERR(req)) { @@ -714,21 +710,38 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, req->r_pagelist = as_ctx.pagelist; as_ctx.pagelist = NULL; } - if (try_async && - (req->r_dir_caps = - try_prep_async_create(dir, dentry, &lo, - &req->r_deleg_ino))) { + + if (try_async && (req->r_dir_caps = + try_prep_async_create(dir, dentry, &lo, &req->r_deleg_ino))) { + struct ceph_vino vino = { .ino = req->r_deleg_ino, + .snap = CEPH_NOSNAP }; + set_bit(CEPH_MDS_R_ASYNC, &req->r_req_flags); req->r_args.open.flags |= cpu_to_le32(CEPH_O_EXCL); req->r_callback = ceph_async_create_cb; + + /* Hash inode before RPC */ + new_inode = ceph_get_inode(dir->i_sb, vino, new_inode); + if (IS_ERR(new_inode)) { + err = PTR_ERR(new_inode); + new_inode = NULL; + goto out_req; + } + WARN_ON_ONCE(!(new_inode->i_state & I_NEW)); + err = ceph_mdsc_submit_request(mdsc, dir, req); if (!err) { - err = ceph_finish_async_create(dir, dentry, + err = ceph_finish_async_create(dir, new_inode, dentry, file, mode, req, &as_ctx, &lo); + new_inode = NULL; } else if (err == -EJUKEBOX) { restore_deleg_ino(dir, req->r_deleg_ino); ceph_mdsc_put_request(req); + discard_new_inode(new_inode); + ceph_release_acl_sec_ctx(&as_ctx); + memset(&as_ctx, 0, sizeof(as_ctx)); + new_inode = NULL; try_async = false; goto retry; } @@ -737,6 +750,8 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, } set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); + req->r_new_inode = new_inode; + new_inode = NULL; err = ceph_mdsc_do_request(mdsc, (flags & (O_CREAT|O_TRUNC)) ? dir : NULL, req); @@ -774,6 +789,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, } out_req: ceph_mdsc_put_request(req); + iput(new_inode); out_ctx: ceph_release_acl_sec_ctx(&as_ctx); dout("atomic_open result=%d\n", err); diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index a527c5dbf93f..e3c81b950f74 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -49,15 +49,67 @@ static int ceph_set_ino_cb(struct inode *inode, void *data) return 0; } -struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino) +/** + * ceph_new_inode - allocate a new inode in advance of an expected create + * @dir: parent directory for new inode + * @mode: mode of new inode + */ +struct inode *ceph_new_inode(struct inode *dir, struct dentry *dentry, + umode_t *mode, struct ceph_acl_sec_ctx *as_ctx) { + int err; struct inode *inode; - inode = iget5_locked(sb, (unsigned long)vino.ino, ceph_ino_compare, - ceph_set_ino_cb, &vino); + inode = new_inode_pseudo(dir->i_sb); if (!inode) return ERR_PTR(-ENOMEM); + if (!S_ISLNK(*mode)) { + err = ceph_pre_init_acls(dir, mode, as_ctx); + if (err < 0) + goto out_err; + } + + err = ceph_security_init_secctx(dentry, *mode, as_ctx); + if (err < 0) + goto out_err; + + inode->i_state = 0; + inode->i_mode = *mode; + return inode; +out_err: + iput(inode); + return ERR_PTR(err); +} + +/** + * ceph_get_inode - find or create/hash a new inode + * @sb: superblock to search and allocate in + * @vino: vino to search for + * @new: optional new inode to insert if one isn't found (may be NULL) + * + * Search for or insert a new inode into the hash for the given vino, and return a + * reference to it. If new is non-NULL, its reference is consumed. + */ +struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino, struct inode *new) +{ + struct inode *inode; + + if (new) { + inode = inode_insert5(new, (unsigned long)vino.ino, ceph_ino_compare, + ceph_set_ino_cb, &vino); + if (inode != new) + iput(new); + } else { + inode = iget5_locked(sb, (unsigned long)vino.ino, ceph_ino_compare, + ceph_set_ino_cb, &vino); + } + + if (!inode) { + dout("No inode found for %llx.%llx\n", vino.ino, vino.snap); + return ERR_PTR(-ENOMEM); + } + dout("get_inode on %llu=%llx.%llx got %p new %d\n", ceph_present_inode(inode), ceph_vinop(inode), inode, !!(inode->i_state & I_NEW)); return inode; @@ -72,7 +124,7 @@ struct inode *ceph_get_snapdir(struct inode *parent) .ino = ceph_ino(parent), .snap = CEPH_SNAPDIR, }; - struct inode *inode = ceph_get_inode(parent->i_sb, vino); + struct inode *inode = ceph_get_inode(parent->i_sb, vino, NULL); struct ceph_inode_info *ci = ceph_inode(inode); BUG_ON(!S_ISDIR(parent->i_mode)); @@ -1313,7 +1365,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) tvino.ino = le64_to_cpu(rinfo->targeti.in->ino); tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid); - in = ceph_get_inode(sb, tvino); + in = ceph_get_inode(sb, tvino, xchg(&req->r_new_inode, NULL)); if (IS_ERR(in)) { err = PTR_ERR(in); goto done; @@ -1507,7 +1559,7 @@ static int readdir_prepopulate_inodes_only(struct ceph_mds_request *req, vino.ino = le64_to_cpu(rde->inode.in->ino); vino.snap = le64_to_cpu(rde->inode.in->snapid); - in = ceph_get_inode(req->r_dentry->d_sb, vino); + in = ceph_get_inode(req->r_dentry->d_sb, vino, NULL); if (IS_ERR(in)) { err = PTR_ERR(in); dout("new_inode badness got %d\n", err); @@ -1711,7 +1763,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, if (d_really_is_positive(dn)) { in = d_inode(dn); } else { - in = ceph_get_inode(parent->d_sb, tvino); + in = ceph_get_inode(parent->d_sb, tvino, NULL); if (IS_ERR(in)) { dout("new_inode badness\n"); d_drop(dn); diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 76d8d9495d1d..4107dc64cc8c 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -820,6 +820,7 @@ void ceph_mdsc_release_request(struct kref *kref) ceph_async_iput(req->r_parent); } ceph_async_iput(req->r_target_inode); + ceph_async_iput(req->r_new_inode); if (req->r_dentry) dput(req->r_dentry); if (req->r_old_dentry) diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 658800605bfb..63999f7db014 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -260,6 +260,7 @@ struct ceph_mds_request { struct inode *r_parent; /* parent dir inode */ struct inode *r_target_inode; /* resulting inode */ + struct inode *r_new_inode; /* new inode (for creates) */ #define CEPH_MDS_R_DIRECT_IS_HASH (1) /* r_direct_hash is valid */ #define CEPH_MDS_R_ABORTED (2) /* call was aborted */ diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 3b8ffa6aee46..d788fa9b3eaa 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -929,6 +929,7 @@ static inline bool __ceph_have_pending_cap_snap(struct ceph_inode_info *ci) /* inode.c */ struct ceph_mds_reply_info_in; struct ceph_mds_reply_dirfrag; +struct ceph_acl_sec_ctx; extern const struct inode_operations ceph_file_iops; @@ -936,8 +937,10 @@ extern struct inode *ceph_alloc_inode(struct super_block *sb); extern void ceph_evict_inode(struct inode *inode); extern void ceph_free_inode(struct inode *inode); +struct inode *ceph_new_inode(struct inode *dir, struct dentry *dentry, + umode_t *mode, struct ceph_acl_sec_ctx *as_ctx); extern struct inode *ceph_get_inode(struct super_block *sb, - struct ceph_vino vino); + struct ceph_vino vino, struct inode *new); extern struct inode *ceph_get_snapdir(struct inode *parent); extern int ceph_fill_file_size(struct inode *inode, int issued, u32 truncate_seq, u64 truncate_size, u64 size); From patchwork Fri Sep 4 16:05:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292053 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C132AC2BB84 for ; Fri, 4 Sep 2020 16:06:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 954BC20795 for ; Fri, 4 Sep 2020 16:06:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235560; bh=djcR09Qz49eEKVMn/byLIYIaDNp4Zxi+8Bn0ieaznIc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=M/IehCOI0l9Jo6VZYlVE6VN2sMeVUzCI5fw07zPRv0JMMyqFOBN26Kdncq8mkfT4O mwMs6MahjD7xcyDdgsDouB6QPRf63LH6OXDn/+W3xnC5fqswSw7rwX4qgzsJP2Uytl 8pNaR1RpqdZb0hlWWflQ4Jc1lFkmluljsCkEw9HY= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726714AbgIDQFz (ORCPT ); Fri, 4 Sep 2020 12:05:55 -0400 Received: from mail.kernel.org ([198.145.29.99]:51368 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727930AbgIDQFt (ORCPT ); Fri, 4 Sep 2020 12:05:49 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4C3DD20829; Fri, 4 Sep 2020 16:05:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235548; bh=djcR09Qz49eEKVMn/byLIYIaDNp4Zxi+8Bn0ieaznIc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S00ISbuLRv+005/DhHSOogcaJywOGDyvnnGtl4M71r2PE9KaQUkxoJLig2YKygZ7/ emhUmRpo6JSZZ56nLMoy1fJZFhqR80rqqhUDvTKKzs6mEj3LfTPBajglQ93CQdpA5j s0G99OGB8PAQ0Jq4RWHmHpoYC8hfoEq7/MZzdmAo= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 11/18] ceph: add routine to create context prior to RPC Date: Fri, 4 Sep 2020 12:05:30 -0400 Message-Id: <20200904160537.76663-12-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org After pre-creating a new inode, do an fscrypt prepare on it, fetch a new encryption context and then marshal that into the security context to be sent along with the RPC. Signed-off-by: Jeff Layton --- fs/ceph/crypto.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/ceph/crypto.h | 8 ++++++ fs/ceph/inode.c | 10 ++++++-- fs/ceph/super.h | 3 +++ 4 files changed, 82 insertions(+), 2 deletions(-) diff --git a/fs/ceph/crypto.c b/fs/ceph/crypto.c index 22a09d422b72..f4849f8b32df 100644 --- a/fs/ceph/crypto.c +++ b/fs/ceph/crypto.c @@ -67,3 +67,66 @@ int ceph_fscrypt_set_ops(struct super_block *sb) } return 0; } + +int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, + struct ceph_acl_sec_ctx *as) +{ + int ret, ctxsize; + size_t name_len; + char *name; + struct ceph_pagelist *pagelist = as->pagelist; + bool encrypted = false; + + ret = fscrypt_prepare_new_inode(dir, inode, &encrypted); + if (ret) + return ret; + if (!encrypted) + return 0; + + inode_set_flags(inode, S_ENCRYPTED, S_ENCRYPTED); + + /* No need to set context for dummy encryption */ + if (fscrypt_get_dummy_context(inode->i_sb)) + return 0; + + ctxsize = fscrypt_new_context_from_inode((union fscrypt_context *)&as->fscrypt, inode); + + /* marshal it in page array */ + if (!pagelist) { + pagelist = ceph_pagelist_alloc(GFP_KERNEL); + if (!pagelist) + return -ENOMEM; + ret = ceph_pagelist_reserve(pagelist, PAGE_SIZE); + if (ret) + goto out; + ceph_pagelist_encode_32(pagelist, 1); + } + + name = CEPH_XATTR_NAME_ENCRYPTION_CONTEXT; + name_len = strlen(name); + ret = ceph_pagelist_reserve(pagelist, 4 * 2 + name_len + ctxsize); + if (ret) + goto out; + + if (as->pagelist) { + BUG_ON(pagelist->length <= sizeof(__le32)); + if (list_is_singular(&pagelist->head)) { + le32_add_cpu((__le32*)pagelist->mapped_tail, 1); + } else { + struct page *page = list_first_entry(&pagelist->head, + struct page, lru); + void *addr = kmap_atomic(page); + le32_add_cpu((__le32*)addr, 1); + kunmap_atomic(addr); + } + } + + ceph_pagelist_encode_32(pagelist, name_len); + ceph_pagelist_append(pagelist, name, name_len); + ceph_pagelist_encode_32(pagelist, ctxsize); + ceph_pagelist_append(pagelist, as->fscrypt, ctxsize); +out: + if (pagelist && !as->pagelist) + ceph_pagelist_release(pagelist); + return ret; +} diff --git a/fs/ceph/crypto.h b/fs/ceph/crypto.h index af06dca5f5a6..bf893bd215c3 100644 --- a/fs/ceph/crypto.h +++ b/fs/ceph/crypto.h @@ -11,6 +11,8 @@ #define CEPH_XATTR_NAME_ENCRYPTION_CONTEXT "encryption.ctx" int ceph_fscrypt_set_ops(struct super_block *sb); +int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, + struct ceph_acl_sec_ctx *as); #else /* CONFIG_FS_ENCRYPTION */ @@ -19,6 +21,12 @@ static inline int ceph_fscrypt_set_ops(struct super_block *sb) return 0; } +static inline int ceph_fscrypt_prepare_context(struct inode *dir, struct inode *inode, + struct ceph_acl_sec_ctx *as) +{ + return 0; +} + #endif /* CONFIG_FS_ENCRYPTION */ #endif diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index e3c81b950f74..651148194316 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -18,6 +18,7 @@ #include "super.h" #include "mds_client.h" #include "cache.h" +#include "crypto.h" #include /* @@ -70,12 +71,17 @@ struct inode *ceph_new_inode(struct inode *dir, struct dentry *dentry, goto out_err; } + inode->i_state = 0; + inode->i_mode = *mode; + err = ceph_security_init_secctx(dentry, *mode, as_ctx); if (err < 0) goto out_err; - inode->i_state = 0; - inode->i_mode = *mode; + err = ceph_fscrypt_prepare_context(dir, inode, as_ctx); + if (err) + goto out_err; + return inode; out_err: iput(inode); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index d788fa9b3eaa..cf04fcd3de69 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -995,6 +995,9 @@ struct ceph_acl_sec_ctx { #ifdef CONFIG_CEPH_FS_SECURITY_LABEL void *sec_ctx; u32 sec_ctxlen; +#endif +#ifdef CONFIG_FS_ENCRYPTION + u8 fscrypt[FSCRYPT_SET_CONTEXT_MAX_SIZE]; #endif struct ceph_pagelist *pagelist; }; From patchwork Fri Sep 4 16:05:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292049 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.3 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, UNWANTED_LANGUAGE_BODY, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B671FC433E2 for ; Fri, 4 Sep 2020 16:07:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8E48320772 for ; Fri, 4 Sep 2020 16:07:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235623; bh=DFOG7GZ6OylpP0sQqUAusLwuDKNBcXtVUCDGQyCRqbk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=hn2ApA1sBQVDUqBGy0Ujso/q4l1ZZETxcKSZnZBfeVejl4M6XOIrpS3G9F1Qu4HKY oWH53Dhxd2PaBWGswWRKdmGG244hhivQHX+id+1gC6psKcEqOY4iutTEe+WqEbNx60 rhBnEc7XDLHMkg4O+4/dzPey3mybm7I2LkhbZoeQ= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727889AbgIDQG7 (ORCPT ); Fri, 4 Sep 2020 12:06:59 -0400 Received: from mail.kernel.org ([198.145.29.99]:51384 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727937AbgIDQFu (ORCPT ); Fri, 4 Sep 2020 12:05:50 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 93C2120796; Fri, 4 Sep 2020 16:05:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235550; bh=DFOG7GZ6OylpP0sQqUAusLwuDKNBcXtVUCDGQyCRqbk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=veB4VermXqsC1eoPTMoZobeYYssvu+MQH3GV9hYpFf3iF1d5kBIrDiS9Y/txZFw/p 9tR/qzce/hsajAx8rm/lpWimtU1VbjSBkLXe3iYcsEHCAnHBzLrPHU3AErIaARBt5h u+AwJBXIcxwu65YBDhhBLhYcGeWoSq8lzi0q9cZ4= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 13/18] ceph: make ceph_msdc_build_path use ref-walk Date: Fri, 4 Sep 2020 12:05:32 -0400 Message-Id: <20200904160537.76663-14-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org Encryption potentially requires allocation, at which point we'll need to be in a non-atomic context. Convert ceph_msdc_build_path to take dentry spinlocks and references instead of using rcu_read_lock to walk the path. This is slightly less efficient, and we may want to eventually allow using RCU when the leaf dentry isn't encrypted. Signed-off-by: Jeff Layton --- fs/ceph/mds_client.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 4107dc64cc8c..e3dc061252d4 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2327,7 +2327,8 @@ static inline u64 __get_oldest_tid(struct ceph_mds_client *mdsc) char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, int stop_on_nosnap) { - struct dentry *temp; + struct dentry *cur; + struct inode *inode; char *path; int pos; unsigned seq; @@ -2344,34 +2345,35 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, path[pos] = '\0'; seq = read_seqbegin(&rename_lock); - rcu_read_lock(); - temp = dentry; + cur = dget(dentry); for (;;) { - struct inode *inode; + struct dentry *temp; - spin_lock(&temp->d_lock); - inode = d_inode(temp); + spin_lock(&cur->d_lock); + inode = d_inode(cur); if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { dout("build_path path+%d: %p SNAPDIR\n", - pos, temp); - } else if (stop_on_nosnap && inode && dentry != temp && + pos, cur); + } else if (stop_on_nosnap && inode && dentry != cur && ceph_snap(inode) == CEPH_NOSNAP) { - spin_unlock(&temp->d_lock); + spin_unlock(&cur->d_lock); pos++; /* get rid of any prepended '/' */ break; } else { - pos -= temp->d_name.len; + pos -= cur->d_name.len; if (pos < 0) { - spin_unlock(&temp->d_lock); + spin_unlock(&cur->d_lock); break; } - memcpy(path + pos, temp->d_name.name, temp->d_name.len); + memcpy(path + pos, cur->d_name.name, cur->d_name.len); } + temp = cur; + cur = dget(temp->d_parent); spin_unlock(&temp->d_lock); - temp = READ_ONCE(temp->d_parent); + dput(temp); /* Are we at the root? */ - if (IS_ROOT(temp)) + if (IS_ROOT(cur)) break; /* Are we out of buffer? */ @@ -2380,8 +2382,9 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, path[pos] = '/'; } - base = ceph_ino(d_inode(temp)); - rcu_read_unlock(); + inode = d_inode(cur); + base = inode ? ceph_ino(inode) : 0; + dput(cur); if (read_seqretry(&rename_lock, seq)) goto retry; From patchwork Fri Sep 4 16:05:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292051 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2055EC2D0A7 for ; Fri, 4 Sep 2020 16:06:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EA9DB20829 for ; Fri, 4 Sep 2020 16:06:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235607; bh=L2/V/5hUAv0dQLRJb7AhQdxLOxUodIGz52r4rMuTRRs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=Hei9VvxnQq+V9Mu6up9WeALeaCNxq8B/I0XEBhxrYMDDzadR8PCpDl81ktwgZ0xN2 AdbqupbE9LN9NuLwqA73vwZzeqnMyzJl81QDJQm6QmWf7oDD2oD03S/3NM1v5lEfIp 4YHlofwdfJH17bgnSiNimb+eqQIqhhp1JNh2R4QM= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728060AbgIDQGi (ORCPT ); Fri, 4 Sep 2020 12:06:38 -0400 Received: from mail.kernel.org ([198.145.29.99]:51326 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727952AbgIDQFv (ORCPT ); Fri, 4 Sep 2020 12:05:51 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DDA3B20772; Fri, 4 Sep 2020 16:05:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235551; bh=L2/V/5hUAv0dQLRJb7AhQdxLOxUodIGz52r4rMuTRRs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=EEgtSJ3jSaTR88quYfZvTQY3HQnGwwZan9OlEFXbWDgDoKH7NemLL0fWOU8QHrwXH /ELlAZY0oh8F/580vZbcXSccObbqQjhBGAYNSF5WVPo3+tsk7CbBJox3fObwexGNwc dIB+ldrAG1pEfrecoIp3CGdedDMwHtM1+l+mmNP0= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 15/18] ceph: make d_revalidate call fscrypt revalidator for encrypted dentries Date: Fri, 4 Sep 2020 12:05:34 -0400 Message-Id: <20200904160537.76663-16-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org If we have an encrypted dentry, then we need to test whether a new key might have been established or removed. Do that before we test anything else about the dentry. Signed-off-by: Jeff Layton --- fs/ceph/dir.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index b3f2741becdb..cc85933413b9 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1695,6 +1695,12 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags) dout("d_revalidate %p '%pd' inode %p offset 0x%llx\n", dentry, dentry, inode, ceph_dentry(dentry)->offset); + if (IS_ENCRYPTED(dir)) { + valid = fscrypt_d_revalidate(dentry, flags); + if (valid <= 0) + return valid; + } + mdsc = ceph_sb_to_client(dir->i_sb)->mdsc; /* always trust cached snapped dentries, snapdir dentry */ From patchwork Fri Sep 4 16:05:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 292052 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3A3FCC433E2 for ; Fri, 4 Sep 2020 16:06:38 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 038A32083B for ; Fri, 4 Sep 2020 16:06:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235598; bh=90Pjn6niQISxMuTZw2qsWFhkmn8VzkRJzBny3pfcgr0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=QletmSQr4ufKOcF7+PWivvNLsVkV/UWPkdAS0DSnTQydqZvDNm+LEe0AwuuOqVVyi qgJCZkVexd/Bno4G469KMfqOhZw6tADPzbdEuM4s2FgVUz0wkJeuWbg2O6ZgmlFVvF 5Hq/jRMKZiaJgmlFz4kcfn9bUKhQiouGaeeYmsZw= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726135AbgIDQGd (ORCPT ); Fri, 4 Sep 2020 12:06:33 -0400 Received: from mail.kernel.org ([198.145.29.99]:51308 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727965AbgIDQFx (ORCPT ); Fri, 4 Sep 2020 12:05:53 -0400 Received: from tleilax.com (68-20-15-154.lightspeed.rlghnc.sbcglobal.net [68.20.15.154]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 47B6820795; Fri, 4 Sep 2020 16:05:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1599235552; bh=90Pjn6niQISxMuTZw2qsWFhkmn8VzkRJzBny3pfcgr0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Wo3+ym1VH+1BCt3catzUZr2BZFJBtrQWU3YrefcJ0RhtFXzZTnahO8d6+a8uzD8/H gSSRFZDXP8kOoVUEfrT1Vmog44PEW3YbSt3VzIDWhJrsLYGoa/wGroPMhHcZsfWf6T M8lcCseF2cFWafZiawVfIjJB5BhgDgqFmIzVHgMU= From: Jeff Layton To: ceph-devel@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-fscrypt@vger.kernel.org, ebiggers@kernel.org Subject: [RFC PATCH v2 17/18] ceph: add fscrypt support to ceph_fill_trace Date: Fri, 4 Sep 2020 12:05:36 -0400 Message-Id: <20200904160537.76663-18-jlayton@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200904160537.76663-1-jlayton@kernel.org> References: <20200904160537.76663-1-jlayton@kernel.org> MIME-Version: 1.0 Sender: ceph-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: ceph-devel@vger.kernel.org When we get a dentry in a trace, decrypt the name so we can properly instantiate the dentry. Signed-off-by: Jeff Layton --- fs/ceph/inode.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 7d66f41a6592..e578e4cdcf30 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1328,6 +1328,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) !test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) { struct qstr dname; struct dentry *dn, *parent; + struct fscrypt_str oname = FSTR_INIT(NULL, 0); BUG_ON(!rinfo->head->is_target); BUG_ON(req->r_dentry); @@ -1335,8 +1336,20 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) parent = d_find_any_alias(dir); BUG_ON(!parent); - dname.name = rinfo->dname; - dname.len = rinfo->dname_len; + err = ceph_fname_alloc_buffer(dir, &oname); + if (err < 0) { + dput(parent); + goto done; + } + + err = ceph_fname_to_usr(dir, rinfo->dname, rinfo->dname_len, NULL, &oname); + if (err < 0) { + dput(parent); + ceph_fname_free_buffer(dir, &oname); + goto done; + } + dname.name = oname.name; + dname.len = oname.len; dname.hash = full_name_hash(parent, dname.name, dname.len); tvino.ino = le64_to_cpu(rinfo->targeti.in->ino); tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid); @@ -1351,9 +1364,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) dname.len, dname.name, dn); if (!dn) { dput(parent); + ceph_fname_free_buffer(dir, &oname); err = -ENOMEM; goto done; } + if (IS_ENCRYPTED(dir) && !fscrypt_has_encryption_key(dir)) { + spin_lock(&dn->d_lock); + dn->d_flags |= DCACHE_ENCRYPTED_NAME; + spin_unlock(&dn->d_lock); + } err = 0; } else if (d_really_is_positive(dn) && (ceph_ino(d_inode(dn)) != tvino.ino || @@ -1365,6 +1384,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) dput(dn); goto retry_lookup; } + ceph_fname_free_buffer(dir, &oname); req->r_dentry = dn; dput(parent);