-
Notifications
You must be signed in to change notification settings - Fork 2.3k
feat(jailer): add Landlock LSM sandboxing via --landlock flag #5771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
pavitrabhalla
wants to merge
11
commits into
firecracker-microvm:main
Choose a base branch
from
superserve-ai:pavitrabhalla/issue-5513-impl
base: main
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.
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
cdb6bbe
feat(jailer): add Landlock LSM sandboxing via --landlock flag
pavitrabhalla 212aef7
style(jailer): fix long lines in landlock module
pavitrabhalla ba3b9a8
docs(changelog): add entry for jailer --landlock flag
pavitrabhalla 91b4002
fix(jailer): add missing landlock field in test ArgVals initializer
pavitrabhalla c9dd4ad
style: apply mdformat to CHANGELOG.md
pavitrabhalla 309e302
fix(jailer): replace assert!(_.is_ok/err()) with unwrap in tests
pavitrabhalla 5e16265
chore(deps): update Cargo.lock for landlock dependency
pavitrabhalla 2287d75
chore: trigger CI
pavitrabhalla 7d56be5
Merge branch 'main' into pavitrabhalla/issue-5513-impl
pavitrabhalla 97767e6
fix(jailer): address upstream PR review feedback on Landlock implemen…
pavitrabhalla 53f29e1
docs(jailer): add official Landlock doc link in module comment
pavitrabhalla 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
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 |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| //! Landlock LSM integration for the Firecracker jailer. | ||
| //! | ||
| //! [Landlock](https://docs.kernel.org/userspace-api/landlock.html) is a Linux security module | ||
| //! (available since kernel 5.13) that | ||
| //! allows a process to restrict its own file system access. The jailer uses it as a | ||
| //! defense-in-depth mechanism: even if a guest VM escapes the pivot_root chroot, the Landlock | ||
| //! rules—applied before the exec—prevent Firecracker from accessing files outside the jail | ||
| //! directory. | ||
| //! | ||
| //! Usage: | ||
| //! 1. Call [`prepare_ruleset`] **before** `chroot()` to open a file descriptor referencing the | ||
| //! jail directory by inode. The inode reference survives `pivot_root`. | ||
| //! 2. After all post-chroot setup is done, call [`enforce`] on the returned ruleset right before | ||
| //! `exec`. The restrictions are inherited by the exec'd process. | ||
|
|
||
| use std::path::Path; | ||
|
|
||
| use landlock::{ | ||
| ABI, Access, AccessFs, PathBeneath, PathFd, Ruleset, RulesetAttr, RulesetCreated, | ||
| RulesetCreatedAttr, | ||
| }; | ||
|
|
||
| use crate::JailerError; | ||
|
|
||
| /// Create a Landlock ruleset that grants all file-system access rights within `jail_dir` and | ||
| /// denies everything outside. | ||
| /// | ||
| /// Must be called **before** `chroot()`/`pivot_root()` so that the `PathFd` captures the inode | ||
| /// of the jail directory while it is still reachable by its host path. The returned | ||
| /// [`RulesetCreated`] holds the open `PathFd` and can safely be passed across the `pivot_root` | ||
| /// boundary. | ||
| /// | ||
| /// # Errors | ||
| /// | ||
| /// Returns [`JailerError::Landlock`] if the kernel does not support Landlock, | ||
| /// if `jail_dir` cannot be opened, or if any ruleset syscall fails. | ||
| pub fn prepare_ruleset(jail_dir: &Path) -> Result<RulesetCreated, JailerError> { | ||
| let abi = ABI::V4; | ||
|
|
||
| let path_fd = PathFd::new(jail_dir).map_err(|err| { | ||
| JailerError::Landlock(format!( | ||
| "Failed to open Landlock path fd for {:?}: {}", | ||
| jail_dir, err | ||
| )) | ||
| })?; | ||
|
|
||
| Ruleset::default() | ||
| .handle_access(AccessFs::from_all(abi)) | ||
| .map_err(|err| JailerError::Landlock(format!("Failed to create Landlock ruleset: {err}")))? | ||
| .create() | ||
| .map_err(|err| JailerError::Landlock(format!("Failed to create Landlock ruleset: {err}")))? | ||
| .add_rule(PathBeneath::new(path_fd, AccessFs::from_all(abi))) | ||
| .map_err(|err| JailerError::Landlock(format!("Failed to add Landlock rule: {err}"))) | ||
| } | ||
|
|
||
| /// Enforce a prepared Landlock ruleset on the current thread. | ||
| /// | ||
| /// The restrictions are inherited across `exec`, so calling this right before `execve` will | ||
| /// confine the jailed Firecracker process to only the paths allowed by the ruleset. | ||
| /// | ||
| /// # Errors | ||
| /// | ||
| /// Returns [`JailerError::Landlock`] if `restrict_self` fails. | ||
| pub fn enforce(ruleset: RulesetCreated) -> Result<(), JailerError> { | ||
| ruleset.restrict_self().map_err(|err| { | ||
| JailerError::Landlock(format!("Failed to enforce Landlock ruleset: {err}")) | ||
| })?; | ||
| Ok(()) | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use landlock::CompatLevel; | ||
| use vmm_sys_util::tempdir::TempDir; | ||
|
|
||
| use super::*; | ||
|
|
||
| /// Returns true if the running kernel supports Landlock (any ABI version). | ||
| /// | ||
| /// Uses the Landlock crate's own compatibility check (via `HardRequirement`) rather than | ||
| /// parsing the kernel version string, since Landlock may be backported to older kernels. | ||
| fn is_landlock_supported() -> bool { | ||
| Ruleset::default() | ||
| .set_compatibility(CompatLevel::HardRequirement) | ||
| .handle_access(AccessFs::from_all(ABI::V1)) | ||
| .and_then(|r| r.create()) | ||
| .is_ok() | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_prepare_ruleset_valid_dir() { | ||
| if !is_landlock_supported() { | ||
| // Skip on kernels that don't support Landlock. | ||
| return; | ||
| } | ||
| let tmp = TempDir::new_with_prefix("landlock_test_").unwrap(); | ||
| prepare_ruleset(tmp.as_path()).unwrap(); | ||
| } | ||
|
|
||
| #[test] | ||
| fn test_prepare_ruleset_nonexistent_dir() { | ||
| let result = prepare_ruleset(Path::new("/nonexistent/path/for/landlock/test")); | ||
| result.unwrap_err(); | ||
| } | ||
| } | ||
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
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.