Commit 2993f3c
committed
Harden virtio-blk and virtio-net
Address ten correctness and safety issues across the virtqueue chain
walking, descriptor validation, and back-pressure paths.
Chain walking. Both devices walked exactly one (virtio-net) or three
(virtio-blk) descriptors per request, so a guest that split a packet or
a >4 KiB block I/O across multiple descriptors got partial transfers and
the next chain descriptor was reinterpreted as a new request head. Both
device emulators now snapshot the entire chain via VRING_DESC_F_NEXT,
sized to the VIRTQ_SIZE-bounded stack array, and route data through
readv/writev (net) or per-segment diskimg I/O (blk).
Descriptor direction. Neither device validated VRING_DESC_F_WRITE before
touching guest memory, so a buggy or malicious guest could hand a
"readable-only" status descriptor and have the device write into memory
it never offered for writes. Every consumer site now checks direction
matches the request type and rejects mismatches with VIRTIO_BLK_S_IOERR
or an empty USED publication.
NULL guards. virtq_get_avail can legitimately return NULL on a
malformed chain; the prior code dereferenced the result on virtio-blk's
data and status reads, which is a host segfault, not a queue stall.
Every consumer site now NULL-checks. On a malformed chain the device
stalls the queue rather than publishing USED with chain[0].id (the
buffer ID lives on the chain's last descriptor in packed virtqueues, so
publishing with a head id risks pointing the driver at an unrelated
in-flight chain).
Always-publish-USED. Every error path in virtio-blk/virtio-net used to
return without flipping USED on the head, leaking descriptors and
eventually drifting the device's view of the ring out of sync with the
driver's. Successful walks now always publish USED — IOERR with len=1
on validation failure, the real status byte plus device-writable byte
count on success.
Stack-array bounds. Per-iteration desc_snap[VIRTQ_SIZE] / iov[VIRTQ_SIZE]
arrays are sized to the host-advertised queue depth. virtio-pci now
clamps guest writes to queue_size at VIRTQ_SIZE and the walkers cap at
VIRTQ_SIZE, so a guest cannot make the walk overrun the stack arrays.
Atomic event flag stores. virtq_handle_avail reads guest_event->flags
with __ATOMIC_ACQUIRE; the worker threads paired this with plain stores,
so the compiler was free to tear or reorder against the surrounding
completion writes. A new virtq_set_guest_event_flags helper replaces
every plain store with __atomic_store_n / __ATOMIC_RELEASE.
virtio-blk SG arithmetic. data_size widened from uint16_t to uint32_t
so >64 KiB segments don't silently truncate before reaching diskimg I/O.
Per-segment writable_total now accumulates in uint64_t with
__builtin_add_overflow, capping at UINT32_MAX-1 so the reported used.len
plus the trailing status byte fits the packed-ring uint32_t.
VIRTIO_BLK_F_FLUSH. Without the negotiated FLUSH feature the Linux
virtio-blk driver runs in writeback-without-barriers mode, so guest
fsync(2) returns success while data sits in the host page cache. The
device now advertises VIRTIO_BLK_F_FLUSH, dispatches T_FLUSH to a new
diskimg_flush() (fdatasync), and fsyncs the backing file at exit.
TX back-pressure. The TX worker previously required tapfd POLLOUT in
its poll predicate; with a level-triggered ioeventfd POLLIN that meant
100% CPU until the TAP drained. The poll set now drops the TAP
predicate by default, drains the ioeventfd on a guest kick, and arms
POLLOUT only after a transient writev() EAGAIN. On EAGAIN the chain's
next_avail_idx and used_wrap_count are rolled back so the TAP-blocked
chain is retried on POLLOUT rather than silently dropped.1 parent 2231254 commit 2993f3c
9 files changed
Lines changed: 441 additions & 156 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
25 | 30 | | |
26 | 31 | | |
27 | 32 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
20 | 21 | | |
21 | 22 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
70 | 70 | | |
71 | 71 | | |
72 | 72 | | |
73 | | - | |
74 | | - | |
75 | | - | |
76 | | - | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
77 | 95 | | |
78 | | - | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
79 | 114 | | |
80 | 115 | | |
81 | | - | |
82 | | - | |
83 | | - | |
84 | | - | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
85 | 123 | | |
86 | | - | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
87 | 167 | | |
88 | 168 | | |
89 | 169 | | |
90 | 170 | | |
91 | 171 | | |
92 | 172 | | |
93 | | - | |
94 | | - | |
95 | | - | |
| 173 | + | |
96 | 174 | | |
97 | | - | |
98 | | - | |
99 | | - | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
100 | 178 | | |
101 | 179 | | |
102 | | - | |
103 | | - | |
104 | | - | |
105 | | - | |
106 | | - | |
107 | | - | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
142 | | - | |
143 | | - | |
144 | | - | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
145 | 185 | | |
146 | | - | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
147 | 193 | | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
156 | 199 | | |
157 | | - | |
158 | | - | |
159 | | - | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
164 | 210 | | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
169 | 220 | | |
170 | | - | |
171 | | - | |
172 | | - | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
173 | 249 | | |
174 | 250 | | |
175 | 251 | | |
| |||
225 | 301 | | |
226 | 302 | | |
227 | 303 | | |
228 | | - | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
229 | 309 | | |
230 | 310 | | |
231 | 311 | | |
| |||
245 | 325 | | |
246 | 326 | | |
247 | 327 | | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
248 | 332 | | |
249 | 333 | | |
250 | 334 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
16 | 20 | | |
17 | 21 | | |
18 | 22 | | |
19 | 23 | | |
20 | 24 | | |
21 | | - | |
| 25 | + | |
22 | 26 | | |
23 | 27 | | |
24 | 28 | | |
| |||
0 commit comments