Skip to content

Commit 7e2b402

Browse files
committed
Fix test breakage in Seccomp mode.
Travis is now using Seccomp, and Docker's default Seccomp policy disables execveat (though, weirdly, not fexecve). It also prohibits any operations on AF_ALG sockets. While I'm here, replace close/dup with dup2, which is more reliable. Also, drop the fork mutex earlier. This way all of the exeve tests will run, even if one fails. https://docs.docker.com/engine/security/seccomp/
1 parent adcfaf5 commit 7e2b402

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

test/sys/test_socket.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,10 @@ pub fn test_af_alg_cipher() {
244244
ControlMessage, MsgFlags};
245245
use nix::sys::socket::sockopt::AlgSetKey;
246246

247+
// Travis's seccomp profile blocks AF_ALG
248+
// https://docs.docker.com/engine/security/seccomp/
249+
skip_if_seccomp!(test_af_alg_cipher);
250+
247251
let alg_type = "skcipher";
248252
let alg_name = "ctr(aes)";
249253
// 256-bits secret key
@@ -308,6 +312,10 @@ pub fn test_af_alg_aead() {
308312
ControlMessage, MsgFlags};
309313
use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize};
310314

315+
// Travis's seccomp profile blocks AF_ALG
316+
// https://docs.docker.com/engine/security/seccomp/
317+
skip_if_seccomp!(test_af_alg_aead);
318+
311319
let auth_size = 4usize;
312320
let assoc_size = 16u32;
313321

test/test.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,35 @@ macro_rules! skip_if_not_root {
7373
};
7474
}
7575

76+
cfg_if! {
77+
if #[cfg(any(target_os = "android", target_os = "linux"))] {
78+
macro_rules! skip_if_seccomp {
79+
($name:expr) => {
80+
if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
81+
for l in s.lines() {
82+
let mut fields = l.split_whitespace();
83+
if fields.next() == Some("Seccomp:") &&
84+
fields.next() != Some("0")
85+
{
86+
use ::std::io::Write;
87+
let stderr = ::std::io::stderr();
88+
let mut handle = stderr.lock();
89+
writeln!(handle,
90+
"{} cannot be run in Seccomp mode. Skipping test.",
91+
stringify!($name)).unwrap();
92+
return;
93+
}
94+
}
95+
}
96+
}
97+
}
98+
} else {
99+
macro_rules! skip_if_seccomp {
100+
($name:expr) => {}
101+
}
102+
}
103+
}
104+
76105
mod sys;
77106
mod test_dir;
78107
mod test_fcntl;

test/test_unistd.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,13 @@ macro_rules! execve_test_factory(
184184
($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
185185
#[test]
186186
fn $test_name() {
187-
let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
187+
if "execveat" == stringify!($syscall) {
188+
// Though undocumented, Docker's default seccomp profile seems to
189+
// block this syscall. https://github.com/nix-rust/nix/issues/1122
190+
skip_if_seccomp!($test_name);
191+
}
192+
193+
let m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
188194
// The `exec`d process will write to `writer`, and we'll read that
189195
// data from `reader`.
190196
let (reader, writer) = pipe().unwrap();
@@ -194,12 +200,9 @@ macro_rules! execve_test_factory(
194200
// The tests make sure not to do that, though.
195201
match fork().unwrap() {
196202
Child => {
197-
// Close stdout.
198-
close(1).unwrap();
199203
// Make `writer` be the stdout of the new process.
200-
dup(writer).unwrap();
201-
// exec!
202-
$syscall(
204+
dup2(writer, 1).unwrap();
205+
let r = $syscall(
203206
$exe,
204207
$(&CString::new($pathname).unwrap(), )*
205208
&[CString::new(b"".as_ref()).unwrap(),
@@ -208,11 +211,17 @@ macro_rules! execve_test_factory(
208211
.as_ref()).unwrap()],
209212
&[CString::new(b"foo=bar".as_ref()).unwrap(),
210213
CString::new(b"baz=quux".as_ref()).unwrap()]
211-
$(, $flags)*).unwrap();
214+
$(, $flags)*);
215+
let _ = std::io::stderr()
216+
.write_all(format!("{:?}", r).as_bytes());
217+
// Should only get here in event of error
218+
unsafe{ _exit(1) };
212219
},
213220
Parent { child } => {
214221
// Wait for the child to exit.
215-
waitpid(child, None).unwrap();
222+
let ws = waitpid(child, None);
223+
drop(m);
224+
assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
216225
// Read 1024 bytes.
217226
let mut buf = [0u8; 1024];
218227
read(reader, &mut buf).unwrap();

0 commit comments

Comments
 (0)