-
Notifications
You must be signed in to change notification settings - Fork 112
Add LinuxContainerExecutor
to Wasmtime and WasmEdge shims
#156
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
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
558732d
implements can_handle in wasmtime executor.
Mossaka 8b49b0c
test: add a python container to wasmtime shim for testing
Mossaka bf71029
feat: add docker buildx to CI
Mossaka 2827e2a
add --load to test/py-flask to fix the CI issue
Mossaka bde59f0
feat: removed py-flask image and use hello-world image from docker.io
Mossaka e24adc0
refactor: move reset_stdio method to wasitest module
Mossaka 2c7cc73
Merge remote-tracking branch 'upstream/main' into issue64
Mossaka 0f93233
fix: changed the hello-world image to nginx for testing in k8s
Mossaka 6a86100
feat: implement can_handle for default executor
Mossaka 01d4a64
refactor: restructure the files. adding a new executors mod
Mossaka 11403c2
Merge remote-tracking branch 'upstream/main' into issue64
Mossaka eb9f6e9
fix: removed the extra lines in CI
Mossaka ef1b387
fix: fetch nginx from docker.io in k8s
Mossaka 2f07ec5
fix: remove never pull policy from k8s
Mossaka 70668d5
feat: implement check for shebang in the linux executor
Mossaka 7116634
isolate test/k3s deploy.yaml file since wasmedge doesn't have default…
Mossaka f5cca54
Merge remote-tracking branch 'upstream/main' into issue64
Mossaka a5dd8be
simplify the logic in verifying ELF file and shebang and apply review…
Mossaka f46aa5f
simplify the can_handle logic in wasi executor
Mossaka 3dee7bf
pass std i/o to default executor
Mossaka 23ff239
Merge branch 'main' into issue64
Mossaka bd4f5b8
feat: add container executor to wasmedge shim
Mossaka 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,6 @@ | |
pub mod sandbox; | ||
|
||
pub mod services; | ||
|
||
#[cfg(feature = "libcontainer")] | ||
pub mod libcontainer_instance; |
133 changes: 133 additions & 0 deletions
133
crates/containerd-shim-wasm/src/libcontainer_instance/container_executor.rs
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,133 @@ | ||
use crate::sandbox::oci; | ||
use libcontainer::workload::default::DefaultExecutor; | ||
use libcontainer::workload::{Executor, ExecutorError}; | ||
use nix::unistd::{dup, dup2}; | ||
|
||
use libc::{STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO}; | ||
use oci_spec::runtime::Spec; | ||
use std::io::Read; | ||
use std::{fs::OpenOptions, os::fd::RawFd, path::PathBuf}; | ||
|
||
#[derive(Default)] | ||
pub struct LinuxContainerExecutor { | ||
stdin: Option<RawFd>, | ||
stdout: Option<RawFd>, | ||
stderr: Option<RawFd>, | ||
default_executor: DefaultExecutor, | ||
} | ||
|
||
impl LinuxContainerExecutor { | ||
pub fn new(stdin: Option<RawFd>, stdout: Option<RawFd>, stderr: Option<RawFd>) -> Self { | ||
Self { | ||
stdin, | ||
stdout, | ||
stderr, | ||
..Default::default() | ||
} | ||
} | ||
} | ||
|
||
impl Executor for LinuxContainerExecutor { | ||
fn exec(&self, spec: &Spec) -> Result<(), ExecutorError> { | ||
redirect_io(self.stdin, self.stdout, self.stderr).map_err(|err| { | ||
log::error!("failed to redirect io: {}", err); | ||
ExecutorError::Other(format!("failed to redirect io: {}", err)) | ||
})?; | ||
self.default_executor.exec(spec) | ||
} | ||
|
||
fn can_handle(&self, spec: &Spec) -> bool { | ||
let args = oci::get_args(spec); | ||
|
||
if args.is_empty() { | ||
return false; | ||
} | ||
|
||
let executable = args[0].as_str(); | ||
|
||
// mostly follows youki's verify_binary implementation | ||
// https://github.com/containers/youki/blob/2d6fd7650bb0f22a78fb5fa982b5628f61fe25af/crates/libcontainer/src/process/container_init_process.rs#L106 | ||
let path = if executable.contains('/') { | ||
PathBuf::from(executable) | ||
} else { | ||
let path = std::env::var("PATH").unwrap_or_default(); | ||
// check each path in $PATH | ||
let mut found = false; | ||
let mut found_path = PathBuf::default(); | ||
for p in path.split(':') { | ||
let path = PathBuf::from(p).join(executable); | ||
if path.exists() { | ||
found = true; | ||
found_path = path; | ||
break; | ||
} | ||
} | ||
if !found { | ||
return false; | ||
} | ||
found_path | ||
}; | ||
|
||
// check execute permission | ||
use std::os::unix::fs::PermissionsExt; | ||
let metadata = path.metadata(); | ||
if metadata.is_err() { | ||
log::info!("failed to get metadata of {:?}", path); | ||
return false; | ||
} | ||
let metadata = metadata.unwrap(); | ||
let permissions = metadata.permissions(); | ||
if !metadata.is_file() || permissions.mode() & 0o001 == 0 { | ||
log::info!("{} is not a file or has no execute permission", executable); | ||
return false; | ||
} | ||
|
||
// check the shebang and ELF magic number | ||
// https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header | ||
let mut buffer = [0; 4]; | ||
|
||
let file = OpenOptions::new().read(true).open(path); | ||
if file.is_err() { | ||
log::info!("failed to open {}", executable); | ||
return false; | ||
} | ||
let mut file = file.unwrap(); | ||
match file.read_exact(&mut buffer) { | ||
Ok(_) => {} | ||
Err(err) => { | ||
log::info!("failed to read shebang of {}: {}", executable, err); | ||
return false; | ||
} | ||
} | ||
match buffer { | ||
// ELF magic number | ||
[0x7f, 0x45, 0x4c, 0x46] => true, | ||
// shebang | ||
[0x23, 0x21, ..] => true, | ||
_ => { | ||
log::info!("{} is not a valid script or elf file", executable); | ||
false | ||
} | ||
} | ||
} | ||
|
||
fn name(&self) -> &'static str { | ||
self.default_executor.name() | ||
} | ||
} | ||
|
||
fn redirect_io(stdin: Option<i32>, stdout: Option<i32>, stderr: Option<i32>) -> anyhow::Result<()> { | ||
if let Some(stdin) = stdin { | ||
dup(STDIN_FILENO)?; | ||
dup2(stdin, STDIN_FILENO)?; | ||
} | ||
if let Some(stdout) = stdout { | ||
dup(STDOUT_FILENO)?; | ||
dup2(stdout, STDOUT_FILENO)?; | ||
} | ||
if let Some(stderr) = stderr { | ||
dup(STDERR_FILENO)?; | ||
dup2(stderr, STDERR_FILENO)?; | ||
} | ||
Ok(()) | ||
} |
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,5 @@ | ||
pub mod container_executor; | ||
pub mod instance; | ||
|
||
pub use container_executor::LinuxContainerExecutor; | ||
pub use instance::LibcontainerInstance; |
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
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
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.