From patchwork Mon Oct 5 07:36:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Satya Tangirala X-Patchwork-Id: 11816181 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 29D5614F7 for ; Mon, 5 Oct 2020 07:36:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EB52C20774 for ; Mon, 5 Oct 2020 07:36:21 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="a+/jJaTT" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725925AbgJEHgV (ORCPT ); Mon, 5 Oct 2020 03:36:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59988 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725912AbgJEHgS (ORCPT ); Mon, 5 Oct 2020 03:36:18 -0400 Received: from mail-yb1-xb4a.google.com (mail-yb1-xb4a.google.com [IPv6:2607:f8b0:4864:20::b4a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A69DBC0613CE for ; Mon, 5 Oct 2020 00:36:16 -0700 (PDT) Received: by mail-yb1-xb4a.google.com with SMTP id d15so9049287ybk.0 for ; Mon, 05 Oct 2020 00:36:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=+f82j/3GlQU62Y+UZX8Y8sm58itldJWXgxM/FZt85xk=; b=a+/jJaTTU96Kl2L3e8OrrWdHr+OeqqOVvfjVHr7exfq0mYagEabyuFkeH1edmSYUio iO1flJe0v7aQmci2hmcQcxy0csarT7zJCvNK0vBXsSjH+mBq8iRt9uwBNQIGSsggGBtu kiD8XIRgunHpbeTHY2IrThmrDGDGheQj/xhPHg1hVuJOZOtn/LSpSGsV0QFEtA1FBpK0 hI26d2U0BrBEr6f6ocgT5kBwIahP2deWttKPvE7akKTBL6hwmoP/xm/DUQKQ0h47UVRd 9ntNvM0LQd58/HDvR0Yuhw8s1bhbYFOEbQPQPm7kag+HoRS9gP6a6ECLBiO/4/PbHzRq u9/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=+f82j/3GlQU62Y+UZX8Y8sm58itldJWXgxM/FZt85xk=; b=ra8zLm3qa7y9aQTW+Hreyg71E/MfPJWU0hM3eue/YndIkEefTzdZrMx6FQD4TS7nT6 4GFIwlJNj2WsTdldxAmPoc4n/Jnusbgl/sZCzb+bRuYB9ArK14ziyZ/rP0vLdBF5zCfA 7/g4HCcVG5REK1eP7gV0Ddh/PtdDRngunyubFtuSjIbu/DxvEOeb5itTDYyU+xn8KtpT XSLoIq65NPUQ+VPdMj1YEbLRRk8JKHMpASjmjqCB48Nax5L0STTEqJGLdzerzTn/HNE/ viW/LNVDXtKNaJDC5/OvvQfke6BuYsvJ+Mi4Vt1huApMn5Zj3qFCocFt+gKhvxZZQrMQ cBug== X-Gm-Message-State: AOAM531Xr7u5OQ/Z7HVnbWiNxGLVUmTm9gCloY5AbtgA2SUjSjUNpmc2 iEXe0aMvh++ihTrSc6NjvSIk9KEFa9E= X-Google-Smtp-Source: ABdhPJwkz/io1x0y+WIuy1g8ndag+QHgzZX9J3u1S7xLPdsLKURB4BMyOE+QUxPwR3tjcapzSV74oh2t+3E= Sender: "satyat via sendgmr" X-Received: from satyaprateek.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:1092]) (user=satyat job=sendgmr) by 2002:a25:454:: with SMTP id 81mr16674210ybe.297.1601883375806; Mon, 05 Oct 2020 00:36:15 -0700 (PDT) Date: Mon, 5 Oct 2020 07:36:04 +0000 In-Reply-To: <20201005073606.1949772-1-satyat@google.com> Message-Id: <20201005073606.1949772-2-satyat@google.com> Mime-Version: 1.0 References: <20201005073606.1949772-1-satyat@google.com> X-Mailer: git-send-email 2.28.0.806.g8561365e88-goog Subject: [PATCH 1/3] fscrypt, f2fs: replace fscrypt_get_devices with fscrypt_get_device From: Satya Tangirala To: "Theodore Y . Ts'o" , Jaegeuk Kim , Eric Biggers , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, Satya Tangirala Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org The new function takes the super_block and the index of a device, and returns the request_queue of the device at that index (whereas the old function would take a pointer to an array of request_queues and fill them all up). This allows callers to avoid allocating an array of request_queues in some cases (when they don't need the array for anything else). Signed-off-by: Satya Tangirala --- fs/crypto/inline_crypt.c | 33 ++++++++++++++------------------- fs/f2fs/super.c | 16 ++++++++++------ include/linux/fscrypt.h | 4 ++-- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index faa25541ccb6..5bbce79df638 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -33,13 +33,15 @@ static int fscrypt_get_num_devices(struct super_block *sb) return 1; } -static void fscrypt_get_devices(struct super_block *sb, int num_devs, - struct request_queue **devs) +static struct request_queue *fscrypt_get_device(struct super_block *sb, + unsigned int device_index) { - if (num_devs == 1) - devs[0] = bdev_get_queue(sb->s_bdev); + if (sb->s_cop->get_device) + return sb->s_cop->get_device(sb, device_index); + else if (WARN_ON_ONCE(device_index != 0)) + return NULL; else - sb->s_cop->get_devices(sb, devs); + return bdev_get_queue(sb->s_bdev); } static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci) @@ -70,7 +72,7 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci) struct super_block *sb = inode->i_sb; struct blk_crypto_config crypto_cfg; int num_devs; - struct request_queue **devs; + struct request_queue *dev; int i; /* The file must need contents encryption, not filenames encryption */ @@ -106,20 +108,14 @@ int fscrypt_select_encryption_impl(struct fscrypt_info *ci) crypto_cfg.data_unit_size = sb->s_blocksize; crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci); num_devs = fscrypt_get_num_devices(sb); - devs = kmalloc_array(num_devs, sizeof(*devs), GFP_NOFS); - if (!devs) - return -ENOMEM; - fscrypt_get_devices(sb, num_devs, devs); for (i = 0; i < num_devs; i++) { - if (!blk_crypto_config_supported(devs[i], &crypto_cfg)) - goto out_free_devs; + dev = fscrypt_get_device(sb, i); + if (!dev || !blk_crypto_config_supported(dev, &crypto_cfg)) + return 0; } ci->ci_inlinecrypt = true; -out_free_devs: - kfree(devs); - return 0; } @@ -141,9 +137,6 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, if (!blk_key) return -ENOMEM; - blk_key->num_devs = num_devs; - fscrypt_get_devices(sb, num_devs, blk_key->devs); - err = blk_crypto_init_key(&blk_key->base, raw_key, crypto_mode, fscrypt_get_dun_bytes(ci), sb->s_blocksize); if (err) { @@ -158,8 +151,10 @@ int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, * aren't destroyed until after the filesystem was already unmounted * (namely, the per-mode keys in struct fscrypt_master_key). */ + blk_key->num_devs = num_devs; for (i = 0; i < num_devs; i++) { - if (!blk_get_queue(blk_key->devs[i])) { + blk_key->devs[i] = fscrypt_get_device(sb, i); + if (!blk_key->devs[i] || !blk_get_queue(blk_key->devs[i])) { fscrypt_err(inode, "couldn't get request_queue"); err = -EAGAIN; goto fail; diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index dfa072fa8081..9a6d375cbe4b 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2509,14 +2509,18 @@ static int f2fs_get_num_devices(struct super_block *sb) return 1; } -static void f2fs_get_devices(struct super_block *sb, - struct request_queue **devs) +static struct request_queue *f2fs_get_device(struct super_block *sb, + unsigned int device_index) { struct f2fs_sb_info *sbi = F2FS_SB(sb); - int i; - for (i = 0; i < sbi->s_ndevs; i++) - devs[i] = bdev_get_queue(FDEV(i).bdev); + if (WARN_ON_ONCE(device_index >= f2fs_get_num_devices(sb))) + return NULL; + + if (!f2fs_is_multi_device(sbi)) + return bdev_get_queue(sb->s_bdev); + + return bdev_get_queue(FDEV(device_index).bdev); } static const struct fscrypt_operations f2fs_cryptops = { @@ -2529,7 +2533,7 @@ static const struct fscrypt_operations f2fs_cryptops = { .has_stable_inodes = f2fs_has_stable_inodes, .get_ino_and_lblk_bits = f2fs_get_ino_and_lblk_bits, .get_num_devices = f2fs_get_num_devices, - .get_devices = f2fs_get_devices, + .get_device = f2fs_get_device, }; #endif diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index 991ff8575d0e..d835fd19a20a 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -70,8 +70,8 @@ struct fscrypt_operations { void (*get_ino_and_lblk_bits)(struct super_block *sb, int *ino_bits_ret, int *lblk_bits_ret); int (*get_num_devices)(struct super_block *sb); - void (*get_devices)(struct super_block *sb, - struct request_queue **devs); + struct request_queue *(*get_device)(struct super_block *sb, + unsigned int dev_index); }; static inline struct fscrypt_info *fscrypt_get_info(const struct inode *inode) From patchwork Mon Oct 5 07:36:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Satya Tangirala X-Patchwork-Id: 11816185 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 62AB1618 for ; Mon, 5 Oct 2020 07:36:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 34E1920665 for ; Mon, 5 Oct 2020 07:36:28 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="IhFgftIz" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725931AbgJEHgV (ORCPT ); Mon, 5 Oct 2020 03:36:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59998 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725923AbgJEHgS (ORCPT ); Mon, 5 Oct 2020 03:36:18 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 99693C0613A8 for ; Mon, 5 Oct 2020 00:36:18 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id f199so8921908yba.12 for ; Mon, 05 Oct 2020 00:36:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=6it/52lmg4W3wLyYi3d7Plv4UDu4Yutc2uS93yL0Ts0=; b=IhFgftIzZAnmJlKhGAq4n5Lm1PzuUm13YbZgx99S+eVswOrPQ4lVhCGiB1Nrtzhy99 JFXQw8gJ9TKa45+e0vk/alX272T+Jx9D/px6F4eZscMd95Ry/I1mVU62KHFe/dvJKX45 Q+sgCc1h4ROQKS/A4nUdQaQXKiWuKT17OrUq0KUpr3R2rv4z4Hbc0Abs07xh2pOOaSu7 PZG0pfGQyD5sD89p6WN51RCXXn7YF8MhHjeyGe6qB2A4zQI41JRUw5UpIWT3NHHMuEhb wwpSWF7WsBVYYKHMCd1UH20niAprgz6Spxr3nUM/Q4rocEt9mwITrZGxA1EZ8NbrFted s5rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=6it/52lmg4W3wLyYi3d7Plv4UDu4Yutc2uS93yL0Ts0=; b=U0L+Oy5YbwVy9QRxstJtgwqgre/JRiA/OHUbnrkDMYHt82YhJ4aQarGUIVp4gUe8sm isqGruPiwZpzkisPEbzQFVYFBCh8JV0Kv4anDUbECoctKs4/bo3FoFE6mxNkjXth+jYK m7jklC9yNxdO6jrv+NwO2pCKDDNKC5MtkeNUodVL2ZKKoZORPKnh69eo9YbqHv8M6aWY +Q84Djm6Mzj65/0xTEVihyeSZiIndFmSi8XpYuOTuWsQ4vnGxwvtFhuRL00INec2CETy iSVfiYEybi0+Qd9e3uDlO8SVY7bFq6sgq0/tkuBU9UOnmY9+67Ipd8MlHMznJpLF0oE2 wSaw== X-Gm-Message-State: AOAM532TnYqFh3Ajr1xjzE/huKUlPbb7ZC1AnOFth0xH1uU2yKS/1As3 yvBnjeoCMyiXXl5Sn4dbCYLRSZBqSsE= X-Google-Smtp-Source: ABdhPJzAsZ1vv0A688VdcDETTl2/ICPFDeu2DtSgo3iuR4LMbMtyGfdsDa3+pOa8x9USbzNA3lSdPduDRCg= Sender: "satyat via sendgmr" X-Received: from satyaprateek.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:1092]) (user=satyat job=sendgmr) by 2002:a25:a083:: with SMTP id y3mr17551841ybh.296.1601883377704; Mon, 05 Oct 2020 00:36:17 -0700 (PDT) Date: Mon, 5 Oct 2020 07:36:05 +0000 In-Reply-To: <20201005073606.1949772-1-satyat@google.com> Message-Id: <20201005073606.1949772-3-satyat@google.com> Mime-Version: 1.0 References: <20201005073606.1949772-1-satyat@google.com> X-Mailer: git-send-email 2.28.0.806.g8561365e88-goog Subject: [PATCH 2/3] fscrypt: Add metadata encryption support From: Satya Tangirala To: "Theodore Y . Ts'o" , Jaegeuk Kim , Eric Biggers , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, Satya Tangirala Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org Introduces functions that help with metadata encryption. In particular, we introduce: fscrypt_setup_metadata_encryption() - filesystems should call this function to set up metadata encryption on a super block with the encryption algorithm (the desired FSCRYPT_MODE_*) and the key descriptor of the encryption key. The key descriptor is looked up in the logon keyring of the current session using "fscrypt:" as the descriptor prefix. fscrypt_metadata_crypt_bio() - filesystems should call this function on a bio that it wants metadata crypted. This function will set a bio-crypt-ctx on the bio if the metadata key was set up with fscrypt_setup_metadata_encryption(). The DUN for the first block in the bio is the offset of that block from the start of the filesystem. fscrypt_free_metadata_encryption() - this function should be called when the super block is being freed. It ensures that the metadata encryption key is evicted, if necessary, from devices. Note that the filesystem (rather than fscrypt) controls precisely which blocks are encrypted with the metadata encryption key and which blocks are encrypted with other keys/not encrypted at all. Fscrypt only provides some convenience functions that ultimately help encrypt a bio with the metadata encryption key when desired. Signed-off-by: Satya Tangirala --- fs/crypto/Kconfig | 6 + fs/crypto/Makefile | 1 + fs/crypto/fscrypt_private.h | 19 ++++ fs/crypto/inline_crypt.c | 18 --- fs/crypto/metadata_crypt.c | 220 ++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 3 + include/linux/fscrypt.h | 47 ++++++++ 7 files changed, 296 insertions(+), 18 deletions(-) create mode 100644 fs/crypto/metadata_crypt.c diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index a5f5c30368a2..3010e91f6659 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -30,3 +30,9 @@ config FS_ENCRYPTION_INLINE_CRYPT depends on FS_ENCRYPTION && BLK_INLINE_ENCRYPTION help Enable fscrypt to use inline encryption hardware if available. + +config FS_ENCRYPTION_METADATA + bool "Enable metadata encryption with fscrypt" + depends on FS_ENCRYPTION && BLK_INLINE_ENCRYPTION + help + Enable fscrypt to encrypt metadata. \ No newline at end of file diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 652c7180ec6d..8403c7956983 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -12,3 +12,4 @@ fscrypto-y := crypto.o \ fscrypto-$(CONFIG_BLOCK) += bio.o fscrypto-$(CONFIG_FS_ENCRYPTION_INLINE_CRYPT) += inline_crypt.o +fscrypto-$(CONFIG_FS_ENCRYPTION_METADATA) += metadata_crypt.o \ No newline at end of file diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 8117a61b6f55..dca254590a70 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -327,6 +327,25 @@ int fscrypt_hkdf_expand(const struct fscrypt_hkdf *hkdf, u8 context, void fscrypt_destroy_hkdf(struct fscrypt_hkdf *hkdf); /* inline_crypt.c */ + +static inline int fscrypt_get_num_devices(struct super_block *sb) +{ + if (sb->s_cop->get_num_devices) + return sb->s_cop->get_num_devices(sb); + return 1; +} + +static inline struct request_queue *fscrypt_get_device(struct super_block *sb, + unsigned int device_index) +{ + if (sb->s_cop->get_device) + return sb->s_cop->get_device(sb, device_index); + else if (WARN_ON_ONCE(device_index != 0)) + return NULL; + else + return bdev_get_queue(sb->s_bdev); +} + #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT int fscrypt_select_encryption_impl(struct fscrypt_info *ci); diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c index 5bbce79df638..f8f7363ebcd0 100644 --- a/fs/crypto/inline_crypt.c +++ b/fs/crypto/inline_crypt.c @@ -26,24 +26,6 @@ struct fscrypt_blk_crypto_key { struct request_queue *devs[]; }; -static int fscrypt_get_num_devices(struct super_block *sb) -{ - if (sb->s_cop->get_num_devices) - return sb->s_cop->get_num_devices(sb); - return 1; -} - -static struct request_queue *fscrypt_get_device(struct super_block *sb, - unsigned int device_index) -{ - if (sb->s_cop->get_device) - return sb->s_cop->get_device(sb, device_index); - else if (WARN_ON_ONCE(device_index != 0)) - return NULL; - else - return bdev_get_queue(sb->s_bdev); -} - static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_info *ci) { struct super_block *sb = ci->ci_inode->i_sb; diff --git a/fs/crypto/metadata_crypt.c b/fs/crypto/metadata_crypt.c new file mode 100644 index 000000000000..5e16df130509 --- /dev/null +++ b/fs/crypto/metadata_crypt.c @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Metadata encryption support for fscrypt + * + * Copyright 2020 Google LLC + */ + +#include +#include +#include +#include +#include + +#include "fscrypt_private.h" + +/* TODO: mostly copied from keysetup_v1.c - maybe refactor this function */ +static int fscrypt_metadata_get_key_from_id(const char *prefix, + char *descriptor_hex, + unsigned int min_keysize, + char *raw_key) +{ + char *description; + struct key *key; + const struct user_key_payload *ukp; + const struct fscrypt_key *payload; + int err = -ENOKEY; + + if (strlen(descriptor_hex) != FSCRYPT_KEY_DESCRIPTOR_SIZE * 2) + return -EINVAL; + + description = kasprintf(GFP_NOFS, "%s%s", prefix, descriptor_hex); + if (!description) + return -ENOMEM; + + key = request_key(&key_type_logon, description, NULL); + kfree(description); + if (IS_ERR(key)) + return PTR_ERR(key); + + down_read(&key->sem); + ukp = user_key_payload_locked(key); + + if (!ukp) /* was the key revoked before we acquired its semaphore? */ + goto out; + + payload = (const struct fscrypt_key *)ukp->data; + + if (ukp->datalen != sizeof(struct fscrypt_key) || + payload->size < 1 || payload->size > FSCRYPT_MAX_KEY_SIZE) { + fscrypt_warn(NULL, + "key with description '%s' has invalid payload", + key->description); + goto out; + } + + if (payload->size < min_keysize) { + fscrypt_warn(NULL, + "key with description '%s' is too short (got %u bytes, need %u+ bytes)", + key->description, payload->size, min_keysize); + goto out; + } + + memcpy(raw_key, payload->raw, min_keysize); + err = 0; + +out: + up_read(&key->sem); + key_put(key); + + return err; +} + +/** + * fscrypt_setup_metadata_encryption() - prepare a super_block for metadata + * encryption + * @sb: The super_block to set up metadata encryption for + * @key_desc_hex: The key descriptor (in hex) to look for in the logon keyring. + * @fscrypt_mode_num: The FSCRYPT_MODE_* to use as the encryption algorithm. + * + * Return: 0 on success, negative number on error. + */ +int fscrypt_setup_metadata_encryption(struct super_block *sb, + char *key_desc_hex, + int fscrypt_mode_num) +{ + int err = 0; + enum blk_crypto_mode_num crypto_mode; + unsigned int lblk_bits = 64; + unsigned int dun_bytes; + unsigned int dummy; + char raw_key[FSCRYPT_MAX_KEY_SIZE]; + + if (fscrypt_mode_num > __FSCRYPT_MODE_MAX || fscrypt_mode_num < 0 || + !fscrypt_modes[fscrypt_mode_num].cipher_str) { + fscrypt_warn(NULL, "Invalid fscrypt mode %d specified for metadata encryption.", + fscrypt_mode_num); + return -EOPNOTSUPP; + } + + if (sb->s_cop->get_ino_and_lblk_bits) + sb->s_cop->get_ino_and_lblk_bits(sb, &dummy, &lblk_bits); + dun_bytes = DIV_ROUND_UP(lblk_bits, 8); + + if (fscrypt_modes[fscrypt_mode_num].ivsize < dun_bytes) { + fscrypt_warn(NULL, "The fscrypt mode only supports %d DUN bytes, but FS requires support for %d DUN bytes.", + fscrypt_modes[fscrypt_mode_num].ivsize, dun_bytes); + return -EOPNOTSUPP; + } + + crypto_mode = fscrypt_modes[fscrypt_mode_num].blk_crypto_mode; + + err = fscrypt_metadata_get_key_from_id( + FSCRYPT_KEY_DESC_PREFIX, + key_desc_hex, + fscrypt_modes[fscrypt_mode_num].keysize, + raw_key); + if (err) + goto out; + + sb->s_metadata_key = kzalloc(sizeof(*sb->s_metadata_key), GFP_NOFS); + if (!sb->s_metadata_key) { + err = -ENOMEM; + goto out; + } + + err = blk_crypto_init_key(sb->s_metadata_key, raw_key, crypto_mode, + dun_bytes, sb->s_blocksize); + if (err) + goto out_free_key; + + err = blk_crypto_start_using_key(sb->s_metadata_key, + bdev_get_queue(sb->s_bdev)); + if (err) + goto out_free_key; + + goto out; +out_free_key: + fscrypt_free_metadata_encryption(sb); +out: + memzero_explicit(raw_key, sizeof(raw_key)); + return err; +} + +/** + * fscrypt_metadata_crypt_prepare_all_devices() - prepare all devices used by + * the filesystem for metadata encryption. + * @sb: The super_block whose devices to prepare + * + * This function should be called when the filesystem has determined all its + * devices. This might happen only after some initial setup, which is why + * this is a separate function from fscrypt_setup_metadata_encryption(). + * + * Return: 0 on success, negative on error. + */ +int fscrypt_metadata_crypt_prepare_all_devices(struct super_block *sb) +{ + int num_devices; + int i; + struct request_queue *q; + + if (!sb->s_metadata_key) + return 0; + + num_devices = fscrypt_get_num_devices(sb); + for (i = 0; i < num_devices; i++) { + q = fscrypt_get_device(sb, i); + if (!q || blk_crypto_start_using_key(sb->s_metadata_key, q)) + return -EOPNOTSUPP; + } + return 0; +} + +/** + * fscrypt_free_metadata_encryption() - free metadata encryption fields in + * super_block. + * @sb: The super_block to free metatdata encryption fields from + */ +void fscrypt_free_metadata_encryption(struct super_block *sb) +{ + int num_devices; + int i; + struct request_queue *q; + + if (!sb->s_metadata_key) + return; + + num_devices = fscrypt_get_num_devices(sb); + + for (i = 0; i < num_devices; i++) { + q = fscrypt_get_device(sb, i); + if (WARN_ON(!q)) + continue; + blk_crypto_evict_key(q, sb->s_metadata_key); + } + + memzero_explicit(sb->s_metadata_key, sizeof(*sb->s_metadata_key)); + kzfree(sb->s_metadata_key); + sb->s_metadata_key = NULL; +} + +/** + * fscrypt_metadata_crypt_bio() - Add metadata encryption context to bio. + * + * @bio: The bio to add the encryption context to + * @lblk: The logical block number within the filesystem at which this bio + * starts reading/writing data. + * @sb: The superblock of the filesystem + * @gfp_mask: gfp_mask for bio_crypt_context allocation + */ +void fscrypt_metadata_crypt_bio(struct bio *bio, u64 lblk, + struct super_block *sb, gfp_t gfp_mask) +{ + u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE] = { 0 }; + + if (!sb->s_metadata_key) + return; + + dun[0] = lblk; + bio_crypt_set_ctx(bio, sb->s_metadata_key, dun, gfp_mask); +} diff --git a/include/linux/fs.h b/include/linux/fs.h index 7519ae003a08..aba3b0e2d56f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1438,6 +1438,9 @@ struct super_block { const struct fscrypt_operations *s_cop; struct key *s_master_keys; /* master crypto keys in use */ #endif +#ifdef CONFIG_FS_ENCRYPTION_METADATA + struct blk_crypto_key *s_metadata_key; +#endif #ifdef CONFIG_FS_VERITY const struct fsverity_operations *s_vop; #endif diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h index d835fd19a20a..f7cdc8627984 100644 --- a/include/linux/fscrypt.h +++ b/include/linux/fscrypt.h @@ -594,6 +594,53 @@ static inline bool fscrypt_mergeable_bio_bh(struct bio *bio, } #endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ +/* metadata_crypt.c */ +#ifdef CONFIG_FS_ENCRYPTION_METADATA + +int fscrypt_setup_metadata_encryption(struct super_block *sb, + char *key_desc_hex, + int fscrypt_mode_num); + +int fscrypt_metadata_crypt_prepare_all_devices(struct super_block *sb); + +void fscrypt_free_metadata_encryption(struct super_block *sb); + +void fscrypt_metadata_crypt_bio(struct bio *bio, u64 lblk, + struct super_block *sb, gfp_t gfp_mask); + +static inline bool fscrypt_metadata_crypted(struct super_block *sb) +{ + return sb->s_metadata_key; +} + +#else /* CONFIG_FS_ENCRYPTION_METADATA */ + +static inline int fscrypt_setup_metadata_encryption(struct super_block *sb, + char *key_desc_hex, + int fscrypt_mode_num) +{ + return -EOPNOTSUPP; +} + +static inline int +fscrypt_metadata_crypt_prepare_all_devices(struct super_block *sb) +{ + return 0; +} + +static inline void fscrypt_free_metadata_encryption(struct super_block *sb) { } + +static inline void fscrypt_metadata_crypt_bio(struct bio *bio, u64 lblk, + struct super_block *sb, + gfp_t gfp_mask) { } + +static inline bool fscrypt_metadata_crypted(struct super_block *sb) +{ + return false; +} + +#endif /* CONFIG_FS_ENCRYPTION_METADATA */ + /** * fscrypt_inode_uses_inline_crypto() - test whether an inode uses inline * encryption From patchwork Mon Oct 5 07:36:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Satya Tangirala X-Patchwork-Id: 11816183 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5C365618 for ; Mon, 5 Oct 2020 07:36:27 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2793020756 for ; Mon, 5 Oct 2020 07:36:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="E5pc8PA5" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725937AbgJEHgW (ORCPT ); Mon, 5 Oct 2020 03:36:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725870AbgJEHgV (ORCPT ); Mon, 5 Oct 2020 03:36:21 -0400 Received: from mail-pj1-x104a.google.com (mail-pj1-x104a.google.com [IPv6:2607:f8b0:4864:20::104a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 449B2C0613AA for ; Mon, 5 Oct 2020 00:36:20 -0700 (PDT) Received: by mail-pj1-x104a.google.com with SMTP id fw9so2821177pjb.7 for ; Mon, 05 Oct 2020 00:36:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=dHnXF1W/20PFevqIJQyFZ/AoVLSu39bdQ59fV9E+wl8=; b=E5pc8PA5GYGj/I440mjbYVNg36emzQMnO+hi7qYN4H7GqJnYVHd3vHIelRNpOL6eMv tzuxw0/nPDAETVoxt6eZBwD5qBwSLsXfrxPAQgkg88dEnhKX3Q9sFmg/D5CIdREpp+Te SWGF34Yd4MfU5njKKa80akqUVvygeLoXzspfinE1I7MNi9xv1B7i+YvdIl3Z4OvfCwmB EvHpvfAeCGjQuoWQxIW+34RXQrQr0LpJGz/ck5yt4EI4QrC1pglSSUvFmG7iT9G0Q4TW ob8i9FEA29nXx0Nja3rITF7QIujNEBsSdbLQnqDPGYleolUiBe9QLmms/dQDdiu4CGSI 1Ezw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=dHnXF1W/20PFevqIJQyFZ/AoVLSu39bdQ59fV9E+wl8=; b=Cy2+2Fov6tCcZWMWY63T6Av5ISYupMDm8C0ssjwuc0wf7g4crUrMjIUUURSzVyhUr/ dEFh7t9ufmZEUyZzu06kN5ExhezI6gVkzVV81JP1DlTIqJvqNvaPSt6EsXbGqSd2wNSs 7pA9VRM3br8w81gWsPvJMtiFWktr/wcQInWkbkN6NaH3N7/qwtu/E7Pq2pE9meY3QF5b rv94aQ6fbr9qEjEkeC0gjFoLONQh9NZ0rt6O2EhKi6sa+ytWmww8eZ+wcewVia3PCZ3T nO2xKS6dxlnJKjUFcX1Bnvbj3P7MqNXURWyiyx5KbWhpad884MgfBExYNqM9E4nVUnwo PvAw== X-Gm-Message-State: AOAM531q1YO3ofrqzyQfAuDTkJ/+kn25oKn9qok2nIQ3CQ1PobLnS0BG EndLiWQPWaduZmWCR2qZ07JcQEalDso= X-Google-Smtp-Source: ABdhPJxAbpf4N5rScmCx/y+iXragYL3MvKrQA/i8m/yLj2PrWyfMuN7hYU6zLGJn4YKr2zV7v+TlzTn9wpY= Sender: "satyat via sendgmr" X-Received: from satyaprateek.c.googlers.com ([fda3:e722:ac3:10:24:72f4:c0a8:1092]) (user=satyat job=sendgmr) by 2002:aa7:83d9:0:b029:138:b217:f347 with SMTP id j25-20020aa783d90000b0290138b217f347mr6813449pfn.0.1601883379697; Mon, 05 Oct 2020 00:36:19 -0700 (PDT) Date: Mon, 5 Oct 2020 07:36:06 +0000 In-Reply-To: <20201005073606.1949772-1-satyat@google.com> Message-Id: <20201005073606.1949772-4-satyat@google.com> Mime-Version: 1.0 References: <20201005073606.1949772-1-satyat@google.com> X-Mailer: git-send-email 2.28.0.806.g8561365e88-goog Subject: [PATCH 3/3] f2fs: Add metadata encryption support From: Satya Tangirala To: "Theodore Y . Ts'o" , Jaegeuk Kim , Eric Biggers , Chao Yu Cc: linux-kernel@vger.kernel.org, linux-fscrypt@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, Satya Tangirala Precedence: bulk List-ID: X-Mailing-List: linux-fscrypt@vger.kernel.org Wire up metadata encryption support with the fscrypt metadata crypt additions. Introduces a new mount option for metadata encryption - metadata_crypt_key=%s. The argument to this option is the key descriptor of the metadata encryption key in hex. This key descriptor will be looked up in the logon keyring with the "fscrypt:" prefix. E.g. one might pass "-o metadata_crypt_key=ababcdcdefef0101" as the f2fs mount option to the kernel, when the logon keyring has a key with the descriptor "fscrypt:ababcdcdefef0101". Right now, the superblock of the filesystem is itself not encrypted. F2FS reads the superblock using sb_bread, which uses the bd_inode of the block device as the address space for any data it reads from the block device - the data read under the bd_inode address space must be what is physically present on disk (i.e. if the superblock is encrypted, then the ciphertext of the superblock must be present in the page cache in the bd_inode's address space), but f2fs requires that the superblock is decrypted by blk-crypto, which would put the decrypted page contents into the page cache instead. We could make f2fs read the superblock by submitting bios directly with a separate address space, but we choose to just not encrypt the superblock for now. Not encrypting the superblock allows us to store the encryption algorithm used for metadata encryption within the superblock itself, which simplifies a few things. The userspace tools will store the encryption algorithm in the superblock when formatting the FS. Direct I/O with metadata encryption is also not supported for now. Attempts to do direct I/O on a metadata encrypted F2FS filesystem will fall back to using buffered I/O (just as attempts to do direct I/O on fscrypt encrypted files also fall back to buffered I/O). Signed-off-by: Satya Tangirala Reported-by: kernel test robot --- Documentation/filesystems/f2fs.rst | 12 ++++++ fs/f2fs/data.c | 24 +++++++---- fs/f2fs/f2fs.h | 2 + fs/f2fs/super.c | 67 ++++++++++++++++++++++++++++-- include/linux/f2fs_fs.h | 3 +- 5 files changed, 95 insertions(+), 13 deletions(-) diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst index ec8d99703ecb..94a294874707 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -266,6 +266,18 @@ inlinecrypt When possible, encrypt/decrypt the contents of encrypted inline encryption hardware. The on-disk format is unaffected. For more details, see Documentation/block/inline-encryption.rst. +metadata_crypt_key=%s Specify the metadata encryption key for the filesystem. + The argument to this option is the key descriptor of + the metadata encryption key in hex. This key descriptor + will be looked up in the logon keyring with the + "fscrypt:" prefix. So e.g. one might pass "-o + metadata_crypt_key=ababcdcdefef0101" as the f2fs mount + option to the kernel, when the logon keyring has a key + with the descriptor "fscrypt:ababcdcdefef0101". + When an F2FS filesystem has metadata encryption enabled, + all blocks in the FS other than the superblock are + encrypted with the metadata encryption key. The + superblock itself is stored in plaintext. ======================== ============================================================ Debugfs Entries diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 73683e58a08d..1b65313b57c8 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -460,8 +460,8 @@ static struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) return bio; } -static void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, - pgoff_t first_idx, +static void f2fs_set_bio_crypt_ctx(struct bio *bio, block_t blk_addr, + const struct inode *inode, pgoff_t first_idx, const struct f2fs_io_info *fio, gfp_t gfp_mask) { @@ -469,8 +469,13 @@ static void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, * The f2fs garbage collector sets ->encrypted_page when it wants to * read/write raw data without encryption. */ - if (!fio || !fio->encrypted_page) - fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask); + if (!fio || !fio->encrypted_page) { + if (fscrypt_needs_contents_encryption(inode)) + fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask); + else + fscrypt_metadata_crypt_bio(bio, blk_addr, inode->i_sb, + gfp_mask); + } } static bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode, @@ -712,7 +717,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) /* Allocate a new bio */ bio = __bio_alloc(fio, 1); - f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, + f2fs_set_bio_crypt_ctx(bio, fio->new_blkaddr, fio->page->mapping->host, fio->page->index, fio, GFP_NOIO); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { @@ -918,7 +923,8 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) if (!bio) { bio = __bio_alloc(fio, BIO_MAX_PAGES); __attach_io_flag(fio); - f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, + f2fs_set_bio_crypt_ctx(bio, fio->new_blkaddr, + fio->page->mapping->host, fio->page->index, fio, GFP_NOIO); bio_set_op_attrs(bio, fio->op, fio->op_flags); @@ -992,7 +998,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) goto skip; } io->bio = __bio_alloc(fio, BIO_MAX_PAGES); - f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, + f2fs_set_bio_crypt_ctx(io->bio, fio->new_blkaddr, + fio->page->mapping->host, bio_page->index, fio, GFP_NOIO); io->fio = *fio; } @@ -1039,9 +1046,8 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, if (!bio) return ERR_PTR(-ENOMEM); - f2fs_set_bio_crypt_ctx(bio, inode, first_idx, NULL, GFP_NOFS); - f2fs_target_device(sbi, blkaddr, bio); + f2fs_set_bio_crypt_ctx(bio, blkaddr, inode, first_idx, NULL, GFP_NOFS); bio->bi_end_io = f2fs_read_end_io; bio_set_op_attrs(bio, REQ_OP_READ, op_flag); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index d9e52a7f3702..8c5626a6f684 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4095,6 +4095,8 @@ static inline bool f2fs_force_buffered_io(struct inode *inode, if (f2fs_post_read_required(inode)) return true; + if (fscrypt_metadata_crypted(sbi->sb)) + return true; if (f2fs_is_multi_device(sbi)) return true; /* diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 9a6d375cbe4b..1c14c823a4e9 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -146,6 +146,7 @@ enum { Opt_compress_algorithm, Opt_compress_log_size, Opt_compress_extension, + Opt_metadata_crypt_key, Opt_err, }; @@ -213,6 +214,7 @@ static match_table_t f2fs_tokens = { {Opt_compress_algorithm, "compress_algorithm=%s"}, {Opt_compress_log_size, "compress_log_size=%u"}, {Opt_compress_extension, "compress_extension=%s"}, + {Opt_metadata_crypt_key, "metadata_crypt_key=%s"}, {Opt_err, NULL}, }; @@ -465,6 +467,10 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) #ifdef CONFIG_F2FS_FS_COMPRESSION unsigned char (*ext)[F2FS_EXTENSION_LEN]; int ext_cnt; +#endif +#ifdef CONFIG_FS_ENCRYPTION_METADATA + char *key_desc_hex = NULL; + int metadata_crypt_alg = le32_to_cpu(sbi->raw_super->metadata_crypt_alg); #endif char *p, *name; int arg = 0; @@ -937,6 +943,35 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) case Opt_compress_extension: f2fs_info(sbi, "compression options not supported"); break; +#endif +#ifdef CONFIG_FS_ENCRYPTION_METADATA + case Opt_metadata_crypt_key: + if (!metadata_crypt_alg) { + f2fs_err(sbi, "Filesystem doesn't have metadata encryption enabled, but a metadata encryption key was provided"); + return -EINVAL; + } + if (is_remount) { + f2fs_warn(sbi, "Ignoring metadata crypt key specified for remount"); + break; + } + + if (fscrypt_metadata_crypted(sb)) { + f2fs_err(sbi, "Multiple metadata crypt key options specified"); + return -EINVAL; + } + + key_desc_hex = match_strdup(&args[0]); + if (!key_desc_hex) + return -ENOMEM; + + if (fscrypt_setup_metadata_encryption(sb, key_desc_hex, + metadata_crypt_alg)) { + f2fs_err(sbi, "Could not setup metadata encryption"); + kfree(key_desc_hex); + return -EINVAL; + } + kfree(key_desc_hex); + break; #endif default: f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value", @@ -964,6 +999,13 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount) return -EINVAL; } #endif +#ifdef CONFIG_FS_ENCRYPTION_METADATA + if (metadata_crypt_alg && + !fscrypt_metadata_crypted(sb)) { + f2fs_err(sbi, "Filesystem has metadata encryption. Please provide metadata encryption key to mount filesystem"); + return -EINVAL; + } +#endif if (F2FS_IO_SIZE_BITS(sbi) && !f2fs_lfs_mode(sbi)) { f2fs_err(sbi, "Should set mode=lfs with %uKB-sized IO", @@ -1249,6 +1291,8 @@ static void f2fs_put_super(struct super_block *sb) iput(sbi->meta_inode); sbi->meta_inode = NULL; + fscrypt_free_metadata_encryption(sb); + /* * iput() can update stat information, if f2fs_write_checkpoint() * above failed with error. @@ -2504,6 +2548,9 @@ static int f2fs_get_num_devices(struct super_block *sb) { struct f2fs_sb_info *sbi = F2FS_SB(sb); + if (!sbi) + return 0; + if (f2fs_is_multi_device(sbi)) return sbi->s_ndevs; return 1; @@ -2873,6 +2920,13 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi, return -EFSCORRUPTED; } + /* Check if FS has metadata encryption if kernel doesn't support it */ +#ifndef CONFIG_FS_ENCRYPTION_METADATA + if (raw_super->metadata_crypt_alg) { + f2fs_err(sbi, "Filesystem has metadata encryption but kernel support for it wasn't enabled"); + return -EINVAL; + } +#endif /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */ if (sanity_check_area_boundary(sbi, bh)) return -EFSCORRUPTED; @@ -3464,6 +3518,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_sb_buf; } +#ifdef CONFIG_FS_ENCRYPTION + sb->s_cop = &f2fs_cryptops; +#endif err = parse_options(sb, options, false); if (err) goto free_options; @@ -3491,9 +3548,6 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) #endif sb->s_op = &f2fs_sops; -#ifdef CONFIG_FS_ENCRYPTION - sb->s_cop = &f2fs_cryptops; -#endif #ifdef CONFIG_FS_VERITY sb->s_vop = &f2fs_verityops; #endif @@ -3602,6 +3656,12 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) goto free_devices; } + err = fscrypt_metadata_crypt_prepare_all_devices(sb); + if (err) { + f2fs_err(sbi, "Failed to initialize metadata crypt on all devices"); + goto free_devices; + } + err = f2fs_init_post_read_wq(sbi); if (err) { f2fs_err(sbi, "Failed to initialize post read workqueue"); @@ -3864,6 +3924,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) utf8_unload(sbi->s_encoding); #endif free_options: + fscrypt_free_metadata_encryption(sb); #ifdef CONFIG_QUOTA for (i = 0; i < MAXQUOTAS; i++) kfree(F2FS_OPTION(sbi).s_qf_names[i]); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 3c383ddd92dd..34cf0031dc8a 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -118,7 +118,8 @@ struct f2fs_super_block { __u8 hot_ext_count; /* # of hot file extension */ __le16 s_encoding; /* Filename charset encoding */ __le16 s_encoding_flags; /* Filename charset encoding flags */ - __u8 reserved[306]; /* valid reserved region */ + __le32 metadata_crypt_alg; /* The metadata encryption algorithm (FSCRYPT_MODE_*) */ + __u8 reserved[302]; /* valid reserved region */ __le32 crc; /* checksum of superblock */ } __packed;