This repository was archived by the owner on Nov 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
PVF: Move landlock out of thread into process; add landlock exceptions #7580
Draft
mrcnski
wants to merge
16
commits into
master
Choose a base branch
from
mrcnski/pvf-sandbox-whole-process
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from 5 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
3cc75d0
Move landlock out of thread into process; add landlock exceptions
mrcnski 1af053c
Merge branch 'master' into mrcnski/pvf-sandbox-whole-process
mrcnski f34cec4
Add --cache-path cli param
mrcnski d416b57
Finishing touches
mrcnski f1e4381
Remove unneeded argument in test
mrcnski 49f4982
Fix compile error!
mrcnski 4fe842a
Remove some unnecessary unwraps
mrcnski 6d9c276
Add note about `extra_args`
mrcnski 69d15b4
Landlock: disallow listing directories
mrcnski d3231bd
Merge branch 'master' into mrcnski/pvf-sandbox-whole-process
mrcnski c5879b2
Only throw an error if landlock is enabled and expected to work
mrcnski 99761eb
Update Cargo.lock
mrcnski 75ff594
Update a docstring
mrcnski e00d0b4
Change root to be the artifact directory.
mrcnski 8807302
Merge branch 'master' into mrcnski/pvf-sandbox-whole-process
mrcnski cd41603
Experiment with pivot_root in child workers
mrcnski File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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 hidden or 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 |
---|---|---|
|
@@ -37,7 +37,7 @@ use polkadot_node_core_pvf_common::{ | |
}; | ||
use polkadot_parachain::primitives::ValidationResult; | ||
use std::{ | ||
path::PathBuf, | ||
path::{Path, PathBuf}, | ||
sync::{mpsc::channel, Arc}, | ||
time::Duration, | ||
}; | ||
|
@@ -117,14 +117,21 @@ async fn send_response(stream: &mut UnixStream, response: Response) -> io::Resul | |
/// | ||
/// # Parameters | ||
/// | ||
/// The `socket_path` specifies the path to the socket used to communicate with the host. The | ||
/// `node_version`, if `Some`, is checked against the worker version. A mismatch results in | ||
/// immediate worker termination. `None` is used for tests and in other situations when version | ||
/// check is not necessary. | ||
/// - `socket_path` specifies the path to the socket used to communicate with the host. | ||
/// | ||
/// - `node_version`, if `Some`, is checked against the `worker_version`. A mismatch results in | ||
/// immediate worker termination. `None` is used for tests and in other situations when version | ||
/// check is not necessary. | ||
/// | ||
/// - `worker_version`: see above | ||
/// | ||
/// - `cache_path` contains the expected cache path for artifacts and is used to provide a sandbox | ||
/// exception for landlock. | ||
pub fn worker_entrypoint( | ||
socket_path: &str, | ||
node_version: Option<&str>, | ||
worker_version: Option<&str>, | ||
cache_path: &Path, | ||
) { | ||
worker_event_loop( | ||
"execute", | ||
|
@@ -134,6 +141,36 @@ pub fn worker_entrypoint( | |
|mut stream| async move { | ||
let worker_pid = std::process::id(); | ||
|
||
// Try to enable landlock. | ||
{ | ||
#[cfg(target_os = "linux")] | ||
let landlock_status = { | ||
use polkadot_node_core_pvf_common::worker::security::landlock::{ | ||
path_beneath_rules, try_restrict_thread, Access, AccessFs, LANDLOCK_ABI, | ||
}; | ||
|
||
try_restrict_thread(path_beneath_rules( | ||
&[cache_path], | ||
AccessFs::from_read(LANDLOCK_ABI), | ||
)) | ||
.map(LandlockStatus::from_ruleset_status) | ||
.map_err(|e| e.to_string()) | ||
}; | ||
#[cfg(not(target_os = "linux"))] | ||
let landlock_status: Result<LandlockStatus, String> = Ok(LandlockStatus::NotEnforced); | ||
|
||
// TODO: return an error? | ||
// Log if landlock threw an error. | ||
if let Err(err) = landlock_status { | ||
gum::warn!( | ||
target: LOG_TARGET, | ||
%worker_pid, | ||
"error enabling landlock: {}", | ||
err | ||
); | ||
} | ||
} | ||
|
||
let handshake = recv_handshake(&mut stream).await?; | ||
let executor = Executor::new(handshake.executor_params).map_err(|e| { | ||
io::Error::new(io::ErrorKind::Other, format!("cannot create executor: {}", e)) | ||
|
@@ -148,9 +185,11 @@ pub fn worker_entrypoint( | |
artifact_path.display(), | ||
); | ||
|
||
if !artifact_path.starts_with(cache_path) { | ||
return Err(io::Error::new(io::ErrorKind::Other, format!("received an artifact path {artifact_path:?} that does not belong to expected artifact dir {cache_path:?}"))) | ||
} | ||
Comment on lines
+200
to
+202
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: I wonder if an io::Error is the most appropriate error here. To change it we would have to change the error type of this function (would need a new error kind) which would be a bit annoying. But since this would be a logic bug from our side it can be an |
||
|
||
// Get the artifact bytes. | ||
// | ||
// We do this outside the thread so that we can lock down filesystem access there. | ||
let compiled_artifact_blob = match std::fs::read(artifact_path) { | ||
Ok(bytes) => bytes, | ||
Err(err) => { | ||
|
@@ -185,22 +224,11 @@ pub fn worker_entrypoint( | |
let execute_thread = thread::spawn_worker_thread_with_stack_size( | ||
"execute thread", | ||
move || { | ||
// Try to enable landlock. | ||
#[cfg(target_os = "linux")] | ||
let landlock_status = polkadot_node_core_pvf_common::worker::security::landlock::try_restrict_thread() | ||
.map(LandlockStatus::from_ruleset_status) | ||
.map_err(|e| e.to_string()); | ||
#[cfg(not(target_os = "linux"))] | ||
let landlock_status: Result<LandlockStatus, String> = Ok(LandlockStatus::NotEnforced); | ||
|
||
( | ||
validate_using_artifact( | ||
&compiled_artifact_blob, | ||
¶ms, | ||
executor_2, | ||
cpu_time_start, | ||
), | ||
landlock_status, | ||
validate_using_artifact( | ||
&compiled_artifact_blob, | ||
¶ms, | ||
executor_2, | ||
cpu_time_start, | ||
) | ||
}, | ||
Arc::clone(&condvar), | ||
|
@@ -213,24 +241,9 @@ pub fn worker_entrypoint( | |
let response = match outcome { | ||
WaitOutcome::Finished => { | ||
let _ = cpu_time_monitor_tx.send(()); | ||
let (result, landlock_status) = execute_thread.join().unwrap_or_else(|e| { | ||
( | ||
Response::Panic(stringify_panic_payload(e)), | ||
Ok(LandlockStatus::Unavailable), | ||
) | ||
}); | ||
|
||
// Log if landlock threw an error. | ||
if let Err(err) = landlock_status { | ||
gum::warn!( | ||
target: LOG_TARGET, | ||
%worker_pid, | ||
"error enabling landlock: {}", | ||
err | ||
); | ||
} | ||
|
||
result | ||
execute_thread | ||
.join() | ||
.unwrap_or_else(|e| Response::Panic(stringify_panic_payload(e))) | ||
}, | ||
// If the CPU thread is not selected, we signal it to end, the join handle is | ||
// dropped and the thread will finish in the background. | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.