Re: [PATCH] nvme: Cache DMA descriptors to prevent corruption.

From: Tom Roeder
Date: Thu Nov 19 2020 - 20:10:08 EST


On Thu, Nov 19, 2020 at 01:09:14PM -0800, Keith Busch wrote:
On Thu, Nov 19, 2020 at 10:59:19AM -0800, Tom Roeder wrote:
This patch changes the NVMe PCI implementation to cache host_mem_descs
in non-DMA memory instead of depending on descriptors stored in DMA
memory. This change is needed under the malicious-hypervisor threat
model assumed by the AMD SEV and Intel TDX architectures, which encrypt
guest memory to make it unreadable. Some versions of these architectures
also make it cryptographically hard to modify guest memory without
detection.

On these architectures, Linux generally leaves DMA memory unencrypted so
that devices can still communicate directly with the kernel: DMA memory
remains readable to and modifiable by devices. This means that this
memory is also accessible to a hypervisor.

However, this means that a malicious hypervisor could modify the addr or
size fields of descriptors and cause the NVMe driver to call
dma_free_attrs on arbitrary addresses or on the right addresses but with
the wrong size. To prevent this attack, this commit changes the code to
cache those descriptors in non-DMA memory and to use the cached values
when freeing the memory they describe.

If the hypervisor does that, then the device may use the wrong
addresses, too. I guess you can't do anything about that from the
driver, though.
I agree; I don't think there's anything the driver can do about that.


+ /* Cache the host_mem_descs in non-DMA memory so a malicious hypervisor
+ * can't change them.
+ */
+ struct nvme_host_mem_buf_desc *host_mem_descs_cache;
void **host_mem_desc_bufs;

This is never seen by an nvme device, so no need for an nvme specific
type here. You can use arch native types.

Thanks! I'll change the type to a new struct that has the addr and size fields as native integers and send out a v2 for this patch that makes that change and cleans up a couple of minor style issues in my code.