Gentoo Archives: gentoo-commits

From: Mike Pagano <mpagano@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/linux-patches:5.17 commit in: /
Date: Mon, 28 Mar 2022 22:06:17
Message-Id: 1648505063.58d68cf3c08d4109201e1a36068a7e366d6dde84.mpagano@gentoo
1 commit: 58d68cf3c08d4109201e1a36068a7e366d6dde84
2 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org>
3 AuthorDate: Mon Mar 28 22:04:23 2022 +0000
4 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org>
5 CommitDate: Mon Mar 28 22:04:23 2022 +0000
6 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=58d68cf3
7
8 Revert swiotlb: rework fix info leak with DMA_FROM_DEVICE
9
10 Bug: https://bugs.gentoo.org/835513
11
12 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org>
13
14 0000_README | 4 +
15 ...rework-fix-info-leak-with-dma_from_device.patch | 187 +++++++++++++++++++++
16 2 files changed, 191 insertions(+)
17
18 diff --git a/0000_README b/0000_README
19 index 684989ae..19269be2 100644
20 --- a/0000_README
21 +++ b/0000_README
22 @@ -63,6 +63,10 @@ Patch: 2400_mt76-mt7921e-fix-possible-probe-failure-after-reboot.patch
23 From: https://patchwork.kernel.org/project/linux-wireless/patch/70e27cbc652cbdb78277b9c691a3a5ba02653afb.1641540175.git.objelf@×××××.com/
24 Desc: mt76: mt7921e: fix possible probe failure after reboot
25
26 +Patch: 2410_revert-swiotlb-rework-fix-info-leak-with-dma_from_device.patch
27 +From: https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git
28 +Desc: Revert swiotlb: rework fix info leak with DMA_FROM_DEVICE
29 +
30 Patch: 2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch
31 From: https://bugs.gentoo.org/710790
32 Desc: tmp513 requies REGMAP_I2C to build. Select it by default in Kconfig. See bug #710790. Thanks to Phil Stracchino
33
34 diff --git a/2410_revert-swiotlb-rework-fix-info-leak-with-dma_from_device.patch b/2410_revert-swiotlb-rework-fix-info-leak-with-dma_from_device.patch
35 new file mode 100644
36 index 00000000..69476ab1
37 --- /dev/null
38 +++ b/2410_revert-swiotlb-rework-fix-info-leak-with-dma_from_device.patch
39 @@ -0,0 +1,187 @@
40 +From bddac7c1e02ba47f0570e494c9289acea3062cc1 Mon Sep 17 00:00:00 2001
41 +From: Linus Torvalds <torvalds@××××××××××××××××.org>
42 +Date: Sat, 26 Mar 2022 10:42:04 -0700
43 +Subject: Revert "swiotlb: rework "fix info leak with DMA_FROM_DEVICE""
44 +MIME-Version: 1.0
45 +Content-Type: text/plain; charset=UTF-8
46 +Content-Transfer-Encoding: 8bit
47 +
48 +From: Linus Torvalds <torvalds@××××××××××××××××.org>
49 +
50 +commit bddac7c1e02ba47f0570e494c9289acea3062cc1 upstream.
51 +
52 +This reverts commit aa6f8dcbab473f3a3c7454b74caa46d36cdc5d13.
53 +
54 +It turns out this breaks at least the ath9k wireless driver, and
55 +possibly others.
56 +
57 +What the ath9k driver does on packet receive is to set up the DMA
58 +transfer with:
59 +
60 + int ath_rx_init(..)
61 + ..
62 + bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
63 + common->rx_bufsize,
64 + DMA_FROM_DEVICE);
65 +
66 +and then the receive logic (through ath_rx_tasklet()) will fetch
67 +incoming packets
68 +
69 + static bool ath_edma_get_buffers(..)
70 + ..
71 + dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
72 + common->rx_bufsize, DMA_FROM_DEVICE);
73 +
74 + ret = ath9k_hw_process_rxdesc_edma(ah, rs, skb->data);
75 + if (ret == -EINPROGRESS) {
76 + /*let device gain the buffer again*/
77 + dma_sync_single_for_device(sc->dev, bf->bf_buf_addr,
78 + common->rx_bufsize, DMA_FROM_DEVICE);
79 + return false;
80 + }
81 +
82 +and it's worth noting how that first DMA sync:
83 +
84 + dma_sync_single_for_cpu(..DMA_FROM_DEVICE);
85 +
86 +is there to make sure the CPU can read the DMA buffer (possibly by
87 +copying it from the bounce buffer area, or by doing some cache flush).
88 +The iommu correctly turns that into a "copy from bounce bufer" so that
89 +the driver can look at the state of the packets.
90 +
91 +In the meantime, the device may continue to write to the DMA buffer, but
92 +we at least have a snapshot of the state due to that first DMA sync.
93 +
94 +But that _second_ DMA sync:
95 +
96 + dma_sync_single_for_device(..DMA_FROM_DEVICE);
97 +
98 +is telling the DMA mapping that the CPU wasn't interested in the area
99 +because the packet wasn't there. In the case of a DMA bounce buffer,
100 +that is a no-op.
101 +
102 +Note how it's not a sync for the CPU (the "for_device()" part), and it's
103 +not a sync for data written by the CPU (the "DMA_FROM_DEVICE" part).
104 +
105 +Or rather, it _should_ be a no-op. That's what commit aa6f8dcbab47
106 +broke: it made the code bounce the buffer unconditionally, and changed
107 +the DMA_FROM_DEVICE to just unconditionally and illogically be
108 +DMA_TO_DEVICE.
109 +
110 +[ Side note: purely within the confines of the swiotlb driver it wasn't
111 + entirely illogical: The reason it did that odd DMA_FROM_DEVICE ->
112 + DMA_TO_DEVICE conversion thing is because inside the swiotlb driver,
113 + it uses just a swiotlb_bounce() helper that doesn't care about the
114 + whole distinction of who the sync is for - only which direction to
115 + bounce.
116 +
117 + So it took the "sync for device" to mean that the CPU must have been
118 + the one writing, and thought it meant DMA_TO_DEVICE. ]
119 +
120 +Also note how the commentary in that commit was wrong, probably due to
121 +that whole confusion, claiming that the commit makes the swiotlb code
122 +
123 + "bounce unconditionally (that is, also
124 + when dir == DMA_TO_DEVICE) in order do avoid synchronising back stale
125 + data from the swiotlb buffer"
126 +
127 +which is nonsensical for two reasons:
128 +
129 + - that "also when dir == DMA_TO_DEVICE" is nonsensical, as that was
130 + exactly when it always did - and should do - the bounce.
131 +
132 + - since this is a sync for the device (not for the CPU), we're clearly
133 + fundamentally not coping back stale data from the bounce buffers at
134 + all, because we'd be copying *to* the bounce buffers.
135 +
136 +So that commit was just very confused. It confused the direction of the
137 +synchronization (to the device, not the cpu) with the direction of the
138 +DMA (from the device).
139 +
140 +Reported-and-bisected-by: Oleksandr Natalenko <oleksandr@×××××××××.name>
141 +Reported-by: Olha Cherevyk <olha.cherevyk@×××××.com>
142 +Cc: Halil Pasic <pasic@×××××××××.com>
143 +Cc: Christoph Hellwig <hch@×××.de>
144 +Cc: Kalle Valo <kvalo@××××××.org>
145 +Cc: Robin Murphy <robin.murphy@×××.com>
146 +Cc: Toke Høiland-Jørgensen <toke@××××.dk>
147 +Cc: Maxime Bizon <mbizon@×××××××.fr>
148 +Cc: Johannes Berg <johannes@××××××××××××.net>
149 +Signed-off-by: Linus Torvalds <torvalds@××××××××××××××××.org>
150 +Signed-off-by: Greg Kroah-Hartman <gregkh@×××××××××××××××.org>
151 +---
152 + Documentation/core-api/dma-attributes.rst | 8 ++++++++
153 + include/linux/dma-mapping.h | 8 ++++++++
154 + kernel/dma/swiotlb.c | 23 ++++++++---------------
155 + 3 files changed, 24 insertions(+), 15 deletions(-)
156 +
157 +--- a/Documentation/core-api/dma-attributes.rst
158 ++++ b/Documentation/core-api/dma-attributes.rst
159 +@@ -130,3 +130,11 @@ accesses to DMA buffers in both privileg
160 + subsystem that the buffer is fully accessible at the elevated privilege
161 + level (and ideally inaccessible or at least read-only at the
162 + lesser-privileged levels).
163 ++
164 ++DMA_ATTR_OVERWRITE
165 ++------------------
166 ++
167 ++This is a hint to the DMA-mapping subsystem that the device is expected to
168 ++overwrite the entire mapped size, thus the caller does not require any of the
169 ++previous buffer contents to be preserved. This allows bounce-buffering
170 ++implementations to optimise DMA_FROM_DEVICE transfers.
171 +--- a/include/linux/dma-mapping.h
172 ++++ b/include/linux/dma-mapping.h
173 +@@ -62,6 +62,14 @@
174 + #define DMA_ATTR_PRIVILEGED (1UL << 9)
175 +
176 + /*
177 ++ * This is a hint to the DMA-mapping subsystem that the device is expected
178 ++ * to overwrite the entire mapped size, thus the caller does not require any
179 ++ * of the previous buffer contents to be preserved. This allows
180 ++ * bounce-buffering implementations to optimise DMA_FROM_DEVICE transfers.
181 ++ */
182 ++#define DMA_ATTR_OVERWRITE (1UL << 10)
183 ++
184 ++/*
185 + * A dma_addr_t can hold any valid DMA or bus address for the platform. It can
186 + * be given to a device to use as a DMA source or target. It is specific to a
187 + * given device and there may be a translation between the CPU physical address
188 +--- a/kernel/dma/swiotlb.c
189 ++++ b/kernel/dma/swiotlb.c
190 +@@ -627,14 +627,10 @@ phys_addr_t swiotlb_tbl_map_single(struc
191 + for (i = 0; i < nr_slots(alloc_size + offset); i++)
192 + mem->slots[index + i].orig_addr = slot_addr(orig_addr, i);
193 + tlb_addr = slot_addr(mem->start, index) + offset;
194 +- /*
195 +- * When dir == DMA_FROM_DEVICE we could omit the copy from the orig
196 +- * to the tlb buffer, if we knew for sure the device will
197 +- * overwirte the entire current content. But we don't. Thus
198 +- * unconditional bounce may prevent leaking swiotlb content (i.e.
199 +- * kernel memory) to user-space.
200 +- */
201 +- swiotlb_bounce(dev, tlb_addr, mapping_size, DMA_TO_DEVICE);
202 ++ if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
203 ++ (!(attrs & DMA_ATTR_OVERWRITE) || dir == DMA_TO_DEVICE ||
204 ++ dir == DMA_BIDIRECTIONAL))
205 ++ swiotlb_bounce(dev, tlb_addr, mapping_size, DMA_TO_DEVICE);
206 + return tlb_addr;
207 + }
208 +
209 +@@ -701,13 +697,10 @@ void swiotlb_tbl_unmap_single(struct dev
210 + void swiotlb_sync_single_for_device(struct device *dev, phys_addr_t tlb_addr,
211 + size_t size, enum dma_data_direction dir)
212 + {
213 +- /*
214 +- * Unconditional bounce is necessary to avoid corruption on
215 +- * sync_*_for_cpu or dma_ummap_* when the device didn't overwrite
216 +- * the whole lengt of the bounce buffer.
217 +- */
218 +- swiotlb_bounce(dev, tlb_addr, size, DMA_TO_DEVICE);
219 +- BUG_ON(!valid_dma_direction(dir));
220 ++ if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
221 ++ swiotlb_bounce(dev, tlb_addr, size, DMA_TO_DEVICE);
222 ++ else
223 ++ BUG_ON(dir != DMA_FROM_DEVICE);
224 + }
225 +
226 + void swiotlb_sync_single_for_cpu(struct device *dev, phys_addr_t tlb_addr,