mbox series

[v4,0/9] ensure bios aren't split in middle of crypto data unit

Message ID 20210707052943.3960-1-satyaprateek2357@gmail.com (mailing list archive)
Headers show
Series ensure bios aren't split in middle of crypto data unit | expand

Message

Satya Tangirala July 7, 2021, 5:29 a.m. UTC
When a bio has an encryption context, its size must be aligned to its
crypto data unit size. A bio must not be split in the middle of a data
unit. Currently, bios are split at logical block boundaries, but a crypto
data unit size might be larger than the logical block size - e.g. a machine
could be using fscrypt (which uses 4K crypto data units) with an eMMC block
device with inline encryption hardware that has a logical block size of 512
bytes.

Right now, the only user of blk-crypto is fscrypt (on ext4 and f2fs), which
(currently) only submits bios where the size of each segment is a multiple
of data_unit_size.  That happens to avoid most of the cases where bios
could be split in the middle of a data unit.  However, when support for
direct I/O on encrypted files is added, or when support for filesystem
metadata encryption is added, it will be possible for bios to have segment
lengths that are multiples of the logical block size, but not multiples of
the crypto data unit size.  So the block layer needs to start handling this
case appropriately.

So we need to support cases where the data unit size is larger than
the logical block size.

Patch 1 introduces blk_ksm_is_empty() that checks whether a keyslot manager
advertises a non-zero number of crypto capabilities. This function helps
clean up code a little.

Patches 2 and 3 introduce blk_crypto_bio_sectors_alignment() and
bio_required_sector_alignment() respectively. The former returns the
required sector alignment due to any crypto requirements the bio has.  The
latter returns the required sector alignment due to any reason.  The number
of sectors in any bio (and in particular, the number of sectors passed to
bio_split) *must* be aligned to the value returned by the latter function
(which, of course, calls the former function to decide what to return).

Patch 4 introduces restrictions on the data unit sizes advertised by a
keyslot manager. These restrictions come about due to the request_queue's
queue_limits, and are required to ensure that blk_bio_segment_split() can
always split a bio so that it has a limited number of sectors and segments,
and that the number of sectors it has is non-zero and aligned to
bio_required_sector_alignment().

Patches 5, 6 and 7 handle the error code from blk_ksm_register() in all
callers.  This return code was previously ignored by all callers because
the function could only fail if the request_queue had integrity support,
which the callers ensured would not be the case. But the patches in this
series add more cases where this function might fail, so it's better to
just handle the return code properly in all the callers.

Patch 8 updates get_max_io_size() and blk_bio_segment_split() to respect
bio_required_sector_alignment(). get_max_io_size() always returns a
value that is aligned to bio_required_sector_alignment(), and together
with Patch 4, this is enough to ensure that if the bio is split, it is
split at a crypto data unit size boundary.

Since all callers to bio_split() should have been updated by the previous
patches, Patch 9 adds a WARN_ON() to bio_split() when sectors isn't aligned
to bio_required_sector_alignment() (the one exception is bounce.c which is
legacy code and won't interact with inline encryption).

This patch series was tested by running android xfstests on the SDM630
chipset (which has eMMC inline encryption hardware with logical block size
512 bytes) with test_dummy_encryption with and without the 'inlinecrypt'
mount option.

Changes v3 => v4
 - Addressed comments and incorporated fixes from Eric
 - Patch 4 in v3 has been removed (Eric points out it isn't required
   without some of the changes in the device mapper patchset at
   https://lore.kernel.org/linux-block/20210604210908.2105870-1-satyat@google.com/
  so I'll add this patch to that series instead.

Satya Tangirala (9):
  block: introduce blk_ksm_is_empty()
  block: blk-crypto: introduce blk_crypto_bio_sectors_alignment()
  block: introduce bio_required_sector_alignment()
  block: keyslot-manager: introduce
    blk_ksm_restrict_dus_to_queue_limits()
  ufshcd: handle error from blk_ksm_register()
  mmc: handle error from blk_ksm_register()
  dm: handle error from blk_ksm_register()
  blk-merge: Ensure bios aren't split in middle of a crypto data unit
  block: add WARN_ON_ONCE() to bio_split() for sector alignment

 block/bio.c                      |   1 +
 block/blk-crypto-internal.h      |  17 +++++
 block/blk-merge.c                |  49 ++++++++-----
 block/blk.h                      |  17 +++++
 block/keyslot-manager.c          | 120 +++++++++++++++++++++++++++++++
 drivers/md/dm-table.c            |  28 +++++---
 drivers/mmc/core/crypto.c        |  13 +++-
 drivers/scsi/ufs/ufshcd-crypto.c |  13 +++-
 include/linux/keyslot-manager.h  |   2 +
 9 files changed, 227 insertions(+), 33 deletions(-)

Comments

Eric Biggers July 23, 2021, 4:49 p.m. UTC | #1
On Tue, Jul 06, 2021 at 10:29:34PM -0700, Satya Tangirala wrote:
> 
> Changes v3 => v4
>  - Patch 4 in v3 has been removed (Eric points out it isn't required
>    without some of the changes in the device mapper patchset at
>    https://lore.kernel.org/linux-block/20210604210908.2105870-1-satyat@google.com/
>   so I'll add this patch to that series instead.

Wouldn't it make more sense to have the blk-crypto-fallback change in this
series?  My concern was just that it didn't make sense to have it split between
the two patch series -- it seemed like one logical change.

- Eric
Eric Biggers July 23, 2021, 5:52 p.m. UTC | #2
On Fri, Jul 23, 2021 at 09:49:52AM -0700, Eric Biggers wrote:
> On Tue, Jul 06, 2021 at 10:29:34PM -0700, Satya Tangirala wrote:
> > 
> > Changes v3 => v4
> >  - Patch 4 in v3 has been removed (Eric points out it isn't required
> >    without some of the changes in the device mapper patchset at
> >    https://lore.kernel.org/linux-block/20210604210908.2105870-1-satyat@google.com/
> >   so I'll add this patch to that series instead.
> 
> Wouldn't it make more sense to have the blk-crypto-fallback change in this
> series?  My concern was just that it didn't make sense to have it split between
> the two patch series -- it seemed like one logical change.

This series also doesn't actually remove the data_unit_size bvec alignment
requirement from block/blk-crypto.c.  Isn't that the main goal here?  So I
expected that it would be included.

Unless there are special considerations here, I'd expect that all the block
layer changes needed for the fscrypt direct I/O support would be in one patch
series that could go in together, and then the patch series with the direct I/O
support would be only filesystem layer changes.

- Eric
Christoph Hellwig July 24, 2021, 7:36 a.m. UTC | #3
On Tue, Jul 06, 2021 at 10:29:34PM -0700, Satya Tangirala wrote:
> When a bio has an encryption context, its size must be aligned to its
> crypto data unit size. A bio must not be split in the middle of a data
> unit. Currently, bios are split at logical block boundaries, but a crypto
> data unit size might be larger than the logical block size - e.g. a machine
> could be using fscrypt (which uses 4K crypto data units) with an eMMC block
> device with inline encryption hardware that has a logical block size of 512
> bytes.
> 
> Right now, the only user of blk-crypto is fscrypt (on ext4 and f2fs), which
> (currently) only submits bios where the size of each segment is a multiple
> of data_unit_size.  That happens to avoid most of the cases where bios
> could be split in the middle of a data unit.  However, when support for
> direct I/O on encrypted files is added, or when support for filesystem
> metadata encryption is added, it will be possible for bios to have segment
> lengths that are multiples of the logical block size, but not multiples of
> the crypto data unit size.  So the block layer needs to start handling this
> case appropriately.

I'm still not sold on this case yet.  sector size aligned I/O is an
optional feature, and I don't think it is worth this overhead.  And
while file systems metadata can be smaller than the file system block
size in a few cases (e.g. XFS log writes), that is usually an extra
performance optimization and can be trivially disabled in mkfs.