Skip to content

Commit a48da08

Browse files
stefano-garzarellajiangliu
authored andcommitted
vhost: add safety comments on unsafe blocks
In rust-vmm-ci we are enabling `clippy::undocumented_unsafe_blocks` as errors, so let's comment all unsafe blocks to avoid failures in the CI. Signed-off-by: Stefano Garzarella <[email protected]>
1 parent 1256ab9 commit a48da08

File tree

12 files changed

+142
-35
lines changed

12 files changed

+142
-35
lines changed

crates/vhost-user-backend/src/vring.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ mod tests {
515515
assert!(vring.get_ref().enabled);
516516

517517
let eventfd = EventFd::new(0).unwrap();
518+
// SAFETY: Safe because we panic before if eventfd is not valid.
518519
let file = unsafe { File::from_raw_fd(eventfd.as_raw_fd()) };
519520
assert!(vring.get_mut().kick.is_none());
520521
assert!(vring.read_kick().unwrap());
@@ -527,6 +528,7 @@ mod tests {
527528
std::mem::forget(eventfd);
528529

529530
let eventfd = EventFd::new(0).unwrap();
531+
// SAFETY: Safe because we panic before if eventfd is not valid.
530532
let file = unsafe { File::from_raw_fd(eventfd.as_raw_fd()) };
531533
assert!(vring.get_ref().call.is_none());
532534
vring.set_call(Some(file));
@@ -536,6 +538,7 @@ mod tests {
536538
std::mem::forget(eventfd);
537539

538540
let eventfd = EventFd::new(0).unwrap();
541+
// SAFETY: Safe because we panic before if eventfd is not valid.
539542
let file = unsafe { File::from_raw_fd(eventfd.as_raw_fd()) };
540543
assert!(vring.get_ref().err.is_none());
541544
vring.set_err(Some(file));

crates/vhost-user-backend/tests/vhost-user-server.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ fn vhost_user_client(path: &Path, barrier: Arc<Barrier>) {
153153
nix::sys::memfd::MemFdCreateFlag::empty(),
154154
)
155155
.unwrap();
156+
// SAFETY: Safe because we panic before if memfd is not valid.
156157
let file = unsafe { File::from_raw_fd(memfd) };
157158
file.set_len(0x100000).unwrap();
158159
let file_offset = FileOffset::new(file, 0);

crates/vhost/src/vhost_kern/mod.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
102102
/// Get a bitmask of supported virtio/vhost features.
103103
fn get_features(&self) -> Result<u64> {
104104
let mut avail_features: u64 = 0;
105-
// This ioctl is called on a valid vhost fd and has its return value checked.
105+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
106106
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_GET_FEATURES(), &mut avail_features) };
107107
ioctl_result(ret, avail_features)
108108
}
@@ -113,21 +113,21 @@ impl<T: VhostKernBackend> VhostBackend for T {
113113
/// # Arguments
114114
/// * `features` - Bitmask of features to set.
115115
fn set_features(&self, features: u64) -> Result<()> {
116-
// This ioctl is called on a valid vhost fd and has its return value checked.
116+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
117117
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_FEATURES(), &features) };
118118
ioctl_result(ret, ())
119119
}
120120

121121
/// Set the current process as the owner of this file descriptor.
122122
/// This must be run before any other vhost ioctls.
123123
fn set_owner(&self) -> Result<()> {
124-
// This ioctl is called on a valid vhost fd and has its return value checked.
124+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
125125
let ret = unsafe { ioctl(self, VHOST_SET_OWNER()) };
126126
ioctl_result(ret, ())
127127
}
128128

129129
fn reset_owner(&self) -> Result<()> {
130-
// This ioctl is called on a valid vhost fd and has its return value checked.
130+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
131131
let ret = unsafe { ioctl(self, VHOST_RESET_OWNER()) };
132132
ioctl_result(ret, ())
133133
}
@@ -151,7 +151,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
151151
)?;
152152
}
153153

154-
// This ioctl is called with a pointer that is valid for the lifetime
154+
// SAFETY: This ioctl is called with a pointer that is valid for the lifetime
155155
// of this function. The kernel will make its own copy of the memory
156156
// tables. As always, check the return value.
157157
let ret = unsafe { ioctl_with_ptr(self, VHOST_SET_MEM_TABLE(), vhost_memory.as_ptr()) };
@@ -167,15 +167,15 @@ impl<T: VhostKernBackend> VhostBackend for T {
167167
return Err(Error::LogAddress);
168168
}
169169

170-
// This ioctl is called on a valid vhost fd and has its return value checked.
170+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
171171
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_LOG_BASE(), &base) };
172172
ioctl_result(ret, ())
173173
}
174174

175175
/// Specify an eventfd file descriptor to signal on log write.
176176
fn set_log_fd(&self, fd: RawFd) -> Result<()> {
177-
// This ioctl is called on a valid vhost fd and has its return value checked.
178177
let val: i32 = fd;
178+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
179179
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_LOG_FD(), &val) };
180180
ioctl_result(ret, ())
181181
}
@@ -191,7 +191,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
191191
num: u32::from(num),
192192
};
193193

194-
// This ioctl is called on a valid vhost fd and has its return value checked.
194+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
195195
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_VRING_NUM(), &vring_state) };
196196
ioctl_result(ret, ())
197197
}
@@ -210,7 +210,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
210210
// The addresses are converted into the host address space.
211211
let vring_addr = config_data.to_vhost_vring_addr(queue_index, self.mem())?;
212212

213-
// This ioctl is called on a valid vhost fd and has its
213+
// SAFETY: This ioctl is called on a valid vhost fd and has its
214214
// return value checked.
215215
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_VRING_ADDR(), &vring_addr) };
216216
ioctl_result(ret, ())
@@ -227,7 +227,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
227227
num: u32::from(base),
228228
};
229229

230-
// This ioctl is called on a valid vhost fd and has its return value checked.
230+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
231231
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_VRING_BASE(), &vring_state) };
232232
ioctl_result(ret, ())
233233
}
@@ -238,7 +238,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
238238
index: queue_index as u32,
239239
num: 0,
240240
};
241-
// This ioctl is called on a valid vhost fd and has its return value checked.
241+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
242242
let ret = unsafe { ioctl_with_ref(self, VHOST_GET_VRING_BASE(), &vring_state) };
243243
ioctl_result(ret, vring_state.num)
244244
}
@@ -254,7 +254,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
254254
fd: fd.as_raw_fd(),
255255
};
256256

257-
// This ioctl is called on a valid vhost fd and has its return value checked.
257+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
258258
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_VRING_CALL(), &vring_file) };
259259
ioctl_result(ret, ())
260260
}
@@ -271,7 +271,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
271271
fd: fd.as_raw_fd(),
272272
};
273273

274-
// This ioctl is called on a valid vhost fd and has its return value checked.
274+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
275275
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_VRING_KICK(), &vring_file) };
276276
ioctl_result(ret, ())
277277
}
@@ -287,7 +287,7 @@ impl<T: VhostKernBackend> VhostBackend for T {
287287
fd: fd.as_raw_fd(),
288288
};
289289

290-
// This ioctl is called on a valid vhost fd and has its return value checked.
290+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
291291
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_VRING_ERR(), &vring_file) };
292292
ioctl_result(ret, ())
293293
}
@@ -304,8 +304,9 @@ pub trait VhostKernFeatures: Sized + AsRawFd {
304304
/// Get a bitmask of supported vhost backend features.
305305
fn get_backend_features(&self) -> Result<u64> {
306306
let mut avail_features: u64 = 0;
307-
// This ioctl is called on a valid vhost fd and has its return value checked.
307+
308308
let ret =
309+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
309310
unsafe { ioctl_with_mut_ref(self, VHOST_GET_BACKEND_FEATURES(), &mut avail_features) };
310311
ioctl_result(ret, avail_features)
311312
}
@@ -316,7 +317,7 @@ pub trait VhostKernFeatures: Sized + AsRawFd {
316317
/// # Arguments
317318
/// * `features` - Bitmask of features to set.
318319
fn set_backend_features(&mut self, features: u64) -> Result<()> {
319-
// This ioctl is called on a valid vhost fd and has its return value checked.
320+
// SAFETY: This ioctl is called on a valid vhost fd and has its return value checked.
320321
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_BACKEND_FEATURES(), &features) };
321322

322323
if ret >= 0 {
@@ -348,6 +349,8 @@ impl<I: VhostKernBackend + VhostKernFeatures> VhostIotlbBackend for I {
348349
msg_v2.__bindgen_anon_1.iotlb.perm = msg.perm as u8;
349350
msg_v2.__bindgen_anon_1.iotlb.type_ = msg.msg_type as u8;
350351

352+
// SAFETY: This is safe because we are using a valid vhost fd, and
353+
// a valid pointer and size to the vhost_msg_v2 structure.
351354
ret = unsafe {
352355
write(
353356
self.as_raw_fd(),
@@ -367,6 +370,8 @@ impl<I: VhostKernBackend + VhostKernFeatures> VhostIotlbBackend for I {
367370
msg_v1.__bindgen_anon_1.iotlb.perm = msg.perm as u8;
368371
msg_v1.__bindgen_anon_1.iotlb.type_ = msg.msg_type as u8;
369372

373+
// SAFETY: This is safe because we are using a valid vhost fd, and
374+
// a valid pointer and size to the vhost_msg structure.
370375
ret = unsafe {
371376
write(
372377
self.as_raw_fd(),
@@ -386,6 +391,9 @@ impl VhostIotlbMsgParser for vhost_msg {
386391
return Err(Error::InvalidIotlbMsg);
387392
}
388393

394+
// SAFETY: We trust the kernel to return a structure with the union
395+
// fields properly initialized. We are sure it is a vhost_msg, because
396+
// we checked that `self.type_` is VHOST_IOTLB_MSG.
389397
unsafe {
390398
if self.__bindgen_anon_1.iotlb.type_ == 0 {
391399
return Err(Error::InvalidIotlbMsg);
@@ -408,6 +416,9 @@ impl VhostIotlbMsgParser for vhost_msg_v2 {
408416
return Err(Error::InvalidIotlbMsg);
409417
}
410418

419+
// SAFETY: We trust the kernel to return a structure with the union
420+
// fields properly initialized. We are sure it is a vhost_msg_v2, because
421+
// we checked that `self.type_` is VHOST_IOTLB_MSG_V2.
411422
unsafe {
412423
if self.__bindgen_anon_1.iotlb.type_ == 0 {
413424
return Err(Error::InvalidIotlbMsg);

crates/vhost/src/vhost_kern/net.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl<AS: GuestAddressSpace> VhostNet for Net<AS> {
4545
fd: fd.map_or(-1, |v| v.as_raw_fd()),
4646
};
4747

48+
// SAFETY: Safe because the vhost-net fd is valid and we check the return value
4849
let ret = unsafe { ioctl_with_ref(self, VHOST_NET_SET_BACKEND(), &vring_file) };
4950
ioctl_result(ret, ())
5051
}

crates/vhost/src/vhost_kern/vdpa.rs

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ impl<AS: GuestAddressSpace> VhostKernVdpa<AS> {
8484
log_guest_addr: config_data.get_log_addr(),
8585
};
8686

87-
// This ioctl is called on a valid vhost fd and has its
87+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
8888
// return value checked.
8989
let ret = unsafe { ioctl_with_ref(self, VHOST_SET_VRING_ADDR(), &vring_addr) };
9090
ioctl_result(ret, ())
@@ -94,17 +94,25 @@ impl<AS: GuestAddressSpace> VhostKernVdpa<AS> {
9494
impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
9595
fn get_device_id(&self) -> Result<u32> {
9696
let mut device_id: u32 = 0;
97+
98+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
99+
// return value checked.
97100
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_DEVICE_ID(), &mut device_id) };
98101
ioctl_result(ret, device_id)
99102
}
100103

101104
fn get_status(&self) -> Result<u8> {
102105
let mut status: u8 = 0;
106+
107+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
108+
// return value checked.
103109
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_STATUS(), &mut status) };
104110
ioctl_result(ret, status)
105111
}
106112

107113
fn set_status(&self, status: u8) -> Result<()> {
114+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
115+
// return value checked.
108116
let ret = unsafe { ioctl_with_ref(self, VHOST_VDPA_SET_STATUS(), &status) };
109117
ioctl_result(ret, ())
110118
}
@@ -115,6 +123,8 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
115123

116124
config.as_mut_fam_struct().off = offset;
117125

126+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
127+
// return value checked.
118128
let ret = unsafe {
119129
ioctl_with_ptr(
120130
self,
@@ -136,8 +146,9 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
136146
config.as_mut_slice().copy_from_slice(buffer);
137147

138148
let ret =
149+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
150+
// return value checked.
139151
unsafe { ioctl_with_ptr(self, VHOST_VDPA_SET_CONFIG(), config.as_fam_struct_ptr()) };
140-
141152
ioctl_result(ret, ())
142153
}
143154

@@ -147,18 +158,26 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
147158
num: enabled as u32,
148159
};
149160

161+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
162+
// return value checked.
150163
let ret = unsafe { ioctl_with_ref(self, VHOST_VDPA_SET_VRING_ENABLE(), &vring_state) };
151164
ioctl_result(ret, ())
152165
}
153166

154167
fn get_vring_num(&self) -> Result<u16> {
155168
let mut vring_num: u16 = 0;
169+
170+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
171+
// return value checked.
156172
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_VRING_NUM(), &mut vring_num) };
157173
ioctl_result(ret, vring_num)
158174
}
159175

160176
fn set_config_call(&self, fd: &EventFd) -> Result<()> {
161177
let event_fd: ::std::os::raw::c_int = fd.as_raw_fd();
178+
179+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
180+
// return value checked.
162181
let ret = unsafe { ioctl_with_ref(self, VHOST_VDPA_SET_CONFIG_CALL(), &event_fd) };
163182
ioctl_result(ret, ())
164183
}
@@ -167,6 +186,8 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
167186
let mut low_iova_range = vhost_vdpa_iova_range { first: 0, last: 0 };
168187

169188
let ret =
189+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
190+
// return value checked.
170191
unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_IOVA_RANGE(), &mut low_iova_range) };
171192

172193
let iova_range = VhostVdpaIovaRange {
@@ -179,25 +200,37 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
179200

180201
fn get_config_size(&self) -> Result<u32> {
181202
let mut config_size: u32 = 0;
203+
182204
let ret =
205+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
206+
// return value checked.
183207
unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_CONFIG_SIZE(), &mut config_size) };
184208
ioctl_result(ret, config_size)
185209
}
186210

187211
fn get_vqs_count(&self) -> Result<u32> {
188212
let mut vqs_count: u32 = 0;
213+
214+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
215+
// return value checked.
189216
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_VQS_COUNT(), &mut vqs_count) };
190217
ioctl_result(ret, vqs_count)
191218
}
192219

193220
fn get_group_num(&self) -> Result<u32> {
194221
let mut group_num: u32 = 0;
222+
223+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
224+
// return value checked.
195225
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_GROUP_NUM(), &mut group_num) };
196226
ioctl_result(ret, group_num)
197227
}
198228

199229
fn get_as_num(&self) -> Result<u32> {
200230
let mut as_num: u32 = 0;
231+
232+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
233+
// return value checked.
201234
let ret = unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_AS_NUM(), &mut as_num) };
202235
ioctl_result(ret, as_num)
203236
}
@@ -209,6 +242,8 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
209242
};
210243

211244
let ret =
245+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
246+
// return value checked.
212247
unsafe { ioctl_with_mut_ref(self, VHOST_VDPA_GET_VRING_GROUP(), &mut vring_state) };
213248
ioctl_result(ret, vring_state.num)
214249
}
@@ -219,11 +254,15 @@ impl<AS: GuestAddressSpace> VhostVdpa for VhostKernVdpa<AS> {
219254
num: asid,
220255
};
221256

257+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
258+
// return value checked.
222259
let ret = unsafe { ioctl_with_ref(self, VHOST_VDPA_GET_VRING_GROUP(), &vring_state) };
223260
ioctl_result(ret, ())
224261
}
225262

226263
fn suspend(&self) -> Result<()> {
264+
// SAFETY: This ioctl is called on a valid vhost-vdpa fd and has its
265+
// return value checked.
227266
let ret = unsafe { ioctl(self, VHOST_VDPA_SUSPEND()) };
228267
ioctl_result(ret, ())
229268
}
@@ -506,14 +545,16 @@ mod tests {
506545
vdpa.dma_map(0xFFFF_0000, 0xFFFF, std::ptr::null::<u8>(), false)
507546
.unwrap_err();
508547

509-
unsafe {
510-
let layout = Layout::from_size_align(0xFFFF, 1).unwrap();
511-
let ptr = alloc(layout);
548+
let layout = Layout::from_size_align(0xFFFF, 1).unwrap();
512549

513-
vdpa.dma_map(0xFFFF_0000, 0xFFFF, ptr, false).unwrap();
514-
vdpa.dma_unmap(0xFFFF_0000, 0xFFFF).unwrap();
550+
// SAFETY: Safe because layout has non-zero size.
551+
let ptr = unsafe { alloc(layout) };
515552

516-
dealloc(ptr, layout);
517-
};
553+
vdpa.dma_map(0xFFFF_0000, 0xFFFF, ptr, false).unwrap();
554+
vdpa.dma_unmap(0xFFFF_0000, 0xFFFF).unwrap();
555+
556+
// SAFETY: Safe because `ptr` is allocated with the same allocator
557+
// using the same `layout`.
558+
unsafe { dealloc(ptr, layout) };
518559
}
519560
}

0 commit comments

Comments
 (0)