From 8b392de175697f2efb1ac74e68b0da37b0578af0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 28 Mar 2022 10:25:38 +0200 Subject: [PATCH] 5.4-stable patches added patches: swiotlb-fix-info-leak-with-dma_from_device.patch --- queue-5.4/series | 1 + ...b-fix-info-leak-with-dma_from_device.patch | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 queue-5.4/series create mode 100644 queue-5.4/swiotlb-fix-info-leak-with-dma_from_device.patch diff --git a/queue-5.4/series b/queue-5.4/series new file mode 100644 index 00000000000..a5f04fced34 --- /dev/null +++ b/queue-5.4/series @@ -0,0 +1 @@ +swiotlb-fix-info-leak-with-dma_from_device.patch diff --git a/queue-5.4/swiotlb-fix-info-leak-with-dma_from_device.patch b/queue-5.4/swiotlb-fix-info-leak-with-dma_from_device.patch new file mode 100644 index 00000000000..dd68c42c956 --- /dev/null +++ b/queue-5.4/swiotlb-fix-info-leak-with-dma_from_device.patch @@ -0,0 +1,104 @@ +From ddbd89deb7d32b1fbb879f48d68fda1a8ac58e8e Mon Sep 17 00:00:00 2001 +From: Halil Pasic +Date: Fri, 11 Feb 2022 02:12:52 +0100 +Subject: swiotlb: fix info leak with DMA_FROM_DEVICE + +From: Halil Pasic + +commit ddbd89deb7d32b1fbb879f48d68fda1a8ac58e8e upstream. + +The problem I'm addressing was discovered by the LTP test covering +cve-2018-1000204. + +A short description of what happens follows: +1) The test case issues a command code 00 (TEST UNIT READY) via the SG_IO + interface with: dxfer_len == 524288, dxdfer_dir == SG_DXFER_FROM_DEV + and a corresponding dxferp. The peculiar thing about this is that TUR + is not reading from the device. +2) In sg_start_req() the invocation of blk_rq_map_user() effectively + bounces the user-space buffer. As if the device was to transfer into + it. Since commit a45b599ad808 ("scsi: sg: allocate with __GFP_ZERO in + sg_build_indirect()") we make sure this first bounce buffer is + allocated with GFP_ZERO. +3) For the rest of the story we keep ignoring that we have a TUR, so the + device won't touch the buffer we prepare as if the we had a + DMA_FROM_DEVICE type of situation. My setup uses a virtio-scsi device + and the buffer allocated by SG is mapped by the function + virtqueue_add_split() which uses DMA_FROM_DEVICE for the "in" sgs (here + scatter-gather and not scsi generics). This mapping involves bouncing + via the swiotlb (we need swiotlb to do virtio in protected guest like + s390 Secure Execution, or AMD SEV). +4) When the SCSI TUR is done, we first copy back the content of the second + (that is swiotlb) bounce buffer (which most likely contains some + previous IO data), to the first bounce buffer, which contains all + zeros. Then we copy back the content of the first bounce buffer to + the user-space buffer. +5) The test case detects that the buffer, which it zero-initialized, + ain't all zeros and fails. + +One can argue that this is an swiotlb problem, because without swiotlb +we leak all zeros, and the swiotlb should be transparent in a sense that +it does not affect the outcome (if all other participants are well +behaved). + +Copying the content of the original buffer into the swiotlb buffer is +the only way I can think of to make swiotlb transparent in such +scenarios. So let's do just that if in doubt, but allow the driver +to tell us that the whole mapped buffer is going to be overwritten, +in which case we can preserve the old behavior and avoid the performance +impact of the extra bounce. + +Signed-off-by: Halil Pasic +Signed-off-by: Christoph Hellwig +Signed-off-by: Greg Kroah-Hartman +--- + Documentation/DMA-attributes.txt | 10 ++++++++++ + include/linux/dma-mapping.h | 8 ++++++++ + kernel/dma/swiotlb.c | 3 ++- + 3 files changed, 20 insertions(+), 1 deletion(-) + +--- a/Documentation/DMA-attributes.txt ++++ b/Documentation/DMA-attributes.txt +@@ -156,3 +156,13 @@ accesses to DMA buffers in both privileg + subsystem that the buffer is fully accessible at the elevated privilege + level (and ideally inaccessible or at least read-only at the + lesser-privileged levels). ++ ++DMA_ATTR_PRIVILEGED ++------------------- ++ ++Some advanced peripherals such as remote processors and GPUs perform ++accesses to DMA buffers in both privileged "supervisor" and unprivileged ++"user" modes. This attribute is used to indicate to the DMA-mapping ++subsystem that the buffer is fully accessible at the elevated privilege ++level (and ideally inaccessible or at least read-only at the ++lesser-privileged levels). +--- a/include/linux/dma-mapping.h ++++ b/include/linux/dma-mapping.h +@@ -71,6 +71,14 @@ + #define DMA_ATTR_PRIVILEGED (1UL << 9) + + /* ++ * This is a hint to the DMA-mapping subsystem that the device is expected ++ * to overwrite the entire mapped size, thus the caller does not require any ++ * of the previous buffer contents to be preserved. This allows ++ * bounce-buffering implementations to optimise DMA_FROM_DEVICE transfers. ++ */ ++#define DMA_ATTR_OVERWRITE (1UL << 10) ++ ++/* + * A dma_addr_t can hold any valid DMA or bus address for the platform. + * It can be given to a device to use as a DMA source or target. A CPU cannot + * reference a dma_addr_t directly because there may be translation between +--- a/kernel/dma/swiotlb.c ++++ b/kernel/dma/swiotlb.c +@@ -572,7 +572,8 @@ found: + for (i = 0; i < nslots; i++) + io_tlb_orig_addr[index+i] = orig_addr + (i << IO_TLB_SHIFT); + if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) && +- (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) ++ (!(attrs & DMA_ATTR_OVERWRITE) || dir == DMA_TO_DEVICE || ++ dir == DMA_BIDIRECTIONAL)) + swiotlb_bounce(orig_addr, tlb_addr, mapping_size, DMA_TO_DEVICE); + + return tlb_addr; -- 2.47.3