Skip to content

Commit 0e9dfd6

Browse files
authored
LetForkserverExecutor being Send (#3242)
* Implement `Send` for `Shm` it is safe because we take the ownership of the inner map pointer. Only potential violation is deref the underlying pointer but that’s already unsafe. Therefore, the properties of Send still hold within the safe world. * Bump 1.87 * use std::io::pipe so that they are `Send` * clippy * upgrade * Avoid phantomdata to make ForkserverExecutor !Send * Missing gates * Fix nostd * bump in Dockerfile * use dtolnay/rust-toolchain@stable instead * setup latest toolchain on non Linux * Fix typo
1 parent ba93e9d commit 0e9dfd6

File tree

13 files changed

+61
-50
lines changed

13 files changed

+61
-50
lines changed

.github/workflows/build_and_test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ jobs:
4242
- uses: actions/checkout@v4
4343
- if: runner.os == 'Linux'
4444
uses: ./.github/workflows/ubuntu-prepare
45+
- if: runner.os != 'Linux'
46+
uses: dtolnay/rust-toolchain@stable
4547
- name: Install LLVM
4648
if: runner.os == 'MacOS'
4749
run: brew install llvm@${{env.MAIN_LLVM_VERSION}}
@@ -227,8 +229,8 @@ jobs:
227229
runs-on: ubuntu-latest
228230
steps:
229231
- uses: actions/checkout@v4
232+
- uses: dtolnay/rust-toolchain@stable
230233
- uses: taiki-e/install-action@cargo-hack
231-
- run: rustup upgrade
232234
# Note: We currently only specify minimum rust versions for the default workspace members
233235
- run: cargo hack check --rust-version -p libafl -p libafl_bolts -p libafl_derive -p libafl_cc -p libafl_targets
234236

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# syntax=docker/dockerfile:1.2
2-
FROM rust:1.85.0 AS libafl
2+
FROM rust:1.87.0 AS libafl
33
LABEL "maintainer"="afl++ team <[email protected]>"
44
LABEL "about"="LibAFL Docker image"
55

libafl/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ readme = "../../README.md"
1212
license = "MIT OR Apache-2.0"
1313
keywords = ["fuzzing", "testing", "security"]
1414
edition = "2024"
15-
rust-version = "1.85"
15+
rust-version = "1.87"
1616
categories = [
1717
"development-tools::testing",
1818
"emulators",

libafl/src/executors/forkserver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ pub struct ForkserverExecutor<I, OT, S, SHM> {
671671
forkserver: Forkserver,
672672
observers: OT,
673673
map: Option<SHM>,
674-
phantom: PhantomData<(I, S)>,
674+
phantom: PhantomData<fn() -> (I, S)>, // For Send/Sync
675675
map_size: Option<usize>,
676676
min_input_size: usize,
677677
max_input_size: usize,

libafl_bolts/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ readme = "./README.md"
1212
license = "MIT OR Apache-2.0"
1313
keywords = ["fuzzing", "testing", "security"]
1414
edition = "2024"
15-
rust-version = "1.85"
15+
rust-version = "1.87"
1616
categories = [
1717
"development-tools::testing",
1818
"emulators",

libafl_bolts/src/os/pipes.rs

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,55 @@
11
//! Unix `pipe` wrapper for `LibAFL`
22
#[cfg(feature = "std")]
3-
use alloc::rc::Rc;
4-
#[cfg(feature = "std")]
5-
use core::{borrow::Borrow, cell::RefCell};
6-
#[cfg(feature = "std")]
73
use std::{
8-
io::{self, ErrorKind, Read, Write},
9-
os::{
10-
fd::{AsFd, AsRawFd, OwnedFd},
11-
unix::io::RawFd,
12-
},
4+
io::{self, ErrorKind, PipeReader, PipeWriter, Read, Write},
5+
os::unix::io::RawFd,
136
};
147

15-
#[cfg(feature = "std")]
16-
use nix::unistd::{pipe, read, write};
17-
188
#[cfg(feature = "std")]
199
use crate::Error;
2010

2111
/// A unix pipe wrapper for `LibAFL`
2212
#[cfg(feature = "std")]
23-
#[derive(Debug, Clone)]
13+
#[derive(Debug)]
2414
pub struct Pipe {
2515
/// The read end of the pipe
26-
read_end: Option<Rc<RefCell<OwnedFd>>>,
16+
read_end: Option<PipeReader>,
2717
/// The write end of the pipe
28-
write_end: Option<Rc<RefCell<OwnedFd>>>,
18+
write_end: Option<PipeWriter>,
19+
}
20+
21+
#[cfg(feature = "std")]
22+
impl Clone for Pipe {
23+
fn clone(&self) -> Self {
24+
// try_clone only fails if we run out of fds (dup2) so this should be rather safe
25+
let read_end = self
26+
.read_end
27+
.as_ref()
28+
.map(PipeReader::try_clone)
29+
.transpose()
30+
.expect("fail to clone read_end");
31+
let write_end = self
32+
.write_end
33+
.as_ref()
34+
.map(PipeWriter::try_clone)
35+
.transpose()
36+
.expect("fail to clone read_end");
37+
38+
Self {
39+
read_end,
40+
write_end,
41+
}
42+
}
2943
}
3044

3145
#[cfg(feature = "std")]
3246
impl Pipe {
3347
/// Create a new `Unix` pipe
3448
pub fn new() -> Result<Self, Error> {
35-
let (read_end, write_end) = pipe()?;
49+
let (read_end, write_end) = io::pipe()?;
3650
Ok(Self {
37-
read_end: Some(Rc::new(RefCell::new(read_end))),
38-
write_end: Some(Rc::new(RefCell::new(write_end))),
51+
read_end: Some(read_end),
52+
write_end: Some(write_end),
3953
})
4054
}
4155

@@ -54,31 +68,22 @@ impl Pipe {
5468
/// The read end
5569
#[must_use]
5670
pub fn read_end(&self) -> Option<RawFd> {
57-
self.read_end.as_ref().map(|fd| {
58-
let borrowed: &RefCell<OwnedFd> = fd.borrow();
59-
borrowed.borrow().as_raw_fd()
60-
})
71+
self.read_end.as_ref().map(std::os::fd::AsRawFd::as_raw_fd)
6172
}
6273

6374
/// The write end
6475
#[must_use]
6576
pub fn write_end(&self) -> Option<RawFd> {
66-
self.write_end.as_ref().map(|fd| {
67-
let borrowed: &RefCell<OwnedFd> = fd.borrow();
68-
borrowed.borrow().as_raw_fd()
69-
})
77+
self.write_end.as_ref().map(std::os::fd::AsRawFd::as_raw_fd)
7078
}
7179
}
7280

7381
#[cfg(feature = "std")]
7482
impl Read for Pipe {
7583
/// Reads a few bytes
7684
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
77-
match self.read_end() {
78-
Some(read_end) => match read(read_end, buf) {
79-
Ok(res) => Ok(res),
80-
Err(e) => Err(io::Error::from_raw_os_error(e as i32)),
81-
},
85+
match self.read_end.as_mut() {
86+
Some(read_end) => read_end.read(buf),
8287
None => Err(io::Error::new(
8388
ErrorKind::BrokenPipe,
8489
"Read pipe end was already closed",
@@ -91,14 +96,8 @@ impl Read for Pipe {
9196
impl Write for Pipe {
9297
/// Writes a few bytes
9398
fn write(&mut self, buf: &[u8]) -> Result<usize, io::Error> {
94-
match self.write_end.as_ref() {
95-
Some(write_end) => {
96-
let borrowed: &RefCell<OwnedFd> = write_end;
97-
match write((*borrowed).borrow().as_fd(), buf) {
98-
Ok(res) => Ok(res),
99-
Err(e) => Err(io::Error::from_raw_os_error(e as i32)),
100-
}
101-
}
99+
match self.write_end.as_mut() {
100+
Some(write_end) => Ok(write_end.write(buf)?),
102101
None => Err(io::Error::new(
103102
ErrorKind::BrokenPipe,
104103
"Write pipe end was already closed",

libafl_bolts/src/shmem.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,8 @@ pub mod unix_shmem {
715715
shm_fd: c_int,
716716
}
717717

718+
unsafe impl Send for MmapShMem {}
719+
718720
impl MmapShMem {
719721
/// Create a new [`MmapShMem`]
720722
///
@@ -1036,6 +1038,8 @@ pub mod unix_shmem {
10361038
map_size: usize,
10371039
}
10381040

1041+
unsafe impl Send for CommonUnixShMem {}
1042+
10391043
impl CommonUnixShMem {
10401044
/// Create a new shared memory mapping, using shmget/shmat
10411045
pub fn new(map_size: usize) -> Result<Self, Error> {
@@ -1189,6 +1193,8 @@ pub mod unix_shmem {
11891193
map_size: usize,
11901194
}
11911195

1196+
unsafe impl Send for AshmemShMem {}
1197+
11921198
#[allow(non_camel_case_types)] // expect somehow breaks here
11931199
#[derive(Copy, Clone)]
11941200
#[repr(C)]
@@ -1409,6 +1415,8 @@ pub mod unix_shmem {
14091415
map_size: usize,
14101416
}
14111417

1418+
unsafe impl Send for MemfdShMem {}
1419+
14121420
impl MemfdShMem {
14131421
/// Create a new shared memory mapping, using shmget/shmat
14141422
pub fn new(map_size: usize) -> Result<Self, Error> {
@@ -1612,6 +1620,8 @@ pub mod win32_shmem {
16121620
map_size: usize,
16131621
}
16141622

1623+
unsafe impl Send for Win32ShMem {}
1624+
16151625
impl Debug for Win32ShMem {
16161626
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
16171627
f.debug_struct("Win32ShMem")

libafl_cc/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ readme = "README.md"
99
license = "MIT OR Apache-2.0"
1010
keywords = ["fuzzing", "testing", "compiler"]
1111
edition = "2024"
12-
rust-version = "1.85"
12+
rust-version = "1.87"
1313
categories = [
1414
"development-tools::testing",
1515
"emulators",

libafl_concolic/test/runtime_test/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "runtime_test"
33
version.workspace = true
44
edition = "2024"
5-
rust-version = "1.85"
5+
rust-version = "1.87"
66
authors = ["Julius Hohnerlein <[email protected]>"]
77
description = "Runtime test of LibAFL fuzzing with symbolic execution"
88
documentation = "https://docs.rs/libafl"

libafl_derive/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ readme = "../README.md"
99
license = "MIT OR Apache-2.0"
1010
keywords = ["fuzzing", "testing"]
1111
edition = "2024"
12-
rust-version = "1.85"
12+
rust-version = "1.87"
1313
categories = [
1414
"development-tools::testing",
1515
"emulators",

libafl_libfuzzer/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ readme = "../README.md"
77
license = "MIT OR Apache-2.0"
88
keywords = ["fuzzing", "testing", "security"]
99
edition = "2024"
10-
rust-version = "1.85"
10+
rust-version = "1.87"
1111
categories = ["development-tools::testing"]
1212

1313
include = [

libafl_qemu/librasan/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ resolver = "2"
66
version = "0.15.2"
77
license = "MIT OR Apache-2.0"
88
edition = "2024"
9-
rust-version = "1.85"
9+
rust-version = "1.87"
1010

1111
[profile.dev]
1212
panic = "abort"

libafl_targets/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ readme = "../README.md"
99
license = "MIT OR Apache-2.0"
1010
keywords = ["fuzzing", "testing"]
1111
edition = "2024"
12-
rust-version = "1.85"
12+
rust-version = "1.87"
1313
categories = [
1414
"development-tools::testing",
1515
"emulators",

0 commit comments

Comments
 (0)