diff options
Diffstat (limited to 'fs/crypto')
| -rw-r--r-- | fs/crypto/Kconfig | 10 | ||||
| -rw-r--r-- | fs/crypto/Makefile | 3 | ||||
| -rw-r--r-- | fs/crypto/bio.c | 220 | ||||
| -rw-r--r-- | fs/crypto/block.c | 415 | ||||
| -rw-r--r-- | fs/crypto/crypto.c | 182 | ||||
| -rw-r--r-- | fs/crypto/fscrypt_private.h | 120 | ||||
| -rw-r--r-- | fs/crypto/hooks.c | 2 | ||||
| -rw-r--r-- | fs/crypto/inline_crypt.c | 517 | ||||
| -rw-r--r-- | fs/crypto/keyring.c | 264 | ||||
| -rw-r--r-- | fs/crypto/keysetup.c | 181 | ||||
| -rw-r--r-- | fs/crypto/keysetup_v1.c | 95 | ||||
| -rw-r--r-- | fs/crypto/policy.c | 36 |
12 files changed, 796 insertions, 1249 deletions
diff --git a/fs/crypto/Kconfig b/fs/crypto/Kconfig index 464b54610fd3..cd934e31dec4 100644 --- a/fs/crypto/Kconfig +++ b/fs/crypto/Kconfig @@ -1,8 +1,11 @@ # SPDX-License-Identifier: GPL-2.0-only config FS_ENCRYPTION bool "FS Encryption (Per-file encryption)" + select BLK_INLINE_ENCRYPTION if BLOCK + select BLK_INLINE_ENCRYPTION_FALLBACK if BLOCK select CRYPTO select CRYPTO_SKCIPHER + select CRYPTO_LIB_AES select CRYPTO_LIB_SHA256 select CRYPTO_LIB_SHA512 select KEYS @@ -30,11 +33,8 @@ config FS_ENCRYPTION_ALGS select CRYPTO_AES select CRYPTO_CBC select CRYPTO_CTS - select CRYPTO_ECB select CRYPTO_XTS config FS_ENCRYPTION_INLINE_CRYPT - bool "Enable fscrypt to use inline crypto" - depends on FS_ENCRYPTION && BLK_INLINE_ENCRYPTION - help - Enable fscrypt to use inline encryption hardware if available. + bool + default y if FS_ENCRYPTION && BLOCK diff --git a/fs/crypto/Makefile b/fs/crypto/Makefile index 652c7180ec6d..b03e02f0f09d 100644 --- a/fs/crypto/Makefile +++ b/fs/crypto/Makefile @@ -10,5 +10,4 @@ fscrypto-y := crypto.o \ keysetup_v1.o \ policy.o -fscrypto-$(CONFIG_BLOCK) += bio.o -fscrypto-$(CONFIG_FS_ENCRYPTION_INLINE_CRYPT) += inline_crypt.o +fscrypto-$(CONFIG_BLOCK) += block.o diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c deleted file mode 100644 index 6da683ea69dc..000000000000 --- a/fs/crypto/bio.c +++ /dev/null @@ -1,220 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Utility functions for file contents encryption/decryption on - * block device-based filesystems. - * - * Copyright (C) 2015, Google, Inc. - * Copyright (C) 2015, Motorola Mobility - */ - -#include <linux/bio.h> -#include <linux/export.h> -#include <linux/module.h> -#include <linux/namei.h> -#include <linux/pagemap.h> - -#include "fscrypt_private.h" - -/** - * fscrypt_decrypt_bio() - decrypt the contents of a bio - * @bio: the bio to decrypt - * - * Decrypt the contents of a "read" bio following successful completion of the - * underlying disk read. The bio must be reading a whole number of blocks of an - * encrypted file directly into the page cache. If the bio is reading the - * ciphertext into bounce pages instead of the page cache (for example, because - * the file is also compressed, so decompression is required after decryption), - * then this function isn't applicable. This function may sleep, so it must be - * called from a workqueue rather than from the bio's bi_end_io callback. - * - * Return: %true on success; %false on failure. On failure, bio->bi_status is - * also set to an error status. - */ -bool fscrypt_decrypt_bio(struct bio *bio) -{ - struct folio_iter fi; - - bio_for_each_folio_all(fi, bio) { - int err = fscrypt_decrypt_pagecache_blocks(fi.folio, fi.length, - fi.offset); - - if (err) { - bio->bi_status = errno_to_blk_status(err); - return false; - } - } - return true; -} -EXPORT_SYMBOL(fscrypt_decrypt_bio); - -struct fscrypt_zero_done { - atomic_t pending; - blk_status_t status; - struct completion done; -}; - -static void fscrypt_zeroout_range_done(struct fscrypt_zero_done *done) -{ - if (atomic_dec_and_test(&done->pending)) - complete(&done->done); -} - -static void fscrypt_zeroout_range_end_io(struct bio *bio) -{ - struct fscrypt_zero_done *done = bio->bi_private; - - if (bio->bi_status) - cmpxchg(&done->status, 0, bio->bi_status); - fscrypt_zeroout_range_done(done); - bio_put(bio); -} - -static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode, - pgoff_t lblk, sector_t sector, - unsigned int len) -{ - const unsigned int blockbits = inode->i_blkbits; - const unsigned int blocks_per_page = 1 << (PAGE_SHIFT - blockbits); - struct fscrypt_zero_done done = { - .pending = ATOMIC_INIT(1), - .done = COMPLETION_INITIALIZER_ONSTACK(done.done), - }; - - while (len) { - struct bio *bio; - unsigned int n; - - bio = bio_alloc(inode->i_sb->s_bdev, BIO_MAX_VECS, REQ_OP_WRITE, - GFP_NOFS); - bio->bi_iter.bi_sector = sector; - bio->bi_private = &done; - bio->bi_end_io = fscrypt_zeroout_range_end_io; - fscrypt_set_bio_crypt_ctx(bio, inode, lblk, GFP_NOFS); - - for (n = 0; n < BIO_MAX_VECS; n++) { - unsigned int blocks_this_page = - min(len, blocks_per_page); - unsigned int bytes_this_page = blocks_this_page << blockbits; - - __bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0); - len -= blocks_this_page; - lblk += blocks_this_page; - sector += (bytes_this_page >> SECTOR_SHIFT); - if (!len || !fscrypt_mergeable_bio(bio, inode, lblk)) - break; - } - - atomic_inc(&done.pending); - blk_crypto_submit_bio(bio); - } - - fscrypt_zeroout_range_done(&done); - - wait_for_completion(&done.done); - return blk_status_to_errno(done.status); -} - -/** - * fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file - * @inode: the file's inode - * @lblk: the first file logical block to zero out - * @pblk: the first filesystem physical block to zero out - * @len: number of blocks to zero out - * - * Zero out filesystem blocks in an encrypted regular file on-disk, i.e. write - * ciphertext blocks which decrypt to the all-zeroes block. The blocks must be - * both logically and physically contiguous. It's also assumed that the - * filesystem only uses a single block device, ->s_bdev. - * - * Note that since each block uses a different IV, this involves writing a - * different ciphertext to each block; we can't simply reuse the same one. - * - * Return: 0 on success; -errno on failure. - */ -int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk, - sector_t pblk, unsigned int len) -{ - const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode); - const unsigned int du_bits = ci->ci_data_unit_bits; - const unsigned int du_size = 1U << du_bits; - const unsigned int du_per_page_bits = PAGE_SHIFT - du_bits; - const unsigned int du_per_page = 1U << du_per_page_bits; - u64 du_index = (u64)lblk << (inode->i_blkbits - du_bits); - u64 du_remaining = (u64)len << (inode->i_blkbits - du_bits); - sector_t sector = pblk << (inode->i_blkbits - SECTOR_SHIFT); - struct page *pages[16]; /* write up to 16 pages at a time */ - unsigned int nr_pages; - unsigned int i; - unsigned int offset; - struct bio *bio; - int ret, err; - - if (len == 0) - return 0; - - if (fscrypt_inode_uses_inline_crypto(inode)) - return fscrypt_zeroout_range_inline_crypt(inode, lblk, sector, - len); - - BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_VECS); - nr_pages = min_t(u64, ARRAY_SIZE(pages), - (du_remaining + du_per_page - 1) >> du_per_page_bits); - - /* - * We need at least one page for ciphertext. Allocate the first one - * from a mempool, with __GFP_DIRECT_RECLAIM set so that it can't fail. - * - * Any additional page allocations are allowed to fail, as they only - * help performance, and waiting on the mempool for them could deadlock. - */ - for (i = 0; i < nr_pages; i++) { - pages[i] = fscrypt_alloc_bounce_page(i == 0 ? GFP_NOFS : - GFP_NOWAIT); - if (!pages[i]) - break; - } - nr_pages = i; - if (WARN_ON_ONCE(nr_pages <= 0)) - return -EINVAL; - - /* This always succeeds since __GFP_DIRECT_RECLAIM is set. */ - bio = bio_alloc(inode->i_sb->s_bdev, nr_pages, REQ_OP_WRITE, GFP_NOFS); - - do { - bio->bi_iter.bi_sector = sector; - - i = 0; - offset = 0; - do { - err = fscrypt_crypt_data_unit(ci, FS_ENCRYPT, du_index, - ZERO_PAGE(0), pages[i], - du_size, offset); - if (err) - goto out; - du_index++; - sector += 1U << (du_bits - SECTOR_SHIFT); - du_remaining--; - offset += du_size; - if (offset == PAGE_SIZE || du_remaining == 0) { - ret = bio_add_page(bio, pages[i++], offset, 0); - if (WARN_ON_ONCE(ret != offset)) { - err = -EIO; - goto out; - } - offset = 0; - } - } while (i != nr_pages && du_remaining != 0); - - err = submit_bio_wait(bio); - if (err) - goto out; - bio_reset(bio, inode->i_sb->s_bdev, REQ_OP_WRITE); - } while (du_remaining != 0); - err = 0; -out: - bio_put(bio); - for (i = 0; i < nr_pages; i++) - fscrypt_free_bounce_page(pages[i]); - return err; -} -EXPORT_SYMBOL(fscrypt_zeroout_range); diff --git a/fs/crypto/block.c b/fs/crypto/block.c new file mode 100644 index 000000000000..5193f8ba3ee0 --- /dev/null +++ b/fs/crypto/block.c @@ -0,0 +1,415 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * File contents en/decryption on block-based filesystems + * + * Copyright 2019 Google LLC + */ + +/* + * This file implements fscrypt's file contents en/decryption using blk-crypto + * (Documentation/block/inline-encryption.rst). fscrypt assigns a bio_crypt_ctx + * with a key and IV to each bio, and the block layer does the en/decryption. + * + * This file's exported functions are called only by block-based filesystems. + */ + +#include <linux/blk-crypto.h> +#include <linux/blkdev.h> +#include <linux/export.h> +#include <linux/sched/mm.h> +#include <linux/slab.h> +#include <linux/uio.h> + +#include "fscrypt_private.h" + +static unsigned int +fscrypt_get_devices(struct super_block *sb, + struct block_device *devs[FSCRYPT_MAX_DEVICES]) +{ + if (sb->s_cop->get_devices) + return sb->s_cop->get_devices(sb, devs); + devs[0] = sb->s_bdev; + return 1; +} + +static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_inode_info *ci) +{ + const struct super_block *sb = ci->ci_inode->i_sb; + unsigned int flags = fscrypt_policy_flags(&ci->ci_policy); + int dun_bits; + + if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) + return offsetofend(union fscrypt_iv, nonce); + + if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) + return sizeof(__le64); + + if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) + return sizeof(__le32); + + /* Default case: IVs are just the file data unit index */ + dun_bits = fscrypt_max_file_dun_bits(sb, ci->ci_data_unit_bits); + return DIV_ROUND_UP(dun_bits, 8); +} + +/* + * Log a message when starting to use blk-crypto (native) or blk-crypto-fallback + * for an encryption mode for the first time. This is the blk-crypto + * counterpart to the message logged when starting to use the crypto API for the + * first time. A limitation is that these messages don't convey which specific + * filesystems or files are using each implementation. However, *usually* + * systems use just one implementation per mode, which makes these messages + * helpful for debugging problems where the "wrong" implementation is used. + */ +static void fscrypt_log_blk_crypto_impl(struct fscrypt_mode *mode, + struct block_device *dev, + const struct blk_crypto_key *blk_key) +{ + if (blk_crypto_config_supported_natively(dev, &blk_key->crypto_cfg)) { + if (!xchg(&mode->logged_blk_crypto_native, 1)) + pr_info("fscrypt: %s using blk-crypto (native)\n", + mode->friendly_name); + } else if (!xchg(&mode->logged_blk_crypto_fallback, 1)) { + pr_info("fscrypt: %s using blk-crypto-fallback\n", + mode->friendly_name); + } +} + +int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, + const u8 *key_bytes, size_t key_size, + bool is_hw_wrapped, + const struct fscrypt_inode_info *ci) +{ + const struct inode *inode = ci->ci_inode; + struct super_block *sb = inode->i_sb; + bool inlinecrypt = sb->s_flags & SB_INLINECRYPT; + struct fscrypt_mode *mode = ci->ci_mode; + enum blk_crypto_key_type key_type = is_hw_wrapped ? + BLK_CRYPTO_KEY_TYPE_HW_WRAPPED : BLK_CRYPTO_KEY_TYPE_RAW; + struct blk_crypto_key *blk_key; + struct block_device *devs[FSCRYPT_MAX_DEVICES]; + unsigned int num_devs; + unsigned int i; + int err; + + if (is_hw_wrapped && !inlinecrypt) { + /* + * blk_crypto_init_key() would catch this anyway, but this + * provides a clearer error message. + */ + fscrypt_err( + inode, + "Hardware-wrapped keys require inline encryption (-o inlinecrypt)"); + return -EINVAL; + } + + blk_key = kmalloc_obj(*blk_key); + if (!blk_key) + return -ENOMEM; + + err = blk_crypto_init_key(blk_key, key_bytes, key_size, key_type, + mode->blk_crypto_mode, + fscrypt_get_dun_bytes(ci), + 1U << ci->ci_data_unit_bits, + inlinecrypt ? BLK_CRYPTO_CFG_ALLOW_HW : 0); + if (err) { + fscrypt_err(inode, "Error %d initializing blk-crypto key", err); + goto fail; + } + + /* Start using blk-crypto on all the filesystem's block devices. */ + num_devs = fscrypt_get_devices(sb, devs); + for (i = 0; i < num_devs; i++) { + err = blk_crypto_start_using_key(devs[i], blk_key); + if (err) + break; + fscrypt_log_blk_crypto_impl(mode, devs[i], blk_key); + } + if (err) { + if (err == -EOPNOTSUPP && is_hw_wrapped) + fscrypt_err( + inode, + "Hardware-wrapped key required, but no suitable inline encryption capabilities are available"); + else + fscrypt_err(inode, + "Error %d starting to use blk-crypto", err); + goto fail; + } + + prep_key->blk_key = blk_key; + return 0; + +fail: + kfree_sensitive(blk_key); + return err; +} + +void fscrypt_destroy_inline_crypt_key(struct super_block *sb, + struct fscrypt_prepared_key *prep_key) +{ + struct blk_crypto_key *blk_key = prep_key->blk_key; + struct block_device *devs[FSCRYPT_MAX_DEVICES]; + unsigned int num_devs; + unsigned int i; + + if (!blk_key) + return; + + /* + * Evict the key from all the filesystem's block devices. + * This *must* be done before the key is freed. + */ + num_devs = fscrypt_get_devices(sb, devs); + for (i = 0; i < num_devs; i++) + blk_crypto_evict_key(devs[i], blk_key); + + kfree_sensitive(blk_key); +} + +/* + * Ask the inline encryption hardware to derive the software secret from a + * hardware-wrapped key. Returns -EOPNOTSUPP if hardware-wrapped keys aren't + * supported on this filesystem or hardware. + */ +int fscrypt_derive_sw_secret(struct super_block *sb, + const u8 *wrapped_key, size_t wrapped_key_size, + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) +{ + int err; + + /* The filesystem must be mounted with -o inlinecrypt. */ + if (!(sb->s_flags & SB_INLINECRYPT)) { + fscrypt_warn(NULL, + "%s: filesystem not mounted with inlinecrypt\n", + sb->s_id); + return -EOPNOTSUPP; + } + + err = blk_crypto_derive_sw_secret(sb->s_bdev, wrapped_key, + wrapped_key_size, sw_secret); + if (err == -EOPNOTSUPP) + fscrypt_warn(NULL, + "%s: block device doesn't support hardware-wrapped keys\n", + sb->s_id); + return err; +} + +static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci, + loff_t pos, u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]) +{ + union fscrypt_iv iv; + int i; + + fscrypt_generate_iv(&iv, pos >> ci->ci_data_unit_bits, ci); + + BUILD_BUG_ON(FSCRYPT_MAX_IV_SIZE > BLK_CRYPTO_MAX_IV_SIZE); + memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE); + for (i = 0; i < ci->ci_mode->ivsize/sizeof(dun[0]); i++) + dun[i] = le64_to_cpu(iv.dun[i]); +} + +/** + * fscrypt_set_bio_crypt_ctx() - prepare a file contents bio for inline crypto + * @bio: a bio which will eventually be submitted to the file + * @inode: the file's inode + * @pos: the first file position (in bytes) in the I/O + * @gfp_mask: memory allocation flags - these must be a waiting mask so that + * bio_crypt_set_ctx can't fail. + * + * If the contents of the file should be encrypted (or decrypted), then assign + * the appropriate encryption context to the bio. + * + * Normally the bio should be newly allocated (i.e. no pages added yet), as + * otherwise fscrypt_mergeable_bio() won't work as intended. + * + * The encryption context will be freed automatically when the bio is freed. + */ +void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, + loff_t pos, gfp_t gfp_mask) +{ + const struct fscrypt_inode_info *ci; + u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; + + if (!fscrypt_needs_contents_encryption(inode)) + return; + ci = fscrypt_get_inode_info_raw(inode); + + fscrypt_generate_dun(ci, pos, dun); + bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask); +} +EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx); + +/** + * fscrypt_mergeable_bio() - test whether data can be added to a bio + * @bio: the bio being built up + * @inode: the inode for the next part of the I/O + * @pos: the next file position (in bytes) in the I/O + * + * When building a bio which may contain data which should undergo encryption + * (or decryption) via fscrypt, filesystems should call this function to ensure + * that the resulting bio contains only contiguous data unit numbers. This will + * return false if the next part of the I/O cannot be merged with the bio + * because either the encryption key would be different or the encryption data + * unit numbers would be discontiguous. + * + * fscrypt_set_bio_crypt_ctx() must have already been called on the bio. + * + * This function isn't required in cases where crypto-mergeability is ensured in + * another way, such as I/O targeting only a single file (and thus a single key) + * combined with fscrypt_limit_io_blocks() to ensure DUN contiguity. + * + * Return: true iff the I/O is mergeable + */ +bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, + loff_t pos) +{ + const struct bio_crypt_ctx *bc = bio->bi_crypt_context; + const struct fscrypt_inode_info *ci; + u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; + + if (!!bc != fscrypt_needs_contents_encryption(inode)) + return false; + if (!bc) + return true; + ci = fscrypt_get_inode_info_raw(inode); + + /* + * Comparing the key pointers is good enough, as all I/O for each key + * uses the same pointer. I.e., there's currently no need to support + * merging requests where the keys are the same but the pointers differ. + */ + if (bc->bc_key != ci->ci_enc_key.blk_key) + return false; + + fscrypt_generate_dun(ci, pos, next_dun); + return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun); +} +EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); + +/** + * fscrypt_limit_io_blocks() - limit I/O blocks to avoid discontiguous DUNs + * @inode: the file on which I/O is being done + * @lblk: the block at which the I/O is being started from + * @nr_blocks: the number of blocks we want to submit starting at @lblk + * + * Determine the limit to the number of blocks that can be submitted in a bio + * targeting @lblk without causing a data unit number (DUN) discontiguity. + * + * This is normally just @nr_blocks, as normally the DUNs just increment along + * with the logical blocks. (Or the file is not encrypted.) + * + * In rare cases, fscrypt can be using an IV generation method that allows the + * DUN to wrap around within logically contiguous blocks, and that wraparound + * will occur. If this happens, a value less than @nr_blocks will be returned + * so that the wraparound doesn't occur in the middle of a bio, which would + * cause encryption/decryption to produce wrong results. + * + * Return: the actual number of blocks that can be submitted + */ +u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks) +{ + const struct fscrypt_inode_info *ci; + u32 dun; + + if (!fscrypt_needs_contents_encryption(inode)) + return nr_blocks; + + if (nr_blocks <= 1) + return nr_blocks; + + ci = fscrypt_get_inode_info_raw(inode); + if (!(fscrypt_policy_flags(&ci->ci_policy) & + FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) + return nr_blocks; + + /* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */ + + dun = ci->ci_hashed_ino + lblk; + + return min_t(u64, nr_blocks, (u64)U32_MAX + 1 - dun); +} +EXPORT_SYMBOL_GPL(fscrypt_limit_io_blocks); + +struct fscrypt_zero_done { + atomic_t pending; + blk_status_t status; + struct completion done; +}; + +static void fscrypt_zeroout_range_done(struct fscrypt_zero_done *done) +{ + if (atomic_dec_and_test(&done->pending)) + complete(&done->done); +} + +static void fscrypt_zeroout_range_end_io(struct bio *bio) +{ + struct fscrypt_zero_done *done = bio->bi_private; + + if (bio->bi_status) + cmpxchg(&done->status, 0, bio->bi_status); + fscrypt_zeroout_range_done(done); + bio_put(bio); +} + +/** + * fscrypt_zeroout_range() - zero out a range of blocks in an encrypted file + * @inode: the file's inode + * @pos: the first file position (in bytes) to zero out + * @sector: the first sector to zero out + * @len: bytes to zero out + * + * Zero out filesystem blocks in an encrypted regular file on-disk, i.e. write + * ciphertext blocks which decrypt to the all-zeroes block. The blocks must be + * both logically and physically contiguous. It's also assumed that the + * filesystem only uses a single block device, ->s_bdev. @len must be a + * multiple of the file system logical block size. + * + * Note that since each block uses a different IV, this involves writing a + * different ciphertext to each block; we can't simply reuse the same one. + * + * Return: 0 on success; -errno on failure. + */ +int fscrypt_zeroout_range(const struct inode *inode, loff_t pos, + sector_t sector, u64 len) +{ + struct fscrypt_zero_done done = { + .pending = ATOMIC_INIT(1), + .done = COMPLETION_INITIALIZER_ONSTACK(done.done), + }; + + if (len == 0) + return 0; + + do { + struct bio *bio; + unsigned int n; + + bio = bio_alloc(inode->i_sb->s_bdev, BIO_MAX_VECS, REQ_OP_WRITE, + GFP_NOFS); + bio->bi_iter.bi_sector = sector; + bio->bi_private = &done; + bio->bi_end_io = fscrypt_zeroout_range_end_io; + fscrypt_set_bio_crypt_ctx(bio, inode, pos, GFP_NOFS); + + for (n = 0; n < BIO_MAX_VECS; n++) { + unsigned int bytes_this_page = min(len, PAGE_SIZE); + + __bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0); + len -= bytes_this_page; + pos += bytes_this_page; + sector += (bytes_this_page >> SECTOR_SHIFT); + if (!len || !fscrypt_mergeable_bio(bio, inode, pos)) + break; + } + + atomic_inc(&done.pending); + blk_crypto_submit_bio(bio); + } while (len); + + fscrypt_zeroout_range_done(&done); + + wait_for_completion(&done.done); + return blk_status_to_errno(done.status); +} +EXPORT_SYMBOL(fscrypt_zeroout_range); diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 07f9cbfe3ea4..5286a124b0d9 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -38,18 +38,11 @@ MODULE_PARM_DESC(num_prealloc_crypto_pages, static mempool_t *fscrypt_bounce_page_pool = NULL; -static struct workqueue_struct *fscrypt_read_workqueue; static DEFINE_MUTEX(fscrypt_init_mutex); struct kmem_cache *fscrypt_inode_info_cachep; -void fscrypt_enqueue_decrypt_work(struct work_struct *work) -{ - queue_work(fscrypt_read_workqueue, work); -} -EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work); - -struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags) +static struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags) { if (WARN_ON_ONCE(!fscrypt_bounce_page_pool)) { /* @@ -65,8 +58,7 @@ struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags) * fscrypt_free_bounce_page() - free a ciphertext bounce page * @bounce_page: the bounce page to free, or NULL * - * Free a bounce page that was allocated by fscrypt_encrypt_pagecache_blocks(), - * or by fscrypt_alloc_bounce_page() directly. + * Free a bounce page that was allocated by fscrypt_encrypt_pagecache_blocks(). */ void fscrypt_free_bounce_page(struct page *bounce_page) { @@ -91,7 +83,7 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 index, { u8 flags = fscrypt_policy_flags(&ci->ci_policy); - memset(iv, 0, ci->ci_mode->ivsize); + memset(iv, 0, sizeof(*iv)); if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { WARN_ON_ONCE(index > U32_MAX); @@ -107,17 +99,23 @@ void fscrypt_generate_iv(union fscrypt_iv *iv, u64 index, } /* Encrypt or decrypt a single "data unit" of file contents. */ -int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, - fscrypt_direction_t rw, u64 index, - struct page *src_page, struct page *dest_page, - unsigned int len, unsigned int offs) +static int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, + fscrypt_direction_t rw, u64 index, + struct page *src_page, + struct page *dest_page, unsigned int len, + unsigned int offs) { - struct crypto_sync_skcipher *tfm = ci->ci_enc_key.tfm; - SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); + struct crypto_sync_skcipher *tfm; union fscrypt_iv iv; struct scatterlist dst, src; int err; + if (WARN_ON_ONCE(ci == NULL)) /* File hasn't been opened yet? */ + return -ENOKEY; + tfm = ci->ci_enc_key.tfm; + if (WARN_ON_ONCE(tfm == NULL)) /* Called on block-based filesystem? */ + return -ENOKEY; + if (WARN_ON_ONCE(len <= 0)) return -EINVAL; if (WARN_ON_ONCE(len % FSCRYPT_CONTENTS_ALIGNMENT != 0)) @@ -125,18 +123,22 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, fscrypt_generate_iv(&iv, index, ci); - skcipher_request_set_callback( - req, CRYPTO_TFM_REQ_MAY_BACKLOG | CRYPTO_TFM_REQ_MAY_SLEEP, - NULL, NULL); - sg_init_table(&dst, 1); - sg_set_page(&dst, dest_page, len, offs); - sg_init_table(&src, 1); - sg_set_page(&src, src_page, len, offs); - skcipher_request_set_crypt(req, &src, &dst, len, &iv); - if (rw == FS_DECRYPT) - err = crypto_skcipher_decrypt(req); - else - err = crypto_skcipher_encrypt(req); + { + SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); + skcipher_request_set_callback(req, + CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + NULL, NULL); + sg_init_table(&dst, 1); + sg_set_page(&dst, dest_page, len, offs); + sg_init_table(&src, 1); + sg_set_page(&src, src_page, len, offs); + skcipher_request_set_crypt(req, &src, &dst, len, &iv); + if (rw == FS_DECRYPT) + err = crypto_skcipher_decrypt(req); + else + err = crypto_skcipher_encrypt(req); + } if (err) fscrypt_err(ci->ci_inode, "%scryption failed for data unit %llu: %d", @@ -160,7 +162,7 @@ int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, * which the plaintext data was located in the source page. Any other parts of * the bounce page will be left uninitialized. * - * This is for use by the filesystem's ->writepages() method. + * This is for use by the ->writepages() method of non-block-based filesystems. * * The bounce page allocation is mempool-backed, so it will always succeed when * @gfp_flags includes __GFP_DIRECT_RECLAIM, e.g. when it's GFP_NOFS. However, @@ -174,14 +176,20 @@ struct page *fscrypt_encrypt_pagecache_blocks(struct folio *folio, { const struct inode *inode = folio->mapping->host; const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode); - const unsigned int du_bits = ci->ci_data_unit_bits; - const unsigned int du_size = 1U << du_bits; + unsigned int du_bits; + unsigned int du_size; struct page *ciphertext_page; - u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) + - (offs >> du_bits); + u64 index; unsigned int i; int err; + if (WARN_ON_ONCE(ci == NULL)) /* File hasn't been opened yet? */ + return ERR_PTR(-ENOKEY); + + du_bits = ci->ci_data_unit_bits; + du_size = 1U << du_bits; + index = (folio_pos(folio) + offs) >> du_bits; + VM_BUG_ON_FOLIO(folio_test_large(folio), folio); if (WARN_ON_ONCE(!folio_test_locked(folio))) return ERR_PTR(-EINVAL); @@ -222,7 +230,8 @@ EXPORT_SYMBOL(fscrypt_encrypt_pagecache_blocks); * arbitrary page, not necessarily in the original pagecache page. The @inode * and @lblk_num must be specified, as they can't be determined from @page. * - * This is not compatible with fscrypt_operations::supports_subblock_data_units. + * This function only supports non-block-based filesystems that don't support + * sub-block data units (as indicated by the fscrypt_operations fields). * * Return: 0 on success; -errno on failure */ @@ -239,50 +248,6 @@ int fscrypt_encrypt_block_inplace(const struct inode *inode, struct page *page, EXPORT_SYMBOL(fscrypt_encrypt_block_inplace); /** - * fscrypt_decrypt_pagecache_blocks() - Decrypt data from a pagecache folio - * @folio: the pagecache folio containing the data to decrypt - * @len: size of the data to decrypt, in bytes - * @offs: offset within @folio of the data to decrypt, in bytes - * - * Decrypt data that has just been read from an encrypted file. The data must - * be located in a pagecache folio that is still locked and not yet uptodate. - * The length and offset of the data must be aligned to the file's crypto data - * unit size. Alignment to the filesystem block size fulfills this requirement, - * as the filesystem block size is always a multiple of the data unit size. - * - * Return: 0 on success; -errno on failure - */ -int fscrypt_decrypt_pagecache_blocks(struct folio *folio, size_t len, - size_t offs) -{ - const struct inode *inode = folio->mapping->host; - const struct fscrypt_inode_info *ci = fscrypt_get_inode_info_raw(inode); - const unsigned int du_bits = ci->ci_data_unit_bits; - const unsigned int du_size = 1U << du_bits; - u64 index = ((u64)folio->index << (PAGE_SHIFT - du_bits)) + - (offs >> du_bits); - size_t i; - int err; - - if (WARN_ON_ONCE(!folio_test_locked(folio))) - return -EINVAL; - - if (WARN_ON_ONCE(len <= 0 || !IS_ALIGNED(len | offs, du_size))) - return -EINVAL; - - for (i = offs; i < offs + len; i += du_size, index++) { - struct page *page = folio_page(folio, i >> PAGE_SHIFT); - - err = fscrypt_crypt_data_unit(ci, FS_DECRYPT, index, page, - page, du_size, i & ~PAGE_MASK); - if (err) - return err; - } - return 0; -} -EXPORT_SYMBOL(fscrypt_decrypt_pagecache_blocks); - -/** * fscrypt_decrypt_block_inplace() - Decrypt a filesystem block in-place * @inode: The inode to which this block belongs * @page: The page containing the block to decrypt @@ -296,7 +261,8 @@ EXPORT_SYMBOL(fscrypt_decrypt_pagecache_blocks); * arbitrary page, not necessarily in the original pagecache page. The @inode * and @lblk_num must be specified, as they can't be determined from @page. * - * This is not compatible with fscrypt_operations::supports_subblock_data_units. + * This function only supports non-block-based filesystems that don't support + * sub-block data units (as indicated by the fscrypt_operations fields). * * Return: 0 on success; -errno on failure */ @@ -323,31 +289,26 @@ EXPORT_SYMBOL(fscrypt_decrypt_block_inplace); */ int fscrypt_initialize(struct super_block *sb) { - int err = 0; mempool_t *pool; /* pairs with smp_store_release() below */ - if (likely(smp_load_acquire(&fscrypt_bounce_page_pool))) + if (smp_load_acquire(&fscrypt_bounce_page_pool)) return 0; /* No need to allocate a bounce page pool if this FS won't use it. */ if (!sb->s_cop->needs_bounce_pages) return 0; - mutex_lock(&fscrypt_init_mutex); + guard(mutex)(&fscrypt_init_mutex); if (fscrypt_bounce_page_pool) - goto out_unlock; + return 0; - err = -ENOMEM; pool = mempool_create_page_pool(num_prealloc_crypto_pages, 0); if (!pool) - goto out_unlock; + return -ENOMEM; /* pairs with smp_load_acquire() above */ smp_store_release(&fscrypt_bounce_page_pool, pool); - err = 0; -out_unlock: - mutex_unlock(&fscrypt_init_mutex); - return err; + return 0; } void fscrypt_msg(const struct inode *inode, const char *level, @@ -365,7 +326,7 @@ void fscrypt_msg(const struct inode *inode, const char *level, vaf.fmt = fmt; vaf.va = &args; if (inode && inode->i_ino) - printk("%sfscrypt (%s, inode %lu): %pV\n", + printk("%sfscrypt (%s, inode %llu): %pV\n", level, inode->i_sb->s_id, inode->i_ino, &vaf); else if (inode) printk("%sfscrypt (%s): %pV\n", level, inode->i_sb->s_id, &vaf); @@ -374,45 +335,12 @@ void fscrypt_msg(const struct inode *inode, const char *level, va_end(args); } -/** - * fscrypt_init() - Set up for fs encryption. - * - * Return: 0 on success; -errno on failure - */ static int __init fscrypt_init(void) { - int err = -ENOMEM; - - /* - * Use an unbound workqueue to allow bios to be decrypted in parallel - * even when they happen to complete on the same CPU. This sacrifices - * locality, but it's worthwhile since decryption is CPU-intensive. - * - * Also use a high-priority workqueue to prioritize decryption work, - * which blocks reads from completing, over regular application tasks. - */ - fscrypt_read_workqueue = alloc_workqueue("fscrypt_read_queue", - WQ_UNBOUND | WQ_HIGHPRI, - num_online_cpus()); - if (!fscrypt_read_workqueue) - goto fail; - fscrypt_inode_info_cachep = KMEM_CACHE(fscrypt_inode_info, - SLAB_RECLAIM_ACCOUNT); - if (!fscrypt_inode_info_cachep) - goto fail_free_queue; - - err = fscrypt_init_keyring(); - if (err) - goto fail_free_inode_info; - + SLAB_RECLAIM_ACCOUNT | + SLAB_PANIC); + fscrypt_init_keyring(); return 0; - -fail_free_inode_info: - kmem_cache_destroy(fscrypt_inode_info_cachep); -fail_free_queue: - destroy_workqueue(fscrypt_read_workqueue); -fail: - return err; } late_initcall(fscrypt_init) diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h index 4e8e82a9ccf9..74329e0953d1 100644 --- a/fs/crypto/fscrypt_private.h +++ b/fs/crypto/fscrypt_private.h @@ -66,9 +66,6 @@ #define FSCRYPT_CONTEXT_V1 1 #define FSCRYPT_CONTEXT_V2 2 -/* Keep this in sync with include/uapi/linux/fscrypt.h */ -#define FSCRYPT_MODE_MAX FSCRYPT_MODE_AES_256_HCTR2 - struct fscrypt_context_v1 { u8 version; /* FSCRYPT_CONTEXT_V1 */ u8 contents_encryption_mode; @@ -236,7 +233,7 @@ struct fscrypt_symlink_data { * @tfm: crypto API transform object * @blk_key: key for blk-crypto * - * Normally only one of the fields will be non-NULL. + * Only one of the fields is non-NULL. */ struct fscrypt_prepared_key { struct crypto_sync_skcipher *tfm; @@ -245,6 +242,15 @@ struct fscrypt_prepared_key { #endif }; +/* An entry in the linked list ->mk_mode_keys */ +struct fscrypt_mode_key { + struct fscrypt_prepared_key key; + struct list_head link; + u8 hkdf_context; + u8 mode_num; + u8 data_unit_bits; +}; + /* * fscrypt_inode_info - the "encryption key" for an inode * @@ -260,14 +266,6 @@ struct fscrypt_inode_info { /* True if ci_enc_key should be freed when this struct is freed */ u8 ci_owns_key : 1; -#ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT - /* - * True if this inode will use inline encryption (blk-crypto) instead of - * the traditional filesystem-layer encryption. - */ - u8 ci_inlinecrypt : 1; -#endif - /* True if ci_dirhash_key is initialized */ u8 ci_dirhash_key_initialized : 1; @@ -278,9 +276,6 @@ struct fscrypt_inode_info { */ u8 ci_data_unit_bits; - /* Cached value: log2 of number of data units per FS block */ - u8 ci_data_units_per_block_bits; - /* Hashed inode number. Only set for IV_INO_LBLK_32 */ u32 ci_hashed_ino; @@ -334,11 +329,6 @@ typedef enum { /* crypto.c */ extern struct kmem_cache *fscrypt_inode_info_cachep; int fscrypt_initialize(struct super_block *sb); -int fscrypt_crypt_data_unit(const struct fscrypt_inode_info *ci, - fscrypt_direction_t rw, u64 index, - struct page *src_page, struct page *dest_page, - unsigned int len, unsigned int offs); -struct page *fscrypt_alloc_bounce_page(gfp_t gfp_flags); void __printf(3, 4) __cold fscrypt_msg(const struct inode *inode, const char *level, const char *fmt, ...); @@ -405,15 +395,14 @@ void fscrypt_hkdf_expand(const struct hmac_sha512_key *hkdf, u8 context, const u8 *info, unsigned int infolen, u8 *okm, unsigned int okmlen); -/* inline_crypt.c */ +/* block.c */ #ifdef CONFIG_FS_ENCRYPTION_INLINE_CRYPT -int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci, - bool is_hw_wrapped_key); - static inline bool fscrypt_using_inline_encryption(const struct fscrypt_inode_info *ci) { - return ci->ci_inlinecrypt; + const struct inode *inode = ci->ci_inode; + + return S_ISREG(inode->i_mode) && inode->i_sb->s_cop->is_block_based; } int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, @@ -433,30 +422,16 @@ int fscrypt_derive_sw_secret(struct super_block *sb, * @prep_key, depending on which encryption implementation the file will use. */ static inline bool -fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key, +fscrypt_is_key_prepared(const struct fscrypt_prepared_key *prep_key, const struct fscrypt_inode_info *ci) { - /* - * The two smp_load_acquire()'s here pair with the smp_store_release()'s - * in fscrypt_prepare_inline_crypt_key() and fscrypt_prepare_key(). - * I.e., in some cases (namely, if this prep_key is a per-mode - * encryption key) another task can publish blk_key or tfm concurrently, - * executing a RELEASE barrier. We need to use smp_load_acquire() here - * to safely ACQUIRE the memory the other task published. - */ if (fscrypt_using_inline_encryption(ci)) - return smp_load_acquire(&prep_key->blk_key) != NULL; - return smp_load_acquire(&prep_key->tfm) != NULL; + return prep_key->blk_key != NULL; + return prep_key->tfm != NULL; } #else /* CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ -static inline int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci, - bool is_hw_wrapped_key) -{ - return 0; -} - static inline bool fscrypt_using_inline_encryption(const struct fscrypt_inode_info *ci) { @@ -489,16 +464,29 @@ fscrypt_derive_sw_secret(struct super_block *sb, } static inline bool -fscrypt_is_key_prepared(struct fscrypt_prepared_key *prep_key, +fscrypt_is_key_prepared(const struct fscrypt_prepared_key *prep_key, const struct fscrypt_inode_info *ci) { - return smp_load_acquire(&prep_key->tfm) != NULL; + return prep_key->tfm != NULL; } #endif /* !CONFIG_FS_ENCRYPTION_INLINE_CRYPT */ /* keyring.c */ /* + * fscrypt_master_key_user - a user's claim to a master key + */ +struct fscrypt_master_key_user { + struct list_head link; + kuid_t uid; + /* + * This 'struct key' contains no secret. It exists solely to charge the + * appropriate user's key quota. + */ + struct key *quota_key; +}; + +/* * fscrypt_master_key_secret - secret key material of an in-use master key */ struct fscrypt_master_key_secret { @@ -580,8 +568,8 @@ struct fscrypt_master_key { /* * Active and structural reference counts. An active ref guarantees * that the struct continues to exist, continues to be in the keyring - * ->s_master_keys, and that any embedded subkeys (e.g. - * ->mk_direct_keys) that have been prepared continue to exist. + * ->s_master_keys, and that any non-file-scoped subkeys (e.g. + * ->mk_mode_keys) that have been prepared continue to exist. * A structural ref only guarantees that the struct continues to exist. * * There is one active ref associated with ->mk_present being true, and @@ -613,19 +601,18 @@ struct fscrypt_master_key { struct fscrypt_key_specifier mk_spec; /* - * Keyring which contains a key of type 'key_type_fscrypt_user' for each - * user who has added this key. Normally each key will be added by just - * one user, but it's possible that multiple users share a key, and in - * that case we need to keep track of those users so that one user can't - * remove the key before the others want it removed too. + * List of user claims to this key (struct fscrypt_master_key_user). + * Normally each key will be added by just one user, but it's possible + * that multiple users share a key, and in that case we need to keep + * track of those users so that one user can't remove the key before the + * others want it removed too. * - * This is NULL for v1 policy keys; those can only be added by root. + * Used only for v2 policy keys. v1 policy keys can be added only by + * root, so user tracking doesn't apply to them. * - * Locking: protected by ->mk_sem. (We don't just rely on the keyrings - * subsystem semaphore ->mk_users->sem, as we need support for atomic - * search+insert along with proper synchronization with other fields.) + * Locking: protected by ->mk_sem. */ - struct key *mk_users; + struct list_head mk_users; /* * List of inodes that were unlocked using this key. This allows the @@ -635,12 +622,21 @@ struct fscrypt_master_key { spinlock_t mk_decrypted_inodes_lock; /* - * Per-mode encryption keys for the various types of encryption policies - * that use them. Allocated and derived on-demand. + * A list of 'struct fscrypt_mode_key' for the (hkdf_context, mode_num, + * data_unit_bits, inlinecrypt) combinations that are in use for this + * master key, for hkdf_context in [HKDF_CONTEXT_DIRECT_KEY, + * HKDF_CONTEXT_IV_INO_LBLK_32_KEY, HKDF_CONTEXT_IV_INO_LBLK_64_KEY]. + * + * This is a linked list and not a hash table because in practice + * there's just a single encryption policy per master key, using + * _at most_ 2 nodes in this list. Per-file keys don't use this at all. + * + * This list is append-only until the master key is fully removed, at + * which time the list is cleared. Before then, + * fscrypt_mode_key_setup_mutex synchronizes appends, and searches use + * the RCU read lock together with ->mk_sem held for read. */ - struct fscrypt_prepared_key mk_direct_keys[FSCRYPT_MODE_MAX + 1]; - struct fscrypt_prepared_key mk_iv_ino_lblk_64_keys[FSCRYPT_MODE_MAX + 1]; - struct fscrypt_prepared_key mk_iv_ino_lblk_32_keys[FSCRYPT_MODE_MAX + 1]; + struct list_head mk_mode_keys; /* Hash key for inode numbers. Initialized only when needed. */ siphash_key_t mk_ino_hash_key; @@ -699,7 +695,7 @@ int fscrypt_add_test_dummy_key(struct super_block *sb, int fscrypt_verify_key_added(struct super_block *sb, const u8 identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]); -int __init fscrypt_init_keyring(void); +void __init fscrypt_init_keyring(void); /* keysetup.c */ diff --git a/fs/crypto/hooks.c b/fs/crypto/hooks.c index b97de0d1430f..a7a8a3f581a0 100644 --- a/fs/crypto/hooks.c +++ b/fs/crypto/hooks.c @@ -62,7 +62,7 @@ int fscrypt_file_open(struct inode *inode, struct file *filp) dentry_parent = dget_parent(dentry); if (!fscrypt_has_permitted_context(d_inode(dentry_parent), inode)) { fscrypt_warn(inode, - "Inconsistent encryption context (parent directory: %lu)", + "Inconsistent encryption context (parent directory: %llu)", d_inode(dentry_parent)->i_ino); err = -EPERM; } diff --git a/fs/crypto/inline_crypt.c b/fs/crypto/inline_crypt.c deleted file mode 100644 index c0852b920dbc..000000000000 --- a/fs/crypto/inline_crypt.c +++ /dev/null @@ -1,517 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Inline encryption support for fscrypt - * - * Copyright 2019 Google LLC - */ - -/* - * With "inline encryption", the block layer handles the decryption/encryption - * as part of the bio, instead of the filesystem doing the crypto itself via - * crypto API. See Documentation/block/inline-encryption.rst. fscrypt still - * provides the key and IV to use. - */ - -#include <linux/blk-crypto.h> -#include <linux/blkdev.h> -#include <linux/buffer_head.h> -#include <linux/export.h> -#include <linux/sched/mm.h> -#include <linux/slab.h> -#include <linux/uio.h> - -#include "fscrypt_private.h" - -static struct block_device **fscrypt_get_devices(struct super_block *sb, - unsigned int *num_devs) -{ - struct block_device **devs; - - if (sb->s_cop->get_devices) { - devs = sb->s_cop->get_devices(sb, num_devs); - if (devs) - return devs; - } - devs = kmalloc_obj(*devs); - if (!devs) - return ERR_PTR(-ENOMEM); - devs[0] = sb->s_bdev; - *num_devs = 1; - return devs; -} - -static unsigned int fscrypt_get_dun_bytes(const struct fscrypt_inode_info *ci) -{ - const struct super_block *sb = ci->ci_inode->i_sb; - unsigned int flags = fscrypt_policy_flags(&ci->ci_policy); - int dun_bits; - - if (flags & FSCRYPT_POLICY_FLAG_DIRECT_KEY) - return offsetofend(union fscrypt_iv, nonce); - - if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) - return sizeof(__le64); - - if (flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) - return sizeof(__le32); - - /* Default case: IVs are just the file data unit index */ - dun_bits = fscrypt_max_file_dun_bits(sb, ci->ci_data_unit_bits); - return DIV_ROUND_UP(dun_bits, 8); -} - -/* - * Log a message when starting to use blk-crypto (native) or blk-crypto-fallback - * for an encryption mode for the first time. This is the blk-crypto - * counterpart to the message logged when starting to use the crypto API for the - * first time. A limitation is that these messages don't convey which specific - * filesystems or files are using each implementation. However, *usually* - * systems use just one implementation per mode, which makes these messages - * helpful for debugging problems where the "wrong" implementation is used. - */ -static void fscrypt_log_blk_crypto_impl(struct fscrypt_mode *mode, - struct block_device **devs, - unsigned int num_devs, - const struct blk_crypto_config *cfg) -{ - unsigned int i; - - for (i = 0; i < num_devs; i++) { - if (!IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) || - blk_crypto_config_supported_natively(devs[i], cfg)) { - if (!xchg(&mode->logged_blk_crypto_native, 1)) - pr_info("fscrypt: %s using blk-crypto (native)\n", - mode->friendly_name); - } else if (!xchg(&mode->logged_blk_crypto_fallback, 1)) { - pr_info("fscrypt: %s using blk-crypto-fallback\n", - mode->friendly_name); - } - } -} - -/* Enable inline encryption for this file if supported. */ -int fscrypt_select_encryption_impl(struct fscrypt_inode_info *ci, - bool is_hw_wrapped_key) -{ - const struct inode *inode = ci->ci_inode; - struct super_block *sb = inode->i_sb; - struct blk_crypto_config crypto_cfg; - struct block_device **devs; - unsigned int num_devs; - unsigned int i; - - /* The file must need contents encryption, not filenames encryption */ - if (!S_ISREG(inode->i_mode)) - return 0; - - /* The crypto mode must have a blk-crypto counterpart */ - if (ci->ci_mode->blk_crypto_mode == BLK_ENCRYPTION_MODE_INVALID) - return 0; - - /* The filesystem must be mounted with -o inlinecrypt */ - if (!(sb->s_flags & SB_INLINECRYPT)) - return 0; - - /* - * When a page contains multiple logically contiguous filesystem blocks, - * some filesystem code only calls fscrypt_mergeable_bio() for the first - * block in the page. This is fine for most of fscrypt's IV generation - * strategies, where contiguous blocks imply contiguous IVs. But it - * doesn't work with IV_INO_LBLK_32. For now, simply exclude - * IV_INO_LBLK_32 with blocksize != PAGE_SIZE from inline encryption. - */ - if ((fscrypt_policy_flags(&ci->ci_policy) & - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) && - sb->s_blocksize != PAGE_SIZE) - return 0; - - /* - * On all the filesystem's block devices, blk-crypto must support the - * crypto configuration that the file would use. - */ - crypto_cfg.crypto_mode = ci->ci_mode->blk_crypto_mode; - crypto_cfg.data_unit_size = 1U << ci->ci_data_unit_bits; - crypto_cfg.dun_bytes = fscrypt_get_dun_bytes(ci); - crypto_cfg.key_type = is_hw_wrapped_key ? - BLK_CRYPTO_KEY_TYPE_HW_WRAPPED : BLK_CRYPTO_KEY_TYPE_RAW; - - devs = fscrypt_get_devices(sb, &num_devs); - if (IS_ERR(devs)) - return PTR_ERR(devs); - - for (i = 0; i < num_devs; i++) { - if (!blk_crypto_config_supported(devs[i], &crypto_cfg)) - goto out_free_devs; - } - - fscrypt_log_blk_crypto_impl(ci->ci_mode, devs, num_devs, &crypto_cfg); - - ci->ci_inlinecrypt = true; -out_free_devs: - kfree(devs); - - return 0; -} - -int fscrypt_prepare_inline_crypt_key(struct fscrypt_prepared_key *prep_key, - const u8 *key_bytes, size_t key_size, - bool is_hw_wrapped, - const struct fscrypt_inode_info *ci) -{ - const struct inode *inode = ci->ci_inode; - struct super_block *sb = inode->i_sb; - enum blk_crypto_mode_num crypto_mode = ci->ci_mode->blk_crypto_mode; - enum blk_crypto_key_type key_type = is_hw_wrapped ? - BLK_CRYPTO_KEY_TYPE_HW_WRAPPED : BLK_CRYPTO_KEY_TYPE_RAW; - struct blk_crypto_key *blk_key; - struct block_device **devs; - unsigned int num_devs; - unsigned int i; - int err; - - blk_key = kmalloc_obj(*blk_key); - if (!blk_key) - return -ENOMEM; - - err = blk_crypto_init_key(blk_key, key_bytes, key_size, key_type, - crypto_mode, fscrypt_get_dun_bytes(ci), - 1U << ci->ci_data_unit_bits); - if (err) { - fscrypt_err(inode, "error %d initializing blk-crypto key", err); - goto fail; - } - - /* Start using blk-crypto on all the filesystem's block devices. */ - devs = fscrypt_get_devices(sb, &num_devs); - if (IS_ERR(devs)) { - err = PTR_ERR(devs); - goto fail; - } - for (i = 0; i < num_devs; i++) { - err = blk_crypto_start_using_key(devs[i], blk_key); - if (err) - break; - } - kfree(devs); - if (err) { - fscrypt_err(inode, "error %d starting to use blk-crypto", err); - goto fail; - } - - /* - * Pairs with the smp_load_acquire() in fscrypt_is_key_prepared(). - * I.e., here we publish ->blk_key with a RELEASE barrier so that - * concurrent tasks can ACQUIRE it. Note that this concurrency is only - * possible for per-mode keys, not for per-file keys. - */ - smp_store_release(&prep_key->blk_key, blk_key); - return 0; - -fail: - kfree_sensitive(blk_key); - return err; -} - -void fscrypt_destroy_inline_crypt_key(struct super_block *sb, - struct fscrypt_prepared_key *prep_key) -{ - struct blk_crypto_key *blk_key = prep_key->blk_key; - struct block_device **devs; - unsigned int num_devs; - unsigned int i; - - if (!blk_key) - return; - - /* Evict the key from all the filesystem's block devices. */ - devs = fscrypt_get_devices(sb, &num_devs); - if (!IS_ERR(devs)) { - for (i = 0; i < num_devs; i++) - blk_crypto_evict_key(devs[i], blk_key); - kfree(devs); - } - kfree_sensitive(blk_key); -} - -/* - * Ask the inline encryption hardware to derive the software secret from a - * hardware-wrapped key. Returns -EOPNOTSUPP if hardware-wrapped keys aren't - * supported on this filesystem or hardware. - */ -int fscrypt_derive_sw_secret(struct super_block *sb, - const u8 *wrapped_key, size_t wrapped_key_size, - u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE]) -{ - int err; - - /* The filesystem must be mounted with -o inlinecrypt. */ - if (!(sb->s_flags & SB_INLINECRYPT)) { - fscrypt_warn(NULL, - "%s: filesystem not mounted with inlinecrypt\n", - sb->s_id); - return -EOPNOTSUPP; - } - - err = blk_crypto_derive_sw_secret(sb->s_bdev, wrapped_key, - wrapped_key_size, sw_secret); - if (err == -EOPNOTSUPP) - fscrypt_warn(NULL, - "%s: block device doesn't support hardware-wrapped keys\n", - sb->s_id); - return err; -} - -bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode) -{ - return fscrypt_get_inode_info_raw(inode)->ci_inlinecrypt; -} -EXPORT_SYMBOL_GPL(__fscrypt_inode_uses_inline_crypto); - -static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci, - u64 lblk_num, - u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]) -{ - u64 index = lblk_num << ci->ci_data_units_per_block_bits; - union fscrypt_iv iv; - int i; - - fscrypt_generate_iv(&iv, index, ci); - - BUILD_BUG_ON(FSCRYPT_MAX_IV_SIZE > BLK_CRYPTO_MAX_IV_SIZE); - memset(dun, 0, BLK_CRYPTO_MAX_IV_SIZE); - for (i = 0; i < ci->ci_mode->ivsize/sizeof(dun[0]); i++) - dun[i] = le64_to_cpu(iv.dun[i]); -} - -/** - * fscrypt_set_bio_crypt_ctx() - prepare a file contents bio for inline crypto - * @bio: a bio which will eventually be submitted to the file - * @inode: the file's inode - * @first_lblk: the first file logical block number in the I/O - * @gfp_mask: memory allocation flags - these must be a waiting mask so that - * bio_crypt_set_ctx can't fail. - * - * If the contents of the file should be encrypted (or decrypted) with inline - * encryption, then assign the appropriate encryption context to the bio. - * - * Normally the bio should be newly allocated (i.e. no pages added yet), as - * otherwise fscrypt_mergeable_bio() won't work as intended. - * - * The encryption context will be freed automatically when the bio is freed. - */ -void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, - u64 first_lblk, gfp_t gfp_mask) -{ - const struct fscrypt_inode_info *ci; - u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - - if (!fscrypt_inode_uses_inline_crypto(inode)) - return; - ci = fscrypt_get_inode_info_raw(inode); - - fscrypt_generate_dun(ci, first_lblk, dun); - bio_crypt_set_ctx(bio, ci->ci_enc_key.blk_key, dun, gfp_mask); -} -EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx); - -/* Extract the inode and logical block number from a buffer_head. */ -static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh, - const struct inode **inode_ret, - u64 *lblk_num_ret) -{ - struct folio *folio = bh->b_folio; - const struct address_space *mapping; - const struct inode *inode; - - /* - * The ext4 journal (jbd2) can submit a buffer_head it directly created - * for a non-pagecache page. fscrypt doesn't care about these. - */ - mapping = folio_mapping(folio); - if (!mapping) - return false; - inode = mapping->host; - - *inode_ret = inode; - *lblk_num_ret = (folio_pos(folio) + bh_offset(bh)) >> inode->i_blkbits; - return true; -} - -/** - * fscrypt_set_bio_crypt_ctx_bh() - prepare a file contents bio for inline - * crypto - * @bio: a bio which will eventually be submitted to the file - * @first_bh: the first buffer_head for which I/O will be submitted - * @gfp_mask: memory allocation flags - * - * Same as fscrypt_set_bio_crypt_ctx(), except this takes a buffer_head instead - * of an inode and block number directly. - */ -void fscrypt_set_bio_crypt_ctx_bh(struct bio *bio, - const struct buffer_head *first_bh, - gfp_t gfp_mask) -{ - const struct inode *inode; - u64 first_lblk; - - if (bh_get_inode_and_lblk_num(first_bh, &inode, &first_lblk)) - fscrypt_set_bio_crypt_ctx(bio, inode, first_lblk, gfp_mask); -} -EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh); - -/** - * fscrypt_mergeable_bio() - test whether data can be added to a bio - * @bio: the bio being built up - * @inode: the inode for the next part of the I/O - * @next_lblk: the next file logical block number in the I/O - * - * When building a bio which may contain data which should undergo inline - * encryption (or decryption) via fscrypt, filesystems should call this function - * to ensure that the resulting bio contains only contiguous data unit numbers. - * This will return false if the next part of the I/O cannot be merged with the - * bio because either the encryption key would be different or the encryption - * data unit numbers would be discontiguous. - * - * fscrypt_set_bio_crypt_ctx() must have already been called on the bio. - * - * This function isn't required in cases where crypto-mergeability is ensured in - * another way, such as I/O targeting only a single file (and thus a single key) - * combined with fscrypt_limit_io_blocks() to ensure DUN contiguity. - * - * Return: true iff the I/O is mergeable - */ -bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode, - u64 next_lblk) -{ - const struct bio_crypt_ctx *bc = bio->bi_crypt_context; - const struct fscrypt_inode_info *ci; - u64 next_dun[BLK_CRYPTO_DUN_ARRAY_SIZE]; - - if (!!bc != fscrypt_inode_uses_inline_crypto(inode)) - return false; - if (!bc) - return true; - ci = fscrypt_get_inode_info_raw(inode); - - /* - * Comparing the key pointers is good enough, as all I/O for each key - * uses the same pointer. I.e., there's currently no need to support - * merging requests where the keys are the same but the pointers differ. - */ - if (bc->bc_key != ci->ci_enc_key.blk_key) - return false; - - fscrypt_generate_dun(ci, next_lblk, next_dun); - return bio_crypt_dun_is_contiguous(bc, bio->bi_iter.bi_size, next_dun); -} -EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio); - -/** - * fscrypt_mergeable_bio_bh() - test whether data can be added to a bio - * @bio: the bio being built up - * @next_bh: the next buffer_head for which I/O will be submitted - * - * Same as fscrypt_mergeable_bio(), except this takes a buffer_head instead of - * an inode and block number directly. - * - * Return: true iff the I/O is mergeable - */ -bool fscrypt_mergeable_bio_bh(struct bio *bio, - const struct buffer_head *next_bh) -{ - const struct inode *inode; - u64 next_lblk; - - if (!bh_get_inode_and_lblk_num(next_bh, &inode, &next_lblk)) - return !bio->bi_crypt_context; - - return fscrypt_mergeable_bio(bio, inode, next_lblk); -} -EXPORT_SYMBOL_GPL(fscrypt_mergeable_bio_bh); - -/** - * fscrypt_dio_supported() - check whether DIO (direct I/O) is supported on an - * inode, as far as encryption is concerned - * @inode: the inode in question - * - * Return: %true if there are no encryption constraints that prevent DIO from - * being supported; %false if DIO is unsupported. (Note that in the - * %true case, the filesystem might have other, non-encryption-related - * constraints that prevent DIO from actually being supported. Also, on - * encrypted files the filesystem is still responsible for only allowing - * DIO when requests are filesystem-block-aligned.) - */ -bool fscrypt_dio_supported(struct inode *inode) -{ - int err; - - /* If the file is unencrypted, no veto from us. */ - if (!fscrypt_needs_contents_encryption(inode)) - return true; - - /* - * We only support DIO with inline crypto, not fs-layer crypto. - * - * To determine whether the inode is using inline crypto, we have to set - * up the key if it wasn't already done. This is because in the current - * design of fscrypt, the decision of whether to use inline crypto or - * not isn't made until the inode's encryption key is being set up. In - * the DIO read/write case, the key will always be set up already, since - * the file will be open. But in the case of statx(), the key might not - * be set up yet, as the file might not have been opened yet. - */ - err = fscrypt_require_key(inode); - if (err) { - /* - * Key unavailable or couldn't be set up. This edge case isn't - * worth worrying about; just report that DIO is unsupported. - */ - return false; - } - return fscrypt_inode_uses_inline_crypto(inode); -} -EXPORT_SYMBOL_GPL(fscrypt_dio_supported); - -/** - * fscrypt_limit_io_blocks() - limit I/O blocks to avoid discontiguous DUNs - * @inode: the file on which I/O is being done - * @lblk: the block at which the I/O is being started from - * @nr_blocks: the number of blocks we want to submit starting at @lblk - * - * Determine the limit to the number of blocks that can be submitted in a bio - * targeting @lblk without causing a data unit number (DUN) discontiguity. - * - * This is normally just @nr_blocks, as normally the DUNs just increment along - * with the logical blocks. (Or the file is not encrypted.) - * - * In rare cases, fscrypt can be using an IV generation method that allows the - * DUN to wrap around within logically contiguous blocks, and that wraparound - * will occur. If this happens, a value less than @nr_blocks will be returned - * so that the wraparound doesn't occur in the middle of a bio, which would - * cause encryption/decryption to produce wrong results. - * - * Return: the actual number of blocks that can be submitted - */ -u64 fscrypt_limit_io_blocks(const struct inode *inode, u64 lblk, u64 nr_blocks) -{ - const struct fscrypt_inode_info *ci; - u32 dun; - - if (!fscrypt_inode_uses_inline_crypto(inode)) - return nr_blocks; - - if (nr_blocks <= 1) - return nr_blocks; - - ci = fscrypt_get_inode_info_raw(inode); - if (!(fscrypt_policy_flags(&ci->ci_policy) & - FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32)) - return nr_blocks; - - /* With IV_INO_LBLK_32, the DUN can wrap around from U32_MAX to 0. */ - - dun = ci->ci_hashed_ino + lblk; - - return min_t(u64, nr_blocks, (u64)U32_MAX + 1 - dun); -} -EXPORT_SYMBOL_GPL(fscrypt_limit_io_blocks); diff --git a/fs/crypto/keyring.c b/fs/crypto/keyring.c index 9ec6e5ef0947..76e28d1e0064 100644 --- a/fs/crypto/keyring.c +++ b/fs/crypto/keyring.c @@ -65,36 +65,33 @@ static void fscrypt_free_master_key(struct rcu_head *head) kfree_sensitive(mk); } +static void clear_mk_users(struct fscrypt_master_key *mk); + void fscrypt_put_master_key(struct fscrypt_master_key *mk) { if (!refcount_dec_and_test(&mk->mk_struct_refs)) return; /* - * No structural references left, so free ->mk_users, and also free the + * No structural references left, so clear ->mk_users, and also free the * fscrypt_master_key struct itself after an RCU grace period ensures * that concurrent keyring lookups can no longer find it. */ WARN_ON_ONCE(refcount_read(&mk->mk_active_refs) != 0); - if (mk->mk_users) { - /* Clear the keyring so the quota gets released right away. */ - keyring_clear(mk->mk_users); - key_put(mk->mk_users); - mk->mk_users = NULL; - } + clear_mk_users(mk); call_rcu(&mk->mk_rcu_head, fscrypt_free_master_key); } void fscrypt_put_master_key_activeref(struct super_block *sb, struct fscrypt_master_key *mk) { - size_t i; + struct fscrypt_mode_key *node, *tmp; if (!refcount_dec_and_test(&mk->mk_active_refs)) return; /* * No active references left, so complete the full removal of this * fscrypt_master_key struct by removing it from the keyring and - * destroying any subkeys embedded in it. + * destroying any non-file-scoped subkeys. */ if (WARN_ON_ONCE(!sb->s_master_keys)) @@ -110,13 +107,16 @@ void fscrypt_put_master_key_activeref(struct super_block *sb, WARN_ON_ONCE(mk->mk_present); WARN_ON_ONCE(!list_empty(&mk->mk_decrypted_inodes)); - for (i = 0; i <= FSCRYPT_MODE_MAX; i++) { - fscrypt_destroy_prepared_key( - sb, &mk->mk_direct_keys[i]); - fscrypt_destroy_prepared_key( - sb, &mk->mk_iv_ino_lblk_64_keys[i]); - fscrypt_destroy_prepared_key( - sb, &mk->mk_iv_ino_lblk_32_keys[i]); + /* + * Destroy any non-file-scoped subkeys. Since ->mk_active_refs == 0, + * they're no longer referenced by any inodes. Nor can key setup run + * and use them again. So they're no longer needed. (This implies no + * concurrent readers, so we don't need list_del_rcu() for example.) + */ + list_for_each_entry_safe(node, tmp, &mk->mk_mode_keys, link) { + fscrypt_destroy_prepared_key(sb, &node->key); + list_del(&node->link); + kfree(node); } memzero_explicit(&mk->mk_ino_hash_key, sizeof(mk->mk_ino_hash_key)); @@ -162,8 +162,8 @@ static void fscrypt_user_key_describe(const struct key *key, struct seq_file *m) } /* - * Type of key in ->mk_users. Each key of this type represents a particular - * user who has added a particular master key. + * Type of fscrypt_master_key_user::quota_key. This contains no secret; it + * exists solely to charge a user's key quota. * * Note that the name of this key type really should be something like * ".fscrypt-user" instead of simply ".fscrypt". But the shorter name is chosen @@ -177,30 +177,9 @@ static struct key_type key_type_fscrypt_user = { .describe = fscrypt_user_key_describe, }; -#define FSCRYPT_MK_USERS_DESCRIPTION_SIZE \ - (CONST_STRLEN("fscrypt-") + 2 * FSCRYPT_KEY_IDENTIFIER_SIZE + \ - CONST_STRLEN("-users") + 1) - #define FSCRYPT_MK_USER_DESCRIPTION_SIZE \ (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + CONST_STRLEN(".uid.") + 10 + 1) -static void format_mk_users_keyring_description( - char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE], - const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) -{ - sprintf(description, "fscrypt-%*phN-users", - FSCRYPT_KEY_IDENTIFIER_SIZE, mk_identifier); -} - -static void format_mk_user_description( - char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE], - const u8 mk_identifier[FSCRYPT_KEY_IDENTIFIER_SIZE]) -{ - - sprintf(description, "%*phN.uid.%u", FSCRYPT_KEY_IDENTIFIER_SIZE, - mk_identifier, __kuid_val(current_fsuid())); -} - /* Create ->s_master_keys if needed. Synchronized by fscrypt_add_key_mutex. */ static int allocate_filesystem_keyring(struct super_block *sb) { @@ -335,91 +314,94 @@ out: return mk; } -static int allocate_master_key_users_keyring(struct fscrypt_master_key *mk) -{ - char description[FSCRYPT_MK_USERS_DESCRIPTION_SIZE]; - struct key *keyring; - - format_mk_users_keyring_description(description, - mk->mk_spec.u.identifier); - keyring = keyring_alloc(description, GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, - current_cred(), KEY_POS_SEARCH | - KEY_USR_SEARCH | KEY_USR_READ | KEY_USR_VIEW, - KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); - if (IS_ERR(keyring)) - return PTR_ERR(keyring); - - mk->mk_users = keyring; - return 0; -} - -/* - * Find the current user's "key" in the master key's ->mk_users. - * Returns ERR_PTR(-ENOKEY) if not found. - */ -static struct key *find_master_key_user(struct fscrypt_master_key *mk) +/* Find the current user's claim in ->mk_users. ->mk_sem must be held. */ +static struct fscrypt_master_key_user * +find_master_key_user(struct fscrypt_master_key *mk) { - char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE]; - key_ref_t keyref; + struct fscrypt_master_key_user *mk_user; + kuid_t uid = current_fsuid(); - format_mk_user_description(description, mk->mk_spec.u.identifier); - - /* - * We need to mark the keyring reference as "possessed" so that we - * acquire permission to search it, via the KEY_POS_SEARCH permission. - */ - keyref = keyring_search(make_key_ref(mk->mk_users, true /*possessed*/), - &key_type_fscrypt_user, description, false); - if (IS_ERR(keyref)) { - if (PTR_ERR(keyref) == -EAGAIN || /* not found */ - PTR_ERR(keyref) == -EKEYREVOKED) /* recently invalidated */ - keyref = ERR_PTR(-ENOKEY); - return ERR_CAST(keyref); + list_for_each_entry(mk_user, &mk->mk_users, link) { + if (uid_eq(mk_user->uid, uid)) + return mk_user; } - return key_ref_to_ptr(keyref); + return NULL; } /* - * Give the current user a "key" in ->mk_users. This charges the user's quota + * Give the current user a claim in ->mk_users. This charges the user's quota * and marks the master key as added by the current user, so that it cannot be * removed by another user with the key. Either ->mk_sem must be held for * write, or the master key must be still undergoing initialization. */ static int add_master_key_user(struct fscrypt_master_key *mk) { + kuid_t uid = current_fsuid(); char description[FSCRYPT_MK_USER_DESCRIPTION_SIZE]; - struct key *mk_user; + struct key *quota_key; + struct fscrypt_master_key_user *mk_user; int err; - format_mk_user_description(description, mk->mk_spec.u.identifier); - mk_user = key_alloc(&key_type_fscrypt_user, description, - current_fsuid(), current_gid(), current_cred(), - KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL); - if (IS_ERR(mk_user)) - return PTR_ERR(mk_user); + snprintf(description, sizeof(description), "%*phN.uid.%u", + FSCRYPT_KEY_IDENTIFIER_SIZE, mk->mk_spec.u.identifier, + __kuid_val(uid)); + quota_key = key_alloc(&key_type_fscrypt_user, description, uid, + current_gid(), current_cred(), + KEY_POS_SEARCH | KEY_USR_VIEW, 0, NULL); + if (IS_ERR(quota_key)) + return PTR_ERR(quota_key); + + err = key_instantiate_and_link(quota_key, NULL, 0, NULL, NULL); + if (err) { + key_put(quota_key); + return err; + } + + mk_user = kzalloc_obj(*mk_user); + if (!mk_user) { + key_put(quota_key); + return -ENOMEM; + } + mk_user->uid = uid; + mk_user->quota_key = quota_key; + list_add(&mk_user->link, &mk->mk_users); + return 0; +} - err = key_instantiate_and_link(mk_user, NULL, 0, mk->mk_users, NULL); - key_put(mk_user); - return err; +static void unlink_and_free_mk_user(struct fscrypt_master_key_user *mk_user) +{ + list_del(&mk_user->link); + key_put(mk_user->quota_key); + kfree(mk_user); } /* - * Remove the current user's "key" from ->mk_users. + * Remove the current user's claim from ->mk_users. * ->mk_sem must be held for write. * - * Returns 0 if removed, -ENOKEY if not found, or another -errno code. + * Returns 0 if removed or -ENOKEY if not found. */ static int remove_master_key_user(struct fscrypt_master_key *mk) { - struct key *mk_user; - int err; + struct fscrypt_master_key_user *mk_user; mk_user = find_master_key_user(mk); - if (IS_ERR(mk_user)) - return PTR_ERR(mk_user); - err = key_unlink(mk->mk_users, mk_user); - key_put(mk_user); - return err; + if (!mk_user) + return -ENOKEY; + unlink_and_free_mk_user(mk_user); + return 0; +} + +/* + * Clear ->mk_users. Either ->mk_sem must be held for write, or 'mk' must have + * no structural references left. + */ +static void clear_mk_users(struct fscrypt_master_key *mk) +{ + struct fscrypt_master_key_user *mk_user, *tmp; + + list_for_each_entry_safe(mk_user, tmp, &mk->mk_users, link) + unlink_and_free_mk_user(mk_user); } /* @@ -442,13 +424,14 @@ static int add_new_master_key(struct super_block *sb, refcount_set(&mk->mk_struct_refs, 1); mk->mk_spec = *mk_spec; + INIT_LIST_HEAD(&mk->mk_users); + INIT_LIST_HEAD(&mk->mk_decrypted_inodes); spin_lock_init(&mk->mk_decrypted_inodes_lock); + INIT_LIST_HEAD(&mk->mk_mode_keys); + if (mk_spec->type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { - err = allocate_master_key_users_keyring(mk); - if (err) - goto out_put; err = add_master_key_user(mk); if (err) goto out_put; @@ -477,19 +460,13 @@ static int add_existing_master_key(struct fscrypt_master_key *mk, int err; /* - * If the current user is already in ->mk_users, then there's nothing to - * do. Otherwise, we need to add the user to ->mk_users. (Neither is - * applicable for v1 policy keys, which have NULL ->mk_users.) + * For v2 policy keys (FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER): If the current + * user is already in ->mk_users, then there's nothing to do. + * Otherwise, add the user to ->mk_users. */ - if (mk->mk_users) { - struct key *mk_user = find_master_key_user(mk); - - if (mk_user != ERR_PTR(-ENOKEY)) { - if (IS_ERR(mk_user)) - return PTR_ERR(mk_user); - key_put(mk_user); + if (mk->mk_spec.type == FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER) { + if (find_master_key_user(mk) != NULL) return 0; - } err = add_master_key_user(mk); if (err) return err; @@ -520,7 +497,7 @@ static int do_add_master_key(struct super_block *sb, struct fscrypt_master_key *mk; int err; - mutex_lock(&fscrypt_add_key_mutex); /* serialize find + link */ + guard(mutex)(&fscrypt_add_key_mutex); /* serialize find + link */ mk = fscrypt_find_master_key(sb, mk_spec); if (!mk) { @@ -547,7 +524,6 @@ static int do_add_master_key(struct super_block *sb, } fscrypt_put_master_key(mk); } - mutex_unlock(&fscrypt_add_key_mutex); return err; } @@ -888,7 +864,6 @@ int fscrypt_verify_key_added(struct super_block *sb, { struct fscrypt_key_specifier mk_spec; struct fscrypt_master_key *mk; - struct key *mk_user; int err; mk_spec.type = FSCRYPT_KEY_SPEC_TYPE_IDENTIFIER; @@ -900,13 +875,10 @@ int fscrypt_verify_key_added(struct super_block *sb, goto out; } down_read(&mk->mk_sem); - mk_user = find_master_key_user(mk); - if (IS_ERR(mk_user)) { - err = PTR_ERR(mk_user); - } else { - key_put(mk_user); + if (find_master_key_user(mk) != NULL) err = 0; - } + else + err = -ENOKEY; up_read(&mk->mk_sem); fscrypt_put_master_key(mk); out: @@ -969,8 +941,8 @@ static int check_for_busy_inodes(struct super_block *sb, { struct list_head *pos; size_t busy_count = 0; - unsigned long ino; char ino_str[50] = ""; + u64 ino; spin_lock(&mk->mk_decrypted_inodes_lock); @@ -994,7 +966,7 @@ static int check_for_busy_inodes(struct super_block *sb, /* If the inode is currently being created, ino may still be 0. */ if (ino) - snprintf(ino_str, sizeof(ino_str), ", including ino %lu", ino); + snprintf(ino_str, sizeof(ino_str), ", including ino %llu", ino); fscrypt_warn(NULL, "%s: %zu inode(s) still busy after removing key with %s %*phN%s", @@ -1098,16 +1070,18 @@ static int do_remove_key(struct file *filp, void __user *_uarg, bool all_users) down_write(&mk->mk_sem); /* If relevant, remove current user's (or all users) claim to the key */ - if (mk->mk_users && mk->mk_users->keys.nr_leaves_on_tree != 0) { - if (all_users) - err = keyring_clear(mk->mk_users); - else + if (!list_empty(&mk->mk_users)) { + if (all_users) { + clear_mk_users(mk); + err = 0; + } else { err = remove_master_key_user(mk); + } if (err) { up_write(&mk->mk_sem); goto out_put_key; } - if (mk->mk_users->keys.nr_leaves_on_tree != 0) { + if (!list_empty(&mk->mk_users)) { /* * Other users have still added the key too. We removed * the current user's claim to the key, but we still @@ -1193,6 +1167,8 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) struct super_block *sb = file_inode(filp)->i_sb; struct fscrypt_get_key_status_arg arg; struct fscrypt_master_key *mk; + kuid_t uid; + const struct fscrypt_master_key_user *mk_user; int err; if (copy_from_user(&arg, uarg, sizeof(arg))) @@ -1225,19 +1201,13 @@ int fscrypt_ioctl_get_key_status(struct file *filp, void __user *uarg) } arg.status = FSCRYPT_KEY_STATUS_PRESENT; - if (mk->mk_users) { - struct key *mk_user; - arg.user_count = mk->mk_users->keys.nr_leaves_on_tree; - mk_user = find_master_key_user(mk); - if (!IS_ERR(mk_user)) { + uid = current_fsuid(); + list_for_each_entry(mk_user, &mk->mk_users, link) { + arg.user_count++; + if (uid_eq(mk_user->uid, uid)) arg.status_flags |= FSCRYPT_KEY_STATUS_FLAG_ADDED_BY_SELF; - key_put(mk_user); - } else if (mk_user != ERR_PTR(-ENOKEY)) { - err = PTR_ERR(mk_user); - goto out_release_key; - } } err = 0; out_release_key: @@ -1250,21 +1220,19 @@ out: } EXPORT_SYMBOL_GPL(fscrypt_ioctl_get_key_status); -int __init fscrypt_init_keyring(void) +void __init fscrypt_init_keyring(void) { int err; + /* + * Note that register_key_type() fails only if a key type with the same + * name already exists, which should never happen here. + */ err = register_key_type(&key_type_fscrypt_user); if (err) - return err; - + panic("failed to register .fscrypt key type (%d)", err); err = register_key_type(&key_type_fscrypt_provisioning); if (err) - goto err_unregister_fscrypt_user; - - return 0; - -err_unregister_fscrypt_user: - unregister_key_type(&key_type_fscrypt_user); - return err; + panic("failed to register fscrypt-provisioning key type (%d)", + err); } diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 40fa05688d3a..892044ebcaca 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -83,15 +83,13 @@ static struct fscrypt_mode * select_encryption_mode(const union fscrypt_policy *policy, const struct inode *inode) { - BUILD_BUG_ON(ARRAY_SIZE(fscrypt_modes) != FSCRYPT_MODE_MAX + 1); - if (S_ISREG(inode->i_mode)) return &fscrypt_modes[fscrypt_policy_contents_mode(policy)]; if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) return &fscrypt_modes[fscrypt_policy_fnames_mode(policy)]; - WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %lu, which is not encryptable (file type %d)\n", + WARN_ONCE(1, "fscrypt: filesystem tried to load encryption info for inode %llu, which is not encryptable (file type %d)\n", inode->i_ino, (inode->i_mode & S_IFMT)); return ERR_PTR(-EINVAL); } @@ -146,9 +144,9 @@ err_free_tfm: /* * Prepare the crypto transform object or blk-crypto key in @prep_key, given the - * raw key, encryption mode (@ci->ci_mode), flag indicating which encryption - * implementation (fs-layer or blk-crypto) will be used (@ci->ci_inlinecrypt), - * and IV generation method (@ci->ci_policy.flags). + * raw key, encryption mode (@ci->ci_mode), predicate indicating which style of + * key is needed (fscrypt_using_inline_encryption(ci)), IV generation method + * (@ci->ci_policy.flags), and data unit size (@ci->ci_data_unit_bits). */ int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, const u8 *raw_key, const struct fscrypt_inode_info *ci) @@ -163,13 +161,7 @@ int fscrypt_prepare_key(struct fscrypt_prepared_key *prep_key, tfm = fscrypt_allocate_skcipher(ci->ci_mode, raw_key, ci->ci_inode); if (IS_ERR(tfm)) return PTR_ERR(tfm); - /* - * Pairs with the smp_load_acquire() in fscrypt_is_key_prepared(). - * I.e., here we publish ->tfm with a RELEASE barrier so that - * concurrent tasks can ACQUIRE it. Note that this concurrency is only - * possible for per-mode keys, not for per-file keys. - */ - smp_store_release(&prep_key->tfm, tfm); + prep_key->tfm = tfm; return 0; } @@ -190,9 +182,37 @@ int fscrypt_set_per_file_enc_key(struct fscrypt_inode_info *ci, return fscrypt_prepare_key(&ci->ci_enc_key, raw_key, ci); } +/* + * Find the fscrypt_prepared_key (if any) for a particular (mk, hkdf_context, + * mode_num, data_unit_bits, inlinecrypt) combination. + * + * The caller must hold ->mk_sem for reading and ->mk_present must be true, + * ensuring that ->mk_mode_keys is still append-only. + */ +static struct fscrypt_prepared_key * +fscrypt_find_mode_key(struct fscrypt_master_key *mk, u8 hkdf_context, + u8 mode_num, const struct fscrypt_inode_info *ci) +{ + struct fscrypt_mode_key *node; + + /* + * The RCU read lock here is used only to synchronize with concurrent + * list_add_tail_rcu(). Concurrent deletions are impossible here, so + * returning a pointer to a node without taking any refcount is safe. + */ + guard(rcu)(); + list_for_each_entry_rcu(node, &mk->mk_mode_keys, link) { + if (node->hkdf_context == hkdf_context && + node->mode_num == mode_num && + node->data_unit_bits == ci->ci_data_unit_bits && + fscrypt_is_key_prepared(&node->key, ci)) + return &node->key; + } + return NULL; +} + static int setup_per_mode_enc_key(struct fscrypt_inode_info *ci, struct fscrypt_master_key *mk, - struct fscrypt_prepared_key *keys, u8 hkdf_context, bool include_fs_uuid) { const struct inode *inode = ci->ci_inode; @@ -200,71 +220,62 @@ static int setup_per_mode_enc_key(struct fscrypt_inode_info *ci, struct fscrypt_mode *mode = ci->ci_mode; const u8 mode_num = mode - fscrypt_modes; struct fscrypt_prepared_key *prep_key; - u8 mode_key[FSCRYPT_MAX_RAW_KEY_SIZE]; + struct fscrypt_mode_key *new_node; + u8 raw_mode_key[FSCRYPT_MAX_RAW_KEY_SIZE]; u8 hkdf_info[sizeof(mode_num) + sizeof(sb->s_uuid)]; unsigned int hkdf_infolen = 0; - bool use_hw_wrapped_key = false; int err; - if (WARN_ON_ONCE(mode_num > FSCRYPT_MODE_MAX)) - return -EINVAL; - - if (mk->mk_secret.is_hw_wrapped && S_ISREG(inode->i_mode)) { - /* Using a hardware-wrapped key for file contents encryption */ - if (!fscrypt_using_inline_encryption(ci)) { - if (sb->s_flags & SB_INLINECRYPT) - fscrypt_warn(ci->ci_inode, - "Hardware-wrapped key required, but no suitable inline encryption capabilities are available"); - else - fscrypt_warn(ci->ci_inode, - "Hardware-wrapped keys require inline encryption (-o inlinecrypt)"); - return -EINVAL; - } - use_hw_wrapped_key = true; + prep_key = fscrypt_find_mode_key(mk, hkdf_context, mode_num, ci); + if (prep_key) { + ci->ci_enc_key = *prep_key; + return 0; } - prep_key = &keys[mode_num]; - if (fscrypt_is_key_prepared(prep_key, ci)) { + guard(mutex)(&fscrypt_mode_key_setup_mutex); + + prep_key = fscrypt_find_mode_key(mk, hkdf_context, mode_num, ci); + if (prep_key) { ci->ci_enc_key = *prep_key; return 0; } - mutex_lock(&fscrypt_mode_key_setup_mutex); - - if (fscrypt_is_key_prepared(prep_key, ci)) - goto done_unlock; + new_node = kzalloc_obj(*new_node); + if (!new_node) + return -ENOMEM; + new_node->hkdf_context = hkdf_context; + new_node->mode_num = mode_num; + new_node->data_unit_bits = ci->ci_data_unit_bits; + prep_key = &new_node->key; - if (use_hw_wrapped_key) { + if (mk->mk_secret.is_hw_wrapped && S_ISREG(inode->i_mode)) { err = fscrypt_prepare_inline_crypt_key(prep_key, mk->mk_secret.bytes, mk->mk_secret.size, true, ci); - if (err) - goto out_unlock; - goto done_unlock; + } else { + static_assert(sizeof(mode_num) == 1); + static_assert(sizeof(sb->s_uuid) == 16); + static_assert(sizeof(hkdf_info) == 17); + hkdf_info[hkdf_infolen++] = mode_num; + if (include_fs_uuid) { + memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid, + sizeof(sb->s_uuid)); + hkdf_infolen += sizeof(sb->s_uuid); + } + fscrypt_hkdf_expand(&mk->mk_secret.hkdf, hkdf_context, + hkdf_info, hkdf_infolen, raw_mode_key, + mode->keysize); + err = fscrypt_prepare_key(prep_key, raw_mode_key, ci); + memzero_explicit(raw_mode_key, sizeof(raw_mode_key)); } - - BUILD_BUG_ON(sizeof(mode_num) != 1); - BUILD_BUG_ON(sizeof(sb->s_uuid) != 16); - BUILD_BUG_ON(sizeof(hkdf_info) != 17); - hkdf_info[hkdf_infolen++] = mode_num; - if (include_fs_uuid) { - memcpy(&hkdf_info[hkdf_infolen], &sb->s_uuid, - sizeof(sb->s_uuid)); - hkdf_infolen += sizeof(sb->s_uuid); + if (err) { + kfree(new_node); + return err; } - fscrypt_hkdf_expand(&mk->mk_secret.hkdf, hkdf_context, hkdf_info, - hkdf_infolen, mode_key, mode->keysize); - err = fscrypt_prepare_key(prep_key, mode_key, ci); - memzero_explicit(mode_key, mode->keysize); - if (err) - goto out_unlock; -done_unlock: + list_add_tail_rcu(&new_node->link, &mk->mk_mode_keys); ci->ci_enc_key = *prep_key; - err = 0; -out_unlock: - mutex_unlock(&fscrypt_mode_key_setup_mutex); - return err; + return 0; } /* @@ -311,25 +322,24 @@ static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_inode_info *ci, { int err; - err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_32_keys, - HKDF_CONTEXT_IV_INO_LBLK_32_KEY, true); + err = setup_per_mode_enc_key(ci, mk, HKDF_CONTEXT_IV_INO_LBLK_32_KEY, + true); if (err) return err; /* pairs with smp_store_release() below */ if (!smp_load_acquire(&mk->mk_ino_hash_key_initialized)) { - - mutex_lock(&fscrypt_mode_key_setup_mutex); - - if (mk->mk_ino_hash_key_initialized) - goto unlock; - - fscrypt_derive_siphash_key(mk, HKDF_CONTEXT_INODE_HASH_KEY, - NULL, 0, &mk->mk_ino_hash_key); - /* pairs with smp_load_acquire() above */ - smp_store_release(&mk->mk_ino_hash_key_initialized, true); -unlock: - mutex_unlock(&fscrypt_mode_key_setup_mutex); + guard(mutex)(&fscrypt_mode_key_setup_mutex); + + if (!mk->mk_ino_hash_key_initialized) { + fscrypt_derive_siphash_key(mk, + HKDF_CONTEXT_INODE_HASH_KEY, + NULL, 0, + &mk->mk_ino_hash_key); + /* pairs with smp_load_acquire() above */ + smp_store_release(&mk->mk_ino_hash_key_initialized, + true); + } } /* @@ -364,8 +374,8 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_inode_info *ci, * encryption key. This ensures that the master key is * consistently used only for HKDF, avoiding key reuse issues. */ - err = setup_per_mode_enc_key(ci, mk, mk->mk_direct_keys, - HKDF_CONTEXT_DIRECT_KEY, false); + err = setup_per_mode_enc_key(ci, mk, HKDF_CONTEXT_DIRECT_KEY, + false); } else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64) { /* @@ -374,9 +384,8 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_inode_info *ci, * the IVs. This format is optimized for use with inline * encryption hardware compliant with the UFS standard. */ - err = setup_per_mode_enc_key(ci, mk, mk->mk_iv_ino_lblk_64_keys, - HKDF_CONTEXT_IV_INO_LBLK_64_KEY, - true); + err = setup_per_mode_enc_key( + ci, mk, HKDF_CONTEXT_IV_INO_LBLK_64_KEY, true); } else if (ci->ci_policy.v2.flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) { err = fscrypt_setup_iv_ino_lblk_32_key(ci, mk); @@ -388,7 +397,7 @@ static int fscrypt_setup_v2_file_key(struct fscrypt_inode_info *ci, ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE, derived_key, ci->ci_mode->keysize); err = fscrypt_set_per_file_enc_key(ci, derived_key); - memzero_explicit(derived_key, ci->ci_mode->keysize); + memzero_explicit(derived_key, sizeof(derived_key)); } if (err) return err; @@ -485,10 +494,6 @@ static int setup_file_encryption_key(struct fscrypt_inode_info *ci, if (ci->ci_policy.version != FSCRYPT_POLICY_V1) return -ENOKEY; - err = fscrypt_select_encryption_impl(ci, false); - if (err) - return err; - /* * As a legacy fallback for v1 policies, search for the key in * the current task's subscribed keyrings too. Don't move this @@ -510,10 +515,6 @@ static int setup_file_encryption_key(struct fscrypt_inode_info *ci, goto out_release_key; } - err = fscrypt_select_encryption_impl(ci, mk->mk_secret.is_hw_wrapped); - if (err) - goto out_release_key; - switch (ci->ci_policy.version) { case FSCRYPT_POLICY_V1: if (WARN_ON_ONCE(mk->mk_secret.is_hw_wrapped)) { @@ -609,8 +610,6 @@ fscrypt_setup_encryption_info(struct inode *inode, crypt_info->ci_data_unit_bits = fscrypt_policy_du_bits(&crypt_info->ci_policy, inode); - crypt_info->ci_data_units_per_block_bits = - inode->i_blkbits - crypt_info->ci_data_unit_bits; res = setup_file_encryption_key(crypt_info, need_dirhash_key, &mk); if (res) diff --git a/fs/crypto/keysetup_v1.c b/fs/crypto/keysetup_v1.c index 3d673c36b678..87fe13ccb253 100644 --- a/fs/crypto/keysetup_v1.c +++ b/fs/crypto/keysetup_v1.c @@ -20,11 +20,10 @@ * managed alongside the master keys in the filesystem-level keyring) */ -#include <crypto/skcipher.h> +#include <crypto/aes.h> #include <crypto/utils.h> #include <keys/user-type.h> #include <linux/hashtable.h> -#include <linux/scatterlist.h> #include "fscrypt_private.h" @@ -33,48 +32,6 @@ static DEFINE_HASHTABLE(fscrypt_direct_keys, 6); /* 6 bits = 64 buckets */ static DEFINE_SPINLOCK(fscrypt_direct_keys_lock); /* - * v1 key derivation function. This generates the derived key by encrypting the - * master key with AES-128-ECB using the nonce as the AES key. This provides a - * unique derived key with sufficient entropy for each inode. However, it's - * nonstandard, non-extensible, doesn't evenly distribute the entropy from the - * master key, and is trivially reversible: an attacker who compromises a - * derived key can "decrypt" it to get back to the master key, then derive any - * other key. For all new code, use HKDF instead. - * - * The master key must be at least as long as the derived key. If the master - * key is longer, then only the first 'derived_keysize' bytes are used. - */ -static int derive_key_aes(const u8 *master_key, - const u8 nonce[FSCRYPT_FILE_NONCE_SIZE], - u8 *derived_key, unsigned int derived_keysize) -{ - struct crypto_sync_skcipher *tfm; - int err; - - tfm = crypto_alloc_sync_skcipher("ecb(aes)", 0, FSCRYPT_CRYPTOAPI_MASK); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - err = crypto_sync_skcipher_setkey(tfm, nonce, FSCRYPT_FILE_NONCE_SIZE); - if (err == 0) { - SYNC_SKCIPHER_REQUEST_ON_STACK(req, tfm); - struct scatterlist src_sg, dst_sg; - - skcipher_request_set_callback(req, - CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - NULL, NULL); - sg_init_one(&src_sg, master_key, derived_keysize); - sg_init_one(&dst_sg, derived_key, derived_keysize); - skcipher_request_set_crypt(req, &src_sg, &dst_sg, - derived_keysize, NULL); - err = crypto_skcipher_encrypt(req); - } - crypto_free_sync_skcipher(tfm); - return err; -} - -/* * Search the current task's subscribed keyrings for a "logon" key with * description prefix:descriptor, and if found acquire a read lock on it and * return a pointer to its validated payload in *payload_ret. @@ -190,13 +147,19 @@ find_or_insert_direct_key(struct fscrypt_direct_key *to_insert, if (memcmp(ci->ci_policy.v1.master_key_descriptor, dk->dk_descriptor, FSCRYPT_KEY_DESCRIPTOR_SIZE) != 0) continue; + /* The sb is used at eviction time, so it must be the same. */ + if (ci->ci_inode->i_sb != dk->dk_sb) + continue; if (ci->ci_mode != dk->dk_mode) continue; if (!fscrypt_is_key_prepared(&dk->dk_key, ci)) continue; if (crypto_memneq(raw_key, dk->dk_raw, ci->ci_mode->keysize)) continue; - /* using existing tfm with same (descriptor, mode, raw_key) */ + /* + * Use an existing prepared key with the same (descriptor, sb, + * mode, inlinecrypt, raw_key) combination. + */ refcount_inc(&dk->dk_refcount); spin_unlock(&fscrypt_direct_keys_lock); free_direct_key(to_insert); @@ -255,29 +218,41 @@ static int setup_v1_file_key_direct(struct fscrypt_inode_info *ci, return 0; } -/* v1 policy, !DIRECT_KEY: derive the file's encryption key */ +/* + * v1 policy, !DIRECT_KEY: derive the file's encryption key. + * + * The v1 key derivation function generates the derived key by encrypting the + * master key with AES-128-ECB using the file's nonce as the AES key. This + * provides a unique derived key with sufficient entropy for each inode. + * However, it's nonstandard, non-extensible, doesn't evenly distribute the + * entropy from the master key, and is trivially reversible: an attacker who + * compromises a derived key can "decrypt" it to get back to the master key, + * then derive any other key. For all new code, use HKDF instead. + * + * The master key must be at least as long as the derived key. If the master + * key is longer, then only the first ci->ci_mode->keysize bytes are used. + */ static int setup_v1_file_key_derived(struct fscrypt_inode_info *ci, const u8 *raw_master_key) { - u8 *derived_key; + const unsigned int derived_keysize = ci->ci_mode->keysize; + u8 derived_key[FSCRYPT_MAX_RAW_KEY_SIZE]; + struct aes_enckey aes; int err; - /* - * This cannot be a stack buffer because it will be passed to the - * scatterlist crypto API during derive_key_aes(). - */ - derived_key = kmalloc(ci->ci_mode->keysize, GFP_KERNEL); - if (!derived_key) - return -ENOMEM; + if (WARN_ON_ONCE(derived_keysize > FSCRYPT_MAX_RAW_KEY_SIZE || + derived_keysize % AES_BLOCK_SIZE != 0)) + return -EINVAL; - err = derive_key_aes(raw_master_key, ci->ci_nonce, - derived_key, ci->ci_mode->keysize); - if (err) - goto out; + static_assert(FSCRYPT_FILE_NONCE_SIZE == AES_KEYSIZE_128); + aes_prepareenckey(&aes, ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE); + for (unsigned int i = 0; i < derived_keysize; i += AES_BLOCK_SIZE) + aes_encrypt(&aes, &derived_key[i], &raw_master_key[i]); err = fscrypt_set_per_file_enc_key(ci, derived_key); -out: - kfree_sensitive(derived_key); + + memzero_explicit(derived_key, sizeof(derived_key)); + /* No need to zeroize 'aes', as its key is not secret. */ return err; } diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 9915e39362db..6dd510f93e6d 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -177,6 +177,23 @@ static bool supported_iv_ino_lblk_policy(const struct fscrypt_policy_v2 *policy, type, sb->s_id); return false; } + + /* + * IV_INO_LBLK_32 isn't compatible with inline encryption when + * s_blocksize != PAGE_SIZE. In that case the DUN can wrap around in + * the middle of a page, but sometimes fscrypt_mergeable_bio() is called + * only for the first block per page. Since IV_INO_LBLK_32 exists only + * to support inline encryption hardware that is limited to 32-bit DUNs, + * just disallow IV_INO_LBLK_32 with s_blocksize != PAGE_SIZE entirely. + */ + if ((policy->flags & FSCRYPT_POLICY_FLAG_IV_INO_LBLK_32) && + sb->s_blocksize != PAGE_SIZE) { + fscrypt_warn(inode, + "Can't use %s policy on filesystem '%s' with block size != PAGE_SIZE", + type, sb->s_id); + return false; + } + return true; } @@ -507,7 +524,6 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) union fscrypt_policy policy; union fscrypt_policy existing_policy; struct inode *inode = file_inode(filp); - u8 version; int size; int ret; @@ -518,23 +534,11 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) if (size <= 0) return -EINVAL; - /* - * We should just copy the remaining 'size - 1' bytes here, but a - * bizarre bug in gcc 7 and earlier (fixed by gcc r255731) causes gcc to - * think that size can be 0 here (despite the check above!) *and* that - * it's a compile-time constant. Thus it would think copy_from_user() - * is passed compile-time constant ULONG_MAX, causing the compile-time - * buffer overflow check to fail, breaking the build. This only occurred - * when building an i386 kernel with -Os and branch profiling enabled. - * - * Work around it by just copying the first byte again... - */ - version = policy.version; - if (copy_from_user(&policy, arg, size)) + if (copy_from_user((u8 *)&policy + 1, (const u8 __user *)arg + 1, + size - 1)) return -EFAULT; - policy.version = version; - if (!inode_owner_or_capable(&nop_mnt_idmap, inode)) + if (!inode_owner_or_capable(file_mnt_idmap(filp), inode)) return -EACCES; ret = mnt_want_write_file(filp); |
