Skip to content

Commit 713627b

Browse files
committed
Host: move Rng from C to Rust
This allows us to remove the previously unsound api Host::random, which returned a mutable reference from an immutable reference without using interior mutability. After this change we no longer need the Random C APIs, so those are removed.
1 parent 605f3eb commit 713627b

10 files changed

Lines changed: 44 additions & 95 deletions

File tree

src/main/build.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,6 @@ fn run_bindgen(build_common: &ShadowBuildCommon) {
206206
.opaque_type("Logger")
207207
.opaque_type("DescriptorTable")
208208
.opaque_type("MemoryManager")
209-
.opaque_type("Random")
210209
.opaque_type("TaskRef")
211210
.opaque_type("GList")
212211
.blocklist_type("Host")
@@ -241,7 +240,6 @@ fn run_bindgen(build_common: &ShadowBuildCommon) {
241240
.raw_line("use crate::host::syscall::handler::SyscallHandler;")
242241
.raw_line("use crate::host::timer::Timer;")
243242
.raw_line("use crate::utility::counter::Counter;")
244-
.raw_line("use crate::utility::random::Random;")
245243

246244
.raw_line("use atomic_refcell::AtomicRefCell;")
247245
.raw_line("use logger::Logger;")

src/main/core/worker.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ void worker_sendPacket(const Host* srcHost, Packet* packet) {
7373
/* check if network reliability forces us to 'drop' the packet */
7474
gdouble reliability = worker_getReliability(srcIP, dstIP);
7575

76-
Random* random = host_getRandom(srcHost);
77-
gdouble chance = random_nextDouble(random);
76+
gdouble chance = host_rngDouble(srcHost);
7877

7978
/* don't drop control packets with length 0, otherwise congestion
8079
* control has problems responding to packet loss */

src/main/host/descriptor/regular_file.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -318,8 +318,7 @@ static void _regularfile_readRandomBytes(RegularFile* file, const Host* host, vo
318318
trace("RegularFile %p will read %zu bytes from random source for host %s", file, numBytes,
319319
host_getName(host));
320320

321-
Random* rng = host_getRandom(host);
322-
random_nextNBytes(rng, buf, numBytes);
321+
host_rngNextNBytes(host, buf, numBytes);
323322
}
324323

325324
static size_t _regularfile_readvRandomBytes(RegularFile* file, const Host* host,

src/main/host/host.c

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,6 @@ struct _HostCInternal {
8484
/* Lock protecting parts of shimSharedMemBlock. */
8585
ShimShmemHostLock* shimShmemHostLock;
8686

87-
/* random stream */
88-
Random* random;
89-
9087
#ifdef USE_PERF_TIMERS
9188
/* track the time spent executing this host */
9289
GTimer* executionTimer;
@@ -190,7 +187,6 @@ void hostc_setup(HostCInternal* host, DNS* dns, gulong rawCPUFreq, const gchar*
190187
g_mkdir_with_parents(host->dataDirPath, 0775);
191188
}
192189

193-
host->random = random_new(host->params.nodeSeed);
194190
host->cpu = cpu_new(host->params.cpuFrequency, rawCPUFreq, host->params.cpuThreshold,
195191
host->params.cpuPrecision);
196192

@@ -295,10 +291,6 @@ void hostc_shutdown(HostCInternal* host) {
295291
tracker_free(host->tracker);
296292
}
297293

298-
if(host->random) {
299-
random_free(host->random);
300-
}
301-
302294
if(host->params.pcapDir) g_free((gchar*)host->params.pcapDir);
303295

304296
if(host->dataDirPath) {
@@ -459,11 +451,6 @@ in_addr_t hostc_getDefaultIP(HostCInternal* host) {
459451
return address_toNetworkIP(host->defaultAddress);
460452
}
461453

462-
Random* hostc_getRandom(HostCInternal* host) {
463-
MAGIC_ASSERT(host);
464-
return host->random;
465-
}
466-
467454
gboolean hostc_autotuneReceiveBuffer(HostCInternal* host) {
468455
MAGIC_ASSERT(host);
469456
return host->params.autotuneRecvBuf;
@@ -596,8 +583,9 @@ in_port_t _hostc_incrementPort(in_port_t port, in_port_t port_on_overflow) {
596583
return htons(val);
597584
}
598585

599-
static in_port_t _hostc_getRandomPort(HostCInternal* host) {
600-
gdouble randomFraction = random_nextDouble(host->random);
586+
static in_port_t _hostc_getRandomPort(const Host* rhost) {
587+
HostCInternal* host = host_internal(rhost);
588+
gdouble randomFraction = host_rngDouble(rhost);
601589
gdouble numPotentialPorts = (gdouble)(UINT16_MAX - MIN_RANDOM_PORT);
602590

603591
gdouble randomPick = round(randomFraction * numPotentialPorts);
@@ -610,8 +598,9 @@ static in_port_t _hostc_getRandomPort(HostCInternal* host) {
610598
return htons(randomHostPort);
611599
}
612600

613-
in_port_t hostc_getRandomFreePort(HostCInternal* host, ProtocolType type, in_addr_t interfaceIP,
601+
in_port_t hostc_getRandomFreePort(const Host* rhost, ProtocolType type, in_addr_t interfaceIP,
614602
in_addr_t peerIP, in_port_t peerPort) {
603+
HostCInternal* host = host_internal(rhost);
615604
MAGIC_ASSERT(host);
616605

617606
/* we need a random port that is free everywhere we need it to be.
@@ -622,7 +611,7 @@ in_port_t hostc_getRandomFreePort(HostCInternal* host, ProtocolType type, in_add
622611
/* if choosing randomly doesn't succeed within 10 tries, then we have already
623612
* allocated a lot of ports (>90% on average). then we fall back to linear search. */
624613
for(guint i = 0; i < 10; i++) {
625-
in_port_t randomPort = _hostc_getRandomPort(host);
614+
in_port_t randomPort = _hostc_getRandomPort(rhost);
626615

627616
/* this will check all interfaces in the case of INADDR_ANY */
628617
if (hostc_isInterfaceAvailable(host, type, interfaceIP, randomPort, peerIP, peerPort)) {
@@ -633,7 +622,7 @@ in_port_t hostc_getRandomFreePort(HostCInternal* host, ProtocolType type, in_add
633622
/* now if we tried too many times and still don't have a port, fall back
634623
* to a linear search to make sure we get a free port if we have one.
635624
* but start from a random port instead of the min. */
636-
in_port_t start = _hostc_getRandomPort(host);
625+
in_port_t start = _hostc_getRandomPort(rhost);
637626
in_port_t next = _hostc_incrementPort(start, htons(MIN_RANDOM_PORT));
638627
while(next != start) {
639628
/* this will check all interfaces in the case of INADDR_ANY */

src/main/host/host.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ Tsc* hostc_getTsc(HostCInternal* host);
5858
const gchar* hostc_getName(HostCInternal* host);
5959
Address* hostc_getDefaultAddress(HostCInternal* host);
6060
in_addr_t hostc_getDefaultIP(HostCInternal* host);
61-
Random* hostc_getRandom(HostCInternal* host);
6261
gdouble hostc_getNextPacketPriority(HostCInternal* host);
6362

6463
gboolean hostc_autotuneReceiveBuffer(HostCInternal* host);
@@ -83,7 +82,7 @@ gboolean hostc_isInterfaceAvailable(HostCInternal* host, ProtocolType type, in_a
8382
void hostc_associateInterface(HostCInternal* host, const CompatSocket* socket,
8483
in_addr_t bindAddress);
8584
void hostc_disassociateInterface(HostCInternal* host, const CompatSocket* socket);
86-
in_port_t hostc_getRandomFreePort(HostCInternal* host, ProtocolType type, in_addr_t interfaceIP,
85+
in_port_t hostc_getRandomFreePort(const Host* host, ProtocolType type, in_addr_t interfaceIP,
8786
in_addr_t peerIP, in_port_t peerPort);
8887

8988
Arc_AtomicRefCell_AbstractUnixNamespace* hostc_getAbstractUnixNamespace(HostCInternal* host);

src/main/host/host.rs

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use log::trace;
22
use once_cell::unsync::OnceCell;
3+
use rand::SeedableRng;
4+
use rand_xoshiro::Xoshiro256PlusPlus;
5+
use shadow_shim_helper_rs::rootedcell::refcell::RootedRefCell;
36
use shadow_shim_helper_rs::rootedcell::Root;
47
use std::net::IpAddr;
58
use std::os::raw::c_char;
@@ -52,6 +55,8 @@ pub struct Host {
5255

5356
event_queue: Arc<Mutex<EventQueue>>,
5457

58+
random: RootedRefCell<Xoshiro256PlusPlus>,
59+
5560
params: cshadow::HostParameters,
5661
}
5762

@@ -78,12 +83,17 @@ impl Host {
7883
// TODO: remove params from HostCInternal.
7984
let chost = unsafe { cshadow::hostc_new(&params) };
8085
let root = Root::new();
86+
let random = RootedRefCell::new(
87+
&root,
88+
Xoshiro256PlusPlus::seed_from_u64(params.nodeSeed as u64),
89+
);
8190
Self {
8291
chost: unsafe { SyncSendPointer::new(chost) },
8392
info: OnceCell::new(),
8493
root,
8594
event_queue: Arc::new(Mutex::new(EventQueue::new())),
8695
params,
96+
random,
8797
}
8898
}
8999

@@ -161,10 +171,9 @@ impl Host {
161171
crate::core::logger::log_wrapper::c_to_rust_log_level(level).map(|l| l.to_level_filter())
162172
}
163173

164-
pub fn random(&self) -> &mut impl rand::Rng {
165-
let ptr = unsafe { cshadow::hostc_getRandom(self.chost()) };
166-
let random = unsafe { ptr.as_mut() }.unwrap();
167-
&mut random.0
174+
pub fn with_random_mut<Res>(&self, f: impl FnOnce(&mut Xoshiro256PlusPlus) -> Res) -> Res {
175+
let mut rng = self.random.borrow_mut(&self.root);
176+
f(&mut *rng)
168177
}
169178

170179
pub fn get_new_event_id(&self) -> u64 {
@@ -292,11 +301,11 @@ mod export {
292301
use std::os::raw::c_char;
293302

294303
use libc::{in_addr_t, in_port_t};
304+
use rand::{Rng, RngCore};
295305

296306
use crate::{
297307
cshadow::{CEmulatedTime, CSimulationTime, HostCInternal},
298308
network::router::Router,
299-
utility::random::Random,
300309
};
301310

302311
use super::*;
@@ -368,12 +377,6 @@ mod export {
368377
unsafe { cshadow::hostc_getDefaultIP(hostrc.chost()) }
369378
}
370379

371-
#[no_mangle]
372-
pub unsafe extern "C" fn host_getRandom(hostrc: *const Host) -> *mut Random {
373-
let hostrc = unsafe { hostrc.as_ref().unwrap() };
374-
unsafe { cshadow::hostc_getRandom(hostrc.chost()) }
375-
}
376-
377380
#[no_mangle]
378381
pub unsafe extern "C" fn host_getNextPacketPriority(hostrc: *const Host) -> f64 {
379382
let hostrc = unsafe { hostrc.as_ref().unwrap() };
@@ -510,7 +513,7 @@ mod export {
510513
let hostrc = unsafe { hostrc.as_ref().unwrap() };
511514
unsafe {
512515
cshadow::hostc_getRandomFreePort(
513-
hostrc.chost(),
516+
hostrc,
514517
protocol_type,
515518
interface_ip,
516519
peer_ip,
@@ -642,6 +645,22 @@ mod export {
642645
hostrc.schedule_task_with_delay(task, delay)
643646
}
644647

648+
#[no_mangle]
649+
pub unsafe extern "C" fn host_rngDouble(host: *const Host) -> f64 {
650+
let host = unsafe { host.as_ref().unwrap() };
651+
host.with_random_mut(|rng| rng.gen())
652+
}
653+
654+
/// Fills the buffer with pseudo-random bytes.
655+
#[no_mangle]
656+
pub extern "C" fn host_rngNextNBytes(host: *const Host, buf: *mut u8, len: usize) {
657+
let host = unsafe { host.as_ref().unwrap() };
658+
host.with_random_mut(|rng| {
659+
let buf = unsafe { std::slice::from_raw_parts_mut(buf, len) };
660+
rng.fill_bytes(buf);
661+
})
662+
}
663+
645664
/// Should only be used from host.c
646665
#[no_mangle]
647666
pub unsafe extern "C" fn host_internal(hostrc: *const Host) -> *mut HostCInternal {

src/main/host/syscall/handler/random.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ impl SyscallHandler {
3131
};
3232

3333
// Get random bytes using host rng to maintain determinism.
34-
ctx.host.random().fill_bytes(&mut mem_ref);
34+
ctx.host.with_random_mut(|rng| rng.fill_bytes(&mut mem_ref));
3535

3636
// We must flush the memory reference to write it back.
3737
match mem_ref.flush() {

src/main/host/syscall/handler/socket.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ impl SyscallHandler {
126126

127127
debug!("Attempting to bind fd {} to {:?}", fd, addr);
128128

129-
Socket::bind(socket, addr.as_ref(), ctx.host.random())
129+
ctx.host
130+
.with_random_mut(|rng| Socket::bind(socket, addr.as_ref(), rng))
130131
}
131132

132133
#[log_syscall(/* rv */ libc::ssize_t, /* sockfd */ libc::c_int, /* buf */ *const libc::c_char,

src/main/utility/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ pub mod pcap_writer;
1515
pub mod perf_timer;
1616
pub mod pod;
1717
pub mod proc_maps;
18-
pub mod random;
1918
pub mod shm_cleanup;
2019
pub mod status_bar;
2120
pub mod stream_len;

src/main/utility/random.rs

Lines changed: 0 additions & 54 deletions
This file was deleted.

0 commit comments

Comments
 (0)