From: sashiko-bot@kernel.org
To: "Linlin Zhang" <linlin.zhang@oss.qualcomm.com>
Cc: "Eugenio Perez" <eperezma@redhat.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
virtualization@lists.linux.dev
Subject: Re: [PATCH v3 2/2] virtio_blk: add inline encryption support
Date: Sun, 20 Sep 2026 12:38:40 +0000 [thread overview]
Message-ID: <20260920123840.EF61D1F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260920122444.2549493-3-linlin.zhang@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] block: memory leak of sensitive cryptographic key material in virtio_blk
- [High] block: DMA cacheline sharing in virtblk_ctrl_request causes data corruption
- [High] block: deadlock in virtblk_crypto_generate_key() due to vdev_mutex
- [Medium] block: incorrect bitwise arithmetic in get_supported_blk_key_types() breaks negotiation
- [Medium] block: Kconfig VIRTIO_BLK_INLINE_ENCRYPTION tristate causes linker errors
--
commit 3dd149ac489e952ca2319a45325b2d578747f639
Author: linlzhan <linlin.zhang@oss.qualcomm.com>
virtio_blk: add inline encryption support
This commit adds support for the virtio-blk inline encryption feature,
allowing the guest to offload per-I/O encryption to the host. It wires up
device characteristics to a blk_crypto_profile and manages keys via the
control virtqueue.
> diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
> index 858320b6ebb7e..58bb050d4617c 100644
> --- a/drivers/block/Kconfig
> +++ b/drivers/block/Kconfig
> @@ -372,4 +372,16 @@ config BLK_DEV_ZONED_LOOP
>
> If unsure, say N.
>
> +config VIRTIO_BLK_INLINE_ENCRYPTION
> + tristate "Virtio block inline encryption support"
> + depends on VIRTIO_BLK && BLK_INLINE_ENCRYPTION
[Severity: Medium]
Should this option be a bool instead of a tristate?
If a user configures CONFIG_VIRTIO_BLK=y and CONFIG_BLK_INLINE_ENCRYPTION=m,
this dependency evaluates to 'm'. Because the inline encryption code is
integrated directly into virtio_blk.c using IS_ENABLED(), it gets compiled
as built-in alongside virtio_blk. It will then attempt to link against
blk_crypto_profile_init() and other block crypto symbols which are loadable
modules, causing unresolved symbol errors during linking.
> diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
> index 2fad86e8f7a9a..30c303364ca97 100644
> --- a/drivers/block/virtio_blk.c
> +++ b/drivers/block/virtio_blk.c
[ ... ]
> @@ -124,7 +136,21 @@ struct virtblk_req {
> };
>
> struct virtblk_ctrl_request {
> + /* Type byte, always its own out-sg for every command. */
> __virtio32 type;
> + /* Out request, sent as a second, separate out-sg if any. */
> + union {
> + struct virtio_blk_crypto_key_desc key_desc;
> + struct virtio_blk_crypto_key_blob blob;
> + } out_req;
> +
> + /* In response */
> + union {
> + struct virtio_blk_crypto_key_blob blob;
> + struct virtio_blk_crypto_sw_secret secret;
> + struct virtio_blk_crypto_modes modes;
> + } in_resp;
> + /* Status byte, always its own in-sg for every command. */
> u8 status;
>
> struct completion *compl;
[Severity: High]
Could this struct layout cause cacheline corruption on architectures with
non-coherent DMA?
The virtblk_ctrl_request struct dynamically allocates fields mapped for
DMA_TO_DEVICE (type, out_req) and DMA_FROM_DEVICE (status, in_resp),
alongside CPU-modified fields (abandoned, compl). Because the struct is
not cacheline aligned internally, these fields share CPU cachelines. If the
CPU writes to the abandoned field while a DMA operation is occurring, or
before dma_unmap_sg() invalidates the cache for DMA_FROM_DEVICE, the cache
coherency conflict might overwrite or discard data.
[ ... ]
> +static int virtblk_crypto_keyslot_program(struct blk_crypto_profile *profile,
> + const struct blk_crypto_key *key,
> + unsigned int slot)
> +{
[ ... ]
> + creq->type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_CRYPTO_KEYSLOT_PROGRAM);
> +
> + err = set_virtblk_crypto_key_desc(vblk->vdev, creq, key, slot);
> + if (err)
> + goto out_free;
> +
> + sg_init_one(&type_sg, &creq->type, sizeof(creq->type));
> + sg_init_one(&out_req_sg, &creq->out_req.key_desc, sizeof(creq->out_req.key_desc));
> + sg_init_one(&status_sg, &creq->status, sizeof(creq->status));
> + sgs[0] = &type_sg;
> + sgs[1] = &out_req_sg;
> + sgs[2] = &status_sg;
> +
> + err = virtblk_ctrl_vq_request(vblk, creq, sgs, 2, 1);
[Severity: Medium]
This is a pre-existing issue, but does virtblk_ctrl_vq_request() contain a
race condition when handling timeouts for these allocated control requests?
If wait_for_completion_timeout() times out, virtblk_ctrl_vq_request() sets
creq->abandoned = true to inform the callback to free the memory. However, if
the interrupt fires exactly after the timeout expires but before the lock is
acquired, virtblk_ctrlq_callback() reads abandoned == false and assumes the
waiting thread will free it. The waiting thread then returns -ETIMEDOUT and
skips freeing it, leading to a permanent leak of both creq and compl.
> + if (err == -ETIMEDOUT)
> + goto out_unlock;
> + if (err)
> + goto out_free;
> +
> + err = blk_status_to_errno(virtblk_result(creq->status));
> +out_free:
> + kfree(creq);
[Severity: High]
Does this leak sensitive cryptographic key material in memory?
The creq buffer contains the plaintext or wrapped key descriptor, but it is
freed via kfree() instead of kfree_sensitive(). The fscrypt subsystem rules
mandate that keys must be zeroized after use to prevent memory disclosure.
[ ... ]
> +static int virtblk_crypto_derive_sw_secret(struct blk_crypto_profile *profile,
> + const u8 *eph_key, size_t eph_key_size,
> + u8 sw_secret[BLK_CRYPTO_SW_SECRET_SIZE])
> +{
[ ... ]
> + err = blk_status_to_errno(virtblk_result(creq->status));
> + if (err)
> + goto out_free;
> +
> + memcpy(sw_secret, creq->in_resp.secret.secret, BLK_CRYPTO_SW_SECRET_SIZE);
> +out_free:
> + kfree(creq);
[Severity: High]
Similar to virtblk_crypto_keyslot_program(), does this leave the highly
sensitive derived software secret in memory instead of zeroizing it with
kfree_sensitive()?
[ ... ]
> +static int virtblk_crypto_generate_key(struct blk_crypto_profile *profile,
> + u8 lt_key[BLK_CRYPTO_MAX_HW_WRAPPED_KEY_SIZE])
> +{
> + struct virtio_blk *vblk = virtblk_from_profile(profile);
> + struct scatterlist type_sg, resp_sg, status_sg, *sgs[3];
> + struct virtblk_ctrl_request *creq;
> + unsigned int key_size;
> + int err;
> +
> + mutex_lock(&vblk->vdev_mutex);
> + if (!vblk->vdev) {
> + err = -ENXIO;
> + goto out_unlock;
> + }
> +
> + creq = kzalloc_obj(*creq, GFP_KERNEL);
[Severity: High]
Can holding vdev_mutex during a GFP_KERNEL allocation cause a deadlock here?
Under memory pressure, GFP_KERNEL triggers direct reclaim, which flushes
dirty pages to the block device. If the bio requires inline encryption, the
block layer synchronously calls virtblk_crypto_keyslot_program() from the I/O
submission path. That callback immediately attempts to acquire vdev_mutex,
which is already held by the sleeping thread, causing a strict AB-BA/AA
deadlock.
[ ... ]
> +static unsigned int get_supported_blk_key_types(u8 virtio_key_types)
> +{
> + unsigned int supported = 0;
> +
> + if (virtio_key_types & VIRTIO_BLK_CRYPTO_KEY_TYPE_RAW)
> + supported |= virtio_key_type_to_blk(VIRTIO_BLK_CRYPTO_KEY_TYPE_RAW);
> + if (virtio_key_types & VIRTIO_BLK_CRYPTO_KEY_TYPE_HW_WRAPPED)
> + supported |= virtio_key_type_to_blk(VIRTIO_BLK_CRYPTO_KEY_TYPE_HW_WRAPPED);
> +
> + return supported;
> +}
[Severity: Medium]
Does this construct an invalid capability bitmask by directly bitwise ORing
raw enum values instead of shifting them?
The block layer's profile->key_types_supported strictly requires a bitmask
where support is represented as (1 << BLK_CRYPTO_KEY_TYPE_...). For
BLK_CRYPTO_KEY_TYPE_HW_WRAPPED (value 2), the accumulated enum value sets
bit 1, making supported equal to 3. The core block layer later checks
3 & (1 << 2), which evaluates to 0, incorrectly causing
blk_crypto_config_supported() to reject hardware-wrapped keys as unsupported.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260920122444.2549493-1-linlin.zhang@oss.qualcomm.com?part=2
next prev parent reply other threads:[~2026-09-20 12:38 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-20 12:24 [PATCH v3 0/2] FBE virtualization: inline encryption for virtio-blk guests Linlin Zhang
2026-09-20 12:24 ` [PATCH v3 1/2] virtio_blk: Add control virtqueue support Linlin Zhang
2026-09-20 12:35 ` sashiko-bot
2026-10-08 11:10 ` Linlin Zhang
2026-09-20 12:24 ` [PATCH v3 2/2] virtio_blk: add inline encryption support Linlin Zhang
2026-09-20 12:38 ` sashiko-bot [this message]
2026-10-08 11:10 ` Linlin Zhang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260920123840.EF61D1F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=eperezma@redhat.com \
--cc=linlin.zhang@oss.qualcomm.com \
--cc=mst@redhat.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=virtualization@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.