On Fri, Apr 10, 2026 at 06:40:30AM -0700, Linlin Zhang wrote: > From: Eric Biggers <[email protected]> > > Add a new device-mapper target "dm-inlinecrypt" that is similar to > dm-crypt but uses the blk-crypto API instead of the regular crypto API. > This allows it to take advantage of inline encryption hardware such as > that commonly built into UFS host controllers. > > The table syntax matches dm-crypt's, but for now only a stripped-down > set of parameters is supported. For example, for now AES-256-XTS is the > only supported cipher. > > dm-inlinecrypt is based on Android's dm-default-key with the > controversial passthrough support removed. Note that due to the removal > of passthrough support, use of dm-inlinecrypt in combination with > fscrypt causes double encryption of file contents (similar to dm-crypt + > fscrypt), with the fscrypt layer not being able to use the inline > encryption hardware. This makes dm-inlinecrypt unusable on systems such > as Android that use fscrypt and where a more optimized approach is > needed. It is however suitable as a replacement for dm-crypt. > > dm-inlinecrypt supports both keyring key and hex key, the former avoids > the key to be exposed in dm-table message. Similar to dm-default-key in > Android, it will fallabck to the software block crypto once the inline > crypto hardware cannot support the expected cipher. > > Test: > dmsetup create inlinecrypt_logon --table "0 `blockdev --getsz $1` \ > inlinecrypt aes-xts-plain64 :64:logon:fde:dminlinecrypt_test_key 0 $1 0" > > Signed-off-by: Eric Biggers <[email protected]> > Signed-off-by: Linlin Zhang <[email protected]> > --- > drivers/md/Kconfig | 10 + > drivers/md/Makefile | 1 + > drivers/md/dm-inlinecrypt.c | 559 ++++++++++++++++++++++++++++++++++++ > 3 files changed, 570 insertions(+) > create mode 100644 drivers/md/dm-inlinecrypt.c <snip> > diff --git a/drivers/md/dm-inlinecrypt.c b/drivers/md/dm-inlinecrypt.c > new file mode 100644 > index 000000000000..b6e98fdf8af1 > --- /dev/null > +++ b/drivers/md/dm-inlinecrypt.c <snip> > +static int inlinecrypt_map(struct dm_target *ti, struct bio *bio) > +{ > + const struct inlinecrypt_ctx *ctx = ti->private; > + sector_t sector_in_target; > + u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE] = {}; > + > + bio_set_dev(bio, ctx->dev->bdev); > + > + /* > + * If the bio is a device-level request which doesn't target a specific > + * sector, there's nothing more to do. > + */ > + if (bio_sectors(bio) == 0) > + return DM_MAPIO_REMAPPED; > + > + /* > + * The bio should never have an encryption context already, since > + * dm-inlinecrypt doesn't pass through any inline encryption > + * capabilities to the layer above it. > + */ > + if (WARN_ON_ONCE(bio_has_crypt_ctx(bio))) > + return DM_MAPIO_KILL; > + > + /* Map the bio's sector to the underlying device. (512-byte sectors) */ > + sector_in_target = dm_target_offset(ti, bio->bi_iter.bi_sector); > + bio->bi_iter.bi_sector = ctx->start + sector_in_target; > + /* > + * If the bio doesn't have any data (e.g. if it's a DISCARD request), > + * there's nothing more to do. > + */ > + if (!bio_has_data(bio)) > + return DM_MAPIO_REMAPPED; > + > + /* Calculate the DUN and enforce data-unit (crypto sector) alignment. */ > + dun[0] = ctx->iv_offset + sector_in_target; /* 512-byte sectors */ > + if (dun[0] & ((ctx->sector_size >> SECTOR_SHIFT) - 1)) > + return DM_MAPIO_KILL; > + dun[0] >>= ctx->sector_bits - SECTOR_SHIFT; /* crypto sectors */ > + > + /* > + * This check isn't necessary as we should have calculated max_dun > + * correctly, but be safe. > + */ > + if (WARN_ON_ONCE(dun[0] > ctx->max_dun)) > + return DM_MAPIO_KILL; > + > + bio_crypt_set_ctx(bio, &ctx->key, dun, GFP_NOIO); > + > + /* > + * Since we've added an encryption context to the bio and > + * blk-crypto-fallback may be needed to process it, it's necessary to > + * use the fallback-aware bio submission code rather than > + * unconditionally returning DM_MAPIO_REMAPPED. > + * > + * To get the correct accounting for a dm target in the case where > + * __blk_crypto_submit_bio() doesn't take ownership of the bio (returns > + * true), call __blk_crypto_submit_bio() directly and return > + * DM_MAPIO_REMAPPED in that case, rather than relying on > + * blk_crypto_submit_bio() which calls submit_bio() in that case. > + */ > + if (__blk_crypto_submit_bio(bio))
This will still double account for fallback writes (which call submit_bio() on the encrypted bios, and return DM_MAPIO_SUBMITTED here). -Ben > + return DM_MAPIO_REMAPPED; > + return DM_MAPIO_SUBMITTED; > +}

