Skip to content

Commit c86a562

Browse files
committed
unittest: net: Fix undefined behavior in TestHelper::get_default
This function used an unsound `mem::transmute` to invalidly extend a lifetime with the goal of creating a self-referential struct. Sadly, after returning from `get_default`, the `GuestMemoryMmap` gets moved to a different stack frame, and so all references that this function created become dangling pointers. Fix this by not trying to create self-referential struct. Signed-off-by: Patrick Roy <[email protected]>
1 parent 271aed8 commit c86a562

File tree

3 files changed

+63
-39
lines changed

3 files changed

+63
-39
lines changed

src/vmm/src/devices/virtio/net/device.rs

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,7 @@ pub mod tests {
956956
use crate::dumbo::EthernetFrame;
957957
use crate::logger::IncMetric;
958958
use crate::rate_limiter::{BucketUpdate, RateLimiter, TokenBucket, TokenType};
959+
use crate::utilities::test_utils::single_region_mem;
959960
use crate::vstate::memory::{Address, GuestMemory};
960961

961962
#[test]
@@ -1113,7 +1114,8 @@ pub mod tests {
11131114

11141115
#[test]
11151116
fn test_rx_missing_queue_signal() {
1116-
let mut th = TestHelper::get_default();
1117+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1118+
let mut th = TestHelper::get_default(&mem);
11171119
th.activate_net();
11181120

11191121
th.add_desc_chain(NetQueue::Rx, 0, &[(0, 4096, VIRTQ_DESC_F_WRITE)]);
@@ -1130,7 +1132,8 @@ pub mod tests {
11301132

11311133
#[test]
11321134
fn test_rx_read_only_descriptor() {
1133-
let mut th = TestHelper::get_default();
1135+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1136+
let mut th = TestHelper::get_default(&mem);
11341137
th.activate_net();
11351138

11361139
th.add_desc_chain(
@@ -1150,7 +1153,8 @@ pub mod tests {
11501153

11511154
#[test]
11521155
fn test_rx_short_writable_descriptor() {
1153-
let mut th = TestHelper::get_default();
1156+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1157+
let mut th = TestHelper::get_default(&mem);
11541158
th.activate_net();
11551159

11561160
th.add_desc_chain(NetQueue::Rx, 0, &[(0, 100, VIRTQ_DESC_F_WRITE)]);
@@ -1162,7 +1166,8 @@ pub mod tests {
11621166

11631167
#[test]
11641168
fn test_rx_partial_write() {
1165-
let mut th = TestHelper::get_default();
1169+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1170+
let mut th = TestHelper::get_default(&mem);
11661171
th.activate_net();
11671172

11681173
// The descriptor chain is created so that the last descriptor doesn't fit in the
@@ -1185,7 +1190,8 @@ pub mod tests {
11851190

11861191
#[test]
11871192
fn test_rx_retry() {
1188-
let mut th = TestHelper::get_default();
1193+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1194+
let mut th = TestHelper::get_default(&mem);
11891195
th.activate_net();
11901196

11911197
// Add invalid descriptor chain - read only descriptor.
@@ -1235,7 +1241,8 @@ pub mod tests {
12351241

12361242
#[test]
12371243
fn test_rx_complex_desc_chain() {
1238-
let mut th = TestHelper::get_default();
1244+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1245+
let mut th = TestHelper::get_default(&mem);
12391246
th.activate_net();
12401247

12411248
// Create a valid Rx avail descriptor chain with multiple descriptors.
@@ -1273,7 +1280,8 @@ pub mod tests {
12731280

12741281
#[test]
12751282
fn test_rx_multiple_frames() {
1276-
let mut th = TestHelper::get_default();
1283+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1284+
let mut th = TestHelper::get_default(&mem);
12771285
th.activate_net();
12781286

12791287
// Create 2 valid Rx avail descriptor chains. Each one has enough space to fit the
@@ -1316,7 +1324,8 @@ pub mod tests {
13161324

13171325
#[test]
13181326
fn test_tx_missing_queue_signal() {
1319-
let mut th = TestHelper::get_default();
1327+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1328+
let mut th = TestHelper::get_default(&mem);
13201329
th.activate_net();
13211330
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
13221331

@@ -1336,7 +1345,8 @@ pub mod tests {
13361345

13371346
#[test]
13381347
fn test_tx_writeable_descriptor() {
1339-
let mut th = TestHelper::get_default();
1348+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1349+
let mut th = TestHelper::get_default(&mem);
13401350
th.activate_net();
13411351
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
13421352

@@ -1355,7 +1365,8 @@ pub mod tests {
13551365

13561366
#[test]
13571367
fn test_tx_short_frame() {
1358-
let mut th = TestHelper::get_default();
1368+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1369+
let mut th = TestHelper::get_default(&mem);
13591370
th.activate_net();
13601371
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
13611372

@@ -1377,7 +1388,8 @@ pub mod tests {
13771388

13781389
#[test]
13791390
fn test_tx_big_frame() {
1380-
let mut th = TestHelper::get_default();
1391+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1392+
let mut th = TestHelper::get_default(&mem);
13811393
th.activate_net();
13821394
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
13831395

@@ -1403,7 +1415,8 @@ pub mod tests {
14031415

14041416
#[test]
14051417
fn test_tx_empty_frame() {
1406-
let mut th = TestHelper::get_default();
1418+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1419+
let mut th = TestHelper::get_default(&mem);
14071420
th.activate_net();
14081421
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
14091422

@@ -1425,7 +1438,8 @@ pub mod tests {
14251438

14261439
#[test]
14271440
fn test_tx_retry() {
1428-
let mut th = TestHelper::get_default();
1441+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1442+
let mut th = TestHelper::get_default(&mem);
14291443
th.activate_net();
14301444
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
14311445

@@ -1467,7 +1481,8 @@ pub mod tests {
14671481

14681482
#[test]
14691483
fn test_tx_complex_descriptor() {
1470-
let mut th = TestHelper::get_default();
1484+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1485+
let mut th = TestHelper::get_default(&mem);
14711486
th.activate_net();
14721487
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
14731488

@@ -1495,7 +1510,8 @@ pub mod tests {
14951510

14961511
#[test]
14971512
fn test_tx_tap_failure() {
1498-
let mut th = TestHelper::get_default();
1513+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1514+
let mut th = TestHelper::get_default(&mem);
14991515
th.activate_net();
15001516
// force the next write to the tap to return an error by simply closing the fd
15011517
// SAFETY: its a valid fd
@@ -1519,7 +1535,8 @@ pub mod tests {
15191535

15201536
#[test]
15211537
fn test_tx_multiple_frame() {
1522-
let mut th = TestHelper::get_default();
1538+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1539+
let mut th = TestHelper::get_default(&mem);
15231540
th.activate_net();
15241541
let tap_traffic_simulator = TapTrafficSimulator::new(if_index(&th.net().tap));
15251542

@@ -1672,7 +1689,8 @@ pub mod tests {
16721689

16731690
#[test]
16741691
fn test_process_error_cases() {
1675-
let mut th = TestHelper::get_default();
1692+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1693+
let mut th = TestHelper::get_default(&mem);
16761694
th.activate_net();
16771695

16781696
// RX rate limiter events should error since the limiter is not blocked.
@@ -1697,7 +1715,8 @@ pub mod tests {
16971715
// * interrupt_evt.write
16981716
#[test]
16991717
fn test_read_tap_fail_event_handler() {
1700-
let mut th = TestHelper::get_default();
1718+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1719+
let mut th = TestHelper::get_default(&mem);
17011720
th.activate_net();
17021721
// force the next write to the tap to return an error by simply closing the fd
17031722
// SAFETY: its a valid fd
@@ -1727,7 +1746,8 @@ pub mod tests {
17271746

17281747
#[test]
17291748
fn test_deferred_frame() {
1730-
let mut th = TestHelper::get_default();
1749+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1750+
let mut th = TestHelper::get_default(&mem);
17311751
th.activate_net();
17321752

17331753
let rx_packets_count = th.net().metrics.rx_packets_count.count();
@@ -1779,7 +1799,8 @@ pub mod tests {
17791799

17801800
#[test]
17811801
fn test_rx_rate_limiter_handling() {
1782-
let mut th = TestHelper::get_default();
1802+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1803+
let mut th = TestHelper::get_default(&mem);
17831804
th.activate_net();
17841805

17851806
th.net().rx_rate_limiter = RateLimiter::new(0, 0, 0, 0, 0, 0).unwrap();
@@ -1793,7 +1814,8 @@ pub mod tests {
17931814

17941815
#[test]
17951816
fn test_tx_rate_limiter_handling() {
1796-
let mut th = TestHelper::get_default();
1817+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1818+
let mut th = TestHelper::get_default(&mem);
17971819
th.activate_net();
17981820

17991821
th.net().tx_rate_limiter = RateLimiter::new(0, 0, 0, 0, 0, 0).unwrap();
@@ -1808,7 +1830,8 @@ pub mod tests {
18081830

18091831
#[test]
18101832
fn test_bandwidth_rate_limiter() {
1811-
let mut th = TestHelper::get_default();
1833+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1834+
let mut th = TestHelper::get_default(&mem);
18121835
th.activate_net();
18131836

18141837
// Test TX bandwidth rate limiting
@@ -1948,7 +1971,8 @@ pub mod tests {
19481971

19491972
#[test]
19501973
fn test_ops_rate_limiter() {
1951-
let mut th = TestHelper::get_default();
1974+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
1975+
let mut th = TestHelper::get_default(&mem);
19521976
th.activate_net();
19531977

19541978
// Test TX ops rate limiting
@@ -2059,7 +2083,8 @@ pub mod tests {
20592083

20602084
#[test]
20612085
fn test_patch_rate_limiters() {
2062-
let mut th = TestHelper::get_default();
2086+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
2087+
let mut th = TestHelper::get_default(&mem);
20632088
th.activate_net();
20642089

20652090
th.net().rx_rate_limiter = RateLimiter::new(10, 0, 10, 2, 0, 2).unwrap();
@@ -2100,7 +2125,8 @@ pub mod tests {
21002125

21012126
#[test]
21022127
fn test_virtio_device() {
2103-
let mut th = TestHelper::get_default();
2128+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
2129+
let mut th = TestHelper::get_default(&mem);
21042130
th.activate_net();
21052131
let net = th.net.lock().unwrap();
21062132

@@ -2121,7 +2147,8 @@ pub mod tests {
21212147
fn test_queues_notification_suppression() {
21222148
let features = 1 << VIRTIO_RING_F_EVENT_IDX;
21232149

2124-
let mut th = TestHelper::get_default();
2150+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
2151+
let mut th = TestHelper::get_default(&mem);
21252152
th.net().set_acked_features(features);
21262153
th.activate_net();
21272154

src/vmm/src/devices/virtio/net/event_handler.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,13 @@ impl MutEventSubscriber for Net {
134134
pub mod tests {
135135
use crate::devices::virtio::net::test_utils::test::TestHelper;
136136
use crate::devices::virtio::net::test_utils::NetQueue;
137-
use crate::devices::virtio::net::TX_INDEX;
137+
use crate::devices::virtio::net::{MAX_BUFFER_SIZE, TX_INDEX};
138+
use crate::utilities::test_utils::single_region_mem;
138139

139140
#[test]
140141
fn test_event_handler() {
141-
let mut th = TestHelper::get_default();
142+
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
143+
let mut th = TestHelper::get_default(&mem);
142144

143145
// Push a queue event, use the TX_QUEUE_EVENT in this test.
144146
th.add_desc_chain(NetQueue::Tx, 0, &[(0, 4096, 0)]);

src/vmm/src/devices/virtio/net/test_utils.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ pub mod test {
300300
#![allow(clippy::undocumented_unsafe_blocks)]
301301
use std::os::unix::ffi::OsStrExt;
302302
use std::sync::{Arc, Mutex, MutexGuard};
303-
use std::{cmp, fmt, mem};
303+
use std::{cmp, fmt};
304304

305305
use event_manager::{EventManager, SubscriberId, SubscriberOps};
306306

@@ -311,18 +311,17 @@ pub mod test {
311311
use crate::devices::virtio::net::test_utils::{
312312
assign_queues, default_net, inject_tap_tx_frame, NetEvent, NetQueue,
313313
};
314-
use crate::devices::virtio::net::{Net, MAX_BUFFER_SIZE, RX_INDEX, TX_INDEX};
314+
use crate::devices::virtio::net::{Net, RX_INDEX, TX_INDEX};
315315
use crate::devices::virtio::queue::{VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE};
316316
use crate::devices::virtio::test_utils::{VirtQueue, VirtqDesc};
317317
use crate::logger::IncMetric;
318-
use crate::utilities::test_utils::single_region_mem;
319318
use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemoryMmap};
320319

321320
pub struct TestHelper<'a> {
322321
pub event_manager: EventManager<Arc<Mutex<Net>>>,
323322
pub subscriber_id: SubscriberId,
324323
pub net: Arc<Mutex<Net>>,
325-
pub mem: GuestMemoryMmap,
324+
pub mem: &'a GuestMemoryMmap,
326325
pub rxq: VirtQueue<'a>,
327326
pub txq: VirtQueue<'a>,
328327
}
@@ -343,18 +342,14 @@ pub mod test {
343342
impl<'a> TestHelper<'a> {
344343
const QUEUE_SIZE: u16 = 16;
345344

346-
pub fn get_default() -> TestHelper<'a> {
345+
pub fn get_default(mem: &'a GuestMemoryMmap) -> TestHelper<'a> {
347346
let mut event_manager = EventManager::new().unwrap();
348347
let mut net = default_net();
349-
let mem = single_region_mem(2 * MAX_BUFFER_SIZE);
350348

351-
// transmute mem_ref lifetime to 'a
352-
let mem_ref = unsafe { mem::transmute::<&GuestMemoryMmap, &'a GuestMemoryMmap>(&mem) };
353-
354-
let rxq = VirtQueue::new(GuestAddress(0), mem_ref, Self::QUEUE_SIZE);
349+
let rxq = VirtQueue::new(GuestAddress(0), mem, Self::QUEUE_SIZE);
355350
let txq = VirtQueue::new(
356351
rxq.end().unchecked_align_up(VirtqDesc::ALIGNMENT),
357-
mem_ref,
352+
mem,
358353
Self::QUEUE_SIZE,
359354
);
360355
assign_queues(&mut net, rxq.create_queue(), txq.create_queue());

0 commit comments

Comments
 (0)