This repository has been 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: add landlock sandboxing #7303
Merged
+445
−95
Merged
Changes from 9 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
146e6e2
Begin adding landlock + test
mrcnski 950add0
Move PVF implementer's guide section to own page, document security
mrcnski e48605a
Implement test
mrcnski d1af7ee
Add some docs
mrcnski 3e5b6cd
Do some cleanup
mrcnski 39f2495
Fix typo
mrcnski e555165
Warn on host startup if landlock is not supported
mrcnski 30178c9
Clarify docs a bit
mrcnski c096284
Minor improvements
mrcnski 41d8d1a
Add some docs about determinism
mrcnski 6524c81
Address review comments (mainly add warning on landlock error)
mrcnski a9b2dfd
Update node/core/pvf/src/host.rs
mrcnski b9d8fc1
Update node/core/pvf/src/host.rs
mrcnski 609a82a
Merge branch 'master' into mrcnski/pvf-landlock
mrcnski e9b5c17
Fix unused fn
mrcnski 08d98e9
Update ABI docs to reflect latest discussions
mrcnski 2d72e31
Remove outdated notes
mrcnski e079ce5
Try to trigger new test-linux-oldkernel-stable job
mrcnski 3765203
Merge branch 'master' into mrcnski/pvf-landlock
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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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,141 @@ | ||
// Copyright (C) Parity Technologies (UK) Ltd. | ||
// This file is part of Polkadot. | ||
|
||
// Polkadot is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// Polkadot is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
//! Functionality for securing workers. | ||
//! | ||
//! This is needed because workers are used to compile and execute untrusted code (PVFs). | ||
|
||
/// The [landlock] docs say it best: | ||
/// | ||
/// > "Landlock is a security feature available since Linux 5.13. The goal is to enable to restrict | ||
/// ambient rights (e.g., global filesystem access) for a set of processes by creating safe security | ||
/// sandboxes as new security layers in addition to the existing system-wide access-controls. This | ||
/// kind of sandbox is expected to help mitigate the security impact of bugs, unexpected or | ||
/// malicious behaviors in applications. Landlock empowers any process, including unprivileged ones, | ||
/// to securely restrict themselves." | ||
/// | ||
/// [landlock]: https://docs.rs/landlock/latest/landlock/index.html | ||
#[cfg(target_os = "linux")] | ||
pub mod landlock { | ||
// Export for checking the status. | ||
pub use landlock::RulesetStatus; | ||
|
||
use landlock::{Access, AccessFs, Ruleset, RulesetAttr, RulesetError, ABI}; | ||
|
||
/// Version of landlock ABI. Use the latest version supported by our reference kernel version. | ||
/// | ||
/// - Reference kernel version: 5.16+ | ||
/// - ABI V1: 5.13 | ||
/// - ABI V2: 5.19 | ||
/// | ||
/// Please update these docs if they are out-of-date, and bump the ABI version to the minimum | ||
/// ABI supported by the reference kernel version. | ||
pub const LANDLOCK_ABI: ABI = ABI::V1; | ||
|
||
// TODO: <https://github.com/landlock-lsm/rust-landlock/issues/36> | ||
/// Returns to what degree landlock is enabled on the current Linux environment. | ||
pub fn get_status() -> Result<RulesetStatus, Box<dyn std::error::Error>> { | ||
match std::thread::spawn(|| try_restrict_thread()).join() { | ||
Ok(Ok(status)) => Ok(status), | ||
Ok(Err(ruleset_err)) => Err(ruleset_err.into()), | ||
Err(_err) => Err("a panic occurred in try_restrict_thread".into()), | ||
} | ||
} | ||
|
||
/// Returns a single bool indicating whether landlock is fully enabled on the current Linux | ||
/// environment. | ||
pub fn is_fully_enabled() -> bool { | ||
matches!(get_status(), Ok(RulesetStatus::FullyEnforced)) | ||
} | ||
|
||
/// Tries to restrict the current thread with the following landlock access controls: | ||
/// | ||
/// 1. all global filesystem access | ||
/// 2. ... more may be supported in the future. | ||
/// | ||
/// If landlock is not supported in the current environment this is simply a noop. | ||
/// | ||
/// # Returns | ||
/// | ||
/// The status of the restriction (whether it was fully, partially, or not-at-all enforced). | ||
pub fn try_restrict_thread() -> Result<RulesetStatus, RulesetError> { | ||
let status = Ruleset::new() | ||
.handle_access(AccessFs::from_all(LANDLOCK_ABI))? | ||
.create()? | ||
.restrict_self()?; | ||
Ok(status.ruleset) | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
use std::{fs, io::ErrorKind, thread}; | ||
|
||
#[test] | ||
fn restricted_thread_cannot_access_fs() { | ||
// TODO: This would be nice: <https://github.com/rust-lang/rust/issues/68007>. | ||
if !is_fully_enabled() { | ||
return | ||
} | ||
|
||
// Restricted thread cannot read from FS. | ||
let handle = thread::spawn(|| { | ||
// Write to a tmp file, this should succeed before landlock is applied. | ||
let text = "foo"; | ||
let tmpfile = tempfile::NamedTempFile::new().unwrap(); | ||
let path = tmpfile.path(); | ||
fs::write(path, text).unwrap(); | ||
let s = fs::read_to_string(path).unwrap(); | ||
assert_eq!(s, text); | ||
|
||
let status = try_restrict_thread().unwrap(); | ||
if !matches!(status, RulesetStatus::FullyEnforced) { | ||
panic!("Ruleset should be enforced since we checked if landlock is enabled"); | ||
} | ||
|
||
// Try to read from the tmp file after landlock. | ||
let result = fs::read_to_string(path); | ||
assert!(matches!( | ||
result, | ||
Err(err) if matches!(err.kind(), ErrorKind::PermissionDenied) | ||
)); | ||
}); | ||
|
||
assert!(handle.join().is_ok()); | ||
|
||
// Restricted thread cannot write to FS. | ||
let handle = thread::spawn(|| { | ||
let text = "foo"; | ||
let tmpfile = tempfile::NamedTempFile::new().unwrap(); | ||
let path = tmpfile.path(); | ||
|
||
let status = try_restrict_thread().unwrap(); | ||
if !matches!(status, RulesetStatus::FullyEnforced) { | ||
panic!("Ruleset should be enforced since we checked if landlock is enabled"); | ||
} | ||
|
||
// Try to write to the tmp file after landlock. | ||
let result = fs::write(path, text); | ||
assert!(matches!( | ||
result, | ||
Err(err) if matches!(err.kind(), ErrorKind::PermissionDenied) | ||
)); | ||
}); | ||
|
||
assert!(handle.join().is_ok()); | ||
} | ||
} | ||
} |
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, instead of simply really doing nothing, I think we should issue a warning that landlock is not available and for maximum security encourage the operator to upgrade their Kernel/make sure landlock is available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same for non Linux - a warning that the landlock sandboxing is not available would be a good idea, I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can emit a warning (once on host startup I think), but the way the validator guide is written right now, I'm not sure how much control a validator can have on their kernel version/configuration:
I guess we could recommend "try to find a VPS with landlock enabled", but unless we give specific recommendations, it might be hard to find this info.
For people not running on a VPS, I found a guide for enabling landlock, but I haven't tested it, and I'm not a Linux expert. I'm not sure we should be officially recommending random guides from the internet...
Advice would be really appreciated. Let me know what you think!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, so given the above, I'm not sure how actionable a warning would be. It could just be noise for most operators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found out that landlock is enabled by default on most distros including Ubuntu 22.04 LTS (what we recommend). And I don't see any reason why a VPS would explicitly opt-out of a security feature. So, we can simply emit a warning like this:
This comment was marked as duplicate.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a good idea, I've added it to #7073 (see description). I don't think we can mandate it right now because like half of validators are on too-old kernel versions (according to the visible telemetry data). We already need to announce that "secure mode" change in advance, maybe we can also mention that validators should upgrade to kernel 5.13+ to avoid running in "insecure mode". I will bug Will again to see if we can get that announcement going.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, makes sense then. So, keep the warning for now and make it mandatory at a later date.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed this makes sense, I would nevertheless suggest a soft launch:
Updating the wiki would be good as well, but is least likely to be read by already operating operators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eskimor I missed your comment before merging. Here's what we have now, let me know what needs a follow-up: