Skip to content
This repository was archived by the owner on Nov 10, 2022. It is now read-only.

Commit 4b318f3

Browse files
committed
Add --module-on-fd CLI arg
This patch brings back the ability to load the module to be run from an open file descriptor, which must be 3 or higher (so as not to collide with stdin/stdout/stderr). It also tweaks CLI parsing slightly - the '--' separating wasmldr args from module args is now required. Signed-off-by: Will Woods <[email protected]>
1 parent 2a60abc commit 4b318f3

File tree

5 files changed

+73
-18
lines changed

5 files changed

+73
-18
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ log = "0.4"
3030
wasmparser = "0.80"
3131
structopt = "0.3.22"
3232
anyhow = "1.0"
33+
cfg-if = "1.0"
3334

3435
[build-dependencies]
3536
wat = "1.0"

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,9 @@ $ RUST_LOG=enarx_wasmldr=info RUST_BACKTRACE=1 cargo run return_1.wasm
2424
]
2525
```
2626

27-
On Unix platforms, the command can also read the workload from the
28-
file descriptor (3):
27+
On Unix platforms, the command can also read the workload from an open file descriptor:
2928
```console
30-
$ RUST_LOG=enarx_wasmldr=info RUST_BACKTRACE=1 cargo run 3< return_1.wasm
29+
$ RUST_LOG=enarx_wasmldr=info RUST_BACKTRACE=1 cargo run -- --module-on-fd=3 3< return_1.wasm
3130
```
3231

3332

src/cli.rs

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@
22

33
#![allow(missing_docs, unused_variables)] // This is a work-in-progress, so...
44

5+
use anyhow::{bail, Result};
56
use structopt::{clap::AppSettings, StructOpt};
67

7-
use anyhow::{bail, Result};
88
use std::path::PathBuf;
9+
use std::str::FromStr;
10+
11+
#[cfg(unix)]
12+
use std::os::unix::io::RawFd;
913

10-
// The main StructOpt for running `wasmldr` directly
14+
// The main StructOpt for CLI options
1115
#[derive(StructOpt, Debug)]
12-
#[structopt(setting=AppSettings::TrailingVarArg)]
16+
#[structopt(
17+
setting = AppSettings::DeriveDisplayOrder,
18+
setting = AppSettings::UnifiedHelpMessage,
19+
)]
20+
/// Enarx Keep Configurator and WebAssembly Loader
1321
pub struct RunOptions {
1422
/// Pass an environment variable to the program
1523
#[structopt(
@@ -25,15 +33,24 @@ pub struct RunOptions {
2533
#[structopt(long, value_name = "FUNCTION")]
2634
invoke: Option<String>,
2735

36+
#[cfg(unix)]
37+
/// Load WebAssembly module from the given FD (must be >=3)
38+
#[structopt(long, value_name = "FD", parse(try_from_str = parse_module_fd))]
39+
pub module_on_fd: Option<RawFd>,
40+
2841
// TODO: --inherit-env
2942
// TODO: --stdin, --stdout, --stderr
3043
/// Path of the WebAssembly module to run
31-
#[structopt(index = 1, required = true, value_name = "MODULE", parse(from_os_str))]
32-
pub module: PathBuf,
44+
#[structopt(
45+
index = 1,
46+
required_unless = "module-on-fd",
47+
value_name = "MODULE",
48+
parse(from_os_str)
49+
)]
50+
pub module: Option<PathBuf>,
3351

34-
// NOTE: this has to come last for TrailingVarArg
3552
/// Arguments to pass to the WebAssembly module
36-
#[structopt(value_name = "ARGS")]
53+
#[structopt(value_name = "ARGS", last = true)]
3754
pub args: Vec<String>,
3855
}
3956

@@ -44,3 +61,11 @@ fn parse_env_var(s: &str) -> Result<(String, String)> {
4461
}
4562
Ok((parts[0].to_owned(), parts[1].to_owned()))
4663
}
64+
65+
fn parse_module_fd(s: &str) -> Result<RawFd> {
66+
let fd = RawFd::from_str(s)?;
67+
if fd <= 2 {
68+
bail!("FD must be >= 3");
69+
}
70+
Ok(fd)
71+
}

src/main.rs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,9 @@
1919
//! ]
2020
//! ```
2121
//!
22-
//! On Unix platforms, the command can also read the workload from the
23-
//! file descriptor (3):
22+
//! On Unix platforms, the command can also read the workload from an open file descriptor:
2423
//! ```console
25-
//! $ RUST_LOG=enarx_wasmldr=info RUST_BACKTRACE=1 cargo run 3< return_1.wasm
24+
//! $ RUST_LOG=enarx_wasmldr=info RUST_BACKTRACE=1 cargo run -- --module-on-fd=3 3< return_1.wasm
2625
//! ```
2726
//!
2827
#![deny(missing_docs)]
@@ -31,14 +30,21 @@
3130
mod cli;
3231
mod workload;
3332

33+
use anyhow::{Context, Result};
34+
use cfg_if::cfg_if;
3435
use log::{debug, info};
3536
use structopt::StructOpt;
3637

3738
use std::fs::File;
3839
use std::io::Read;
3940

40-
fn main() {
41-
// Initialize the logger, taking settings from the default env vars
41+
#[cfg(unix)]
42+
use std::os::unix::io::FromRawFd;
43+
44+
fn main() -> Result<()> {
45+
// Initialize the logger, taking filtering and style settings from the
46+
// default env vars (RUST_LOG and RUST_LOG_STYLE).
47+
// The log target is the default target (stderr), so no files get opened.
4248
env_logger::Builder::from_default_env().init();
4349

4450
info!("version {} starting up", env!("CARGO_PKG_VERSION"));
@@ -47,9 +53,30 @@ fn main() {
4753
let opts = cli::RunOptions::from_args();
4854
info!("opts: {:#?}", opts);
4955

50-
info!("reading {:?}", opts.module);
51-
// TODO: don't just panic here...
52-
let mut reader = File::open(&opts.module).expect("Unable to open file");
56+
cfg_if! {
57+
if #[cfg(unix)] {
58+
let mut reader = match opts.module_on_fd {
59+
Some(fd) => {
60+
info!("reading module from fd {:?}", fd);
61+
// SAFETY: unsafe if something is using the given fd.
62+
// parse_module_fd() enforces fd >= 3, and nothing above
63+
// opens/duplicates new file descriptors, so we're OK.
64+
unsafe { File::from_raw_fd(fd) }
65+
},
66+
None => {
67+
let path = opts.module.expect("required_unless failure");
68+
info!("reading module from {:?}", path);
69+
File::open(&path)
70+
.with_context(|| format!("failed opening {:?}", path))?
71+
},
72+
};
73+
} else {
74+
let path = opts.module.expect("missing required arg");
75+
info!("reading module from {:?}", path);
76+
let mut reader = File::open(&path)
77+
.with_context(|| format!("failed opening {:?}", path))?;
78+
}
79+
}
5380

5481
let mut bytes = Vec::new();
5582
reader
@@ -65,4 +92,6 @@ fn main() {
6592
info!("got result: {:#?}", result);
6693
// TODO: exit with the resulting code, if the result is a return code
6794
// FUTURE: produce attestation report here
95+
96+
Ok(())
6897
}

0 commit comments

Comments
 (0)