generated from rust-vmm/crate-template
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for seccomp thread sync feature
- Adds public functions `seccompiler::apply_filter_all_threads` and private `apply_filter_with_flags` - Moves the body of apply_filter into apply_filter_with_flags - Uses seccomp call directly in apply_filter, so new Error variant is added. - Error variant also added for TSYNC failures Resolves #57 Signed-off-by: Harry Stern <[email protected]>
- Loading branch information
1 parent
83dcac7
commit 5a2a6d5
Showing
5 changed files
with
165 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"coverage_score": 93.6, | ||
"coverage_score": 93.0, | ||
"exclude_path": "tests/integration_tests.rs,tests/json.rs", | ||
"crate_features": "json" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
#![allow(clippy::undocumented_unsafe_blocks)] | ||
|
||
/// This test is in a separate top-level test file so that it is isolated from the other tests - | ||
/// each file in the tests/ directory gets compiled to a separate binary and is run as a separate | ||
/// process. | ||
use std::collections::BTreeMap; | ||
|
||
use std::sync::mpsc::sync_channel; | ||
use std::thread; | ||
|
||
use seccompiler::{ | ||
apply_filter_all_threads, BpfProgram, SeccompAction, SeccompFilter, SeccompRule, | ||
}; | ||
use std::env::consts::ARCH; | ||
|
||
fn check_getpid_fails() { | ||
let pid = unsafe { libc::getpid() }; | ||
let errno = std::io::Error::last_os_error().raw_os_error().unwrap(); | ||
|
||
assert_eq!(pid, -1, "getpid should return -1 as set in SeccompFilter"); | ||
assert_eq!(errno, 0, "there should be no errors"); | ||
} | ||
|
||
#[test] | ||
/// Test seccomp's TSYNC functionality, which syncs the current filter to all threads in the | ||
/// process. | ||
fn test_tsync() { | ||
// These channels will block on send until the receiver has called recv. | ||
let (setup_tx, setup_rx) = sync_channel::<()>(0); | ||
let (finish_tx, finish_rx) = sync_channel::<()>(0); | ||
|
||
// first check getpid is working | ||
let pid = unsafe { libc::getpid() }; | ||
let errno = std::io::Error::last_os_error().raw_os_error().unwrap(); | ||
|
||
assert!(pid > 0, "getpid should return the actual pid"); | ||
assert_eq!(errno, 0, "there should be no errors"); | ||
|
||
// create two threads, one which applies the filter to all threads and another which tries | ||
// to call getpid. | ||
let seccomp_thread = thread::spawn(move || { | ||
let rules = vec![(libc::SYS_getpid, vec![])]; | ||
|
||
let rule_map: BTreeMap<i64, Vec<SeccompRule>> = rules.into_iter().collect(); | ||
|
||
// Build seccomp filter only disallowing getpid | ||
let filter = SeccompFilter::new( | ||
rule_map, | ||
SeccompAction::Allow, | ||
SeccompAction::Errno(1u32), | ||
ARCH.try_into().unwrap(), | ||
) | ||
.unwrap(); | ||
|
||
let filter: BpfProgram = filter.try_into().unwrap(); | ||
apply_filter_all_threads(&filter).unwrap(); | ||
|
||
// Verify seccomp is working in this thread | ||
check_getpid_fails(); | ||
|
||
// seccomp setup done, let the other thread start | ||
setup_tx.send(()).unwrap(); | ||
|
||
// don't close this thread until the other thread is done asserting. This way we can be | ||
// sure the thread that loaded the filter is definitely active when the other thread runs. | ||
finish_rx.recv().unwrap(); | ||
println!("exit seccomp thread"); | ||
}); | ||
|
||
let test_thread = thread::spawn(move || { | ||
// wait until seccomp setup is done | ||
setup_rx.recv().unwrap(); | ||
|
||
// Verify seccomp is working in this thread after disallowing it in other thread | ||
check_getpid_fails(); | ||
|
||
// let other thread know we've passed | ||
finish_tx.send(()).unwrap(); | ||
println!("exit io thread"); | ||
}); | ||
|
||
let seccomp_res = seccomp_thread.join(); | ||
assert!( | ||
seccomp_res.is_ok(), | ||
"seccomp thread failed: {:?}", | ||
seccomp_res.unwrap_err() | ||
); | ||
let test_res = test_thread.join(); | ||
assert!( | ||
test_res.is_ok(), | ||
"test thread failed: {:?}", | ||
test_res.unwrap_err() | ||
); | ||
|
||
// Verify seccomp is working in the parent thread as well | ||
check_getpid_fails(); | ||
} |