Commit 9932f00b authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux

Pull fscrypt updates from Eric Biggers:

 - Various cleanups for the interface between fs/crypto/ and
   filesystems, from Christoph Hellwig

 - Simplify and optimize the implementation of v1 key derivation by
   using the AES library instead of the crypto_skcipher API

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux:
  fscrypt: use AES library for v1 key derivation
  ext4: use a byte granularity cursor in ext4_mpage_readpages
  fscrypt: pass a real sector_t to fscrypt_zeroout_range
  fscrypt: pass a byte length to fscrypt_zeroout_range
  fscrypt: pass a byte offset to fscrypt_zeroout_range
  fscrypt: pass a byte length to fscrypt_zeroout_range_inline_crypt
  fscrypt: pass a byte offset to fscrypt_zeroout_range_inline_crypt
  fscrypt: pass a byte offset to fscrypt_set_bio_crypt_ctx
  fscrypt: pass a byte offset to fscrypt_mergeable_bio
  fscrypt: pass a byte offset to fscrypt_generate_dun
  fscrypt: move fscrypt_set_bio_crypt_ctx_bh to buffer.c
  ext4, fscrypt: merge fscrypt_mergeable_bio_bh into io_submit_need_new_bio
  ext4: factor out a io_submit_need_new_bio helper
  ext4: open code fscrypt_set_bio_crypt_ctx_bh
  ext4: initialize the write hint in io_submit_init_bio
parents 81dc1e4d 1546d3fe
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -2667,6 +2667,21 @@ static void end_bio_bh_io_sync(struct bio *bio)
	bio_put(bio);
}

static void buffer_set_crypto_ctx(struct bio *bio, const struct buffer_head *bh,
				  gfp_t gfp_mask)
{
	const struct address_space *mapping = folio_mapping(bh->b_folio);

	/*
	 * The ext4 journal (jbd2) can submit a buffer_head it directly created
	 * for a non-pagecache page.  fscrypt doesn't care about these.
	 */
	if (!mapping)
		return;
	fscrypt_set_bio_crypt_ctx(bio, mapping->host,
			folio_pos(bh->b_folio) + bh_offset(bh), gfp_mask);
}

static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,
			  enum rw_hint write_hint,
			  struct writeback_control *wbc)
@@ -2693,7 +2708,8 @@ static void submit_bh_wbc(blk_opf_t opf, struct buffer_head *bh,

	bio = bio_alloc(bh->b_bdev, 1, opf, GFP_NOIO);

	fscrypt_set_bio_crypt_ctx_bh(bio, bh, GFP_NOIO);
	if (IS_ENABLED(CONFIG_FS_ENCRYPTION))
		buffer_set_crypto_ctx(bio, bh, GFP_NOIO);

	bio->bi_iter.bi_sector = bh->b_blocknr * (bh->b_size >> 9);
	bio->bi_write_hint = write_hint;
+1 −1
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ config FS_ENCRYPTION
	bool "FS Encryption (Per-file encryption)"
	select CRYPTO
	select CRYPTO_SKCIPHER
	select CRYPTO_LIB_AES
	select CRYPTO_LIB_SHA256
	select CRYPTO_LIB_SHA512
	select KEYS
@@ -30,7 +31,6 @@ config FS_ENCRYPTION_ALGS
	select CRYPTO_AES
	select CRYPTO_CBC
	select CRYPTO_CTS
	select CRYPTO_ECB
	select CRYPTO_XTS

config FS_ENCRYPTION_INLINE_CRYPT
+17 −21
Original line number Diff line number Diff line
@@ -70,11 +70,9 @@ static void fscrypt_zeroout_range_end_io(struct bio *bio)
}

static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
					      pgoff_t lblk, sector_t sector,
					      unsigned int len)
					      loff_t pos, sector_t sector,
					      u64 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),
@@ -89,18 +87,16 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
		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);
		fscrypt_set_bio_crypt_ctx(bio, inode, pos, 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;
			unsigned int bytes_this_page = min(len, PAGE_SIZE);

			__bio_add_page(bio, ZERO_PAGE(0), bytes_this_page, 0);
			len -= blocks_this_page;
			lblk += blocks_this_page;
			len -= bytes_this_page;
			pos += bytes_this_page;
			sector += (bytes_this_page >> SECTOR_SHIFT);
			if (!len || !fscrypt_mergeable_bio(bio, inode, lblk))
			if (!len || !fscrypt_mergeable_bio(bio, inode, pos))
				break;
		}

@@ -117,31 +113,31 @@ static int fscrypt_zeroout_range_inline_crypt(const struct inode *inode,
/**
 * 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
 * @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.
 * 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, pgoff_t lblk,
			  sector_t pblk, unsigned int len)
int fscrypt_zeroout_range(const struct inode *inode, loff_t pos,
			  sector_t sector, u64 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);
	u64 du_index = pos >> du_bits;
	u64 du_remaining = len >> du_bits;
	struct page *pages[16]; /* write up to 16 pages at a time */
	unsigned int nr_pages;
	unsigned int i;
@@ -153,7 +149,7 @@ int fscrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
		return 0;

	if (fscrypt_inode_uses_inline_crypto(inode))
		return fscrypt_zeroout_range_inline_crypt(inode, lblk, sector,
		return fscrypt_zeroout_range_inline_crypt(inode, pos, sector,
							  len);

	BUILD_BUG_ON(ARRAY_SIZE(pages) > BIO_MAX_VECS);
+0 −3
Original line number Diff line number Diff line
@@ -278,9 +278,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;

+8 −78
Original line number Diff line number Diff line
@@ -268,14 +268,12 @@ bool __fscrypt_inode_uses_inline_crypto(const struct inode *inode)
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])
				 loff_t pos, 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);
	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);
@@ -287,7 +285,7 @@ static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci,
 * 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
 * @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.
 *
@@ -300,7 +298,7 @@ static void fscrypt_generate_dun(const struct fscrypt_inode_info *ci,
 * 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)
			       loff_t pos, gfp_t gfp_mask)
{
	const struct fscrypt_inode_info *ci;
	u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE];
@@ -309,61 +307,16 @@ void fscrypt_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode,
		return;
	ci = fscrypt_get_inode_info_raw(inode);

	fscrypt_generate_dun(ci, first_lblk, dun);
	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);

/* 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
 * @pos: the next file position (in bytes) 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
@@ -381,7 +334,7 @@ EXPORT_SYMBOL_GPL(fscrypt_set_bio_crypt_ctx_bh);
 * Return: true iff the I/O is mergeable
 */
bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
			   u64 next_lblk)
			   loff_t pos)
{
	const struct bio_crypt_ctx *bc = bio->bi_crypt_context;
	const struct fscrypt_inode_info *ci;
@@ -401,34 +354,11 @@ bool fscrypt_mergeable_bio(struct bio *bio, const struct inode *inode,
	if (bc->bc_key != ci->ci_enc_key.blk_key)
		return false;

	fscrypt_generate_dun(ci, next_lblk, next_dun);
	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_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
Loading