Skip to content

Commit

Permalink
PVF host: Make unavailable security features print a warning
Browse files Browse the repository at this point in the history
The warning should say that this will soon be required to run securely, with a
link to the announcement.

See #1444
  • Loading branch information
mrcnski committed Nov 9, 2023
1 parent d347d68 commit 7bb717a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 51 deletions.
1 change: 1 addition & 0 deletions polkadot/node/core/pvf/src/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ pub async fn start(config: Config, metrics: Metrics) -> (ValidationHost, impl Fu
// Run checks for supported security features once per host startup. Warn here if not enabled.
let security_status = {
// TODO: add check that syslog is available and that seccomp violations are logged?
security::check_secure_mode_platform_requirement();
let (can_enable_landlock, can_enable_seccomp, can_unshare_user_namespace_and_change_root) = join!(
security::check_landlock(&config.prepare_worker_program_path),
security::check_seccomp(&config.prepare_worker_program_path),
Expand Down
133 changes: 82 additions & 51 deletions polkadot/node/core/pvf/src/security.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,40 @@ use tokio::{
io::{AsyncReadExt, AsyncSeekExt, SeekFrom},
};

const SECURE_MODE_ANNOUNCEMENT: &'static str =
"In the next release this will be a hard error by default. More information: \
https://github.com/w3f/polkadot-wiki/issues/4881";

/// Warns if a secure validator cannot be built for the target OS and architecture.
pub fn check_secure_mode_platform_requirement() {
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
return ()
} else {
let msg = "Secure validators are only supported on CPUs from the x86_64 family (usually Intel or AMD).";
}
}
} else {
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
let msg = "Secure validators are only supported on Linux.";
} else {
let msg = "Secure validators are only supported on Linux and on CPUs from the x86_64 family (usually Intel or AMD).";
}
}
}
};

gum::warn!(
target: LOG_TARGET,
"{} {}",
msg,
SECURE_MODE_ANNOUNCEMENT
);
}

/// Check if we can sandbox the root and emit a warning if not.
///
/// We do this check by spawning a new process and trying to sandbox it. To get as close as possible
Expand All @@ -32,25 +66,20 @@ pub async fn check_can_unshare_user_namespace_and_change_root(
) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
match tokio::process::Command::new(prepare_worker_program_path)
let msg = match tokio::process::Command::new(prepare_worker_program_path)
.arg("--check-can-unshare-user-namespace-and-change-root")
.output()
.await
{
Ok(output) if output.status.success() => true,
Ok(output) if output.status.success() => return true,
Ok(output) => {
let stderr = std::str::from_utf8(&output.stderr)
.expect("child process writes a UTF-8 string to stderr; qed")
.trim();
gum::warn!(
target: LOG_TARGET,
?prepare_worker_program_path,
// Docs say to always print status using `Display` implementation.
status = %output.status,
%stderr,
"Cannot unshare user namespace and change root, which are Linux-specific kernel security features. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running with support for unsharing user namespaces for maximum security."
);
false
format!(
"Cannot unshare user namespace and change root, which are Linux-specific kernel security features. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running with support for unsharing user namespaces for maximum security. Error: {}",
stderr
)
},
Err(err) => {
gum::warn!(
Expand All @@ -59,17 +88,21 @@ pub async fn check_can_unshare_user_namespace_and_change_root(
"Could not start child process: {}",
err
);
false
return false
},
}
};
} else {
gum::warn!(
target: LOG_TARGET,
"Cannot unshare user namespace and change root, which are Linux-specific kernel security features. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running on Linux with support for unsharing user namespaces for maximum security."
);
false
let msg = "Cannot unshare user namespace and change root, which are Linux-specific kernel security features. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running on Linux with support for unsharing user namespaces for maximum security.";
}
}

gum::warn!(
target: LOG_TARGET,
"{} {}",
msg,
SECURE_MODE_ANNOUNCEMENT
);
false
}

/// Check if landlock is supported and emit a warning if not.
Expand All @@ -83,23 +116,19 @@ pub async fn check_landlock(
) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
match tokio::process::Command::new(prepare_worker_program_path)
let msg = match tokio::process::Command::new(prepare_worker_program_path)
.arg("--check-can-enable-landlock")
.status()
.await
{
Ok(status) if status.success() => true,
Ok(status) if status.success() => return true,
Ok(status) => {
let abi =
polkadot_node_core_pvf_common::worker::security::landlock::LANDLOCK_ABI as u8;
gum::warn!(
target: LOG_TARGET,
?prepare_worker_program_path,
?status,
%abi,
"Cannot fully enable landlock, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider upgrading the kernel version for maximum security."
);
false
format!(
"Cannot fully enable landlock, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider upgrading the kernel version for maximum security. Landlock ABI: {}",
abi
)
},
Err(err) => {
gum::warn!(
Expand All @@ -108,17 +137,21 @@ pub async fn check_landlock(
"Could not start child process: {}",
err
);
false
return false
},
}
};
} else {
gum::warn!(
target: LOG_TARGET,
"Cannot enable landlock, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running on Linux with landlock support for maximum security."
);
false
let msg = "Cannot enable landlock, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running on Linux with landlock support for maximum security.";
}
}

gum::warn!(
target: LOG_TARGET,
"{} {}",
msg,
SECURE_MODE_ANNOUNCEMENT
);
false
}

/// Check if seccomp is supported and emit a warning if not.
Expand All @@ -132,20 +165,14 @@ pub async fn check_seccomp(
) -> bool {
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
match tokio::process::Command::new(prepare_worker_program_path)
let msg = match tokio::process::Command::new(prepare_worker_program_path)
.arg("--check-can-enable-seccomp")
.status()
.await
{
Ok(status) if status.success() => true,
Ok(status) if status.success() => return true,
Ok(status) => {
gum::warn!(
target: LOG_TARGET,
?prepare_worker_program_path,
?status,
"Cannot fully enable seccomp, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider upgrading the kernel version for maximum security."
);
false
"Cannot fully enable seccomp, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider upgrading the kernel version for maximum security."
},
Err(err) => {
gum::warn!(
Expand All @@ -154,17 +181,21 @@ pub async fn check_seccomp(
"Could not start child process: {}",
err
);
false
return false
},
}
};
} else {
gum::warn!(
target: LOG_TARGET,
"Cannot enable seccomp, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running on Linux with seccomp support for maximum security."
);
false
let msg = "Cannot enable seccomp, a Linux-specific kernel security feature. Running validation of malicious PVF code has a higher risk of compromising this machine. Consider running on Linux with seccomp support for maximum security.";
}
}

gum::warn!(
target: LOG_TARGET,
"{} {}",
msg,
SECURE_MODE_ANNOUNCEMENT
);
false
}

const AUDIT_LOG_PATH: &'static str = "/var/log/audit/audit.log";
Expand Down

0 comments on commit 7bb717a

Please sign in to comment.