Skip to content

Commit 1b2c0b1

Browse files
committed
refactor: improve clarity regarding some NetBSD quirks
1 parent bb10e23 commit 1b2c0b1

File tree

5 files changed

+29
-10
lines changed

5 files changed

+29
-10
lines changed

src/alloc.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,21 @@ mod tests {
190190

191191
#[test]
192192
fn alloc_frees_memory_when_dropped() -> Result<()> {
193-
let base = alloc(1, Protection::READ_WRITE)?.as_ptr::<()>();
193+
// Designing these tests can be quite tricky sometimes. When a page is
194+
// allocated and then released, a subsequent `query` may allocate memory in
195+
// the same location that has just been freed. For instance, NetBSD's
196+
// kinfo_getvmmap uses `mmap` internally, which can lead to potentially
197+
// confusing outcomes. To mitigate this, an additional buffer region is
198+
// allocated to ensure that any memory allocated indirectly through `query`
199+
// occupies a separate location in memory.
200+
let (start, _buffer) = (
201+
alloc(1, Protection::READ_WRITE)?,
202+
alloc(1, Protection::READ_WRITE)?,
203+
);
204+
205+
let base = start.as_ptr::<()>();
206+
std::mem::drop(start);
207+
194208
let query = crate::query(base);
195209
assert!(matches!(query, Err(Error::UnmappedRegion)));
196210
Ok(())
@@ -205,7 +219,7 @@ mod tests {
205219
}
206220

207221
#[test]
208-
#[cfg(not(target_os = "openbsd"))]
222+
#[cfg(not(any(target_os = "openbsd", target_os = "netbsd")))]
209223
fn alloc_can_allocate_executable_region() -> Result<()> {
210224
let memory = alloc(1, Protection::WRITE_EXECUTE)?;
211225
assert_eq!(memory.len(), page::size());

src/os/openbsd.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl Iterator for QueryIter {
3030
fn next(&mut self) -> Option<Self::Item> {
3131
let mut len = std::mem::size_of::<kinfo_vmentry>();
3232

33-
// Albeit it would be preferred to query the information for all virtual
33+
// Although it would be preferred to query the information for all virtual
3434
// pages at once, the system call does not seem to respond consistently. If
3535
// called once during a process' lifetime, it returns all pages, but if
3636
// called again, it returns an empty buffer. This may be caused due to an

src/os/unix.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@ pub fn page_size() -> usize {
88
}
99

1010
pub unsafe fn alloc(base: *const (), size: usize, protection: Protection) -> Result<*const ()> {
11-
#[cfg(not(target_os = "netbsd"))]
12-
let prot = protection.to_native();
11+
let mut prot = protection.to_native();
12+
13+
// This adjustment ensures that the behavior of memory protection is
14+
// orthogonal across all platforms by aligning NetBSD's protection flags
15+
// and PaX behavior with those of other operating systems.
16+
if cfg!(target_os = "netbsd") {
17+
let max_protection = (PROT_READ | PROT_WRITE | PROT_EXEC) << 3;
18+
prot |= max_protection;
19+
}
1320

14-
// PROT_MPROTECT usage for avoiding problems with NetBSD pax
15-
#[cfg(target_os = "netbsd")]
16-
let prot = protection.to_native() | (PROT_READ | PROT_WRITE | PROT_EXEC) << 3;
1721
let mut flags = MAP_PRIVATE | MAP_ANON;
1822

1923
if !base.is_null() {

src/protect.rs

+1
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ mod tests {
170170
#[test]
171171
#[cfg(not(any(
172172
target_os = "openbsd",
173+
target_os = "netbsd",
173174
all(target_vendor = "apple", target_arch = "aarch64")
174175
)))]
175176
fn protect_can_alter_text_segments() {

src/query.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ impl Iterator for QueryIter {
3737
Ok(region) => {
3838
let range = region.as_range();
3939

40-
// Skip the region if it is prior to the queried range
40+
// Skip the region if it precedes the queried range
4141
if range.end <= self.origin as usize {
4242
continue;
4343
}
4444

45-
// Stop iteration if the region is after the queried range
45+
// Stop iteration if the region is past the queried range
4646
if range.start >= regions.upper_bound() {
4747
break;
4848
}

0 commit comments

Comments
 (0)