From patchwork Wed Apr 18 18:09:47 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Biggers X-Patchwork-Id: 10348747 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 2C75E6053F for ; Wed, 18 Apr 2018 18:12:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1C2FC28478 for ; Wed, 18 Apr 2018 18:12:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0FEB32863D; Wed, 18 Apr 2018 18:12:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 737C728478 for ; Wed, 18 Apr 2018 18:12:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752689AbeDRSMz (ORCPT ); Wed, 18 Apr 2018 14:12:55 -0400 Received: from mail-pl0-f68.google.com ([209.85.160.68]:35662 "EHLO mail-pl0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752658AbeDRSMy (ORCPT ); Wed, 18 Apr 2018 14:12:54 -0400 Received: by mail-pl0-f68.google.com with SMTP id w21-v6so1593214plq.2 for ; Wed, 18 Apr 2018 11:12:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=AV/k5NHG9o96jox/mnL0divpKd2C4WTIKCu7Yr3SEIA=; b=QLl7+xb7+Q0CD2EJo8XFqnaR4PBf8ComgsxvrS104uVUqQwo99QgwgIoHgPNr59s2H 4EQAwSRxMPR0u2Ar0e5W2w6mluwQQF6y+7g+lswB5t4CaH1/c7jjQj/B6lZE5BDcZUpF FUh7HN/Rdz0i48r8bSHieypMmS89cGbijVVYJmGshOLleEIxMtNUTICA3h8bvr2Ni0rB YZOlJvU54vfgnTX4P6sa9YPviJstw/OyC8EgvdPC/qnUFSToSCQt8dIy/9LximOCZhj0 wymfJxFEgpHdS1oH5GISHCfbegg+lFoRdd8U/TJxZtSKrI1JeoeipVra+xQoVmFB7Y85 zOTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=AV/k5NHG9o96jox/mnL0divpKd2C4WTIKCu7Yr3SEIA=; b=mZNXoFu5yMQDAmoW5f+5Bb/tpY76fnpb6dm79STwkh18TGIDk7+rNTUV15w1kQguwU 9fJKdQZeKe2xtGbEEWgwGRaJQ5kTC5Uz064+boQQc+78KlNckeU1hfETwfKY1r2Bnug8 epxIrniMetMZjLzGgPftEmsyzeL1veRYkFFnThx2v/nq0RIRNyhDLWTailwD74cer01b nEYe6DvMX0d6s8boFacZ0Cy3Iq80R+WdpPDR5lXDmKKgN6Nk3/MJjFbOpByNOUMkbK6d SrISTRbXIblMBPYRFTYp8SyKfwQAMe1KalVPN1p3mYyuVmr0oy6+6q0y6wmLz/J3YBpu h+0Q== X-Gm-Message-State: ALQs6tCyko0WU83NMkgzrIwXcUzMA22nY/dgNyCQjXvYnaVVr1Hxf8c7 05PfIHb3luT4RaK5fz8acqPMRw== X-Google-Smtp-Source: AIpwx4+7gNuo7OzrEK5ba9KyQYZiBAzPxCedCxWHk4OCnras5Mxb0CXHgfgWOM+/6HmhfOFth4AM4Q== X-Received: by 2002:a17:902:60cd:: with SMTP id k13-v6mr2999370pln.44.1524075174027; Wed, 18 Apr 2018 11:12:54 -0700 (PDT) Received: from ebiggers-linuxstation.kir.corp.google.com ([2620:15c:17:3:dc28:5c82:b905:e8a8]) by smtp.gmail.com with ESMTPSA id c12sm3075140pfn.13.2018.04.18.11.12.52 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 18 Apr 2018 11:12:53 -0700 (PDT) From: Eric Biggers To: linux-f2fs-devel@lists.sourceforge.net, Jaegeuk Kim Cc: linux-fscrypt@vger.kernel.org, "Theodore Y . Ts'o" , Michael Halcrow , Victor Hsieh , Eric Biggers Subject: [PATCH v2 1/2] fscrypt: allow synchronous bio decryption Date: Wed, 18 Apr 2018 11:09:47 -0700 Message-Id: <20180418180948.152031-2-ebiggers@google.com> X-Mailer: git-send-email 2.17.0.484.g0c8726318c-goog In-Reply-To: <20180418180948.152031-1-ebiggers@google.com> References: <20180418180948.152031-1-ebiggers@google.com> Sender: linux-fscrypt-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Currently, fscrypt provides fscrypt_decrypt_bio_pages() which decrypts a bio's pages asynchronously, then unlocks them afterwards. But, this assumes that decryption is the last "postprocessing step" for the bio, so it's incompatible with additional postprocessing steps such as authenticity verification after decryption. Therefore, rename the existing fscrypt_decrypt_bio_pages() to fscrypt_enqueue_decrypt_bio(). Then, add fscrypt_decrypt_bio() which decrypts the pages in the bio synchronously without unlocking the pages, nor setting them Uptodate; and add fscrypt_enqueue_decrypt_work(), which enqueues work on the fscrypt_read_workqueue. The new functions will be used by filesystems that support both fscrypt and fs-verity. Signed-off-by: Eric Biggers --- fs/crypto/bio.c | 35 +++++++++++++++++++++------------ fs/crypto/crypto.c | 8 +++++++- fs/crypto/fscrypt_private.h | 1 - fs/ext4/readpage.c | 2 +- fs/f2fs/data.c | 2 +- include/linux/fscrypt_notsupp.h | 13 +++++++++--- include/linux/fscrypt_supp.h | 5 ++++- 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c index 0d5e6a569d58..0959044c5cee 100644 --- a/fs/crypto/bio.c +++ b/fs/crypto/bio.c @@ -26,15 +26,8 @@ #include #include "fscrypt_private.h" -/* - * Call fscrypt_decrypt_page on every single page, reusing the encryption - * context. - */ -static void completion_pages(struct work_struct *work) +static void __fscrypt_decrypt_bio(struct bio *bio, bool done) { - struct fscrypt_ctx *ctx = - container_of(work, struct fscrypt_ctx, r.work); - struct bio *bio = ctx->r.bio; struct bio_vec *bv; int i; @@ -46,22 +39,38 @@ static void completion_pages(struct work_struct *work) if (ret) { WARN_ON_ONCE(1); SetPageError(page); - } else { + } else if (done) { SetPageUptodate(page); } - unlock_page(page); + if (done) + unlock_page(page); } +} + +void fscrypt_decrypt_bio(struct bio *bio) +{ + __fscrypt_decrypt_bio(bio, false); +} +EXPORT_SYMBOL(fscrypt_decrypt_bio); + +static void completion_pages(struct work_struct *work) +{ + struct fscrypt_ctx *ctx = + container_of(work, struct fscrypt_ctx, r.work); + struct bio *bio = ctx->r.bio; + + __fscrypt_decrypt_bio(bio, true); fscrypt_release_ctx(ctx); bio_put(bio); } -void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, struct bio *bio) +void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio) { INIT_WORK(&ctx->r.work, completion_pages); ctx->r.bio = bio; - queue_work(fscrypt_read_workqueue, &ctx->r.work); + fscrypt_enqueue_decrypt_work(&ctx->r.work); } -EXPORT_SYMBOL(fscrypt_decrypt_bio_pages); +EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio); void fscrypt_pullback_bio_page(struct page **page, bool restore) { diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index ce654526c0fb..0758d32ad01b 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -45,12 +45,18 @@ static mempool_t *fscrypt_bounce_page_pool = NULL; static LIST_HEAD(fscrypt_free_ctxs); static DEFINE_SPINLOCK(fscrypt_ctx_lock); -struct workqueue_struct *fscrypt_read_workqueue; +static struct workqueue_struct *fscrypt_read_workqueue; static DEFINE_MUTEX(fscrypt_init_mutex); static struct kmem_cache *fscrypt_ctx_cachep; struct kmem_cache *fscrypt_info_cachep; +void fscrypt_enqueue_decrypt_work(struct work_struct *work) +{ + queue_work(fscrypt_read_workqueue, work); +} +EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work); + /** * fscrypt_release_ctx() - Releases an encryption context * @ctx: The encryption context to release. diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index ad6722bae8b7..4012558f6115 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -97,7 +97,6 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode, /* crypto.c */ extern struct kmem_cache *fscrypt_info_cachep; extern int fscrypt_initialize(unsigned int cop_flags); -extern struct workqueue_struct *fscrypt_read_workqueue; extern int fscrypt_do_page_crypto(const struct inode *inode, fscrypt_direction_t rw, u64 lblk_num, struct page *src_page, diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index 9ffa6fad18db..19b87a8de6ff 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -77,7 +77,7 @@ static void mpage_end_io(struct bio *bio) if (bio->bi_status) { fscrypt_release_ctx(bio->bi_private); } else { - fscrypt_decrypt_bio_pages(bio->bi_private, bio); + fscrypt_enqueue_decrypt_bio(bio->bi_private, bio); return; } } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 02237d4d91f5..39225519de1c 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -66,7 +66,7 @@ static void f2fs_read_end_io(struct bio *bio) if (bio->bi_status) { fscrypt_release_ctx(bio->bi_private); } else { - fscrypt_decrypt_bio_pages(bio->bi_private, bio); + fscrypt_enqueue_decrypt_bio(bio->bi_private, bio); return; } } diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h index 44b50c04bae9..9770be37c9d4 100644 --- a/include/linux/fscrypt_notsupp.h +++ b/include/linux/fscrypt_notsupp.h @@ -25,6 +25,10 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) } /* crypto.c */ +static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work) +{ +} + static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode, gfp_t gfp_flags) { @@ -160,10 +164,13 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, } /* bio.c */ -static inline void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, - struct bio *bio) +static inline void fscrypt_decrypt_bio(struct bio *bio) +{ +} + +static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, + struct bio *bio) { - return; } static inline void fscrypt_pullback_bio_page(struct page **page, bool restore) diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h index 477a7a6504d2..2c9a86ac5e83 100644 --- a/include/linux/fscrypt_supp.h +++ b/include/linux/fscrypt_supp.h @@ -59,6 +59,7 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode) } /* crypto.c */ +extern void fscrypt_enqueue_decrypt_work(struct work_struct *); extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t); extern void fscrypt_release_ctx(struct fscrypt_ctx *); extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *, @@ -188,7 +189,9 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname, } /* bio.c */ -extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *); +extern void fscrypt_decrypt_bio(struct bio *); +extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, + struct bio *bio); extern void fscrypt_pullback_bio_page(struct page **, bool); extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t, unsigned int);