Skip to content

Commit abd58ce

Browse files
committed
Reduce unsafe code
1 parent 83887ce commit abd58ce

File tree

9 files changed

+328
-273
lines changed

9 files changed

+328
-273
lines changed

.github/workflows/rust.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,18 @@ jobs:
6363
cargo build -Zunstable-options --out-dir=../out --target=$TARGET
6464
- name: Run tests
6565
run: |
66-
sudo ./out/minion-tests
66+
sudo ./out/minion-tests --trace
67+
timeout-minutes: 3
68+
- name: Collect logs
69+
if: always()
70+
run: |
71+
mkdir /tmp/logs
72+
cp ./strace* /tmp/logs
73+
- uses: actions/upload-artifact@v1
74+
if: always()
75+
with:
76+
path: /tmp/logs
77+
name: tests-trace
6778
nightly-checks:
6879
runs-on: ubuntu-latest
6980
steps:

minion-ffi/src/lib.rs

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,11 @@ pub enum WaitOutcome {
4040
Timeout,
4141
}
4242

43+
/// # Safety
44+
/// `buf` must be valid, readable pointer
4345
unsafe fn get_string(buf: *const c_char) -> OsString {
4446
use std::os::unix::ffi::OsStrExt;
45-
let buf = CStr::from_ptr(buf);
47+
let buf = unsafe { CStr::from_ptr(buf) };
4648
let buf = buf.to_bytes();
4749
let s = OsStr::from_bytes(buf);
4850
s.to_os_string()
@@ -79,7 +81,7 @@ pub extern "C" fn minion_backend_create(out: &mut *mut Backend) -> ErrorCode {
7981
#[no_mangle]
8082
#[must_use]
8183
pub unsafe extern "C" fn minion_backend_free(b: *mut Backend) -> ErrorCode {
82-
let b = Box::from_raw(b);
84+
let b = unsafe { Box::from_raw(b) };
8385
mem::drop(b);
8486
ErrorCode::Ok
8587
}
@@ -112,7 +114,9 @@ pub unsafe extern "C" fn minion_dominion_check_cpu_tle(
112114
) -> ErrorCode {
113115
match dominion.0.check_cpu_tle() {
114116
Ok(st) => {
115-
out.write(st);
117+
unsafe {
118+
out.write(st);
119+
}
116120
ErrorCode::Ok
117121
}
118122
Err(_) => ErrorCode::Unknown,
@@ -128,7 +132,9 @@ pub unsafe extern "C" fn minion_dominion_check_real_tle(
128132
) -> ErrorCode {
129133
match dominion.0.check_real_tle() {
130134
Ok(st) => {
131-
out.write(st);
135+
unsafe {
136+
out.write(st);
137+
}
132138
ErrorCode::Ok
133139
}
134140
Err(_) => ErrorCode::Unknown,
@@ -153,7 +159,7 @@ pub unsafe extern "C" fn minion_dominion_create(
153159
out: &mut *mut Dominion,
154160
) -> ErrorCode {
155161
let mut exposed_paths = Vec::new();
156-
{
162+
unsafe {
157163
let mut p = options.shared_directories;
158164
while !(*p).host_path.is_null() {
159165
let opt = minion::PathExpositionOptions {
@@ -168,6 +174,7 @@ pub unsafe extern "C" fn minion_dominion_create(
168174
p = p.offset(1);
169175
}
170176
}
177+
let isolation_root = unsafe { get_string(options.isolation_root) }.into();
171178
let opts = minion::DominionOptions {
172179
max_alive_process_count: options.process_limit as _,
173180
memory_limit: u64::from(options.memory_limit),
@@ -179,7 +186,7 @@ pub unsafe extern "C" fn minion_dominion_create(
179186
options.real_time_limit.seconds.into(),
180187
options.real_time_limit.nanoseconds,
181188
),
182-
isolation_root: get_string(options.isolation_root).into(),
189+
isolation_root,
183190
exposed_paths,
184191
};
185192
let d = backend.0.new_dominion(opts);
@@ -195,7 +202,7 @@ pub unsafe extern "C" fn minion_dominion_create(
195202
#[no_mangle]
196203
#[must_use]
197204
pub unsafe extern "C" fn minion_dominion_free(dominion: *mut Dominion) -> ErrorCode {
198-
let b = Box::from_raw(dominion);
205+
let b = unsafe { Box::from_raw(dominion) };
199206
mem::drop(b);
200207
ErrorCode::Ok
201208
}
@@ -274,15 +281,15 @@ pub unsafe extern "C" fn minion_cp_spawn(
274281
out: &mut *mut ChildProcess,
275282
) -> ErrorCode {
276283
let mut arguments = Vec::new();
277-
{
284+
unsafe {
278285
let mut p = options.argv;
279286
while !(*p).is_null() {
280287
arguments.push(get_string(*p));
281288
p = p.offset(1);
282289
}
283290
}
284291
let mut environment = Vec::new();
285-
{
292+
unsafe {
286293
let mut p = options.envp;
287294
while !(*p).name.is_null() {
288295
let name = get_string((*p).name);
@@ -295,18 +302,22 @@ pub unsafe extern "C" fn minion_cp_spawn(
295302
p = p.offset(1);
296303
}
297304
}
298-
let stdio = minion::StdioSpecification {
299-
stdin: minion::InputSpecification::handle(options.stdio.stdin),
300-
stdout: minion::OutputSpecification::handle(options.stdio.stdout),
301-
stderr: minion::OutputSpecification::handle(options.stdio.stderr),
305+
let stdio = unsafe {
306+
minion::StdioSpecification {
307+
stdin: minion::InputSpecification::handle(options.stdio.stdin),
308+
stdout: minion::OutputSpecification::handle(options.stdio.stdout),
309+
stderr: minion::OutputSpecification::handle(options.stdio.stderr),
310+
}
302311
};
303-
let options = minion::ChildProcessOptions {
304-
path: get_string(options.image_path).into(),
305-
arguments,
306-
environment,
307-
dominion: (*options.dominion).0.clone(),
308-
stdio,
309-
pwd: get_string(options.workdir).into(),
312+
let options = unsafe {
313+
minion::ChildProcessOptions {
314+
path: get_string(options.image_path).into(),
315+
arguments,
316+
environment,
317+
dominion: (*options.dominion).0.clone(),
318+
stdio,
319+
pwd: get_string(options.workdir).into(),
320+
}
310321
};
311322
let cp = backend.0.spawn(options).unwrap();
312323
let cp = ChildProcess(cp);
@@ -336,7 +347,9 @@ pub unsafe extern "C" fn minion_cp_wait(
336347
minion::WaitOutcome::AlreadyFinished => WaitOutcome::AlreadyFinished,
337348
minion::WaitOutcome::Timeout => WaitOutcome::Timeout,
338349
};
339-
out.write(outcome);
350+
unsafe {
351+
out.write(outcome);
352+
}
340353
ErrorCode::Ok
341354
}
342355
Result::Err(_) => ErrorCode::Unknown,
@@ -346,24 +359,33 @@ pub unsafe extern "C" fn minion_cp_wait(
346359
#[no_mangle]
347360
pub static EXIT_CODE_STILL_RUNNING: i64 = 1234_4321;
348361

362+
/// Returns child process (pointed by `cp`) exit code.
363+
///
364+
/// `out` will contain exit code. If child is still running,
365+
/// `out` will not be written to.
366+
///
367+
/// if `finish_flag` is non-null it will be written 0/1 flag:
368+
/// has child finished.
349369
/// # Safety
350370
/// Provided pointers must be valid
351371
#[no_mangle]
352372
#[must_use]
353373
pub unsafe extern "C" fn minion_cp_exitcode(
354-
cp: &mut ChildProcess,
374+
cp: &ChildProcess,
355375
out: *mut i64,
356-
finish_flag: *mut bool,
376+
finish_flag: *mut u8,
357377
) -> ErrorCode {
358378
match cp.0.get_exit_code() {
359379
Result::Ok(exit_code) => {
360380
if let Some(code) = exit_code {
361-
out.write(code);
381+
unsafe {
382+
out.write(code);
383+
}
362384
} else {
363-
out.write(EXIT_CODE_STILL_RUNNING)
385+
unsafe { out.write(EXIT_CODE_STILL_RUNNING) }
364386
}
365387
if !finish_flag.is_null() {
366-
finish_flag.write(exit_code.is_some());
388+
unsafe { finish_flag.write(exit_code.is_some() as u8) };
367389
}
368390
ErrorCode::Ok
369391
}
@@ -376,6 +398,6 @@ pub unsafe extern "C" fn minion_cp_exitcode(
376398
#[no_mangle]
377399
#[must_use]
378400
pub unsafe extern "C" fn minion_cp_free(cp: *mut ChildProcess) -> ErrorCode {
379-
mem::drop(Box::from_raw(cp));
401+
mem::drop(unsafe { Box::from_raw(cp) });
380402
ErrorCode::Ok
381403
}

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ impl InputSpecification {
213213
/// # Safety
214214
/// See requirements of `handle`
215215
pub unsafe fn handle_of<T: std::os::unix::io::IntoRawFd>(obj: T) -> Self {
216-
Self::handle(obj.into_raw_fd() as u64)
216+
unsafe { Self::handle(obj.into_raw_fd() as u64) }
217217
}
218218
}
219219

@@ -258,7 +258,7 @@ impl OutputSpecification {
258258
/// # Safety
259259
/// See requirements of `handle`
260260
pub unsafe fn handle_of<T: std::os::unix::io::IntoRawFd>(obj: T) -> Self {
261-
Self::handle(obj.into_raw_fd() as u64)
261+
unsafe { Self::handle(obj.into_raw_fd() as u64) }
262262
}
263263
}
264264

src/linux/dominion.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
linux::{
33
jail_common,
44
pipe::setup_pipe,
5-
util::{err_exit, ExitCode, Handle, IpcSocketExt, Pid},
5+
util::{ExitCode, Handle, IpcSocketExt, Pid},
66
zygote,
77
},
88
Dominion, DominionOptions,
@@ -164,9 +164,11 @@ impl LinuxDominion {
164164
let mut read_end = 0;
165165
let mut write_end = 0;
166166
setup_pipe(&mut read_end, &mut write_end)?;
167-
if -1 == libc::fcntl(read_end, libc::F_SETFL, libc::O_NONBLOCK) {
168-
err_exit("fcntl");
169-
}
167+
nix::fcntl::fcntl(
168+
read_end,
169+
nix::fcntl::FcntlArg::F_SETFL(nix::fcntl::OFlag::O_NONBLOCK),
170+
)?;
171+
170172
let jail_options = jail_common::JailOptions {
171173
max_alive_process_count: options.max_alive_process_count,
172174
memory_limit: options.memory_limit,

src/linux/util.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::{
77
use tiny_nix_ipc::{self, Socket};
88

99
pub type Handle = RawFd;
10+
1011
pub type Pid = libc::pid_t;
1112
pub type ExitCode = i64;
1213
pub type Uid = libc::uid_t;
@@ -27,7 +28,7 @@ pub fn err_exit(syscall_name: &str) -> ! {
2728
}
2829
}
2930

30-
unsafe fn sock_lock(sock: &mut Socket, expected_class: &'static [u8]) -> crate::Result<()> {
31+
fn sock_lock(sock: &mut Socket, expected_class: &'static [u8]) -> crate::Result<()> {
3132
use std::io::Write;
3233
let mut logger = strace_logger();
3334
let mut recv_buf = vec![0; expected_class.len()];
@@ -51,41 +52,41 @@ unsafe fn sock_lock(sock: &mut Socket, expected_class: &'static [u8]) -> crate::
5152
Ok(())
5253
}
5354

54-
unsafe fn sock_wake(sock: &mut Socket, wake_class: &'static [u8]) -> crate::Result<()> {
55+
fn sock_wake(sock: &mut Socket, wake_class: &'static [u8]) -> crate::Result<()> {
5556
match sock.send_slice(&wake_class, None) {
5657
Ok(_) => Ok(()),
5758
Err(_) => Err(crate::Error::Sandbox),
5859
}
5960
}
6061

6162
pub trait IpcSocketExt {
62-
unsafe fn lock(&mut self, expected_class: &'static [u8]) -> crate::Result<()>;
63-
unsafe fn wake(&mut self, wake_class: &'static [u8]) -> crate::Result<()>;
63+
fn lock(&mut self, expected_class: &'static [u8]) -> crate::Result<()>;
64+
fn wake(&mut self, wake_class: &'static [u8]) -> crate::Result<()>;
6465

65-
unsafe fn send<T: serde::ser::Serialize>(&mut self, data: &T) -> crate::Result<()>;
66-
unsafe fn recv<T: serde::de::DeserializeOwned>(&mut self) -> crate::Result<T>;
66+
fn send<T: serde::ser::Serialize>(&mut self, data: &T) -> crate::Result<()>;
67+
fn recv<T: serde::de::DeserializeOwned>(&mut self) -> crate::Result<T>;
6768
}
6869

6970
const MAX_MSG_SIZE: usize = 16384;
7071

7172
impl IpcSocketExt for Socket {
72-
unsafe fn lock(&mut self, expected_class: &'static [u8]) -> crate::Result<()> {
73+
fn lock(&mut self, expected_class: &'static [u8]) -> crate::Result<()> {
7374
sock_lock(self, expected_class)
7475
}
7576

76-
unsafe fn wake(&mut self, wake_class: &'static [u8]) -> crate::Result<()> {
77+
fn wake(&mut self, wake_class: &'static [u8]) -> crate::Result<()> {
7778
sock_wake(self, wake_class)
7879
}
7980

80-
unsafe fn send<T: serde::ser::Serialize>(&mut self, data: &T) -> crate::Result<()> {
81+
fn send<T: serde::ser::Serialize>(&mut self, data: &T) -> crate::Result<()> {
8182
let data = serde_json::to_vec(data).unwrap();
8283
assert!(data.len() <= MAX_MSG_SIZE);
8384
self.send_slice(&data, None)
8485
.map(|_num_written| ())
8586
.map_err(|_e| crate::errors::Error::Sandbox)
8687
}
8788

88-
unsafe fn recv<T: serde::de::DeserializeOwned>(&mut self) -> crate::Result<T> {
89+
fn recv<T: serde::de::DeserializeOwned>(&mut self) -> crate::Result<T> {
8990
use std::io::Write;
9091
let mut logger = StraceLogger::new();
9192
let mut buf = vec![0; MAX_MSG_SIZE];

0 commit comments

Comments
 (0)