diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c8c5cc56b..d36172752 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -115,7 +115,7 @@ jobs: uses: actions/checkout@v3 with: repository: 'veracruz-project/video-object-detection' - ref: '20230704' + #ref: '20230704' submodules: recursive set-safe-directory: true - name: Build diff --git a/crates/examples/rust-examples/aesctr-native/src/main.rs b/crates/examples/rust-examples/aesctr-native/src/main.rs index 2b5637672..a299de866 100644 --- a/crates/examples/rust-examples/aesctr-native/src/main.rs +++ b/crates/examples/rust-examples/aesctr-native/src/main.rs @@ -57,13 +57,15 @@ fn main() -> anyhow::Result<()> { let aes_ctr_enc_input = AesCtrInput { key, iv, - input_path: PathBuf::from("/output/data.dat"), - output_path: PathBuf::from("/output/enc.dat"), + input_path: PathBuf::from("./output/data.dat"), + output_path: PathBuf::from("./output/enc.dat"), is_encryption: true, }; write(&aes_ctr_enc_input.input_path, input)?; let aes_ctr_enc_input_bytes = postcard::to_allocvec(&aes_ctr_enc_input)?; - write("/services/aesctr.dat", aes_ctr_enc_input_bytes)?; + write("/tmp/aes/input", aes_ctr_enc_input_bytes)?; + // wait the service finish + let _ = read("/tmp/aes/output"); let output = read(aes_ctr_enc_input.output_path)?; if output != expected_output { failed = true; @@ -82,20 +84,22 @@ fn main() -> anyhow::Result<()> { let aes_ctr_enc_input = AesCtrInput { key, iv, - input_path: PathBuf::from("/output/data.dat"), - output_path: PathBuf::from("/output/dec.dat"), + input_path: PathBuf::from("./output/data.dat"), + output_path: PathBuf::from("./output/dec.dat"), is_encryption: false, }; write(&aes_ctr_enc_input.input_path, input)?; let aes_ctr_enc_input_bytes = postcard::to_allocvec(&aes_ctr_enc_input)?; - write("/services/aesctr.dat", aes_ctr_enc_input_bytes)?; + write("/tmp/aes/input", aes_ctr_enc_input_bytes)?; + // wait the service finish + let _ = read("/tmp/aes/output"); let output = read(aes_ctr_enc_input.output_path)?; if output != expected_output { failed = true; } if !failed { - write("/output/aesctr_native_pass.txt", [])?; + write("./output/aesctr_native_pass.txt", [])?; } Ok(()) } diff --git a/crates/examples/rust-examples/audio-event-triangulation/src/main.rs b/crates/examples/rust-examples/audio-event-triangulation/src/main.rs index 130ef66b6..312c852e9 100644 --- a/crates/examples/rust-examples/audio-event-triangulation/src/main.rs +++ b/crates/examples/rust-examples/audio-event-triangulation/src/main.rs @@ -147,7 +147,7 @@ fn main() -> anyhow::Result<()> { // an input errors let mut raw_events = Vec::new(); for i in 0.. { - let filename = format!("/input-{}", i); + let filename = format!("./input-{}", i); let event = match fs::read(filename) { Ok(event) => event, Err(err) => match err.kind() { @@ -172,6 +172,6 @@ fn main() -> anyhow::Result<()> { let raw_location = encode_location(location); // write our output through libveracruz - fs::write("/output", &raw_location)?; + fs::write("./output", &raw_location)?; Ok(()) } diff --git a/crates/examples/rust-examples/file-seek/src/main.rs b/crates/examples/rust-examples/file-seek/src/main.rs index 7c3914079..8d9eb29d8 100644 --- a/crates/examples/rust-examples/file-seek/src/main.rs +++ b/crates/examples/rust-examples/file-seek/src/main.rs @@ -17,8 +17,8 @@ use anyhow; use std::{fs::File, io::prelude::*, io::SeekFrom}; -const INPUT_FILENAME: &'static str = "/input/README.md"; -const OUTPUT_FILENAME: &'static str = "/output/NEW_README.md"; +const INPUT_FILENAME: &'static str = "./input/README.markdown"; +const OUTPUT_FILENAME: &'static str = "./output/NEW_README.markdown"; fn main() -> anyhow::Result<()> { let mut f = File::open(INPUT_FILENAME)?; diff --git a/crates/examples/rust-examples/huffman-encoding/src/main.rs b/crates/examples/rust-examples/huffman-encoding/src/main.rs index b5159b929..c1d0c3791 100644 --- a/crates/examples/rust-examples/huffman-encoding/src/main.rs +++ b/crates/examples/rust-examples/huffman-encoding/src/main.rs @@ -19,8 +19,8 @@ use anyhow::{self, Ok}; use std::{collections::HashMap, fs}; -const INPUT_FILENAME: &'static str = "/input/hello-world-1.dat"; -const OUTPUT_FILENAME: &'static str = "/output/encoded_output.dat"; +const INPUT_FILENAME: &'static str = "./input/hello-world-1.dat"; +const OUTPUT_FILENAME: &'static str = "./output/encoded_output.dat"; type Link = Option>; diff --git a/crates/examples/rust-examples/idash2017-logistic-regression/src/main.rs b/crates/examples/rust-examples/idash2017-logistic-regression/src/main.rs index 027c05162..7e9696582 100644 --- a/crates/examples/rust-examples/idash2017-logistic-regression/src/main.rs +++ b/crates/examples/rust-examples/idash2017-logistic-regression/src/main.rs @@ -285,7 +285,7 @@ fn true_ip(lhs: &[f64], rhs: &[f64]) -> anyhow::Result { /// them together into a single compound dataset, then trains a logistic regressor on this new /// dataset. Input and output are assumed to be encoded in Postcard. fn main() -> anyhow::Result<()> { - for path in fs::read_dir("/input/idash2017")? { + for path in fs::read_dir("./input/idash2017")? { let path = path?.path(); println!("path in: {:?}", path); let file_name = path.file_name().ok_or(anyhow!("cannot get file name"))?; @@ -302,7 +302,8 @@ fn main() -> anyhow::Result<()> { )?; println!("result: {:?}, {:?}, {:?}", w_data, correct, auc); let result_encode = postcard::to_allocvec::<(Vec, f64, f64)>(&(w_data, correct, auc))?; - let mut output = PathBuf::from("/output/idash2017/"); + fs::create_dir_all("./output/idash2017/")?; + let mut output = PathBuf::from("./output/idash2017/"); output.push(file_name); println!("output {:?}", output); std::fs::OpenOptions::new() diff --git a/crates/examples/rust-examples/image-processing/src/main.rs b/crates/examples/rust-examples/image-processing/src/main.rs index 056acaaf0..69fdcc54b 100644 --- a/crates/examples/rust-examples/image-processing/src/main.rs +++ b/crates/examples/rust-examples/image-processing/src/main.rs @@ -30,7 +30,7 @@ use image::{imageops, GenericImageView, ImageFormat}; fn main() -> anyhow::Result<()> { // Use the open function to load an image from a Path. // `open` returns a `DynamicImage` on success. - let mut img = image::open("/input/image-processing.png")?; + let mut img = image::open("./input/image-processing.png")?; // Transform the image let subimg = imageops::crop(&mut img, 0, 0, 100, 100); @@ -39,7 +39,7 @@ fn main() -> anyhow::Result<()> { // Write the contents of this image to the Writer in PNG format. subimg .to_image() - .save_with_format("/output/image-processing.png", ImageFormat::Png)?; + .save_with_format("./output/image-processing.png", ImageFormat::Png)?; Ok(()) } diff --git a/crates/examples/rust-examples/intersection-set-sum/src/main.rs b/crates/examples/rust-examples/intersection-set-sum/src/main.rs index 71315319b..82a8c0dfb 100644 --- a/crates/examples/rust-examples/intersection-set-sum/src/main.rs +++ b/crates/examples/rust-examples/intersection-set-sum/src/main.rs @@ -62,8 +62,8 @@ struct Customer { /// structs. Fails with [`return_code::ErrorCode::BadInput`] if the number of inputs provided is /// not equal to 2, or if the inputs cannot be deserialized from Bincode. fn read_inputs() -> anyhow::Result<(Vec, Vec)> { - let adverts = fs::read("/input/intersection-advertisement-viewer.dat")?; - let customs = fs::read("/input/intersection-customer.dat")?; + let adverts = fs::read("./input/intersection-advertisement-viewer.dat")?; + let customs = fs::read("./input/intersection-customer.dat")?; let adverts = postcard::from_bytes(&adverts)?; let customs = postcard::from_bytes(&customs)?; @@ -97,6 +97,6 @@ fn main() -> anyhow::Result<()> { let (adverts, customs) = read_inputs()?; let total = intersection_set_sum(&adverts, &customs); let result_encode = postcard::to_allocvec::(&total)?; - fs::write("/output/intersection-set-sum.dat", result_encode)?; + fs::write("./output/intersection-set-sum.dat", result_encode)?; Ok(()) } diff --git a/crates/examples/rust-examples/linear-regression/src/main.rs b/crates/examples/rust-examples/linear-regression/src/main.rs index f4dce9755..ff6904fcc 100644 --- a/crates/examples/rust-examples/linear-regression/src/main.rs +++ b/crates/examples/rust-examples/linear-regression/src/main.rs @@ -35,7 +35,7 @@ use std::fs; /// and fails with `return_code::ErrorCode::BadInput` if the input cannot be /// decoded from `postcard` into a Rust vector of floating-point pairs. fn read_input() -> anyhow::Result> { - let input = fs::read("/input/linear-regression.dat")?; + let input = fs::read("./input/linear-regression.dat")?; Ok(postcard::from_bytes(&input)?) } @@ -93,6 +93,6 @@ fn main() -> anyhow::Result<()> { let data = read_input()?; let result = linear_regression(&data); let result_encode = postcard::to_allocvec(&result)?; - fs::write("/output/linear-regression.dat", result_encode)?; + fs::write("./output/linear-regression.dat", result_encode)?; Ok(()) } diff --git a/crates/examples/rust-examples/logistic-regression/src/main.rs b/crates/examples/rust-examples/logistic-regression/src/main.rs index a54777326..49294c24a 100644 --- a/crates/examples/rust-examples/logistic-regression/src/main.rs +++ b/crates/examples/rust-examples/logistic-regression/src/main.rs @@ -228,8 +228,8 @@ fn read_all_datasets(input: &[Vec]) -> anyhow::Result> { /// if the deserialization of any dataset fails for any reason, or if the /// datasets have differing dimensionalities. fn read_input() -> anyhow::Result { - let i0 = fs::read("/input/logistic-regression-0.dat")?; - let i1 = fs::read("/input/logistic-regression-1.dat")?; + let i0 = fs::read("./input/logistic-regression-0.dat")?; + let i1 = fs::read("./input/logistic-regression-1.dat")?; let datas = read_all_datasets(&vec![i0, i1])?; Ok(flatten(&datas)) } @@ -266,6 +266,6 @@ fn main() -> anyhow::Result<()> { let dataset = read_input()?; let model = train(&dataset)?; let result_encode = postcard::to_allocvec::>(&model)?; - fs::write("/output/logistic-regression.dat", result_encode)?; + fs::write("./output/logistic-regression.dat", result_encode)?; Ok(()) } diff --git a/crates/examples/rust-examples/moving-average-convergence-divergence/src/main.rs b/crates/examples/rust-examples/moving-average-convergence-divergence/src/main.rs index c86711605..4b6ce6997 100644 --- a/crates/examples/rust-examples/moving-average-convergence-divergence/src/main.rs +++ b/crates/examples/rust-examples/moving-average-convergence-divergence/src/main.rs @@ -162,13 +162,14 @@ fn dec_approx(data: &[f64], norm: f64) -> Vec { /// Entry point: reads the vector of floats, processes them, and writes back a new vector of /// floats as output. fn main() -> anyhow::Result<()> { - for path in fs::read_dir("/input/macd/")? { + for path in fs::read_dir("./input/macd/")? { let path = path?.path(); let dataset = read_inputs(&path)?; let (_wma12, _wma26, _wma_diff, _wma9, _macd_wma, _decision_wma, decisions_wma_approx) = computation(dataset.as_slice()); let result_encode = postcard::to_allocvec::>(&decisions_wma_approx)?; - let mut output = PathBuf::from("/output/macd/"); + fs::create_dir_all("./output/macd/")?; + let mut output = PathBuf::from("./output/macd/"); output.push(path.file_name().ok_or(anyhow!("cannot get file name"))?); fs::write(output, result_encode)?; } diff --git a/crates/examples/rust-examples/nop/src/main.rs b/crates/examples/rust-examples/nop/src/main.rs index 153578d78..ce67456e8 100644 --- a/crates/examples/rust-examples/nop/src/main.rs +++ b/crates/examples/rust-examples/nop/src/main.rs @@ -18,4 +18,6 @@ //! and copyright information. /// Entry point: immediately returns success. -fn main() {} +fn main() { + println!("hello"); +} diff --git a/crates/examples/rust-examples/number-stream-accumulation/src/main.rs b/crates/examples/rust-examples/number-stream-accumulation/src/main.rs index 0408d4689..c26e02354 100644 --- a/crates/examples/rust-examples/number-stream-accumulation/src/main.rs +++ b/crates/examples/rust-examples/number-stream-accumulation/src/main.rs @@ -42,7 +42,7 @@ fn main() -> anyhow::Result<()> { count + 1, (last_result_or_init + stream1 + stream2), ))?; - fs::write("/output/accumulation.dat", result_encode)?; + fs::write("./output/accumulation.dat", result_encode)?; Ok(()) } @@ -69,13 +69,13 @@ fn read_last_result_or_init() -> anyhow::Result<(u64, f64)> { /// Read from 'stream-0' and 'stream-1' at `offset` fn read_stream(offset: u64) -> anyhow::Result<(f64, f64)> { - let mut stream0 = File::open("/input/number-stream-1.dat")?; + let mut stream0 = File::open("./input/number-stream-1.dat")?; stream0.seek(SeekFrom::Start(offset))?; let mut data0 = Vec::new(); stream0.read_to_end(&mut data0)?; let n1: f64 = postcard::from_bytes(&data0)?; - let mut stream1 = File::open("/input/number-stream-2.dat")?; + let mut stream1 = File::open("./input/number-stream-2.dat")?; stream1.seek(SeekFrom::Start(offset))?; let mut data1 = Vec::new(); stream1.read_to_end(&mut data1)?; diff --git a/crates/examples/rust-examples/postcard-native/src/main.rs b/crates/examples/rust-examples/postcard-native/src/main.rs index 2d8685a7c..d7fcbba82 100644 --- a/crates/examples/rust-examples/postcard-native/src/main.rs +++ b/crates/examples/rust-examples/postcard-native/src/main.rs @@ -15,11 +15,12 @@ //! See the file `LICENSE.md` in the Veracruz root directory for licensing //! and copyright information. -use std::fs; +use std::fs::{read, write}; + fn main() -> anyhow::Result<()> { - let input = fs::read("/input/postcard.dat")?; - fs::write("/services/postcard_string.dat", input)?; - let rst = fs::read("/services/postcard_result.dat")?; - fs::write("/output/postcard_native.txt", &rst)?; + let input = read("./input/postcard.dat")?; + write("/tmp/postcard/input", input)?; + let rst = read("/tmp/postcard/output")?; + write("./output/postcard_native.txt", &rst)?; Ok(()) } diff --git a/crates/examples/rust-examples/postcard-wasm/src/main.rs b/crates/examples/rust-examples/postcard-wasm/src/main.rs index be4c2f609..10a21a90d 100644 --- a/crates/examples/rust-examples/postcard-wasm/src/main.rs +++ b/crates/examples/rust-examples/postcard-wasm/src/main.rs @@ -67,9 +67,9 @@ pub struct Struct3 { } fn main() -> anyhow::Result<()> { - let input = fs::read("/input/postcard.dat")?; + let input = fs::read("./input/postcard.dat")?; let rst: Vec = from_bytes(&input)?; let rst = serde_json::to_string(&rst)?; - fs::write("/output/postcard_wasm.txt", rst)?; + fs::write("./output/postcard_wasm.txt", rst)?; Ok(()) } diff --git a/crates/examples/rust-examples/prime-numbers-generator/generate-set/src/main.rs b/crates/examples/rust-examples/prime-numbers-generator/generate-set/src/main.rs index 36b5eec6c..fc13f04a0 100644 --- a/crates/examples/rust-examples/prime-numbers-generator/generate-set/src/main.rs +++ b/crates/examples/rust-examples/prime-numbers-generator/generate-set/src/main.rs @@ -16,7 +16,7 @@ use anyhow; use std::fs; -const OUTPUT_FILENAME: &'static str = "/output/number-set.txt"; +const OUTPUT_FILENAME: &'static str = "./output/number-set.txt"; fn main() -> anyhow::Result<()> { let mut set: Vec = Vec::new(); diff --git a/crates/examples/rust-examples/prime-numbers-generator/keep-primes/src/main.rs b/crates/examples/rust-examples/prime-numbers-generator/keep-primes/src/main.rs index f6941c5dd..0fb65e11e 100644 --- a/crates/examples/rust-examples/prime-numbers-generator/keep-primes/src/main.rs +++ b/crates/examples/rust-examples/prime-numbers-generator/keep-primes/src/main.rs @@ -16,7 +16,7 @@ use anyhow; use std::fs; -const FILENAME: &'static str = "/output/number-set.txt"; +const FILENAME: &'static str = "./output/number-set.txt"; fn main() -> anyhow::Result<()> { let content = String::from_utf8(fs::read(FILENAME)?)?; diff --git a/crates/examples/rust-examples/private-set-intersection-sum/src/main.rs b/crates/examples/rust-examples/private-set-intersection-sum/src/main.rs index 5437dba7b..1c2757121 100644 --- a/crates/examples/rust-examples/private-set-intersection-sum/src/main.rs +++ b/crates/examples/rust-examples/private-set-intersection-sum/src/main.rs @@ -68,12 +68,13 @@ fn set_intersection_sum(data: Vec<((u64, u64), u32)>, sample: Vec<(u64, u64)>) - /// The program entry point: reads exactly one input, decodes it and computes the set /// intersection-sum before re-encoding it into Postcard and returning. fn main() -> anyhow::Result<()> { - for path in fs::read_dir("/input/private-set-inter-sum/")? { + for path in fs::read_dir("./input/private-set-inter-sum/")? { let path = path?.path(); let (data, sample) = read_inputs(&path)?; let result = set_intersection_sum(data, sample); let result_encode = postcard::to_allocvec::<(usize, u64)>(&result)?; - let mut output = PathBuf::from("/output/private-set-inter-sum/"); + fs::create_dir_all("./output/private-set-inter-sum/")?; + let mut output = PathBuf::from("./output/private-set-inter-sum/"); output.push(path.file_name().ok_or(anyhow!("cannot get file name"))?); fs::write(output, result_encode)?; } diff --git a/crates/examples/rust-examples/private-set-intersection/src/main.rs b/crates/examples/rust-examples/private-set-intersection/src/main.rs index 12a95d276..bf7d4eaac 100644 --- a/crates/examples/rust-examples/private-set-intersection/src/main.rs +++ b/crates/examples/rust-examples/private-set-intersection/src/main.rs @@ -36,9 +36,9 @@ struct Person { /// returns a `Vec` of all hash-sets, one from each input provider. Fails with /// `return_code::ErrorCode::BadInput` if any input cannot be deserialized from Bincode. fn read_inputs() -> anyhow::Result>> { - let input0 = fs::read("/input/private-set-1.dat")?; + let input0 = fs::read("./input/private-set-1.dat")?; let data0 = postcard::from_bytes(&input0)?; - let input1 = fs::read("/input/private-set-2.dat")?; + let input1 = fs::read("./input/private-set-2.dat")?; let data1 = postcard::from_bytes(&input1)?; Ok(vec![data0, data1]) } @@ -70,6 +70,6 @@ fn main() -> anyhow::Result<()> { let inputs = read_inputs()?; let result = set_intersection(&inputs); let result_encode = postcard::to_allocvec::>(&result)?; - fs::write("/output/private-set.dat", result_encode)?; + fs::write("./output/private-set.dat", result_encode)?; Ok(()) } diff --git a/crates/examples/rust-examples/random-source/src/main.rs b/crates/examples/rust-examples/random-source/src/main.rs index eb6800b1e..9ba3c34a2 100644 --- a/crates/examples/rust-examples/random-source/src/main.rs +++ b/crates/examples/rust-examples/random-source/src/main.rs @@ -25,9 +25,10 @@ use std::fs; /// Write 32 random bytes to 'output'. The result is a Postcard-encoded vector of u8. fn main() -> anyhow::Result<()> { - let output = "/output/random.dat"; + let output = "./output/random.dat"; let bytes = rand::thread_rng().gen::<[u8; 32]>(); let rst = postcard::to_allocvec(&bytes.to_vec())?; + fs::create_dir_all("output/")?; fs::write(output, rst)?; Ok(()) } diff --git a/crates/examples/rust-examples/random-u32-list/src/main.rs b/crates/examples/rust-examples/random-u32-list/src/main.rs index 5e359ff92..cd7b1d46e 100644 --- a/crates/examples/rust-examples/random-u32-list/src/main.rs +++ b/crates/examples/rust-examples/random-u32-list/src/main.rs @@ -18,13 +18,8 @@ use rand::Rng; use std::fs; fn main() -> anyhow::Result<()> { - let output = "/output/unsorted_numbers.txt"; - let bytes = rand::thread_rng() - .gen::<[u32; 32]>() - .iter() - .map(|n| n.to_string()) - .collect::>() - .join(","); + let output = "./output/unsorted_numbers.txt"; + let bytes = rand::thread_rng().gen::<[u32; 32]>().iter().map(|n| n.to_string()).collect::>().join(","); println!("{}", bytes); fs::write(output, bytes)?; Ok(()) diff --git a/crates/examples/rust-examples/read-file/src/main.rs b/crates/examples/rust-examples/read-file/src/main.rs index 6ac942244..2ef364484 100644 --- a/crates/examples/rust-examples/read-file/src/main.rs +++ b/crates/examples/rust-examples/read-file/src/main.rs @@ -18,23 +18,23 @@ use std::{fs, io::Write}; /// Read data from a file, encode using postcard, then write to another file. fn main() -> anyhow::Result<()> { - let input = "/input/hello-world-1.dat"; - let output = "/output/hello-world-1.dat"; + let input = "./input/hello-world-1.dat"; + let output = "./output/hello-world-1.dat"; let mut input_string = fs::read(input)?; println!("hello"); - fs::create_dir_all("/output/test")?; + fs::create_dir_all("./output/test")?; std::fs::OpenOptions::new() .write(true) .create(true) .truncate(true) - .open("/output/test/test.txt")? + .open("./output/test/test.txt")? .write(&postcard::to_allocvec("hello")?)?; println!("rust"); input_string.append(&mut "\"read_dir on '/output':".as_bytes().to_vec()); - for file in fs::read_dir("/output/")? { + for file in fs::read_dir("./output/")? { input_string.append(&mut file?.path().to_str().unwrap().as_bytes().to_vec()); } input_string.append(&mut "\"".as_bytes().to_vec()); diff --git a/crates/examples/rust-examples/shamir-secret-sharing/src/main.rs b/crates/examples/rust-examples/shamir-secret-sharing/src/main.rs index ca8f4f460..f1dcbeba9 100644 --- a/crates/examples/rust-examples/shamir-secret-sharing/src/main.rs +++ b/crates/examples/rust-examples/shamir-secret-sharing/src/main.rs @@ -194,7 +194,7 @@ fn shares_read_all() -> io::Result>> { // open files until one fails let mut shares = vec![]; for i in 0.. { - let filename = format!("/input/shamir-{}.dat", i); + let filename = format!("./input/shamir-{}.dat", i); let share = match fs::read(filename) { Ok(share) => share, Err(err) => match err.kind() { @@ -218,6 +218,7 @@ fn main() -> anyhow::Result<()> { let secret = shares_reconstruct(&shares); // write our output - fs::write("/output/shamir.dat", &secret)?; + let _ = fs::create_dir_all("./output/"); + fs::write("./output/shamir.dat", &secret)?; Ok(()) } diff --git a/crates/examples/rust-examples/sort-numbers/src/main.rs b/crates/examples/rust-examples/sort-numbers/src/main.rs index a99daec31..537f07476 100644 --- a/crates/examples/rust-examples/sort-numbers/src/main.rs +++ b/crates/examples/rust-examples/sort-numbers/src/main.rs @@ -16,8 +16,8 @@ use anyhow; use std::fs; -const INPUT_FILENAME: &'static str = "/output/unsorted_numbers.txt"; -const OUTPUT_FILENAME: &'static str = "/output/sorted_numbers.txt"; +const INPUT_FILENAME: &'static str = "./output/unsorted_numbers.txt"; +const OUTPUT_FILENAME: &'static str = "./output/sorted_numbers.txt"; fn main() -> anyhow::Result<()> { let file_vec = fs::read(INPUT_FILENAME)?; diff --git a/crates/examples/rust-examples/string-edit-distance/src/main.rs b/crates/examples/rust-examples/string-edit-distance/src/main.rs index ab88a4e2b..e45ed4a81 100644 --- a/crates/examples/rust-examples/string-edit-distance/src/main.rs +++ b/crates/examples/rust-examples/string-edit-distance/src/main.rs @@ -29,8 +29,8 @@ use strsim::jaro_winkler; /// provided to the program is not exactly 2. /// fn read_inputs() -> anyhow::Result<(String, String)> { - let this = String::from_utf8(fs::read("/input/hello-world-1.dat")?)?; - let that = String::from_utf8(fs::read("/input/hello-world-2.dat")?)?; + let this = String::from_utf8(fs::read("./input/hello-world-1.dat")?)?; + let that = String::from_utf8(fs::read("./input/hello-world-2.dat")?)?; Ok((this, that)) } @@ -43,6 +43,6 @@ fn main() -> anyhow::Result<()> { let (left, right) = read_inputs()?; let distance = jaro_winkler(&left, &right); let result_encode = postcard::to_allocvec::(&distance)?; - fs::write("/output/string-edit-distance.dat", result_encode)?; + fs::write("./output/string-edit-distance.dat", result_encode)?; Ok(()) } diff --git a/crates/examples/rust-examples/string-search/src/main.rs b/crates/examples/rust-examples/string-search/src/main.rs index 79099d51d..0cc77adac 100644 --- a/crates/examples/rust-examples/string-search/src/main.rs +++ b/crates/examples/rust-examples/string-search/src/main.rs @@ -16,8 +16,8 @@ use anyhow::{self, Ok}; use std::fs; -const INPUT_FILENAME: &'static str = "/input/hello-world-1.dat"; -const OUTPUT_FILENAME: &'static str = "/output/search_results.dat"; +const INPUT_FILENAME: &'static str = "./input/hello-world-1.dat"; +const OUTPUT_FILENAME: &'static str = "./output/search_results.dat"; fn main() -> anyhow::Result<()> { let query = std::env::var("QUERY")?.to_string(); // search argument diff --git a/crates/examples/rust-examples/tflite-inference-native-mnist/src/main.rs b/crates/examples/rust-examples/tflite-inference-native-mnist/src/main.rs index 12a1ecb6c..0c927d308 100644 --- a/crates/examples/rust-examples/tflite-inference-native-mnist/src/main.rs +++ b/crates/examples/rust-examples/tflite-inference-native-mnist/src/main.rs @@ -49,7 +49,7 @@ const MNIST_MODEL_INPUT_SIZE: (u32, u32) = (28, 28); fn main() -> anyhow::Result<()> { // Read image of a handwritten digit. The digit must be white on a black // background - let img = image::open("/input/digit.png")?; + let img = image::open("./input/digit.png")?; // Resize image to model's input size let img = imageops::resize( &img, @@ -68,7 +68,7 @@ fn main() -> anyhow::Result<()> { // Invoke service let tflite_inference_input = TfLiteInferenceInput { input_tensor_path: PathBuf::from("/program_internal/grayscale_image.bin"), - model_path: PathBuf::from("/input/MNISTnet_uint8_quant.tflite"), + model_path: PathBuf::from("./input/MNISTnet_uint8_quant.tflite"), output_tensor_path: PathBuf::from("/program_internal/output.dat"), num_threads: -1, // Let TF Lite pick how many threads it needs }; diff --git a/crates/execution-engine/Cargo.toml b/crates/execution-engine/Cargo.toml index 0911a0ad3..0cce158e3 100644 --- a/crates/execution-engine/Cargo.toml +++ b/crates/execution-engine/Cargo.toml @@ -10,39 +10,27 @@ default = [] nitro = [ "mbedtls/monitor_getrandom", "platform-services/nitro", - "policy-utils/std", - "wasmtime", ] std = [ "nix", "platform-services/std", - "policy-utils/std", - "wasmtime", ] [dependencies] log = "0.4.13" anyhow = "1" -byteorder = "1.4.3" cfg-if = "1" -err-derive = "0.2" lazy_static = { version = "1.4.0", features = ["spin_no_std"] } mbedtls = { path = "../third-party/rust-mbedtls/mbedtls", default-features = false, features = ["std", "aesni", "padlock", "tls13"] } -nix = { version = "0.26", optional = true } -num = { version = "0.4", default-features = false } -num-derive = { version = "0.3", default-features = false } -num-traits = { version = "0.2", default-features = false } +nix = { version = "0.26", optional = true, features=["fs"] } postcard = { version = "1.0.0", features = [ "alloc", "use-std" ] } platform-services = { path = "../platform-services" } -policy-utils = { path = "../policy-utils" } +policy-utils = { path = "../policy-utils", features = ["std"] } serde = { version = "1.0.185", features = ["derive"] } serde_json = "1.0" -strum = "0.24" -strum_macros = "0.24" -typetag = "0.1.8" wasi-types = { path = "../third-party/wasi-types" } -wasmi = { path = "../third-party/wasmi" } -wasmtime = { version = "10.0.1", optional = true } +wasmtime = "11" +wasmtime-wasi = "11" [lib] name = "execution_engine" diff --git a/crates/execution-engine/src/engines/common.rs b/crates/execution-engine/src/engines/common.rs deleted file mode 100644 index 0f2eaa4ce..000000000 --- a/crates/execution-engine/src/engines/common.rs +++ /dev/null @@ -1,2053 +0,0 @@ -//! Common code for any implementation of WASI -//! -//! This module contains: -//! - An interface for handling memory access. -//! - An interface for executing a program. -//! - A Wasi wrapper which wraps the strictly Wasi-like API in the virtual file -//! system, and converts Wasm number- and address-based parameters to -//! properly-typed parameters with Rust-style error handling (and vice versa). -//! -//! ## Authors -//! -//! The Veracruz Development Team. -//! -//! ## Licensing and copyright notice -//! -//! See the `LICENSE.md` file in the Veracruz root directory for -//! information on licensing and copyright. - -#![allow(non_camel_case_types, clippy::too_many_arguments)] - -use crate::{ - engines::strace::Strace, - fs::{FileSystem, FileSystemResult, TryFromOrErrNo}, - Options, -}; -use anyhow::Result; -use byteorder::{LittleEndian, ReadBytesExt}; -use err_derive::Error; -use platform_services::{getclockres, getclocktime, getrandom, result}; -use serde::{Deserialize, Serialize}; -use std::{ - convert::AsMut, convert::AsRef, convert::TryFrom, io::Cursor, marker::PhantomData, mem, - mem::size_of, ops::Deref, ops::DerefMut, slice, slice::from_raw_parts, - slice::from_raw_parts_mut, string::String, vec::Vec, -}; -use strum_macros::{EnumString, IntoStaticStr}; -use wasi_types::{ - Advice, ClockId, DirEnt, ErrNo, Event, EventFdState, EventRwFlags, EventType, Fd, FdFlags, - IoVec, LookupFlags, OpenFlags, RiFlags, Rights, RoFlags, SdFlags, SetTimeFlags, SiFlags, - Signal, Subscription, SubscriptionClock, SubscriptionFdReadwrite, SubscriptionUnion, Timestamp, - Whence, -}; - -//////////////////////////////////////////////////////////////////////////////// -// Common constants. -//////////////////////////////////////////////////////////////////////////////// - -/// List of WASI API function names. -/// These can be converted between primitive numbers and enum values via -/// `primitive` derive macros, and between lowercase string and enum values via -/// `strum`. -#[derive( - IntoStaticStr, - EnumString, - Debug, - PartialEq, - Clone, - FromPrimitive, - ToPrimitive, - Serialize, - Deserialize, - Copy, -)] -#[strum(serialize_all = "lowercase")] -pub enum WasiAPIName { - ARGS_GET = 1, - ARGS_SIZES_GET, - ENVIRON_GET, - ENVIRON_SIZES_GET, - CLOCK_RES_GET, - CLOCK_TIME_GET, - FD_ADVISE, - FD_ALLOCATE, - FD_CLOSE, - FD_DATASYNC, - FD_FDSTAT_GET, - FD_FDSTAT_SET_FLAGS, - FD_FDSTAT_SET_RIGHTS, - FD_FILESTAT_GET, - FD_FILESTAT_SET_SIZE, - FD_FILESTAT_SET_TIMES, - FD_PREAD, - FD_PRESTAT_GET, - FD_PRESTAT_DIR_NAME, - FD_PWRITE, - FD_READ, - FD_READDIR, - FD_RENUMBER, - FD_SEEK, - FD_SYNC, - FD_TELL, - FD_WRITE, - PATH_CREATE_DIRECTORY, - PATH_FILESTAT_GET, - PATH_FILESTAT_SET_TIMES, - PATH_LINK, - PATH_OPEN, - PATH_READLINK, - PATH_REMOVE_DIRECTORY, - PATH_RENAME, - PATH_SYMLINK, - PATH_UNLINK_FILE, - POLL_ONEOFF, - PROC_EXIT, - PROC_RAISE, - SCHED_YIELD, - RANDOM_GET, - SOCK_RECV, - SOCK_SEND, - SOCK_SHUTDOWN, - #[strum(disabled)] - _LAST, -} - -/// List of Veracruz API function names. -#[derive( - IntoStaticStr, - EnumString, - Debug, - PartialEq, - Clone, - FromPrimitive, - ToPrimitive, - Serialize, - Deserialize, - Copy, -)] -#[strum(serialize_all = "lowercase")] -pub enum VeracruzAPIName { - FD_CREATE, -} - -//////////////////////////////////////////////////////////////////////////////// -// Miscellanea that doesn't fit elsewhere. -//////////////////////////////////////////////////////////////////////////////// - -/// Unpack a sequence of `bytes` and return a `T`. -pub trait Unpack: Sized { - /// Size in bytes of the structure in the Wasm memory space. Note that this - /// may be different than the resulting type since it is in a different - /// memory space on a machine that likely has different pointer sizes. - const SIZE: u32; - - /// Unpack the `T` - fn unpack(bytes: &[u8]) -> FileSystemResult; -} - -impl Unpack for IoVec { - const SIZE: u32 = size_of::() as u32; - - fn unpack(bytes: &[u8]) -> FileSystemResult { - if bytes.len() != size_of::() { - return Err(ErrNo::Inval); - } - let mut rdr = Cursor::new(bytes); - let buf = rdr.read_u32::()?; - let len = rdr.read_u32::()?; - Ok(IoVec { buf, len }) - } -} - -impl Unpack for Subscription { - const SIZE: u32 = size_of::() as u32; - - fn unpack(bytes: &[u8]) -> FileSystemResult { - if bytes.len() != size_of::() { - return Err(ErrNo::Inval); - } - let mut rdr = Cursor::new(bytes); - let userdata = rdr.read_u64::()?; - // build SubscriptionUnion - let tag = rdr.read_u64::()?; - let u = match tag { - // build clock - 0 => { - let clock_id = rdr.read_u64::()?; - let clock_id = u32::try_from(clock_id).map_err(|_| ErrNo::Inval)?; - let clock_id = ClockId::try_from(clock_id).map_err(|_| ErrNo::Inval)?; - let timeout = rdr.read_u64::()?.into(); - let precision = rdr.read_u64::()?.into(); - // NOTE: not sure if flags is read correctly as it is u16 - let flags = rdr.read_u64::()?; - let flags = u16::try_from(flags).map_err(|_| ErrNo::Inval)?; - let clock = SubscriptionClock { - clock_id, - timeout, - precision, - flags, - }; - SubscriptionUnion::Clock(clock) - } - // FdRead or FdWrite - 1 | 2 => { - let fd = rdr.read_u64::()?; - let fd = u32::try_from(fd).map_err(|_| ErrNo::Inval)?.into(); - // Read the unused bytes - rdr.read_u64::()?; - rdr.read_u64::()?; - rdr.read_u64::()?; - let fd_rw = SubscriptionFdReadwrite { fd }; - if tag == 1 { - SubscriptionUnion::FdRead(fd_rw) - } else { - SubscriptionUnion::FdWrite(fd_rw) - } - } - _otherwise => return Err(ErrNo::Inval), - }; - Ok(Subscription { userdata, u }) - } -} - -impl Unpack for Event { - const SIZE: u32 = size_of::() as u32; - - fn unpack(bytes: &[u8]) -> FileSystemResult { - if bytes.len() != size_of::() { - return Err(ErrNo::Inval); - } - let mut rdr = Cursor::new(bytes); - let user_data = rdr.read_u64::()?; - let error = rdr.read_u16::()?; - let error = ErrNo::try_from(error).map_err(|_| ErrNo::Inval)?; - // NOTE: not sure if ty (type) is read correctly as it is u16 - let ty = rdr.read_u48::()?; - let ty = u8::try_from(ty).map_err(|_| ErrNo::Inval)?; - let ty = EventType::try_from(ty).map_err(|_| ErrNo::Inval)?; - let fd_state = if ty == EventType::FdRead || ty == EventType::FdWrite { - let file_size = rdr.read_u64::()?; - // NOTE: not sure if flag is read correctly as it is u64 - let flags = rdr.read_u64::()?; - let flags = u16::try_from(flags).map_err(|_| ErrNo::Inval)?; - let flags = EventRwFlags::try_from(flags).map_err(|_| ErrNo::Inval)?; - Some(EventFdState { file_size, flags }) - } else { - None - }; - Ok(Event { - user_data, - error, - ty, - fd_state, - }) - } -} - -/// A trait for slices of memory that MemoryHandler operates on -/// -/// Note! This is not the same as just AsRef<[u8]>! -/// -/// MemorySlice is an AsRef<[u8]> with the additional requirement that -/// the underlying type is movable even when references are borrowed. -/// -/// This is true for most types you may want to implement MemorySlice for, -/// such as `&[u8]`, `MutexGuard<[u8]>`, or even `Vec`. But this will fail -/// if your as_ref implementation returns references into the original struct, -/// which is allowed for AsRef<[u8]>, such as in the case of `[u8; 128]`. -/// -/// Of course, this behavior is invalid for normal Rust references, since -/// preventing underlying data moves is the whole point of the borrow-checker -/// in the first place. So we need to access the underlying data through -/// pointers or reborrowed dereferences in order to create disjoint lifetimes. -/// -/// This means implementors of MemorySlice will most like require unsafe code. -/// -/// --- -/// -/// In exchange for the requirement that the underlying type is movable, -/// consumers of MemorySlice promise to manually enforce the expected lifetime -/// of the MemorySlice. That is, accesses to the underlying borrows are only -/// legal while the MemorySlice is allocated. -/// -/// To help with this, we introduce a new wrapper, Bound<'a, T>, for explicitly -/// limiting the lifetime of traits like MemorySlice. -/// -/// So, while we can't leverage Rust's borrow checker to enforce these -/// lifetimes, we can at least ensure that the proper lifetimes are enforced -/// for any code that depends on MemoryHandler. -/// -pub trait MemorySlice: AsRef<[u8]> { - #[inline] - fn as_raw_parts(&self) -> (*const u8, usize) { - let ref_ = self.as_ref(); - (ref_.as_ptr(), ref_.len()) - } -} - -/// A trait for slices of mutable memory that MemoryHandler operates on -/// -/// Note! This is not the same as just AsMut<[u8]>! -/// -/// See MemorySlice for more info -/// -pub trait MemorySliceMut: AsMut<[u8]> { - #[inline] - fn as_raw_parts_mut(&mut self) -> (*mut u8, usize) { - let ref_ = self.as_mut(); - (ref_.as_mut_ptr(), ref_.len()) - } -} - -impl MemorySlice for &'static [u8] {} -impl MemorySliceMut for &'static mut [u8] {} - -/// Bound<'a, T> is a wrapper that explicitly enforces unrelated lifetimes -/// on objects -/// -/// It combines PhantomData and Deref to provide a simple wrapper that is -/// guaranteed by the borrow checker to not outlive the provided lifetime. -/// -/// This wrapper is useful for reintroducing lifetimes that have been stripped -/// away be unsafe code. -/// -#[derive(Debug, Copy, Clone)] -pub struct Bound<'a, T>(T, PhantomData<&'a T>); - -impl<'a, T> Bound<'a, T> { - #[inline] - pub fn new(t: T) -> Self { - Self(t, PhantomData) - } -} - -impl<'a, T> Deref for Bound<'a, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - &self.0 - } -} - -/// BoundMut<'a, T> is a wrapper that explicitly enforces unrelated lifetimes -/// on objects -/// -/// It combines PhantomData and DerefMut to provide a simple wrapper that is -/// guaranteed by the borrow checker to not outlive the provided lifetime. -/// -/// This wrapper is useful for reintroducing lifetimes that have been stripped -/// away be unsafe code. -/// -#[derive(Debug)] -pub struct BoundMut<'a, T>(T, PhantomData<&'a mut T>); - -impl<'a, T> BoundMut<'a, T> { - #[inline] - pub fn new(t: T) -> Self { - Self(t, PhantomData) - } -} - -impl<'a, T> Deref for BoundMut<'a, T> { - type Target = T; - #[inline] - fn deref(&self) -> &T { - &self.0 - } -} - -impl<'a, T> DerefMut for BoundMut<'a, T> { - #[inline] - fn deref_mut(&mut self) -> &mut T { - &mut self.0 - } -} - -/// Number of `iovec`s to store internally before needing dynamic memory -const IOVECSLICES_SOO_COUNT: usize = 2; - -/// A type wrapping an array of IoVecs as directly-accessible slices. -/// -/// This indirection is needed to hold the MemoryHandler::Slice type which -/// needs to be stored somewhere -/// -/// This may allocate, though most iovecs are fairly small. As an extra -/// optimization, if there are only 1 or 2 iovecs, these are stored directly -/// in the struct with no allocation. 1 iovec is the most common, though -/// 2 iovecs is used sometimes for things like appending newlines to stdout. -/// At the time of writing I have never seen >2 iovecs used in a call, though -/// it's certainly possible for aggressively optimized io. -/// -pub struct IoVecSlices<'a, R> { - _ref: R, - slices: IoVecSlicesStorage<'a>, -} - -enum IoVecSlicesStorage<'a> { - Small([Option<&'a [u8]>; IOVECSLICES_SOO_COUNT]), - Large(Vec<&'a [u8]>), -} - -impl<'a, R> AsRef<[&'a [u8]]> for IoVecSlices<'a, R> { - fn as_ref(&self) -> &[&'a [u8]] { - match &self.slices { - IoVecSlicesStorage::Small(arr) => { - // NB: this looks a bit scary, but is just casting our - // `[Option<&[u8]>; 2]` into a `&[&[u8]]`. This is perfectly - // valid Rust, though requires unsafety to do this without - // memory allocation. - let len = arr.iter().take_while(|x| x.is_some()).count(); - unsafe { slice::from_raw_parts(arr.as_ptr() as *const &'a [u8], len) } - } - IoVecSlicesStorage::Large(vec) => &vec, - } - } -} - -/// A type wrapping a mutable array of IoVecs as directly-accessible slices. -/// -/// This indirection is needed to hold the MemoryHandler::SliceMut type which -/// needs to be stored somewhere -/// -/// This may allocate, though most iovecs are fairly small. As an extra -/// optimization, if there are only 1 or 2 iovecs, these are stored directly -/// in the struct with no allocation. 1 iovec is the most common, though -/// 2 iovecs is used sometimes for things like appending newlines to stdout. -/// At the time of writing I have never seen >2 iovecs used in a call, though -/// it's certainly possible for aggressively optimized io. -/// -pub struct IoVecSlicesMut<'a, R> { - _ref: R, - slices: IoVecSlicesMutStorage<'a>, -} - -enum IoVecSlicesMutStorage<'a> { - Small([Option<&'a mut [u8]>; IOVECSLICES_SOO_COUNT]), - Large(Vec<&'a mut [u8]>), -} - -impl<'a, R> AsMut<[&'a mut [u8]]> for IoVecSlicesMut<'a, R> { - fn as_mut(&mut self) -> &mut [&'a mut [u8]] { - match &mut self.slices { - IoVecSlicesMutStorage::Small(arr) => { - // NB: this looks a bit scary, but is just casting our - // `[Option<&[u8]>; 2]` into a `&[&[u8]]`. This is perfectly - // valid Rust, though requires unsafety to do this without - // memory allocation. - let len = arr.iter().take_while(|x| x.is_some()).count(); - unsafe { slice::from_raw_parts_mut(arr.as_mut_ptr() as *mut &'a mut [u8], len) } - } - IoVecSlicesMutStorage::Large(ref mut vec) => vec, - } - } -} - -/// A `MemoryHandler` trait for interacting with the Wasm memory space. -/// -/// The API here is a bit tricky because we want to be able to leverage -/// direct access to linear memory if available, and this is provided in -/// different ways by different engines. -/// -/// To make this extra confusing, we would normally use GATs to implement -/// this, but they are unfinished and only available on nightly. So instead -/// we need to use a bit of unsafe code in order to provide the correct -/// lifetimes. -/// -/// As a user, don't worry! The resulting API should be completely safe to use -/// within Rust's rules. As an implementor maybe worry a little bit. -/// -/// --- -/// -/// At minimum, an implementation must implement `get_slice`, `get_slice_mut`, -/// and `get_size`. Without GATs, we can't describe the correct lifetimes in -/// this trait, so instead we require that `get_slice` and `get_slice` return -/// associated types that implement a "lifetime-less" MemorySlice trait. It's -/// up to the implementor to satisfy this, which most likely means unsafe code -/// going through a pointer-type-cast in order to create a disjoint lifetime. -/// -/// To keep this from just being completely unsafe, we reintroduce the lifetime -/// requirements with the `Bound` and `BoundMut` wrappers. These wrappers ensure -/// the structure remains allocated for the original lifetime, but in a scope -/// where we can describe the lifetime in the MemoryHandler trait. -/// -/// --- -/// -/// In addition to all this, `MemorySlice` and `MemorySliceMut` have a special -/// requirement that the underlying struct is movable even behind a reference. -/// This is described in more detail in the documentation of `MemorySlice`, and -/// is required for the self-referential slices used in `IoVecSlice` and -/// `IoVecSliceMut` without an unnecessary memory allocation. -/// -/// --- -/// -/// NOTE: we purposely choose `u32` here as the execution engine is likely -/// received `u32` as parameters. -/// -pub trait MemoryHandler { - /// A type representing a direct reference to memory - /// - /// This may both lock the underlying engine and allocate memory (if the - /// engines underlying memory is not directly accessible). These should - /// generally be short-lived to pass to other APIs. - /// - /// Note these have an additional requirement that the underlying type - /// be movable even when borrowed! See MemorySlice for more info. - /// - type Slice: MemorySlice; - - /// A type representing a direct mutable reference to memory - /// - /// This may both lock the underlying engine and allocate memory (if the - /// engines underlying memory is not directly accessible). These should - /// generally be short-lived to pass to other APIs. - /// - /// Note these have an additional requirement that the underlying type - /// be movable even when borrowed! See MemorySliceMut for more info. - /// - type SliceMut: MemorySliceMut; - - /// Get an immutable slice of the memory - /// - /// The resulting type can be used as an AsRef<[u8]>, but is explicitly - /// bounded such that it can only be used in the lifetime of the underlying - /// MemoryHandler. - /// - fn get_slice<'a>( - &'a self, - address: u32, - length: u32, - ) -> FileSystemResult>; - - /// Get a mutable slice of the memory - /// - /// The resulting type can be used as an AsMut<[u8]>, but is explicitly - /// bounded such that it can only be used in the lifetime of the underlying - /// MemoryHandler. - /// - fn get_slice_mut<'a>( - &'a mut self, - address: u32, - length: u32, - ) -> FileSystemResult>; - - /// Get the size of the underlying memory - fn get_size(&self) -> FileSystemResult; - - /// Write the `buffer` to `address`. - fn write_buffer(&mut self, address: u32, buffer: &[u8]) -> FileSystemResult<()> { - self.get_slice_mut(address, u32::try_from_or_errno(buffer.len())?)? - .as_mut() - .copy_from_slice(buffer); - Ok(()) - } - - /// Read into the `buffer` from `address`. - fn read_buffer(&self, address: u32, buffer: &mut [u8]) -> FileSystemResult<()> { - buffer.copy_from_slice( - self.get_slice(address, u32::try_from_or_errno(buffer.len())?)? - .as_ref(), - ); - Ok(()) - } - - /// Reads a string at `address` of `length` from the runtime state's memory, - /// starting at base address `address`. If it fails, return ErrNo. - fn read_cstring(&self, address: u32, length: u32) -> FileSystemResult { - let mut bytes = vec![0u8; usize::try_from_or_errno(length)?]; - self.read_buffer(address, &mut bytes)?; - let rst = String::from_utf8(bytes).map_err(|_e| ErrNo::IlSeq)?; - Ok(rst) - } - - /// The default implementation for reading a u16 from `address`. - fn read_u16(&self, address: u32) -> FileSystemResult { - let mut bytes = [0u8; 2]; - self.read_buffer(address, &mut bytes)?; - Ok(u16::from_le_bytes(bytes)) - } - - /// The default implementation for writing a u32 to `address`. - fn write_u32(&mut self, address: u32, number: u32) -> FileSystemResult<()> { - self.write_buffer(address, &u32::to_le_bytes(number)) - } - - /// The default implementation for reading a u32 from `address`. - fn read_u32(&self, address: u32) -> FileSystemResult { - let mut bytes = [0u8; 4]; - self.read_buffer(address, &mut bytes)?; - Ok(u32::from_le_bytes(bytes)) - } - - /// The default implementation for writing a u64 to `address`. - fn write_u64(&mut self, address: u32, number: u64) -> FileSystemResult<()> { - self.write_buffer(address, &u64::to_le_bytes(number)) - } - - /// The default implementation for reading a u64 from `address`. - fn read_u64(&self, address: u32) -> FileSystemResult { - let mut bytes = [0u8; 8]; - self.read_buffer(address, &mut bytes)?; - Ok(u64::from_le_bytes(bytes)) - } - - /// The default implementation for writing any Sized struct to `address`. - fn write_struct(&mut self, address: u32, element: &T) -> FileSystemResult<()> { - let bytes: &[u8] = - unsafe { from_raw_parts((element as *const T) as *const u8, size_of::()) }; - self.write_buffer(address, bytes) - } - - /// The default implementation for reading any Sized struct from `address`. - fn read_struct(&self, address: u32, element: &mut T) -> FileSystemResult<()> { - let bytes: &mut [u8] = - unsafe { from_raw_parts_mut((element as *mut T) as *mut u8, size_of::()) }; - self.read_buffer(address, bytes) - } - - /// The default implementation for reading an Unpack from `address`. - fn unpack(&self, address: u32) -> FileSystemResult { - let bytes = self.get_slice(address, T::SIZE)?; - T::unpack(bytes.as_ref()) - } - - /// Unpack an array of Unpacks - fn unpack_array(&self, address: u32, count: u32) -> FileSystemResult> { - (0..count) - .map(|i| self.unpack(address + i * T::SIZE)) - .collect() - } - - /// Unpack an array of `iovec` references - /// - /// The result of this is an array of slices that read directly from - /// the underlying memory. The type is complicated in order to ensure the - /// correct lifetime, but it can be treated as a "simple" `AsRef<&[&[u8]]>`. - /// - fn unpack_iovec<'a>( - &'a self, - address: u32, - count: u32, - ) -> FileSystemResult>> { - // Just get a reference to all of memory, it's easier to manipulate - // it this way - let memory = self.get_slice(0, self.get_size()?)?; - let slices = (0..count).map(|i| -> FileSystemResult<&'a [u8]> { - let iovec = IoVec::unpack( - &memory.as_ref()[usize::try_from_or_errno(address + i * IoVec::SIZE)? - ..usize::try_from_or_errno(address + (i + 1) * IoVec::SIZE)?], - )?; - - // Ok here's the gooey center of the the copy-less iovecs. This may - // seem unnecessary but this code finds itself on the hot-path of - // execution the moment io gets involved. - // - // We want to reference directly into the engine's underlying memory - // if possible, and `MemorySlice` trait takes care of that (see - // `MemorySlice` for even more mess). But we take the simple - // reference a bit further here with iovecs since we want to - // reference multiple slices of the underlying memory while - // maintaining the lifetime of the original `MemorySlice`. - // - // To provide this for any generic `AsRef<[u8]>` type requires a - // possibly self-referential type, which gets incredibly hairy in - // Rust. The "safe" way to do this would be to move the - // `MemorySlice` onto the heap and pin it with `Box::pin`, though - // this requires memory allocation and still requires pointers and - // a bit of unsafety to tie everything together. - // - // In theory you could pin the `MemorySlice` to the stack, however - // it would need to be allocated in the callers stack and passed - // to this function, _greatly_ complicating this API (requiring - // `MaybeUninit` in any caller?). - // - // As an alternative, we can just require that the associated - // `MemorySlice` type is movable, even behind a borrow. This is - // outside of Rust's rules, but is actually reasonable for most - // types we would want to use for `MemorySlice`. This requirement - // is satisfied by `&[u8]`, `MutexGuard<[u8]>`, and even `Vec`, - // but not by any type where `as_ref` referenced data in original - // struct, such as `[u8; 128]`. - // - // --- - // - // Of course this sort of lifetime isn't checkable by Rust, since - // preventing borrowed moves is the whole point of the borrow - // checker, so we need to use a bit of unsafety to strip away the - // lifetime. - // - // Note, we still enforce the correct lifetimes for any callers! - // This is accomplished by the `Bound` wrapper. There's more info - // on this on the `MemorySlice` and `Bound` traits/types - // - let slice = &memory.as_ref()[usize::try_from_or_errno(iovec.buf)? - ..usize::try_from_or_errno(iovec.buf + iovec.len)?]; - Ok(unsafe { mem::transmute::<&'_ [u8], &'a [u8]>(slice) }) - }); - - if count <= IOVECSLICES_SOO_COUNT as u32 { - let mut slices = slices.fuse(); - let slices = [slices.next().transpose()?, slices.next().transpose()?]; - Ok(IoVecSlices { - _ref: memory, - slices: IoVecSlicesStorage::Small(slices), - }) - } else { - let slices = slices.collect::>>()?; - Ok(IoVecSlices { - _ref: memory, - slices: IoVecSlicesStorage::Large(slices), - }) - } - } - - /// Unpack an array of mutable iovec references - /// - /// The result of this is an array of slices that writes directly into - /// the underlying memory. The type is complicated in order to ensure the - /// correct lifetime, but it can be treated as a "simple" - /// `AsMut<&mut [&mut [u8]]>`. - /// - fn unpack_iovec_mut<'a>( - &'a mut self, - address: u32, - count: u32, - ) -> FileSystemResult>> { - // Just get a reference to all of memory, it's easier to manipulate - // it this way - let mut memory = self.get_slice_mut(0, self.get_size()?)?; - let slices = (0..count).map(|i| -> FileSystemResult<&'a mut [u8]> { - let iovec = IoVec::unpack( - &memory.as_mut()[usize::try_from_or_errno(address + i * IoVec::SIZE)? - ..usize::try_from_or_errno(address + (i + 1) * IoVec::SIZE)?], - )?; - - // Ok here's the gooey center of the the copy-less iovecs. This may - // seem unnecessary but this code finds itself on the hot-path of - // execution the moment io gets involved. - // - // See `unpack_iovec` for more info about what is going on here - // - - // The _correct_ thing to do here is to - // 1. allocate and read all iovecs first - // 2. sort the iovecs by address - // 3. check for overlapping ranges - // 4. repeat slice::split_at to separate memory into sub-slices - // containing the slices specified by iovec - // - // Or we can not do that and just construct mutable slices that may - // more may not overlap. If they overlap the worst thing that should - // happen is malformed iovecs get malformed data back. - // - let slice = &mut memory.as_mut()[usize::try_from_or_errno(iovec.buf)? - ..usize::try_from_or_errno(iovec.buf + iovec.len)?]; - Ok(unsafe { mem::transmute::<&'_ mut [u8], &'a mut [u8]>(slice) }) - }); - - if count <= IOVECSLICES_SOO_COUNT as u32 { - let mut slices = slices.fuse(); - let slices = [slices.next().transpose()?, slices.next().transpose()?]; - Ok(IoVecSlicesMut { - _ref: memory, - slices: IoVecSlicesMutStorage::Small(slices), - }) - } else { - let slices = slices.collect::>>()?; - Ok(IoVecSlicesMut { - _ref: memory, - slices: IoVecSlicesMutStorage::Large(slices), - }) - } - } - - /// Write the content to the `buf_address` and the starting address to - /// `buf_pointers`. For example: - /// - /// buf_address: - /// -------------------------------------------------------------------- - /// content[0] content[1] ...... - /// -------------------------------------------------------------------- - /// ^ ^ - /// 0x10 0x64 - /// buf_pointers: [0x10, 0x64, ...] - /// - fn write_string_list( - &mut self, - content: &[Vec], - mut buf_address: u32, - mut buf_pointers: u32, - ) -> FileSystemResult<()> { - for to_write in content { - // Write to the buf - self.write_buffer(buf_address, &to_write)?; - // Write to the pointer array - self.write_u32(buf_pointers, buf_address)?; - // Modify the offset - buf_address += to_write.len() as u32; - buf_pointers += size_of::() as u32; - } - Ok(()) - } -} -//////////////////////////////////////////////////////////////////////////////// -// The host runtime state. -//////////////////////////////////////////////////////////////////////////////// - -/// A wrapper on VFS for WASI, which provides common API used by wasm execution -/// engine. -#[derive(Clone)] -pub struct WasiWrapper { - /// The synthetic filesystem associated with this machine. - /// - /// Note: Veracruz runtime should hold the root `FileSystem` handler. - /// The `FileSystem` handler here should be a non-root handler spawned - /// from the root one. Both the Veracruz runtime and this - /// `WasiWrapper` can update, i.e. mutate, the file system internal - /// state, if their local `FileSystem` handlers have the appropriate - /// capabilities. - /// --------------------------- - /// Runtime | WasiWrapper - /// FileSystem(handler)| FileSystem(handler) - /// v | v - /// --------------------------- - /// | ^ ^ | - /// | Internal | - /// ---------------- - filesystem: FileSystem, - /// The environment variables currently set, and their bindings. - environment_variables: Vec<(String, String)>, - /// The program arguments of the executable being executed. - program_arguments: Vec, - /// The exit code returned by the last executing program. - exit_code: Option, - /// Whether clock functions (`clock_getres()`, `clock_gettime()`) should be - /// enabled. - pub(crate) enable_clock: bool, - /// Whether strace is enabled. - pub(crate) enable_strace: bool, -} - -impl WasiWrapper { - /// The name of the WASM program's entry point. - pub(crate) const ENTRY_POINT_NAME: &'static str = "_start"; - /// The name of the WASM program's linear memory. - pub(crate) const LINEAR_MEMORY_NAME: &'static str = "memory"; - /// The name of the containing module for all WASI imports. - pub(crate) const WASI_SNAPSHOT_MODULE_NAME: &'static str = "wasi_snapshot_preview1"; - /// The name of the containing module for Veracruz imports. - pub(crate) const VERACRUZ_SI_MODULE_NAME: &'static str = "veracruz_si"; - - //////////////////////////////////////////////////////////////////////////// - // Creating and modifying runtime states. - //////////////////////////////////////////////////////////////////////////// - - /// Creates a new initial `WasiWrapper`. It will spawn a new filesystem - /// `filesystem` and register a set of environment variable bindings, - /// `environment_variables`. - #[inline] - pub fn new( - filesystem: FileSystem, - Options { - environment_variables, - program_arguments, - enable_clock, - enable_strace, - }: Options, - ) -> FileSystemResult { - Ok(Self { - filesystem, - //TODO make it pass from outside - environment_variables, - program_arguments, - enable_clock, - enable_strace, - exit_code: None, - }) - } - - /////////////////////////////////////////////////////// - //// Functions for the execution engine internal - /////////////////////////////////////////////////////// - - /// Returns the exit code from the `proc_exit` call of the last executing - /// program, if any. - #[inline] - pub(crate) fn exit_code(&self) -> Option { - self.exit_code - } - - /// Return a timestamp value for use by "filestat" functions, - /// which will be zero if the clock is not enabled. - fn filestat_time(&self) -> Timestamp { - let time0 = Timestamp::from_nanos(0); - if !self.enable_clock { - time0 - } else { - match getclocktime(ClockId::RealTime as u8) { - result::Result::Success(timespec) => Timestamp::from_nanos(timespec), - _ => time0, - } - } - } - - fn strace(&self, func: &str) -> Strace { - Strace::func(self.enable_strace, func) - } - - //////////////////////////////////////////////////////////////////////////// - // WASI implementation - //////////////////////////////////////////////////////////////////////////// - - /// The implementation of the WASI `args_get` function. It requires - /// an extra `memory_ref` to interact with the execution engine. - pub(crate) fn args_get( - &self, - memory_ref: &mut T, - address_for_string_ptrs: u32, - buf_address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("args_get"); - let result = (|| { - let buffer = self - .program_arguments - .iter() - .map(|arg| format!("{}\0", arg).into_bytes()) - .collect::>(); - memory_ref.write_string_list(&buffer, buf_address, address_for_string_ptrs) - })(); - strace.arg_dots(); - strace.result(result) - } - - /// The implementation of the WASI `args_sizes_get` function. It requires - /// an extra `memory_ref` to interact with the execution engine. - pub(crate) fn args_sizes_get( - &self, - memory_ref: &mut T, - address_for_counts: u32, - address_for_buffer_size: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("args_sizes_get"); - let result = (|| { - let environc = self.program_arguments.len() as u32; - let environ_buf_size = self - .program_arguments - .iter() - .fold(0, |acc, arg| acc + format!("{}\0", arg).as_bytes().len()); - - memory_ref.write_u32(address_for_counts, environc)?; - memory_ref.write_u32(address_for_buffer_size, environ_buf_size as u32) - })(); - strace.arg_dots(); - strace.result(result) - } - - /// The implementation of the WASI `environ_get` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn environ_get( - &self, - memory_ref: &mut T, - address_for_string_ptrs: u32, - buf_address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("environ_get"); - let result = (|| { - let buffer = self - .environment_variables - .iter() - .map(|(key, value)| { - let environ = format!("{}={}\0", key, value); - environ.into_bytes() - }) - .collect::>(); - memory_ref.write_string_list(&buffer, buf_address, address_for_string_ptrs) - })(); - strace.arg_dots(); - strace.result(result) - } - - /// THe implementation of the WASI `environ_sizes_get` function. It - /// requires extra `memory_ref` to interact with the execution engine. - pub(crate) fn environ_sizes_get( - &self, - memory_ref: &mut T, - address_for_counts: u32, - address_for_buffer_size: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("environ_sizes_get"); - let result = (|| { - let environc = self.environment_variables.len() as u32; - let environ_buf_size = self - .environment_variables - .iter() - .fold(0, |acc, (key, value)| { - acc + format!("{}={}\0", key, value).as_bytes().len() - }); - - memory_ref.write_u32(address_for_counts, environc)?; - memory_ref.write_u32(address_for_buffer_size, environ_buf_size as u32) - })(); - strace.arg_dots(); - strace.result(result) - } - - /// The implementation of the WASI `clock_res_get` function. It requires - /// an extra `memory_ref` to interact with the execution engine. - pub(crate) fn clock_res_get( - &mut self, - memory_ref: &mut T, - clock_id: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("clock_res_get"); - let result = (|| { - let result = if !self.enable_clock { - Err(ErrNo::Access) - } else { - let clock_id = clock_id as u8; - match getclockres(clock_id) { - result::Result::Success(resolution) => Ok(Timestamp::from_nanos(resolution)), - result::Result::Unavailable => Err(ErrNo::NoSys), - _ => Err(ErrNo::Inval), - } - }?; - memory_ref.write_u64(address, result.as_nanos()) - })(); - strace.arg_dec(clock_id); - strace.arg_p_u64(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `clock_time_get` function. It requires - /// an extra `memory_ref` to interact with the execution engine. - pub(crate) fn clock_time_get( - &mut self, - memory_ref: &mut T, - clock_id: u32, - precision: u64, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("clock_time_get"); - let result = (|| { - let result = if !self.enable_clock { - Err(ErrNo::Access) - } else { - let clock_id = clock_id as u8; - match getclocktime(clock_id) { - result::Result::Success(timespec) => Ok(Timestamp::from_nanos(timespec)), - result::Result::Unavailable => Err(ErrNo::NoSys), - _ => Err(ErrNo::Inval), - } - }?; - memory_ref.write_u64(address, result.as_nanos()) - })(); - strace.arg_dec(clock_id); - strace.arg_dec(precision); - strace.arg_p_u64(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_advise` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_advise( - &mut self, - _: &mut T, - fd: u32, - offset: u64, - len: u64, - advice: u8, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_advise"); - let result = (|| { - let advice: Advice = Self::decode_wasi_arg(advice)?; - self.filesystem.fd_advise(fd.into(), offset, len, advice) - })(); - strace.arg_dec(fd); - strace.arg_dec(offset); - strace.arg_dec(len); - strace.arg_dec(advice); - strace.result(result) - } - - /// The implementation of the WASI `fd_allocate` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_allocate( - &mut self, - _: &mut T, - fd: u32, - offset: u64, - len: u64, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_allocate"); - let result = self.filesystem.fd_allocate(fd.into(), offset, len); - strace.arg_dec(fd); - strace.arg_dec(offset); - strace.arg_dec(len); - strace.result(result) - } - - /// The implementation of the WASI `fd_close` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn fd_close( - &mut self, - _memory_ref: &T, - fd: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_close"); - let result = self.filesystem.fd_close(fd.into()); - strace.arg_dec(fd); - strace.result(result) - } - - /// The implementation of the WASI `fd_datasync` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn fd_datasync( - &mut self, - _: &mut T, - fd: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_datasync"); - let result = self.filesystem.fd_datasync(fd.into()); - strace.arg_dec(fd); - strace.result(result) - } - - /// The implementation of the WASI `fd_fdstat_get` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_fdstat_get( - &self, - memory_ref: &mut T, - fd: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_fdstat_get"); - let result = (|| { - let stat = self.filesystem.fd_fdstat_get(fd.into())?; - memory_ref.write_struct(address, &stat) - })(); - strace.arg_dec(fd); - strace.arg_fdstat(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_fdstat_set_flags` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_fdstat_set_flags( - &mut self, - _: &mut T, - fd: u32, - flags: u16, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_fdstat_set_flags"); - let result = (|| { - let flags: FdFlags = Self::decode_wasi_arg(flags)?; - self.filesystem.fd_fdstat_set_flags(fd.into(), flags) - })(); - strace.arg_dec(fd); - strace.arg_hex(flags); - strace.result(result) - } - - /// The implementation of the WASI `fd_fdstat_set_rights` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_fdstat_set_rights( - &mut self, - _: &mut T, - fd: u32, - rights_base: u64, - rights_inheriting: u64, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_fdstat_set_rights"); - let result = (|| { - let rights_base: Rights = Self::decode_wasi_arg(rights_base)?; - let rights_inheriting: Rights = Self::decode_wasi_arg(rights_inheriting)?; - self.filesystem - .fd_fdstat_set_rights(fd.into(), rights_base, rights_inheriting) - })(); - strace.arg_dec(fd); - strace.arg_hex(rights_base); - strace.arg_hex(rights_inheriting); - strace.result(result) - } - - /// The implementation of the WASI `fd_filestat_get` function. It requires - /// an extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_filestat_get( - &self, - memory_ref: &mut T, - fd: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_filestat_get"); - let result = (|| { - let stat = self.filesystem.fd_filestat_get(fd.into()); - memory_ref.write_struct(address, &stat) - })(); - strace.arg_dec(fd); - strace.arg_filestat(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_filestat_set_size` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn fd_filestat_set_size( - &mut self, - _: &mut T, - fd: u32, - size: u64, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_filestat_set_size"); - let result = self.filesystem.fd_filestat_set_size(fd.into(), size); - strace.arg_dec(fd); - strace.arg_dec(size); - strace.result(result) - } - - /// The implementation of the WASI `fd_filestat_set_times` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_filestat_set_times( - &mut self, - _: &mut T, - fd: u32, - atime: u64, - mtime: u64, - fst_flag: u16, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_filestat_set_times"); - let result = (|| { - let fst_flag: SetTimeFlags = Self::decode_wasi_arg(fst_flag)?; - self.filesystem.fd_filestat_set_times( - fd.into(), - atime.into(), - mtime.into(), - fst_flag, - self.filestat_time(), - ) - })(); - strace.arg_dec(fd); - strace.arg_dec(atime); - strace.arg_dec(mtime); - strace.arg_hex(fst_flag); - strace.result(result) - } - - /// The implementation of the WASI `fd_pread` function. It requires an extra - /// `memory_ref` to interact with the execution engine. - pub(crate) fn fd_pread( - &mut self, - memory_ref: &mut T, - fd: u32, - iovec_base: u32, - iovec_count: u32, - offset: u64, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_pread"); - let result = (|| { - let size_read = { - let mut iovecs = memory_ref.unpack_iovec_mut(iovec_base, iovec_count)?; - self.filesystem - .fd_pread(fd.into(), iovecs.as_mut(), offset)? - }; - memory_ref.write_u32(address, size_read as u32) - })(); - strace.arg_dec(fd); - strace.arg_iovec(result, memory_ref, iovec_base, iovec_count, address); - strace.arg_dec(offset); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_prestat_get` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn fd_prestat_get( - &mut self, - memory_ref: &mut T, - fd: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_prestat_get"); - let result = (|| { - let fd = Fd(fd); - let pre = self.filesystem.fd_prestat_get(fd)?; - memory_ref.write_struct(address, &pre) - })(); - strace.arg_dec(fd); - strace.arg_prestat_out(result, memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_prestat_dir_name` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_prestat_dir_name( - &mut self, - memory_ref: &mut T, - fd: u32, - address: u32, - size: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_prestat_dir_name"); - let result = (|| { - let size = size as usize; - let result = self - .filesystem - .fd_prestat_dir_name(fd.into())? - .into_os_string(); - if result.len() > size as usize { - return Err(ErrNo::NameTooLong); - } - let result = result.into_string().map_err(|_| ErrNo::Inval)?; - memory_ref.write_buffer(address, result.as_bytes()) - })(); - strace.arg_dec(fd); - strace.arg_path(memory_ref, address, size); - strace.arg_dec(size); - strace.result(result) - } - - /// The implementation of the WASI `fd_pwrite` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_pwrite( - &mut self, - memory_ref: &mut T, - fd: u32, - iovec_base: u32, - iovec_count: u32, - offset: u64, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_pwrite"); - let result = (|| { - let size_written = { - let iovecs = memory_ref.unpack_iovec(iovec_base, iovec_count)?; - self.filesystem - .fd_pwrite(fd.into(), iovecs.as_ref(), offset)? - }; - memory_ref.write_u32(address, size_written as u32) - })(); - strace.arg_dec(fd); - strace.arg_iovec(result, memory_ref, iovec_base, iovec_count, address); - strace.arg_dec(offset); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_read` function. It requires an extra - /// `memory_ref` to interact with the execution engine. - pub(crate) fn fd_read( - &mut self, - memory_ref: &mut T, - fd: u32, - iovec_base: u32, - iovec_count: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_read"); - let result = (|| { - let size_read = { - let mut iovecs = memory_ref.unpack_iovec_mut(iovec_base, iovec_count)?; - self.filesystem.fd_read(fd.into(), iovecs.as_mut())? - }; - memory_ref.write_u32(address, size_read as u32) - })(); - strace.arg_dec(fd); - strace.arg_iovec(result, memory_ref, iovec_base, iovec_count, address); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_readdir` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn fd_readdir( - &mut self, - memory_ref: &mut T, - fd: u32, - mut buf_ptr: u32, - buf_len: u32, - cookie: u64, - result_ptr: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_readdir"); - let result = (|| { - let dir_entries = self.filesystem.fd_readdir(fd.into(), cookie.into())?; - - let mut written = 0; - for (dir, path) in dir_entries { - // NB: `buf_len` is the number of bytes dir entries can store. - // If there is not enough space, stop writing and leave the rest - // of the buffer untouched. - written += size_of::() as u32; - if written > buf_len { - written = buf_len; - break; - } - memory_ref.write_struct(buf_ptr, &dir)?; - buf_ptr += size_of::() as u32; - - written += path.len() as u32; - if written > buf_len { - written = buf_len; - break; - } - memory_ref.write_buffer(buf_ptr, &path)?; - buf_ptr += path.len() as u32; - } - memory_ref.write_u32(result_ptr, written as u32) - })(); - strace.arg_dec(fd); - strace.arg_dirents(memory_ref, buf_ptr, buf_len, result_ptr); - strace.arg_dec(cookie); - strace.arg_p_u32(memory_ref, result_ptr); - strace.result(result) - } - - /// The implementation of the WASI `fd_renumber` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn fd_renumber( - &mut self, - _: &mut T, - old_fd: u32, - new_fd: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_renumber"); - let result = self.filesystem.fd_renumber(old_fd.into(), new_fd.into()); - strace.arg_dec(old_fd); - strace.arg_dec(new_fd); - strace.result(result) - } - - /// The implementation of the WASI `fd_seek` function. - pub(crate) fn fd_seek( - &mut self, - memory_ref: &mut T, - fd: u32, - offset: i64, - whence: u8, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_seek"); - let result = (|| { - let whence: Whence = Self::decode_wasi_arg(whence)?; - let new_offset = self.filesystem.fd_seek(fd.into(), offset, whence)?; - memory_ref.write_u64(address, new_offset) - })(); - strace.arg_dec(fd); - strace.arg_dec(offset); - strace.arg_dec(whence); - strace.arg_p_u64(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_sync` function. It requires an extra - /// `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn fd_sync(&mut self, _: &mut T, fd: u32) -> FileSystemResult<()> { - let mut strace = self.strace("fd_sync"); - let result = self.filesystem.fd_sync(fd.into()); - strace.arg_dec(fd); - strace.result(result) - } - - /// The implementation of the WASI `fd_tell` function. It requires an extra - /// `memory_ref` to interact with the execution engine. - pub(crate) fn fd_tell( - &self, - memory_ref: &mut T, - fd: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_tell"); - let result = (|| { - let offset = self.filesystem.fd_tell(fd.into())?; - memory_ref.write_u64(address, offset) - })(); - strace.arg_dec(fd); - strace.arg_p_u64(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `fd_write` function. It requires an extra - /// `memory_ref` to interact with the execution engine. - pub(crate) fn fd_write( - &mut self, - memory_ref: &mut T, - fd: u32, - iovec_base: u32, - iovec_count: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("fd_write"); - let result = (|| { - let size_written = { - let iovecs = memory_ref.unpack_iovec(iovec_base, iovec_count)?; - self.filesystem.fd_write(fd.into(), iovecs.as_ref())? - }; - memory_ref.write_u32(address, size_written as u32) - })(); - strace.arg_dec(fd); - strace.arg_iovec(result, memory_ref, iovec_base, iovec_count, address); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `path_create_directory` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_create_directory( - &mut self, - memory_ref: &mut T, - fd: u32, - path_address: u32, - path_length: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_create_directory"); - let result = (|| { - let path = memory_ref.read_cstring(path_address, path_length)?; - self.filesystem.path_create_directory(fd.into(), path) - })(); - strace.arg_dec(fd); - strace.arg_path(memory_ref, path_address, path_length); - strace.result(result) - } - - /// The implementation of the WASI `path_filestat_get` function. It requires - /// an extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_filestat_get( - &mut self, - memory_ref: &mut T, - fd: u32, - flags: u32, - path_address: u32, - path_length: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_filestat_get"); - let result = (|| { - let path = memory_ref.read_cstring(path_address, path_length)?; - let flags: LookupFlags = Self::decode_wasi_arg(flags)?; - let stat = self.filesystem.path_filestat_get(fd.into(), flags, path)?; - memory_ref.write_struct(address, &stat) - })(); - strace.arg_dec(fd); - strace.arg_hex(flags); - strace.arg_path(memory_ref, path_address, path_length); - strace.arg_filestat(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `path_filestat_set_times` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_filestat_set_times( - &mut self, - memory_ref: &mut T, - fd: u32, - flags: u32, - path_address: u32, - path_length: u32, - atime: u64, - mtime: u64, - fst_flag: u16, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_filestat_set_times"); - let result = (|| { - let path = memory_ref.read_cstring(path_address, path_length)?; - let flags: LookupFlags = Self::decode_wasi_arg(flags)?; - let fst_flag: SetTimeFlags = Self::decode_wasi_arg(fst_flag)?; - - self.filesystem.path_filestat_set_times( - fd.into(), - flags, - path, - atime.into(), - mtime.into(), - fst_flag, - self.filestat_time(), - ) - })(); - strace.arg_dec(fd); - strace.arg_hex(flags); - strace.arg_path(memory_ref, path_address, path_length); - strace.arg_dec(atime); - strace.arg_dec(mtime); - strace.arg_hex(fst_flag); - strace.result(result) - } - - /// The implementation of the WASI `path_link` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_link( - &mut self, - memory_ref: &mut T, - old_fd: u32, - old_flags: u32, - old_address: u32, - old_path_len: u32, - new_fd: u32, - new_address: u32, - new_path_len: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_link"); - let result = (|| { - let old_flags: LookupFlags = Self::decode_wasi_arg(old_flags)?; - let old_path = memory_ref.read_cstring(old_address, old_path_len)?; - let new_path = memory_ref.read_cstring(new_address, new_path_len)?; - self.filesystem - .path_link(old_fd.into(), old_flags, old_path, new_fd.into(), new_path) - })(); - strace.arg_dec(old_fd); - strace.arg_hex(old_flags); - strace.arg_path(memory_ref, old_address, old_path_len); - strace.arg_dec(new_fd); - strace.arg_path(memory_ref, new_address, new_path_len); - strace.result(result) - } - - /// The implementation of the WASI `path_open` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_open( - &mut self, - memory_ref: &mut T, - fd: u32, - dir_flags: u32, - path_address: u32, - path_length: u32, - oflags: u16, - fs_rights_base: u64, - fs_rights_inheriting: u64, - fd_flags: u16, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_open"); - let result = (|| { - let fd = Fd(fd); - let path = memory_ref.read_cstring(path_address, path_length)?; - let dir_flags: LookupFlags = Self::decode_wasi_arg(dir_flags)?; - let oflags: OpenFlags = Self::decode_wasi_arg(oflags)?; - let fs_rights_base: Rights = Self::decode_wasi_arg(fs_rights_base)?; - let fs_rights_inheriting: Rights = Self::decode_wasi_arg(fs_rights_inheriting)?; - let fd_flags: FdFlags = Self::decode_wasi_arg(fd_flags)?; - - let new_fd = self.filesystem.path_open( - fd, - dir_flags, - &path, - oflags, - fs_rights_base, - fs_rights_inheriting, - fd_flags, - )?; - memory_ref.write_u32(address, new_fd.into()) - })(); - strace.arg_dec(fd); - strace.arg_hex(dir_flags); - strace.arg_path(memory_ref, path_address, path_length); - strace.arg_hex(oflags); - strace.arg_rights(fs_rights_base); - strace.arg_rights(fs_rights_inheriting); - strace.arg_hex(fd_flags); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `path_readlink` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_readlink( - &mut self, - memory_ref: &mut T, - fd: u32, - path_address: u32, - path_length: u32, - buf: u32, - buf_len: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_readlink"); - let result = (|| { - let path = memory_ref.read_cstring(path_address, path_length)?; - let mut rst = self.filesystem.path_readlink(fd.into(), path)?; - let buf_len = buf_len as usize; - let to_write = if buf_len < rst.len() { - buf_len - } else { - rst.len() - }; - //NOTE: it should at most shrink the size of rst. - rst.resize(to_write, 0); - memory_ref.write_buffer(buf, &rst)?; - memory_ref.write_u32(address, to_write as u32) - })(); - strace.arg_dec(fd); - strace.arg_path(memory_ref, path_address, path_length); - strace.arg_path(memory_ref, buf, buf_len); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `path_remove_directory` function. It - /// requires an extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_remove_directory( - &mut self, - memory_ref: &mut T, - fd: u32, - path_address: u32, - path_length: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_remove_directory"); - let result = (|| { - let path = memory_ref.read_cstring(path_address, path_length)?; - self.filesystem.path_remove_directory(fd.into(), path) - })(); - strace.arg_dec(fd); - strace.arg_path(memory_ref, path_address, path_length); - strace.result(result) - } - - /// The implementation of the WASI `path_rename` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_rename( - &mut self, - memory_ref: &mut T, - old_fd: u32, - old_address: u32, - old_path_len: u32, - new_fd: u32, - new_address: u32, - new_path_len: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_rename"); - let result = (|| { - let old_path = memory_ref.read_cstring(old_address, old_path_len)?; - let new_path = memory_ref.read_cstring(new_address, new_path_len)?; - self.filesystem - .path_rename(old_fd.into(), old_path, new_fd.into(), new_path) - })(); - strace.arg_dec(old_fd); - strace.arg_path(memory_ref, old_address, old_path_len); - strace.arg_dec(new_fd); - strace.arg_path(memory_ref, new_address, old_path_len); - strace.result(result) - } - - /// The implementation of the WASI `path_symlink` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_symlink( - &mut self, - memory_ref: &mut T, - old_address: u32, - old_path_len: u32, - fd: u32, - new_address: u32, - new_path_len: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_symlink"); - let result = (|| { - let old_path = memory_ref.read_cstring(old_address, old_path_len)?; - let new_path = memory_ref.read_cstring(new_address, new_path_len)?; - self.filesystem.path_symlink(old_path, fd.into(), new_path) - })(); - strace.arg_path(memory_ref, old_address, old_path_len); - strace.arg_dec(fd); - strace.arg_path(memory_ref, new_address, old_path_len); - strace.result(result) - } - - /// The implementation of the WASI `path_unlink_file` function. It requires - /// an extra `memory_ref` to interact with the execution engine. - pub(crate) fn path_unlink_file( - &mut self, - memory_ref: &mut T, - fd: u32, - path_address: u32, - path_len: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("path_unlink_file"); - let result = (|| { - let path = memory_ref.read_cstring(path_address, path_len)?; - self.filesystem.path_unlink_file(fd.into(), path) - })(); - strace.arg_dec(fd); - strace.arg_path(memory_ref, path_address, path_len); - strace.result(result) - } - - /// The implementation of the WASI `poll_oneoff` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn poll_oneoff( - &mut self, - memory_ref: &mut T, - subscriptions: u32, - events: u32, - size: u32, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("poll_oneoff"); - let result = (|| { - let subscriptions = memory_ref.unpack_array::(subscriptions, size)?; - let events = memory_ref.unpack_array::(events, size)?; - let rst = self.filesystem.poll_oneoff(subscriptions, events)?; - memory_ref.write_u32(address, rst) - })(); - strace.arg_subscriptions(memory_ref, subscriptions, size); - strace.arg_events(memory_ref, events, size); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `proc_exit` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn proc_exit(&mut self, _: &mut T, exit_code: u32) { - let _strace = self.strace("proc_exit"); - self.exit_code = Some(exit_code) - } - - /// The implementation of the WASI `proc_raise` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn proc_raise( - &mut self, - _: &mut T, - signal: u8, - ) -> FileSystemResult<()> { - let mut strace = self.strace("proc_raise"); - let result = (|| { - let _signal: Signal = Self::decode_wasi_arg(signal)?; - Err(ErrNo::NoSys) - })(); - strace.arg_dec(signal); - strace.result(result) - } - - /// The implementation of the WASI `sched_yield` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - #[inline] - pub(crate) fn sched_yield(&mut self, _: &mut T) -> FileSystemResult<()> { - let mut strace = self.strace("sched_yield"); - strace.result(Err(ErrNo::NoSys)) - } - - pub(crate) fn random_get( - &mut self, - memory_ref: &mut T, - buf_ptr: u32, - length: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("random_get"); - let result = (|| { - let mut bytes = vec![0; length as usize]; - if getrandom(&mut bytes).is_success() { - memory_ref.write_buffer(buf_ptr, &bytes) - } else { - Err(ErrNo::NoSys) - } - })(); - strace.arg_buffer(memory_ref, buf_ptr, length); - strace.result(result) - } - - /// The implementation of the WASI `sock_recv` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn sock_recv( - &mut self, - memory_ref: &mut T, - socket: u32, - ri_address: u32, - ri_len: u32, - ri_flag: u16, - ro_data_len: u32, - ro_flag: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("sock_recv"); - let result = (|| { - let (size_read, ro_flags) = { - let mut iovecs = memory_ref.unpack_iovec_mut(ri_address, ri_len)?; - let ri_flags: RiFlags = Self::decode_wasi_arg(ri_flag)?; - self.filesystem - .sock_recv(socket.into(), iovecs.as_mut(), ri_flags)? - }; - let ro_flags = RoFlags::empty() | ro_flags; - memory_ref.write_u32(ro_data_len, size_read as u32)?; - memory_ref.write_buffer(ro_flag, &u16::to_le_bytes(ro_flags.bits())) - })(); - strace.arg_dec(socket); - strace.arg_iovec(result, memory_ref, ri_address, ri_len, ro_data_len); - strace.arg_hex(ri_flag); - strace.arg_p_u32(memory_ref, ro_data_len); - strace.arg_p_u16_hex(memory_ref, ro_flag); - strace.result(result) - } - - /// The implementation of the WASI `sock_send` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn sock_send( - &mut self, - memory_ref: &mut T, - socket: u32, - si_address: u32, - si_len: u32, - si_flag: u16, - address: u32, - ) -> FileSystemResult<()> { - let mut strace = self.strace("sock_send"); - let result = (|| { - let size_written = { - let iovecs = memory_ref.unpack_iovec(si_address, si_len)?; - let si_flags: SiFlags = Self::decode_wasi_arg(si_flag)?; - self.filesystem - .sock_send(socket.into(), iovecs.as_ref(), si_flags)? - }; - memory_ref.write_u32(address, size_written as u32) - })(); - strace.arg_iovec(result, memory_ref, si_address, si_len, address); - strace.arg_hex(si_flag); - strace.arg_p_u32(memory_ref, address); - strace.result(result) - } - - /// The implementation of the WASI `sock_recv` function. It requires an - /// extra `memory_ref` to interact with the execution engine. - pub(crate) fn sock_shutdown( - &mut self, - _: &mut T, - socket: u32, - sd_flag: u8, - ) -> FileSystemResult<()> { - let mut strace = self.strace("sock_shutdown"); - let result = (|| { - let sd_flag: SdFlags = Self::decode_wasi_arg(sd_flag)?; - self.filesystem.sock_shutdown(socket.into(), sd_flag) - })(); - strace.arg_dec(socket); - strace.arg_hex(sd_flag); - strace.result(result) - } - - /// This function, added for Veracruz, creates a new anonymous file. - pub(crate) fn fd_create( - &mut self, - memory_ref: &mut T, - address: u32, - ) -> FileSystemResult<()> { - let new_fd = self.filesystem.fd_create()?; - memory_ref.write_u32(address, new_fd.into()) - } - - /////////////////////////////////////// - // Internal methods - /////////////////////////////////////// - /// Converts `arg` of type `R` to type `T`, - /// or returns from the function with the `Inval` error code. - #[inline] - fn decode_wasi_arg, R>(arg: R) -> FileSystemResult { - T::try_from(arg).map_err(|_| ErrNo::Inval) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Fatal execution errors/runtime panics. -//////////////////////////////////////////////////////////////////////////////// - -/// A fatal, runtime error that terminates the Veracruz execution immediately. -/// This is akin to a "kernel panic" for Veracruz: these errors are not passed -/// to the WASM program running on the platform, but are instead fundamental -/// issues that require immediate shutdown as they cannot be fixed. -/// -/// *NOTE*: care should be taken when presenting these errors to users when in -/// release (e.g. not in debug) mode: they can give away a lot of information -/// about what is going on inside the enclave. -#[derive(Debug, Error, Serialize, Deserialize)] -pub enum FatalEngineError { - /// The WASM module supplied by the program supplier was invalid and could - /// not be parsed. - #[error(display = "FatalEngineError: Invalid WASM program (e.g. failed to parse it).")] - InvalidWASMModule, - /// The Veracruz engine was passed bad arguments by the WASM program running - /// on the platform. This should never happen if the WASM program uses - /// `libveracruz` as the platform should ensure H-Calls are always - /// well-formed. Seeing this either indicates a bug in `libveracruz` or a - /// programming error in the source that originated the WASM programming if - /// `libveracruz` was not used. - #[error( - display = "FatalEngineError: Bad arguments passed to host function '{:?}'.", - function_name - )] - BadArgumentsToHostFunction { - /// The name of the host function that was being invoked. - function_name: WasiAPIName, - }, - /// The WASM program tried to invoke an unknown H-call on the Veracruz engine. - #[error(display = "FatalEngineError: Unknown Host call invoked: '{:?}'.", _0)] - UnknownHostFunction(HostFunctionIndexOrName), - /// No linear memory was registered: this is a programming error (a bug) - /// that should be fixed. - #[error(display = "FatalEngineError: No WASM memory registered.")] - NoMemoryRegistered, - /// No program module was registered: this is a programming error (a bug) - /// that should be fixed. - #[error(display = "FatalEngineError: No WASM program module registered.")] - NoProgramModuleRegistered, - /// The WASM program's entry point was missing or malformed. - #[error(display = "FatalEngineError: Failed to find the entry point in the WASM program.")] - NoProgramEntryPoint, - /// The WASM program's entry point was missing or malformed. - #[error(display = "FatalEngineError: Execution engine is not ready.")] - EngineIsNotReady, - /// Wrapper for direct error message. - #[error(display = "FatalEngineError: WASM program returns code other than wasi ErrNo.")] - ReturnedCodeError, - /// The lock to engine could not be obtained. - #[error( - display = "FatalEngineError: Failed to obtain lock on the engine or components of the engine." - )] - FailedLockEngine, - /// The lock to file system could not be obtained. - #[error(display = "FatalEngineError: Failed to obtain lock on the file system.")] - FailedLockFileSystem, - /// Engine trap. - #[error(display = "FatalEngineError: Wasm engine trap: {:?}", _0)] - Trap(String), -} - -/// Either the index or the name of a host call -#[derive(Debug, Serialize, Deserialize)] -pub enum HostFunctionIndexOrName { - Index(usize), - Name(String), -} - -//////////////////////////////////////////////////////////////////////////////// -// Implementation of the H-calls. -//////////////////////////////////////////////////////////////////////////////// - -/// Details the arguments expected by the module's entry point, if any is found. -pub(crate) enum EntrySignature { - /// The expected entry point (e.g. "main") is not found in the WASM module - /// or it was found and it did not have a recognisable type signature. - NoEntryFound, - /// The entry point does not expect any parameters. - NoParameters, - /// The entry point expects a dummy `argv` and an `argc` to be supplied. - ArgvAndArgc, -} - -//////////////////////////////////////////////////////////////////////////////// -// The strategy trait. -//////////////////////////////////////////////////////////////////////////////// - -/// This is what an execution strategy exposes to clients outside of this -/// library. This functionality is sufficient to implement both -/// `freestanding-execution-engine` and `runtime-manager` and if any -/// functionality is missing that these components require then it should be -/// added to this trait and implemented for all supported implementation -/// strategies. -pub trait ExecutionEngine: Send { - /// Entry point for the execution engine: invokes the `program` binary, - /// Returns `Ok(c)` if it successfully executed and returned a - /// success/error code, `c`, or returns `Err(e)` if some fatal execution - /// engine error occurred at runtime causing the pipeline to abort. - fn invoke_entry_point(&mut self, program: Vec) -> Result; -} diff --git a/crates/execution-engine/src/engines/mod.rs b/crates/execution-engine/src/engines/mod.rs index 051036e96..d95636f63 100644 --- a/crates/execution-engine/src/engines/mod.rs +++ b/crates/execution-engine/src/engines/mod.rs @@ -9,8 +9,6 @@ //! See the `LICENSE.md` file in the Veracruz root directory for //! information on licensing and copyright. -pub mod common; -pub mod strace; -pub(crate) mod wasmi; #[cfg(feature = "std")] pub(crate) mod wasmtime; +pub(crate) mod sandbox; diff --git a/crates/execution-engine/src/engines/sandbox.rs b/crates/execution-engine/src/engines/sandbox.rs new file mode 100644 index 000000000..0dba60048 --- /dev/null +++ b/crates/execution-engine/src/engines/sandbox.rs @@ -0,0 +1,218 @@ +//! The Veracruz native module manager +//! +//! This module manages the execution of native modules. It supports the +//! execution of static, dynamic and provisioned native modules (cf. +//! `NativeModuleType` for more details). +//! For the dynamic and provisioned ones, the native module manager prepares a +//! sandbox environment before running them inside it. The execution environment +//! is torn down after computation as a security precaution. +//! +//! Native modules follow the specifications below: +//! - A native module has a name, special file and entry point +//! - A native module has the same access rights to the VFS as the WASM program +//! calling it. Provisioned native modules have their access rights specified +//! in the policy like a regular WASM program +//! - The caller (WASM program or participant) must provide an execution +//! configuration to the native module. For static and dynamic native +//! modules, it is provided via the native module's special file on the VFS. +//! For provisioned native modules, it is provided via the special +//! `EXECUTION_CONFIGURATION_FILE` on the VFS. +//! It is up to the caller and native module to determine how the data is +//! encoded, however dynamic and provisioned native modules MUST read the +//! data from `EXECUTION_CONFIGURATION_FILE`, a file copied into the sandbox +//! environment by the native module manager. Static native modules, on the +//! other hand, read the data via `try_parse()` (cf. the `StaticNativeModule` +//! trait) +//! +//! ## Authors +//! +//! The Veracruz Development Team. +//! +//! ## Licensing and copyright notice +//! +//! See the `LICENSE.md` file in the Veracruz root directory for +//! information on licensing and copyright. + +use anyhow::{anyhow, Result}; +use log::info; +use std::{ + fs::{self, File, remove_dir_all, create_dir_all}, + io::{Write}, + path::{Path, PathBuf}, + process::Command +}; +use policy_utils::principal::PrincipalPermission; +use crate::Execution; +#[cfg(feature = "std")] +use nix::sys::signal; + +/// Path to the native module's manager sysroot on the kernel filesystem. Native +/// module directories are created under this directory. +const NATIVE_MODULE_MANAGER_SYSROOT: &str = "/tmp/nmm/"; + +/// Path to the native module sandboxer. This is the program that actually prepares +/// the sandbox environment and runs the native module in it. +const NATIVE_MODULE_MANAGER_SANDBOXER_PATH: &str = "/tmp/nmm/native-module-sandboxer"; + +/// Execution configuration file name. The input from the calling program is +/// written to this file, under the native module's directory, before running +/// the native module. +const EXECUTION_CONFIGURATION_FILE: &str = "execution_config"; + +/// Sandbox execution handler. +pub struct Sandbox { + native_module_directory: PathBuf, + execution_permissions: PrincipalPermission, +} + +impl Execution for Sandbox { + /// name of this execution. + fn name(&self) -> &str { + "Executing binary in sandbox." + } + + /// Execute the native binary program at `program_path`. + fn execute(&mut self, program_path: &Path) -> Result<()> { + + info!("Binary path {program_path:?}"); + // Inject execution configuration into the native module's directory + let mut config_file = File::create(self.native_module_directory.join(EXECUTION_CONFIGURATION_FILE))?; + + info!("Binary configuration file {config_file:?}"); + config_file.write_all(&vec![])?; + + // Enable SIGCHLD handling in order to synchronously execute the + // sandboxer. + // This is necessary as Veracruz-Server (Linux) disables SIGCHLD + // handling, which is inherited by the runtime manager + #[cfg(feature = "std")] + unsafe { + signal::sigaction( + signal::Signal::SIGCHLD, + &signal::SigAction::new( + signal::SigHandler::SigDfl, + signal::SaFlags::empty(), + signal::SigSet::empty(), + ), + )?; + } + + let execution_permissions = self.execution_permissions.iter().map(|(path, _permission)| { + path.clone() + }).collect(); + + info!("Directories to mount: {execution_permissions:?}"); + + let mount_mappings = build_mappings(&self.native_module_directory, execution_permissions)?; + info!("Binary mounted mapping {mount_mappings}"); + + let program_name = program_path.file_name().and_then(|os_str| os_str.to_str()).ok_or(anyhow!("Failed to extract program name from program path to a native binary."))?; + let entry_point = self.native_module_directory.join(program_name); + fs::copy(program_path, &entry_point)?; + let entry_point = entry_point.to_str().ok_or(anyhow!("Failed to convert entry point to str"))?; + + // Make sure the entry point is executable. + // This is a temporary workaround that only works on Linux. + Command::new("chmod").args(["500", entry_point]).output()?; + + info!("Calling sandboxer..."); + Command::new(NATIVE_MODULE_MANAGER_SANDBOXER_PATH) + .args([ + "--sandbox2tool_resolve_and_add_libraries", + "--sandbox2tool_mount_tmp", + "--sandbox2tool_additional_bind_mounts", + &mount_mappings, + "--sandbox2tool_file_size_creation_limit", + "1048576", + entry_point, + ]) + .output()?; + + info!("Tear down..."); + self.teardown_fs()?; + + Ok(()) + } +} + +impl Sandbox { + /// Create a sandbox at the (sub-)directory `dir_name` + /// on the path `${NATIVE_MODULE_MANAGER_SYSROOT}`, i.e., `/tmp/nmm/`. + pub(crate) fn new(execution_permissions: PrincipalPermission, dir_name: &str) -> Self { + info!("Create a new sandbox {dir_name}"); + let native_module_directory = PathBuf::from(NATIVE_MODULE_MANAGER_SYSROOT).join(dir_name); + + info!("Create a new sandbox from binary {dir_name}, going to be mounted at {native_module_directory:?}."); + let _ = create_dir_all(&native_module_directory); + Self { + native_module_directory, + execution_permissions, + } + } + + fn teardown_fs(&self) -> Result<()> { + remove_dir_all(self.native_module_directory.as_path())?; + Ok(()) + } +} + +impl Drop for Sandbox { + /// Drop the native module manager. + fn drop(&mut self) { + let _ = self.teardown_fs(); + } +} + +/// Build kernel-to-sandbox filesystem mappings palatable to the native +/// module sandboxer. +/// Takes a list of unprefixed paths, i.e. not including the path to the +/// native module's directory. +/// Returns the mappings as a string. +fn build_mappings(native_module_directory: &PathBuf, unprefixed_files: Vec) -> Result { + + info!("construct mappings from source: {unprefixed_files:?}"); + // Convert `path` in `unprefixed_files` into a string of format of + // `{target_path}=>{host_path}`, and then collect the result as a Vec, `mappings`. + let mut mappings = unprefixed_files.into_iter().fold(Ok(Vec::new()), |acc:Result>, path|{ + let mut acc = acc?; + // Remove the prefix, either relative path or abusolute path. + // e.g., `./foo` to `foo`, and `/foo/bar/` to `foo/bar/`. + // The resulting string will be `join` with + // the new prefix `{native_module_directory}`. + let target_path_directory = if path.has_root() { + path.strip_prefix("/")? + } else if path.is_relative() { + path.strip_prefix("./")? + + } else { &path }; + let mut target_path = native_module_directory.join(&target_path_directory).to_str() + .ok_or(anyhow!("Failed to convert native_module_directory to str"))? + .to_string(); + let host_path = path.canonicalize()?; + let host_path = host_path.to_str() + .ok_or(anyhow!("Failed to convert native_module_directory to str"))?; + + // Convert `target_path` and `host_path` to + // a string `{target_path}=>{host_path}`. + target_path.push_str("=>"); + target_path.push_str(host_path); + acc.push( target_path ); + Ok(acc) + })?; + + // Add the final `execution_config` mapping. + let mut execution_config = native_module_directory + .join(EXECUTION_CONFIGURATION_FILE) + .to_str() + .ok_or(anyhow!("Failed to convert {} to str", EXECUTION_CONFIGURATION_FILE))? + .to_owned(); + execution_config.push_str("=>/"); + execution_config.push_str(EXECUTION_CONFIGURATION_FILE); + + mappings.push(execution_config); + + info!("sandbox mappings: {mappings:?}"); + + // Convert the to the final string, where individual mapping is Concatenated by comma `,`. + Ok(mappings.join(",")) +} diff --git a/crates/execution-engine/src/engines/strace.rs b/crates/execution-engine/src/engines/strace.rs deleted file mode 100644 index 429d5dfdf..000000000 --- a/crates/execution-engine/src/engines/strace.rs +++ /dev/null @@ -1,318 +0,0 @@ -//! An implementation of the WASI API for Execution Engine. -//! -//! ## Authors -//! -//! The Veracruz Development Team. -//! -//! ## Licensing and copyright notice -//! -//! See the `LICENSE.md` file in the Veracruz root directory for -//! information on licensing and copyright. - -use super::common::MemoryHandler; -use crate::fs::FileSystemResult; -use log::info; -use std::fmt; - -/// How many characters to display from a string or memory buffer. -const BUFFER_DISPLAY_LEN: usize = 32; - -/// State of strace structure. -enum TraceState { - /// Initial state: we have only seen the function name. - Func, - /// We have seen one or more arguments. - Args, - /// We have seen the result of the function all. - Done, -} - -pub struct Strace { - enabled: bool, - state: TraceState, -} - -// Convert a vector of bytes into a printable ASCII string. -// The string may contain readable text, which is useful to display, -// but it may also contain binary data, so we cannot decode it as UTF-8. -fn strace_string(bytes: &[u8], max: usize) -> String { - let mut res = String::from("\""); - let n = if bytes.len() > max { max } else { bytes.len() }; - for i in 0..n { - if 0x20 <= bytes[i] && bytes[i] < 0x7f { - if bytes[i] == b'\\' || bytes[i] == b'"' { - res.push_str("\\"); - } - res.push_str(&String::from_utf8_lossy(&bytes[i..i + 1].to_vec())) - } else if bytes[i] == 9 { - res.push_str("\\t") - } else if bytes[i] == 10 { - res.push_str("\\n") - } else if i + 1 < n && b'0' <= bytes[i + 1] && bytes[i + 1] <= b'9' { - // The following character is a digit, so use three octal digits. - res.push_str(&format!("\\{:03o}", bytes[i])) - } else { - res.push_str(&format!("\\{:o}", bytes[i])) - } - } - res.push_str("\""); - if bytes.len() > max { - res.push_str("...") - } - res -} - -impl Strace { - /// Start generating strace output, given function name. - pub fn func(enabled: bool, name: &str) -> Self { - if enabled { - info!("{}(", name) - }; - Strace { - enabled, - state: TraceState::Func, - } - } - - /// Common code for handling arguments: prints comma as required. - fn arg_print_comma(&mut self) { - match self.state { - TraceState::Func => self.state = TraceState::Args, - TraceState::Args => { - info!(", "); - } - TraceState::Done => info!("\nUnexpected strace arg: "), - } - } - - /// Handle argument that is a memory buffer. - pub fn arg_buffer(&mut self, mem: &mut T, adr: u32, len: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - let mut bytes = vec![0u8; len as usize]; - match mem.read_buffer(adr, &mut bytes) { - Ok(()) => info!("{}", strace_string(&bytes, BUFFER_DISPLAY_LEN)), - Err(_) => info!("BAD_MEM_REF"), - } - } - - /// Handle argument as decimal value. - pub fn arg_dec(&mut self, n: T) { - if !self.enabled { - return; - } - self.arg_print_comma(); - info!("{}", n) - } - - /// Print ellipsis ("...") for argument that we do not display. - pub fn arg_dots(&mut self) { - if !self.enabled { - return; - } - self.arg_print_comma(); - info!("...") - } - - /// Handle argument that is a directory entry. - pub fn arg_dirents( - &mut self, - _mem: &mut T, - _buf_ptr: u32, - _buf_len: u32, - _result_ptr: u32, - ) { - if !self.enabled { - return; - } - self.arg_print_comma(); - // NOT YET IMPLEMENTED - info!("DIRENTS") - } - - /// Handle argument that represents events (for poll_oneoff). - pub fn arg_events(&mut self, _mem: &mut T, _events: u32, _size: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - // NOT YET IMPLEMENTED - info!("EVENTS") - } - - /// Handle argument fdstat (for fd_fdstat_get). - pub fn arg_fdstat(&mut self, _mem: &mut T, _adr: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - // NOT YET IMPLEMENTED - info!("FDSTAT") - } - - /// Handle argument filestat. - pub fn arg_filestat(&mut self, _mem: &mut T, _adr: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - // NOT YET IMPLEMENTED - info!("FILESTAT") - } - - /// Handle argument as hexadecimal value. - pub fn arg_hex(&mut self, n: T) { - if !self.enabled { - return; - } - self.arg_print_comma(); - info!("0x{:x}", n) - } - - /// Handle argument that is an iovec. - pub fn arg_iovec( - &mut self, - res: FileSystemResult<()>, - memory_ref: &mut T, - base: u32, - count: u32, - address: u32, - ) { - if !self.enabled { - return; - } - self.arg_print_comma(); - if !res.is_ok() { - info!("_"); - return; - } - if let Ok(len) = memory_ref.read_u32(address) { - // This inefficiently copies everything, but it's only used for tracing. - if let Ok(bufs) = memory_ref.unpack_iovec(base, count) { - let mut buf: Vec = Vec::new(); - for b in bufs.as_ref() { - buf.extend(b.as_ref()) - } - buf.truncate(len as usize); - info!("{}", strace_string(&buf, BUFFER_DISPLAY_LEN)) - } else { - info!("BAD_IOVEC") - } - } else { - info!("BAD_IOVEC_LEN") // This will probably never happen. - } - } - - /// Handle argument that is a pointer to u16, displayed as hex. - pub fn arg_p_u16_hex(&mut self, mem: &mut T, adr: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - match mem.read_u16(adr) { - Ok(x) => info!("0x{:x}", x), - Err(_) => info!("BAD_MEM_REF"), - } - } - - /// Handle argument that is a pointer to u32, displayed as hex. - pub fn arg_p_u32(&mut self, mem: &mut T, adr: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - match mem.read_u32(adr) { - Ok(x) => info!("{}", x), - Err(_) => info!("BAD_MEM_REF"), - } - } - - /// Handle argument that is a pointer to u64, displayed as hex. - pub fn arg_p_u64(&mut self, mem: &mut T, adr: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - match mem.read_u64(adr) { - Ok(x) => info!("{}", x), - Err(_) => info!("BAD_MEM_REF"), - } - } - - /// Handle argument that is a file path. - pub fn arg_path(&mut self, mem: &mut T, adr: u32, len: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - let mut bytes = vec![0u8; len as usize]; - match mem.read_buffer(adr, &mut bytes) { - Ok(()) => info!("{}", strace_string(&bytes, 1024)), - Err(_) => info!("BAD_MEM_REF"), - } - } - - /// Handle argument that is prestat (for fd_prestat_get). - pub fn arg_prestat_out( - &mut self, - res: FileSystemResult<()>, - mem: &mut T, - adr: u32, - ) { - if !self.enabled { - return; - } - self.arg_print_comma(); - if res.is_ok() { - match mem.read_u64(adr) { - Ok(x) => { - if x & 0xffffffff == 0 { - info!("{{len={}}}", x >> 32) - } else { - info!("BAD_PRESTAT"); - } - } - Err(_) => info!("BAD_MEM_REF"), - } - } else { - info!("_") - } - } - - /// Handle argument that represents access rights (for path_open). - pub fn arg_rights(&mut self, rights: u64) { - if !self.enabled { - return; - } - self.arg_print_comma(); - info!("0x{:x}", rights) - } - - /// Handle argument subscriptions (for poll_oneoff). - pub fn arg_subscriptions(&mut self, _mem: &mut T, _expr: u32, _size: u32) { - if !self.enabled { - return; - } - self.arg_print_comma(); - // NOT YET IMPLEMENTED - info!("SUBSCRIPTIONS") - } - - /// Handle results returned from function; this function is called last. - pub fn result(&mut self, result: FileSystemResult<()>) -> FileSystemResult<()> { - if !self.enabled { - return result; - } - match self.state { - TraceState::Done => info!("\nUnexpected strace result: "), - _ => self.state = TraceState::Done, - } - match result { - Ok(()) => info!(") = Success"), - Err(x) => info!(") = {:?}", x), - }; - result - } -} diff --git a/crates/execution-engine/src/engines/wasmi.rs b/crates/execution-engine/src/engines/wasmi.rs deleted file mode 100644 index a506ceaae..000000000 --- a/crates/execution-engine/src/engines/wasmi.rs +++ /dev/null @@ -1,1331 +0,0 @@ -//! An implementation of the ExecutionEngine runtime state for WASMI. -//! -//! ## Authors -//! -//! The Veracruz Development Team. -//! -//! ## Copyright -//! -//! See the file `LICENSE.md` in the Veracruz root directory for licensing -//! and copyright information. - -use crate::{ - engines::common::{ - Bound, BoundMut, EntrySignature, ExecutionEngine, FatalEngineError, - HostFunctionIndexOrName, MemoryHandler, VeracruzAPIName, WasiAPIName, WasiWrapper, - }, - fs::{FileSystem, FileSystemResult}, - Options, -}; -use anyhow::{anyhow, Result}; -use log::error; -use num::{FromPrimitive, ToPrimitive}; -use std::{boxed::Box, convert::TryFrom, mem, str::FromStr, string::ToString, vec::Vec}; -use wasi_types::ErrNo; -use wasmi::{ - Error, ExternVal, Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, HostError, - MemoryDescriptor, MemoryRef, Module, ModuleImportResolver, ModuleInstance, ModuleRef, - RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, ValueType, -}; - -#[derive(Debug, PartialEq, Clone, Copy)] -enum APIName { - WasiAPIName(WasiAPIName), - VeracruzAPIName(VeracruzAPIName), -} - -impl FromPrimitive for APIName { - fn from_i64(n: i64) -> Option { - if n < 0 { - None - } else { - Self::from_u64(n as u64) - } - } - fn from_u64(n: u64) -> Option { - if n == 0 { - None - } else if n < WasiAPIName::_LAST as u64 { - Some(APIName::WasiAPIName(WasiAPIName::from_u64(n).unwrap())) - } else { - match VeracruzAPIName::from_u64(n - WasiAPIName::_LAST as u64) { - Some(x) => Some(APIName::VeracruzAPIName(x)), - None => None, - } - } - } -} - -impl ToPrimitive for APIName { - fn to_i64(&self) -> Option { - Some(self.to_u64().unwrap() as i64) - } - fn to_u64(&self) -> Option { - match self { - APIName::WasiAPIName(WasiAPIName::_LAST) => unreachable!(), - APIName::WasiAPIName(x) => x.to_u64(), - APIName::VeracruzAPIName(x) => Some(WasiAPIName::_LAST as u64 + x.to_u64().unwrap()), - } - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Veracruz host errors. -//////////////////////////////////////////////////////////////////////////////// - -#[typetag::serde] -impl HostError for FatalEngineError {} - -//////////////////////////////////////////////////////////////////////////////// -// The WASMI host provisioning state. -//////////////////////////////////////////////////////////////////////////////// - -/// Impl the MemoryHandler for MemoryRef. -/// This allows passing the MemoryRef to WasiWrapper on any VFS call. -impl MemoryHandler for MemoryRef { - type Slice = &'static [u8]; - type SliceMut = &'static mut [u8]; - - fn get_slice(&self, address: u32, length: u32) -> FileSystemResult> { - let address = usize::try_from(address).unwrap(); - let length = usize::try_from(length).unwrap(); - // NOTE in more recent version of Wasmi, MemoryRef has a safe version of - // this function, `direct_access`, that allows access through an `impl AsRef<[u8]>`. - // For now the best we can do is a bit of unsafe code. - // - // Note that MemoryRef is already not threadsafe, so we don't have to worry - // about locking. - // - Ok(Bound::new(self.with_direct_access(|slice| { - let slice = &slice[address..address + length]; - unsafe { mem::transmute::<&'_ [u8], &'static [u8]>(slice) } - }))) - } - - fn get_slice_mut( - &mut self, - address: u32, - length: u32, - ) -> FileSystemResult> { - let address = usize::try_from(address).unwrap(); - let length = usize::try_from(length).unwrap(); - // NOTE in more recent version of Wasmi, MemoryRef has a safe version of - // this function, `direct_access`, that allows access through an `impl AsRef<[u8]>`. - // For now the best we can do is a bit of unsafe code. - // - // Note that MemoryRef is already not threadsafe, so we don't have to worry - // about locking. - // - Ok(BoundMut::new(self.with_direct_access_mut(|slice| { - let slice = &mut slice[address..address + length]; - unsafe { mem::transmute::<&'_ mut [u8], &'static mut [u8]>(slice) } - }))) - } - - fn get_size(&self) -> FileSystemResult { - let bytes = wasmi::memory_units::Bytes::from(self.current_size()).0; - Ok(u32::try_from(bytes).unwrap()) - } -} - -/// The WASMI host provisioning state: the `HostProvisioningState` with the -/// Module and Memory type-variables specialised to WASMI's `ModuleRef` and -/// `MemoryRef` type. -pub(crate) struct WASMIRuntimeState { - /// The WasiWrapper of the FileSystem. - vfs: WasiWrapper, - /// A reference to the WASM program module that will actually execute on - /// the input data sources. - program_module: Option, - /// A reference to the WASM program's linear memory (or "heap"). - memory: Option, -} -pub(crate) type WasiResult = Result; - -/// The return type for H-Call implementations. -/// -/// From *the viewpoint of the host* a H-call can either fail spectacularly -/// with a runtime trap, in which case `Err(err)` is returned, with `err` -/// detailing what went wrong, and the Veracruz host thereafter terminating -/// or otherwise entering an error state, or succeeds with `Ok(())`. -/// -/// From *the viewpoint of the WASM program* a H-call can either fail -/// spectacularly, as above, in which case WASM program execution is aborted -/// with the WASM program itself not being able to do anything about this, -/// succeeds with the desired effect and a success error code returned, or -/// fails with a recoverable error in which case the error code details what -/// went wrong and what can be done to fix it. - -//////////////////////////////////////////////////////////////////////////////// -// Constants. -//////////////////////////////////////////////////////////////////////////////// - -/// A type check struct. -struct TypeCheck {} - -impl TypeCheck { - /// The representation type of the WASI `Advice` type. - const ADVICE: ValueType = ValueType::I32; - /// The base pointer representation type of the WASI `CIOVecArray` type, which - /// is passed as a pair of base address and length. - const CIOVEC_ARRAY_BASE: ValueType = ValueType::I32; - /// The length representation type of the WASI `CIOVecArray` type, which is - /// passed as a pair of base address and length. - const CIOVEC_ARRAY_LENGTH: ValueType = ValueType::I32; - /// The representation type of the WASI `ClockID` type. - const CLOCKID: ValueType = ValueType::I32; - /// The representation type of the WASI `DirCookie` type. - const DIRCOOKIE: ValueType = ValueType::I64; - /// The representation type of the WASI `ErrNo` type. - const ERRNO: ValueType = ValueType::I32; - /// The representation type of the WASI `ExitCode` type. - const EXITCODE: ValueType = ValueType::I32; - /// The representation type of the WASI `FD` type. - const FD: ValueType = ValueType::I32; - /// The representation type of the WASI `FDFlags` type. - const FDFLAGS: ValueType = ValueType::I32; - /// The representation type of the WASI `FileDelta` type. - const FILEDELTA: ValueType = ValueType::I64; - /// The representation type of the WASI `FileSize` type. - const FILESIZE: ValueType = ValueType::I64; - /// The representation type of the WASI `FSTFlags` type. - const FSTFLAGS: ValueType = ValueType::I32; - /// The base pointer representation type of the WASI `IOVecArray` type, which - /// is passed as a pair of base address and length. - const IOVEC_ARRAY_BASE: ValueType = ValueType::I32; - /// The length representation type of the WASI `IOVecArray` type, which is - /// passed as a pair of base address and length. - const IOVEC_ARRAY_LENGTH: ValueType = ValueType::I32; - /// The representation type of the WASI `LookupFlags` type. - const LOOKUP_FLAGS: ValueType = ValueType::I32; - /// The representation type of the WASI `OFlags` type. - const OFLAGS: ValueType = ValueType::I32; - /// The representation type of the WASI `Rights` type. - const RIGHTS: ValueType = ValueType::I64; - /// The representation type of the WASI `SDFlags` type. - const SDFLAGS: ValueType = ValueType::I32; - /// The representation type of the WASI `SIFlags` type. - const SIFLAGS: ValueType = ValueType::I32; - /// The representation type of the WASI `RIFlags` type. - const RIFLAGS: ValueType = ValueType::I32; - /// The representation type of the WASI `Signal` type. - const SIGNAL: ValueType = ValueType::I32; - /// The representation type of the WASI `Size` type. - const SIZE: ValueType = ValueType::I32; - /// The representation type of the WASI `Timestamp` type. - const TIMESTAMP: ValueType = ValueType::I64; - /// The representation type of the WASI `Whence` type. - const WHENCE: ValueType = ValueType::I32; - /// The representation type of WASM `const` pointers (assuming `wasm32`). - const CONST_POINTER: ValueType = ValueType::I32; - /// The representation type of WASM pointers (assuming `wasm32`). - const POINTER: ValueType = ValueType::I32; - /// The representation type of WASM buffer length (assuming `wasm32`). - const SIZE_T: ValueType = ValueType::I32; - - //////////////////////////////////////////////////////////////////////////////// - // Function well-formedness checks. - //////////////////////////////////////////////////////////////////////////////// - - /// Checks the function signature, `signature`, has the correct type for the - /// host call coded by `index`. - pub(self) fn check_signature(index: APIName, signature: &Signature) -> bool { - // Match the parameters - let expected_params = Self::get_params(index); - if signature.params() != expected_params.as_slice() { - return false; - } - // Match the return type. Apart from proc_exit, which has no return, - // the rest should return ErrNo. - if index == APIName::WasiAPIName(WasiAPIName::PROC_EXIT) { - signature.return_type() == None - } else { - signature.return_type() == Some(Self::ERRNO) - } - } - - /// Return the parameters list of a wasi function call `index`. - pub(crate) fn get_params(index: APIName) -> Vec { - match index { - APIName::WasiAPIName(index) => match index { - WasiAPIName::ARGS_GET => vec![Self::POINTER, Self::POINTER], - WasiAPIName::ARGS_SIZES_GET => vec![Self::POINTER, Self::POINTER], - WasiAPIName::ENVIRON_GET => vec![Self::POINTER, Self::POINTER], - WasiAPIName::ENVIRON_SIZES_GET => vec![Self::POINTER, Self::POINTER], - WasiAPIName::CLOCK_RES_GET => vec![Self::CLOCKID, Self::POINTER], - WasiAPIName::CLOCK_TIME_GET => vec![Self::CLOCKID, Self::TIMESTAMP, Self::POINTER], - WasiAPIName::FD_ADVISE => { - vec![Self::FD, Self::FILESIZE, Self::FILESIZE, Self::ADVICE] - } - WasiAPIName::FD_ALLOCATE => vec![Self::FD, Self::FILESIZE, Self::FILESIZE], - WasiAPIName::FD_CLOSE => vec![Self::FD], - WasiAPIName::FD_DATASYNC => vec![Self::FD], - WasiAPIName::FD_FDSTAT_GET => vec![Self::FD, Self::POINTER], - WasiAPIName::FD_FDSTAT_SET_FLAGS => vec![Self::FD, Self::FDFLAGS], - WasiAPIName::FD_FDSTAT_SET_RIGHTS => vec![Self::FD, Self::RIGHTS, Self::RIGHTS], - WasiAPIName::FD_FILESTAT_GET => vec![Self::FD, Self::POINTER], - WasiAPIName::FD_FILESTAT_SET_SIZE => vec![Self::FD, Self::FILESIZE], - WasiAPIName::FD_FILESTAT_SET_TIMES => { - vec![Self::FD, Self::TIMESTAMP, Self::TIMESTAMP, Self::FSTFLAGS] - } - WasiAPIName::FD_PREAD => vec![ - Self::FD, - Self::CIOVEC_ARRAY_BASE, - Self::CIOVEC_ARRAY_LENGTH, - Self::FILESIZE, - Self::POINTER, - ], - WasiAPIName::FD_PRESTAT_GET => vec![Self::FD, Self::POINTER], - WasiAPIName::FD_PRESTAT_DIR_NAME => vec![Self::FD, Self::POINTER, Self::SIZE], - WasiAPIName::FD_PWRITE => vec![ - Self::FD, - Self::CIOVEC_ARRAY_BASE, - Self::CIOVEC_ARRAY_LENGTH, - Self::FILESIZE, - Self::POINTER, - ], - WasiAPIName::FD_READ => vec![ - Self::FD, - Self::IOVEC_ARRAY_BASE, - Self::IOVEC_ARRAY_LENGTH, - Self::POINTER, - ], - WasiAPIName::FD_READDIR => vec![ - Self::FD, - Self::POINTER, - Self::SIZE, - Self::DIRCOOKIE, - Self::POINTER, - ], - WasiAPIName::FD_RENUMBER => vec![Self::FD, Self::FD], - WasiAPIName::FD_SEEK => { - vec![Self::FD, Self::FILEDELTA, Self::WHENCE, Self::POINTER] - } - WasiAPIName::FD_SYNC => vec![Self::FD], - WasiAPIName::FD_TELL => vec![Self::FD, Self::POINTER], - WasiAPIName::FD_WRITE => vec![ - Self::FD, - Self::CIOVEC_ARRAY_BASE, - Self::CIOVEC_ARRAY_LENGTH, - Self::POINTER, - ], - WasiAPIName::PATH_CREATE_DIRECTORY => vec![Self::FD, Self::POINTER, Self::SIZE_T], - WasiAPIName::PATH_FILESTAT_GET => vec![ - Self::FD, - Self::LOOKUP_FLAGS, - Self::POINTER, - Self::SIZE_T, - Self::POINTER, - ], - WasiAPIName::PATH_FILESTAT_SET_TIMES => vec![ - Self::FD, - Self::LOOKUP_FLAGS, - Self::POINTER, - Self::SIZE_T, - Self::TIMESTAMP, - Self::TIMESTAMP, - Self::FSTFLAGS, - ], - WasiAPIName::PATH_LINK => vec![ - Self::FD, - Self::LOOKUP_FLAGS, - Self::POINTER, - Self::SIZE_T, - Self::FD, - Self::POINTER, - Self::SIZE_T, - ], - WasiAPIName::PATH_OPEN => vec![ - Self::FD, - Self::LOOKUP_FLAGS, - Self::POINTER, - Self::SIZE_T, - Self::OFLAGS, - Self::RIGHTS, - Self::RIGHTS, - Self::FDFLAGS, - Self::POINTER, - ], - WasiAPIName::PATH_READLINK => vec![ - Self::FD, - Self::POINTER, - Self::SIZE_T, - Self::POINTER, - Self::SIZE_T, - Self::POINTER, - ], - WasiAPIName::PATH_REMOVE_DIRECTORY => vec![Self::FD, Self::POINTER, Self::SIZE_T], - WasiAPIName::PATH_RENAME => vec![ - Self::FD, - Self::POINTER, - Self::SIZE_T, - Self::FD, - Self::POINTER, - Self::SIZE_T, - ], - WasiAPIName::PATH_SYMLINK => vec![ - Self::POINTER, - Self::SIZE_T, - Self::FD, - Self::POINTER, - Self::SIZE_T, - ], - WasiAPIName::PATH_UNLINK_FILE => vec![Self::FD, Self::POINTER, Self::SIZE_T], - WasiAPIName::POLL_ONEOFF => vec![ - Self::CONST_POINTER, - Self::POINTER, - Self::SIZE, - Self::POINTER, - ], - WasiAPIName::PROC_EXIT => vec![Self::EXITCODE], - WasiAPIName::PROC_RAISE => vec![Self::SIGNAL], - WasiAPIName::SCHED_YIELD => vec![], - WasiAPIName::RANDOM_GET => vec![Self::POINTER, Self::SIZE], - WasiAPIName::SOCK_RECV => vec![ - Self::FD, - Self::IOVEC_ARRAY_BASE, - Self::IOVEC_ARRAY_LENGTH, - Self::RIFLAGS, - Self::POINTER, - Self::POINTER, - ], - WasiAPIName::SOCK_SEND => vec![ - Self::FD, - Self::CIOVEC_ARRAY_BASE, - Self::CIOVEC_ARRAY_LENGTH, - Self::SIFLAGS, - Self::POINTER, - ], - WasiAPIName::SOCK_SHUTDOWN => vec![Self::FD, Self::SDFLAGS], - WasiAPIName::_LAST => unreachable!(), - }, - APIName::VeracruzAPIName(index) => match index { - VeracruzAPIName::FD_CREATE => vec![Self::POINTER], - }, - } - } - - /// Check if the numbers of parameters in `args` is correct against the wasi function call `index`. - /// Return FatalEngineError::BadArgumentsToHostFunction{ index }, if not. - pub(crate) fn check_args_number(args: &RuntimeArgs, index: WasiAPIName) -> Result<()> { - if args.len() == Self::get_params(APIName::WasiAPIName(index)).len() { - Ok(()) - } else { - Err(anyhow!(FatalEngineError::BadArgumentsToHostFunction { - function_name: index, - })) - } - } -} - -/// Checks the signature of the module's entry point, `signature`, against the -/// templates described above for the `EntrySignature` enum type, and returns -/// an instance of that type as appropriate. -fn check_main_signature(signature: &Signature) -> EntrySignature { - let params = signature.params(); - let return_type = signature.return_type(); - - if params == [] && return_type == None { - EntrySignature::NoParameters - } else if params == [ValueType::I32, ValueType::I32] && return_type == None { - EntrySignature::ArgvAndArgc - } else { - EntrySignature::NoEntryFound - } -} - -/// Finds the entry point of the WASM module, `module`, and extracts its -/// signature template. If no entry is found returns -/// `EntrySignature::NoEntryFound`. -fn check_main(module: &ModuleInstance) -> EntrySignature { - match module.export_by_name(WasiWrapper::ENTRY_POINT_NAME) { - Some(ExternVal::Func(funcref)) => check_main_signature(&funcref.signature()), - _otherwise => EntrySignature::NoEntryFound, - } -} - -/// Finds the linear memory of the WASM module, `module`, and returns it, -/// otherwise creating a fatal host error that will kill the Veracruz instance. -fn get_module_memory(module: &ModuleRef) -> Result { - match module.export_by_name(WasiWrapper::LINEAR_MEMORY_NAME) { - Some(ExternVal::Memory(memoryref)) => Ok(memoryref), - _otherwise => Err(anyhow!(FatalEngineError::NoMemoryRegistered)), - } -} - -//////////////////////////////////////////////////////////////////////////////// -// The H-call interface. -//////////////////////////////////////////////////////////////////////////////// - -impl ModuleImportResolver for WASMIRuntimeState { - /// "Resolves" a H-call by translating from a H-call name, `field_name` to - /// the corresponding H-call code, and dispatching appropriately. - fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result { - let index = if let Ok(x) = WasiAPIName::from_str(field_name) { - APIName::WasiAPIName(x) - } else if let Ok(x) = VeracruzAPIName::from_str(field_name) { - APIName::VeracruzAPIName(x) - } else { - return Err(Error::Instantiation(format!( - "Unknown function {} with signature: {:?}.", - field_name, signature - ))); - }; - - if !TypeCheck::check_signature(index, signature) { - Err(Error::Instantiation(format!( - "Function {} has an unexpected type-signature: {:?}.", - field_name, signature - ))) - } else { - Ok(FuncInstance::alloc_host( - signature.clone(), - index.to_usize().unwrap(), - )) - } - } - - fn resolve_global( - &self, - field_name: &str, - _descriptor: &GlobalDescriptor, - ) -> Result { - Err(Error::Instantiation(field_name.to_string())) - } - - fn resolve_memory( - &self, - field_name: &str, - _descriptor: &MemoryDescriptor, - ) -> Result { - Err(Error::Instantiation(field_name.to_string())) - } - - fn resolve_table( - &self, - field_name: &str, - _descriptor: &TableDescriptor, - ) -> Result { - Err(Error::Instantiation(field_name.to_string())) - } -} - -impl Externals for WASMIRuntimeState { - fn invoke_index( - &mut self, - index: usize, - args: RuntimeArgs, - ) -> Result, Trap> { - let call_index = APIName::from_u64(index as u64).ok_or( - FatalEngineError::UnknownHostFunction(HostFunctionIndexOrName::Index(index)), - )?; - - let return_code = match call_index { - APIName::WasiAPIName(wasi_call_index) => match wasi_call_index { - WasiAPIName::ARGS_GET => self.wasi_args_get(args), - WasiAPIName::ARGS_SIZES_GET => self.wasi_args_sizes_get(args), - WasiAPIName::ENVIRON_GET => self.wasi_environ_get(args), - WasiAPIName::ENVIRON_SIZES_GET => self.wasi_environ_sizes_get(args), - WasiAPIName::CLOCK_RES_GET => self.wasi_clock_res_get(args), - WasiAPIName::CLOCK_TIME_GET => self.wasi_clock_time_get(args), - WasiAPIName::FD_ADVISE => self.wasi_fd_advise(args), - WasiAPIName::FD_ALLOCATE => self.wasi_fd_allocate(args), - WasiAPIName::FD_CLOSE => self.wasi_fd_close(args), - WasiAPIName::FD_DATASYNC => self.wasi_fd_datasync(args), - WasiAPIName::FD_FDSTAT_GET => self.wasi_fd_fdstat_get(args), - WasiAPIName::FD_FDSTAT_SET_FLAGS => self.wasi_fd_fdstat_set_flags(args), - WasiAPIName::FD_FDSTAT_SET_RIGHTS => self.wasi_fd_fdstat_set_rights(args), - WasiAPIName::FD_FILESTAT_GET => self.wasi_fd_filestat_get(args), - WasiAPIName::FD_FILESTAT_SET_SIZE => self.wasi_fd_filestat_set_size(args), - WasiAPIName::FD_FILESTAT_SET_TIMES => self.wasi_fd_filestat_set_times(args), - WasiAPIName::FD_PREAD => self.wasi_fd_pread(args), - WasiAPIName::FD_PRESTAT_GET => self.wasi_fd_prestat_get(args), - WasiAPIName::FD_PRESTAT_DIR_NAME => self.wasi_fd_prestat_dir_name(args), - WasiAPIName::FD_PWRITE => self.wasi_fd_pwrite(args), - WasiAPIName::FD_READ => self.wasi_fd_read(args), - WasiAPIName::FD_READDIR => self.wasi_fd_readdir(args), - WasiAPIName::FD_RENUMBER => self.wasi_fd_renumber(args), - WasiAPIName::FD_SEEK => self.wasi_fd_seek(args), - WasiAPIName::FD_SYNC => self.wasi_fd_sync(args), - WasiAPIName::FD_TELL => self.wasi_fd_tell(args), - WasiAPIName::FD_WRITE => self.wasi_fd_write(args), - WasiAPIName::PATH_CREATE_DIRECTORY => self.wasi_path_create_directory(args), - WasiAPIName::PATH_FILESTAT_GET => self.wasi_path_filestat_get(args), - WasiAPIName::PATH_FILESTAT_SET_TIMES => self.wasi_path_filestat_set_times(args), - WasiAPIName::PATH_LINK => self.wasi_path_link(args), - WasiAPIName::PATH_OPEN => self.wasi_path_open(args), - WasiAPIName::PATH_READLINK => self.wasi_path_readlink(args), - WasiAPIName::PATH_REMOVE_DIRECTORY => self.wasi_path_remove_directory(args), - WasiAPIName::PATH_RENAME => self.wasi_path_rename(args), - WasiAPIName::PATH_SYMLINK => self.wasi_path_symlink(args), - WasiAPIName::PATH_UNLINK_FILE => self.wasi_path_unlink_file(args), - WasiAPIName::POLL_ONEOFF => self.wasi_poll_oneoff(args), - WasiAPIName::PROC_EXIT => self.wasi_proc_exit(args), - WasiAPIName::PROC_RAISE => self.wasi_proc_raise(args), - WasiAPIName::SCHED_YIELD => self.wasi_sched_yield(args), - WasiAPIName::RANDOM_GET => self.wasi_random_get(args), - WasiAPIName::SOCK_RECV => self.wasi_sock_recv(args), - WasiAPIName::SOCK_SEND => self.wasi_sock_send(args), - WasiAPIName::SOCK_SHUTDOWN => self.wasi_sock_shutdown(args), - WasiAPIName::_LAST => unreachable!(), - }, - APIName::VeracruzAPIName(veracruz_call_index) => match veracruz_call_index { - VeracruzAPIName::FD_CREATE => self.veracruz_fd_create(args), - }, - } - .map_err(|e| { - error!("{}", e); - FatalEngineError::Trap(format!("{}", e)) - })?; - Ok(Some(RuntimeValue::I32((return_code as i16).into()))) - } -} - -/// Functionality of the `WASMIRuntimeState` type that relies on it satisfying -/// the `Externals` and `ModuleImportResolver` constraints. -impl WASMIRuntimeState { - /// Creates a new initial `WASMIRuntimeState`. - #[inline] - pub fn new(filesystem: FileSystem, options: Options) -> FileSystemResult { - Ok(Self { - vfs: WasiWrapper::new(filesystem, options)?, - program_module: None, - memory: None, - }) - //NOTE: cannot find a way to immediately call the load_program here, - // therefore we might eliminate the Option on program_module and memory. - } - - #[inline] - /// Returns the ref to the wasm memory or the ErrNo if fails. - pub(crate) fn memory(&self) -> Result { - match &self.memory { - //NOTE: The cost is very minimum as it is a reference to memory. - Some(m) => Ok(m.clone()), - None => Err(anyhow!(FatalEngineError::NoMemoryRegistered)), - } - } - - //////////////////////////////////////////////////////////////////////////// - // Provisioning and program execution-related material. - //////////////////////////////////////////////////////////////////////////// - - /// Loads a compiled program into the host state. Tries to parse `buffer` - /// to obtain a WASM `Module` struct. Returns an appropriate error if this - /// fails. - fn load_program(&mut self, buffer: &[u8]) -> Result<()> { - let module = Module::from_buffer(buffer)?; - let env_resolver = wasmi::ImportsBuilder::new() - .with_resolver(WasiWrapper::WASI_SNAPSHOT_MODULE_NAME, self) - .with_resolver(WasiWrapper::VERACRUZ_SI_MODULE_NAME, self); - - let not_started_module_ref = ModuleInstance::new(&module, &env_resolver)?; - if not_started_module_ref.has_start() { - return Err(anyhow!(FatalEngineError::InvalidWASMModule)); - } - - let module_ref = not_started_module_ref.assert_no_start(); - - let linear_memory = get_module_memory(&module_ref)?; - self.program_module = Some(module_ref); - self.memory = Some(linear_memory); - Ok(()) - } - - /// Invokes an exported entry point function with a given name, - /// `export_name`, in the WASM program provisioned into the Veracruz host - /// state. - fn invoke_export(&mut self, export_name: &str) -> Result, Error> { - // Eliminate this .cloned() call, if possible - let (not_started, program_arguments) = match self.program_module.as_ref().cloned() { - None => { - return Err(Error::Host(Box::new( - FatalEngineError::NoProgramModuleRegistered, - ))) - } - Some(not_started) => match check_main(¬_started) { - EntrySignature::NoEntryFound => { - return Err(Error::Host(Box::new(FatalEngineError::NoProgramEntryPoint))) - } - EntrySignature::ArgvAndArgc => ( - not_started, - vec![RuntimeValue::I32(0), RuntimeValue::I32(0)], - ), - EntrySignature::NoParameters => (not_started, Vec::new()), - }, - }; - - not_started.invoke_export(export_name, &program_arguments, self) - } - - //////////////////////////////////////////////////////////////////////////// - // The WASI host call implementations. - //////////////////////////////////////////////////////////////////////////// - - fn convert_to_errno(input: FileSystemResult<()>) -> WasiResult { - let errno = match input { - Ok(_) => ErrNo::Success, - Err(e) => e, - }; - Ok(errno) - } - - /// The implementation of the WASI `args_get` function. - fn wasi_args_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::ARGS_GET)?; - let string_ptr_address = args.nth_checked::(0)?; - let buf_address = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.args_get( - &mut self.memory()?, - string_ptr_address, - buf_address, - )) - } - - /// The implementation of the WASI `args_sizes_get` function. - fn wasi_args_sizes_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::ARGS_SIZES_GET)?; - let arg_count_address = args.nth_checked::(0)?; - let arg_buf_size_address = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.args_sizes_get( - &mut self.memory()?, - arg_count_address, - arg_buf_size_address, - )) - } - - /// The implementation of the WASI `environ_get` function. - fn wasi_environ_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::ENVIRON_GET)?; - let string_ptr_address = args.nth(0); - let buf_address = args.nth(1); - Self::convert_to_errno(self.vfs.environ_get( - &mut self.memory()?, - string_ptr_address, - buf_address, - )) - } - - /// The implementation of the WASI `environ_sizes_get` function. - fn wasi_environ_sizes_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::ENVIRON_SIZES_GET)?; - let environc_address = args.nth_checked::(0)?; - let environ_buf_size_address = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.environ_sizes_get( - &mut self.memory()?, - environc_address, - environ_buf_size_address, - )) - } - - /// The implementation of the WASI `clock_res_get` function. - fn wasi_clock_res_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::CLOCK_RES_GET)?; - let clock_id = args.nth_checked::(0)?; - let address = args.nth_checked::(1)?; - Self::convert_to_errno( - self.vfs - .clock_res_get(&mut self.memory()?, clock_id, address), - ) - } - - /// The implementation of the WASI `clock_time_get` function. - fn wasi_clock_time_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::CLOCK_TIME_GET)?; - let clock_id = args.nth_checked::(0)?; - let precision = args.nth_checked::(1)?; - let address = args.nth_checked::(2)?; - Self::convert_to_errno(self.vfs.clock_time_get( - &mut self.memory()?, - clock_id, - precision, - address, - )) - } - - /// The implementation of the WASI `fd_advise` function. - fn wasi_fd_advise(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_ADVISE)?; - let fd = args.nth_checked::(0)?; - let offset = args.nth_checked::(1)?; - let len = args.nth_checked::(2)?; - let advice = args.nth::(3); - Self::convert_to_errno( - self.vfs - .fd_advise(&mut self.memory()?, fd, offset, len, advice), - ) - } - - /// The implementation of the WASI `fd_allocate` function. - fn wasi_fd_allocate(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_ALLOCATE)?; - let fd = args.nth_checked::(0)?; - let offset = args.nth_checked::(1)?; - let len = args.nth_checked::(2)?; - Self::convert_to_errno(self.vfs.fd_allocate(&mut self.memory()?, fd, offset, len)) - } - - /// The implementation of the WASI `fd_close` function. - fn wasi_fd_close(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_CLOSE)?; - let fd = args.nth_checked::(0)?; - Self::convert_to_errno(self.vfs.fd_close(&self.memory()?, fd)) - } - - /// The implementation of the WASI `fd_datasync` function. - fn wasi_fd_datasync(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_DATASYNC)?; - let fd = args.nth_checked::(0)?; - Self::convert_to_errno(self.vfs.fd_datasync(&mut self.memory()?, fd)) - } - - /// The implementation of the WASI `fd_fdstat_get` function. - fn wasi_fd_fdstat_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_FDSTAT_GET)?; - let fd = args.nth_checked::(0)?; - let address = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.fd_fdstat_get(&mut self.memory()?, fd, address)) - } - - /// The implementation of the WASI `fd_fdstat_set_flags` function. - fn wasi_fd_fdstat_set_flags(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_FDSTAT_SET_FLAGS)?; - let fd = args.nth_checked::(0)?; - let flags = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.fd_fdstat_set_flags(&mut self.memory()?, fd, flags)) - } - - /// The implementation of the WASI `fd_fdstat_set_rights` function. - fn wasi_fd_fdstat_set_rights(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_FDSTAT_SET_RIGHTS)?; - let fd = args.nth_checked::(0)?; - let rights_base = args.nth_checked::(1)?; - let rights_inheriting = args.nth_checked::(2)?; - Self::convert_to_errno(self.vfs.fd_fdstat_set_rights( - &mut self.memory()?, - fd, - rights_base, - rights_inheriting, - )) - } - - /// The implementation of the WASI `fd_filestat_get` function. - fn wasi_fd_filestat_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_FILESTAT_GET)?; - let fd = args.nth_checked::(0)?; - let address = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.fd_filestat_get(&mut self.memory()?, fd, address)) - } - - /// The implementation of the WASI `fd_filestat_set_size` function. - fn wasi_fd_filestat_set_size(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_FILESTAT_SET_SIZE)?; - let fd = args.nth_checked::(0)?; - let size = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.fd_filestat_set_size(&mut self.memory()?, fd, size)) - } - - /// The implementation of the WASI `fd_filestat_set_times` function. This - /// is not supported by Veracruz and we simply return `ErrNo::NoSys`. - fn wasi_fd_filestat_set_times(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_FILESTAT_SET_TIMES)?; - let fd = args.nth_checked::(0)?; - let atime = args.nth_checked::(1)?; - let mtime = args.nth_checked::(2)?; - let fst_flag = args.nth_checked::(3)?; - Self::convert_to_errno(self.vfs.fd_filestat_set_times( - &mut self.memory()?, - fd, - atime, - mtime, - fst_flag, - )) - } - - /// The implementation of the WASI `fd_pread` function. - fn wasi_fd_pread(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_PREAD)?; - let fd = args.nth_checked::(0)?; - let iovec_base = args.nth_checked::(1)?; - let iovec_length = args.nth_checked::(2)?; - let offset = args.nth_checked::(3)?; - let address = args.nth_checked::(4)?; - Self::convert_to_errno(self.vfs.fd_pread( - &mut self.memory()?, - fd, - iovec_base, - iovec_length, - offset, - address, - )) - } - - /// The implementation of the WASI `fd_prestat_get` function. - fn wasi_fd_prestat_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_PRESTAT_GET)?; - let fd = args.nth_checked::(0)?; - let address = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.fd_prestat_get(&mut self.memory()?, fd, address)) - } - - /// The implementation of the WASI `fd_prestat_dir_name` function. - fn wasi_fd_prestat_dir_name(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_PRESTAT_DIR_NAME)?; - let fd = args.nth_checked::(0)?; - let address = args.nth_checked::(1)?; - let size = args.nth_checked::(2)?; - Self::convert_to_errno( - self.vfs - .fd_prestat_dir_name(&mut self.memory()?, fd, address, size), - ) - } - - /// The implementation of the WASI `fd_pwrite` function. - fn wasi_fd_pwrite(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_PWRITE)?; - let fd = args.nth_checked::(0)?; - let iovec_base = args.nth_checked::(1)?; - let iovec_length = args.nth_checked::(2)?; - let offset = args.nth_checked::(3)?; - let address = args.nth_checked::(4)?; - Self::convert_to_errno(self.vfs.fd_pwrite( - &mut self.memory()?, - fd, - iovec_base, - iovec_length, - offset, - address, - )) - } - - /// The implementation of the WASI `fd_read` function. - fn wasi_fd_read(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_READ)?; - let fd = args.nth_checked::(0)?; - let iovec_base: u32 = args.nth_checked::(1)?; - let iovec_len: u32 = args.nth_checked::(2)?; - let address: u32 = args.nth_checked::(3)?; - Self::convert_to_errno(self.vfs.fd_read( - &mut self.memory()?, - fd, - iovec_base, - iovec_len, - address, - )) - } - - /// The implementation of the WASI `fd_readdir` function. - fn wasi_fd_readdir(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_READDIR)?; - let fd = args.nth_checked::(0)?; - let dirent_base = args.nth_checked::(1)?; - let dirent_length = args.nth_checked::(2)?; - let cookie = args.nth_checked::(3)?; - let address = args.nth_checked::(4)?; - Self::convert_to_errno(self.vfs.fd_readdir( - &mut self.memory()?, - fd, - dirent_base, - dirent_length, - cookie, - address, - )) - } - - /// The implementation of the WASI `fd_renumber` function. - fn wasi_fd_renumber(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_RENUMBER)?; - let old_fd = args.nth_checked::(0)?; - let new_fd = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.fd_renumber(&mut self.memory()?, old_fd, new_fd)) - } - - /// The implementation of the WASI `fd_seek` function. - fn wasi_fd_seek(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_SEEK)?; - let fd = args.nth_checked::(0)?; - let offset = args.nth_checked::(1)?; - let whence = args.nth::(2); - let address = args.nth_checked::(3)?; - Self::convert_to_errno( - self.vfs - .fd_seek(&mut self.memory()?, fd, offset, whence, address), - ) - } - - /// The implementation of the WASI `fd_sync` function. This is not - /// supported by Veracruz. We simply return `ErrNo::NoSys`. - fn wasi_fd_sync(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_SYNC)?; - let fd = args.nth_checked::(0)?; - Self::convert_to_errno(self.vfs.fd_sync(&mut self.memory()?, fd)) - } - - /// The implementation of the WASI `fd_tell` function. - fn wasi_fd_tell(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_TELL)?; - let fd = args.nth_checked::(0)?; - let address = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.fd_tell(&mut self.memory()?, fd, address)) - } - - /// The implementation of the WASI `fd_write` function. - fn wasi_fd_write(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::FD_WRITE)?; - let fd = args.nth_checked::(0)?; - let iovec_base = args.nth_checked::(1)?; - let iovec_len = args.nth_checked::(2)?; - let address = args.nth_checked::(3)?; - Self::convert_to_errno(self.vfs.fd_write( - &mut self.memory()?, - fd, - iovec_base, - iovec_len, - address, - )) - } - - /// The implementation of the WASI `path_create_directory` function. - fn wasi_path_create_directory(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_CREATE_DIRECTORY)?; - let fd = args.nth_checked::(0)?; - let path = args.nth_checked::(1)?; - let path_len = args.nth_checked::(2)?; - Self::convert_to_errno(self.vfs.path_create_directory( - &mut self.memory()?, - fd, - path, - path_len, - )) - } - - /// The implementation of the WASI `path_filestat_get` function. - fn wasi_path_filestat_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_FILESTAT_GET)?; - let fd = args.nth_checked::(0)?; - let flag = args.nth_checked::(1)?; - let path_address = args.nth_checked::(2)?; - let path_length = args.nth_checked::(3)?; - let address = args.nth_checked::(4)?; - Self::convert_to_errno(self.vfs.path_filestat_get( - &mut self.memory()?, - fd, - flag, - path_address, - path_length, - address, - )) - } - - /// The implementation of the WASI `path_filestat_set_times` function. This - /// is not supported by Veracruz. We simply return `ErrNo::NoSys`. - fn wasi_path_filestat_set_times(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_FILESTAT_SET_TIMES)?; - let fd = args.nth_checked::(0)?; - let flag = args.nth_checked::(1)?; - let path_address = args.nth_checked::(2)?; - let path_length = args.nth_checked::(3)?; - let atime = args.nth_checked::(4)?; - let mtime = args.nth_checked::(5)?; - let fst_flags = args.nth_checked::(6)?; - Self::convert_to_errno(self.vfs.path_filestat_set_times( - &mut self.memory()?, - fd, - flag, - path_address, - path_length, - atime, - mtime, - fst_flags, - )) - } - - /// The implementation of the WASI `path_readlink` function. This - /// is not supported by Veracruz. We simply return `ErrNo::NoSys`. - fn wasi_path_link(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_LINK)?; - let old_fd = args.nth_checked::(0)?; - let old_flags = args.nth_checked::(1)?; - let old_address = args.nth_checked::(2)?; - let old_path_len = args.nth_checked::(3)?; - let new_fd = args.nth_checked::(4)?; - let new_address = args.nth_checked::(5)?; - let new_path_len = args.nth_checked::(6)?; - Self::convert_to_errno(self.vfs.path_link( - &mut self.memory()?, - old_fd, - old_flags, - old_address, - old_path_len, - new_fd, - new_address, - new_path_len, - )) - } - - /// The implementation of the WASI `path_open` function. - fn wasi_path_open(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_OPEN)?; - let fd = args.nth_checked::(0)?; - let dirflags = args.nth_checked::(1)?; - let path_address = args.nth_checked::(2)?; - let path_length = args.nth_checked::(3)?; - let oflags = args.nth_checked::(4)?; - let fs_rights_base = args.nth_checked::(5)?; - let fs_rights_inheriting = args.nth_checked::(6)?; - let fd_flags = args.nth_checked::(7)?; - let address = args.nth_checked::(8)?; - Self::convert_to_errno(self.vfs.path_open( - &mut self.memory()?, - fd, - dirflags, - path_address, - path_length, - oflags, - fs_rights_base, - fs_rights_inheriting, - fd_flags, - address, - )) - } - - /// The implementation of the WASI `path_readlink` function. - fn wasi_path_readlink(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_READLINK)?; - let fd = args.nth_checked::(0)?; - let path_address = args.nth_checked::(1)?; - let path_length = args.nth_checked::(2)?; - let buf_address = args.nth_checked::(3)?; - let buf_length = args.nth_checked::(4)?; - let address = args.nth_checked::(5)?; - Self::convert_to_errno(self.vfs.path_readlink( - &mut self.memory()?, - fd, - path_address, - path_length, - buf_address, - buf_length, - address, - )) - } - - /// The implementation of the WASI `path_remove_directory` function. - fn wasi_path_remove_directory(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_REMOVE_DIRECTORY)?; - let fd = args.nth_checked::(0)?; - let path_address = args.nth_checked::(1)?; - let path_length = args.nth_checked::(2)?; - Self::convert_to_errno(self.vfs.path_remove_directory( - &mut self.memory()?, - fd, - path_address, - path_length, - )) - } - - /// The implementation of the WASI `path_rename` function. - fn wasi_path_rename(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_RENAME)?; - let old_fd = args.nth_checked::(0)?; - let old_path_address = args.nth_checked::(1)?; - let old_path_len = args.nth_checked::(2)?; - let new_fd = args.nth_checked::(3)?; - let new_path_address = args.nth_checked::(4)?; - let new_path_len = args.nth_checked::(5)?; - Self::convert_to_errno(self.vfs.path_rename( - &mut self.memory()?, - old_fd, - old_path_address, - old_path_len, - new_fd, - new_path_address, - new_path_len, - )) - } - - /// The implementation of the WASI `path_symlink` function. - fn wasi_path_symlink(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_SYMLINK)?; - let old_path_address = args.nth_checked::(0)?; - let old_path_len = args.nth_checked::(1)?; - let fd = args.nth_checked::(2)?; - let new_path_address = args.nth_checked::(3)?; - let new_path_len = args.nth_checked::(4)?; - Self::convert_to_errno(self.vfs.path_symlink( - &mut self.memory()?, - old_path_address, - old_path_len, - fd, - new_path_address, - new_path_len, - )) - } - - /// The implementation of the WASI `path_unlink_file` function. This is not - /// supported by Veracruz. We simply return `ErrNo::NoSys`. - fn wasi_path_unlink_file(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PATH_UNLINK_FILE)?; - let fd = args.nth_checked::(0)?; - let path_address = args.nth_checked::(1)?; - let path_len = args.nth_checked::(2)?; - Self::convert_to_errno(self.vfs.path_unlink_file( - &mut self.memory()?, - fd, - path_address, - path_len, - )) - } - - /// The implementation of the WASI `poll_oneoff` function. This is not - /// supported by Veracruz. We write `0` as the number of subscriptions that - /// were registered and return `ErrNo::NoSys`. - fn wasi_poll_oneoff(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::POLL_ONEOFF)?; - let subscriptions = args.nth_checked::(0)?; - let events = args.nth_checked::(1)?; - let size = args.nth_checked::(2)?; - let address = args.nth_checked::(3)?; - Self::convert_to_errno(self.vfs.poll_oneoff( - &mut self.memory()?, - subscriptions, - events, - size, - address, - )) - } - - /// The implementation of the WASI `proc_raise` function. This halts - /// termination of the interpreter, returning an error code. No return code - /// is returned to the calling WASM process. - fn wasi_proc_exit(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PROC_EXIT)?; - let exit_code = args.nth_checked::(0)?; - self.vfs.proc_exit(&mut self.memory()?, exit_code); - // NB: this gets routed to the runtime, not the calling WASM program, - // for handling. - Ok(ErrNo::Success) - } - - /// The implementation of the WASI `proc_raise` function. This is not - /// supported by Veracruz and implemented as a no-op, simply returning - /// `ErrNo::NoSys`. - fn wasi_proc_raise(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::PROC_RAISE)?; - let signal = args.nth::(0); - Self::convert_to_errno(self.vfs.proc_raise(&mut self.memory()?, signal)) - } - - /// The implementation of the WASI `sched_yield` function. This is - /// not supported by Veracruz and simply returns `ErrNo::NoSys`. - fn wasi_sched_yield(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::SCHED_YIELD)?; - Self::convert_to_errno(self.vfs.sched_yield(&mut self.memory()?)) - } - - /// The implementation of the WASI `random_get` function, which calls - /// through to the random number generator provided by `platform_services`. - /// Returns `ErrNo::Success` on successful execution of the random number - /// generator, or `ErrNo::NoSys` if a random number generator is not - /// available on this platform, or if the call to the random number - /// generator fails for some reason. - fn wasi_random_get(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::RANDOM_GET)?; - let address = args.nth_checked::(0)?; - let size = args.nth_checked::(1)?; - Self::convert_to_errno(self.vfs.random_get(&mut self.memory()?, address, size)) - } - - /// The implementation of the WASI `sock_send` function. This is not - /// supported by Veracruz and returns `ErrNo::NoSys`, writing back - /// `0` as the length of the transmission. - fn wasi_sock_send(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::SOCK_SEND)?; - let socket = args.nth_checked::(0)?; - let buf_address = args.nth_checked::(1)?; - let buf_len = args.nth_checked::(2)?; - let si_flag = args.nth_checked::(3)?; - let ro_data_len = args.nth_checked::(4)?; - Self::convert_to_errno(self.vfs.sock_send( - &mut self.memory()?, - socket, - buf_address, - buf_len, - si_flag, - ro_data_len, - )) - } - - /// The implementation of the WASI `sock_recv` function. This is not - /// supported by Veracruz and returns `ErrNo::NoSys`, writing back - /// `0` as the length of the transmission. - fn wasi_sock_recv(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::SOCK_RECV)?; - let socket = args.nth_checked::(0)?; - let buf_address = args.nth_checked::(1)?; - let buf_len = args.nth_checked::(2)?; - let ri_flag = args.nth_checked::(3)?; - let ro_data_len = args.nth_checked::(4)?; - let ro_flag = args.nth_checked::(5)?; - Self::convert_to_errno(self.vfs.sock_recv( - &mut self.memory()?, - socket, - buf_address, - buf_len, - ri_flag, - ro_data_len, - ro_flag, - )) - } - - /// The implementation of the WASI `sock_shutdown` function. This is - /// not supported by Veracruz and simply returns `ErrNo::NoSys`. - fn wasi_sock_shutdown(&mut self, args: RuntimeArgs) -> WasiResult { - TypeCheck::check_args_number(&args, WasiAPIName::SOCK_SHUTDOWN)?; - let socket = args.nth_checked::(0)?; - let sd_flag = args.nth::(1); - Self::convert_to_errno(self.vfs.sock_shutdown(&mut self.memory()?, socket, sd_flag)) - } - - fn veracruz_fd_create(&mut self, args: RuntimeArgs) -> WasiResult { - let address = args.nth_checked::(0)?; - Self::convert_to_errno(self.vfs.fd_create(&mut self.memory()?, address)) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// The ExecutionEngine trait implementation. -//////////////////////////////////////////////////////////////////////////////// - -/// The `WASMIRuntimeState` implements everything needed to create a -/// compliant instance of `ExecutionEngine`. -impl ExecutionEngine for WASMIRuntimeState { - /// Executes the program, `program`, within the context of the execution - /// engine options, `options`. - /// - /// Returns `Ok(code)` if the pipeline successfully executed and returned a - /// defined error code, `code`. Alternatively, returns `Err(fatal)` to - /// signal that a fatal runtime error, `fatal`, occurred during the - /// execution of the pipeline. - fn invoke_entry_point(&mut self, program: Vec) -> Result { - self.load_program(&program)?; - - let execute_result = self.invoke_export(WasiWrapper::ENTRY_POINT_NAME); - let exit_code = self.vfs.exit_code(); - - // Get the return code, ZERO as the default, or the exit_code if exists. - match execute_result { - // If the function does not explicitly provide return code, - // either read the exit_code passed by proc_exit call or use ZERO as the default. - Ok(None) => Ok(exit_code.unwrap_or(0)), - // Return the explicit return code - Ok(Some(RuntimeValue::I32(c))) => Ok(c as u32), - // NOTE: Surpress the trap, if the `proc_exit` is called. - // In this case, the error code is exit_code. - Ok(Some(_)) => Err(anyhow!(FatalEngineError::ReturnedCodeError)), - // NOTE: Surpress the trap, if the `proc_exit` is called. - // In this case, the error code is exit_code. - Err(Error::Trap(trap)) => exit_code.ok_or(anyhow!(trap)), - Err(err) => Err(anyhow!(err)), - } - } -} diff --git a/crates/execution-engine/src/engines/wasmtime.rs b/crates/execution-engine/src/engines/wasmtime.rs index 8ea18ae47..9e710c665 100644 --- a/crates/execution-engine/src/engines/wasmtime.rs +++ b/crates/execution-engine/src/engines/wasmtime.rs @@ -12,214 +12,26 @@ #![allow(clippy::too_many_arguments)] use crate::{ - engines::common::{ - Bound, BoundMut, EntrySignature, ExecutionEngine, FatalEngineError, MemoryHandler, - MemorySlice, MemorySliceMut, VeracruzAPIName, WasiAPIName, WasiWrapper, - }, - fs::{FileSystem, FileSystemResult}, - Options, + Execution, + Environment, }; -use anyhow::{anyhow, Result}; +use anyhow::Result; use log::info; use std::{ - convert::TryFrom, - mem, - sync::{Arc, Mutex}, - vec::Vec, + path::Path, + fs::{create_dir_all, File}, }; -use wasi_types::ErrNo; -use wasmtime::{ - AsContext, AsContextMut, Caller, Config, Engine, ExternType, Linker, Memory, Module, Store, - StoreContext, StoreContextMut, ValType, -}; - -//////////////////////////////////////////////////////////////////////////////// -// The Wasmtime runtime state. -//////////////////////////////////////////////////////////////////////////////// - -type SharedMutableWasiWrapper = Arc>; -type CallerWrapper<'a> = Caller<'a, Arc>>; - -/// A macro for lock and return the VFS. -/// If the locks fails, it returns Busy error code. -/// The macro need to pass a stub variable `$var2`. -macro_rules! lock_vfs { - ($var:ident) => { - match $var.lock() { - Ok(v) => v, - Err(_) => return ErrNo::Busy as u32, - } - }; -} - -/// A macro to call try_from on a untyped raw wasi parameter `$var`. -/// It converts `$var` to the typed version, `$t`, of the parameter as a value, -/// or returns from the function with the `Inval` error code. -macro_rules! convert_wasi_arg { - ($var:ident, $t:ty) => { - match <$t>::try_from($var) { - Err(_) => return ErrNo::Inval as u32, - Ok(o) => o, - } - }; -} - -/// An implementation of MemorySlice for Wasmtime. -/// -/// We use `data` function in Memory. -/// Conveniently, Memory is managed by internal reference counting, and already -/// isn't thread-safe, so we don't have to worry too much about the complex -/// lifetime requirements of MemorySlice. -pub struct WasmtimeSlice<'a, T> { - store: StoreContext<'a, T>, - memory: Memory, - address: usize, - length: usize, -} - -/// An implementation of MemorySliceMut for Wasmtime. -/// -/// We use `data_mut` function in Memory. -/// Conveniently, Memory is managed by internal reference counting, and already -/// isn't thread-safe, so we don't have to worry too much about the complex -/// lifetime requirements of MemorySlice. -pub struct WasmtimeSliceMut<'a, T> { - store: StoreContextMut<'a, T>, - memory: Memory, - address: usize, - length: usize, -} - -/// Implementation of AsRef for WasmtimeSlice. Implementation of Wasi is able to use this -/// function to access the linear memory in Wasmtime. -impl<'a, T> AsRef<[u8]> for WasmtimeSlice<'a, T> { - fn as_ref(&self) -> &[u8] { - // NOTE this is currently unsafe, but has a safe variant in recent - // versions of wasmtime - &(self.memory.data(&self.store))[self.address..self.address + self.length] - } -} - -/// Implementation of AsMut for WasmtimeSlice. Implementation of Wasi is able to use this -/// function to access the linear memory in Wasmtime. -impl<'a, T> AsMut<[u8]> for WasmtimeSliceMut<'a, T> { - fn as_mut(&mut self) -> &mut [u8] { - // NOTE this is currently unsafe, but has a safe variant in recent - // versions of wasmtime - &mut (self.memory.data_mut(&mut self.store))[self.address..self.address + self.length] - } -} - -impl MemorySlice for WasmtimeSlice<'_, T> {} -impl MemorySliceMut for WasmtimeSliceMut<'_, T> {} - -/// Impl the MemoryHandler for Caller. -/// This allows passing the Caller to WasiWrapper on any VFS call. Implementation -/// here is *NOT* thread-safe, if multiple threads manipulate this Wasmtime instance. -impl<'a, T: 'static> MemoryHandler for Caller<'a, T> { - type Slice = WasmtimeSlice<'static, T>; - type SliceMut = WasmtimeSliceMut<'static, T>; - - fn get_slice<'b>( - &'b self, - address: u32, - length: u32, - ) -> FileSystemResult> { - // NOTE: manually and temporarily change the mutability. - // The unwrap will fail only if the raw pointer is null, which never happens here. - let memory = match unsafe { (self as *const Self as *mut Self).as_mut() } - .unwrap() - .get_export(WasiWrapper::LINEAR_MEMORY_NAME) - .and_then(|export| export.into_memory()) - { - Some(s) => s, - None => return Err(ErrNo::NoMem), - }; - // Manually bend the lifetime to static. This can be improved when GAT - // fully works in Rust standard. - Ok(Bound::new(WasmtimeSlice { - store: unsafe { - mem::transmute::, StoreContext<'static, T>>(self.as_context()) - }, - memory, - address: address as usize, - length: length as usize, - })) - } - - fn get_slice_mut<'c>( - &'c mut self, - address: u32, - length: u32, - ) -> FileSystemResult> { - let memory = match self - .get_export(WasiWrapper::LINEAR_MEMORY_NAME) - .and_then(|export| export.into_memory()) - { - Some(s) => s, - None => return Err(ErrNo::NoMem), - }; - // Manually bend the lifetime to static. This can be improved when GAT - // fully works in Rust standard. - Ok(BoundMut::new(WasmtimeSliceMut { - store: unsafe { - mem::transmute::, StoreContextMut<'static, T>>( - self.as_context_mut(), - ) - }, - memory, - address: address as usize, - length: length as usize, - })) - } - - fn get_size(&self) -> FileSystemResult { - // NOTE: manually and temporarily change the mutability. - // Invocation of `unwrap` only fails if the raw pointer is NULL, but it never happens here. - let memory = match unsafe { (self as *const Self as *mut Self).as_mut() } - .unwrap() - .get_export(WasiWrapper::LINEAR_MEMORY_NAME) - .and_then(|export| export.into_memory()) - { - Some(s) => s, - None => return Err(ErrNo::NoMem), - }; - Ok(u32::try_from(memory.data_size(&self)).unwrap()) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// Checking function well-formedness. -//////////////////////////////////////////////////////////////////////////////// - -/// Checks whether `main` was declared with `argc` and `argv` or without in the -/// WASM program. -fn check_main(tau: &ExternType) -> EntrySignature { - match tau { - ExternType::Func(tau) => { - let params: Vec = tau.params().collect(); - - if params == [ValType::I32, ValType::I32] { - EntrySignature::ArgvAndArgc - } else if params == [] { - EntrySignature::NoParameters - } else { - EntrySignature::NoEntryFound - } - } - _otherwise => EntrySignature::NoEntryFound, - } -} +use wasmtime::{Config, Engine, Linker, Module, Store}; +use wasmtime_wasi::sync::{Dir, WasiCtxBuilder}; +use policy_utils::principal::PrincipalPermission; //////////////////////////////////////////////////////////////////////////////// // The Wasmtime host provisioning state. //////////////////////////////////////////////////////////////////////////////// /// The facade of WASMTIME host provisioning state. pub struct WasmtimeRuntimeState { - /// The WASI file system wrapper. It is a sharable structure protected by lock. - /// The common pattern is to clone it and try to lock it, to obtain the underlining - /// WasiWrapper. - filesystem: SharedMutableWasiWrapper, + permissions: PrincipalPermission, + environment: Environment, } //////////////////////////////////////////////////////////////////////////////// @@ -228,11 +40,23 @@ pub struct WasmtimeRuntimeState { impl WasmtimeRuntimeState { /// Creates a new initial `HostProvisioningState`. - pub fn new(filesystem: FileSystem, options: Options) -> Result { + pub fn new(permissions: PrincipalPermission, environment: Environment + ) -> Result { + info!("Wasmtime is initialised"); Ok(Self { - filesystem: Arc::new(Mutex::new(WasiWrapper::new(filesystem, options)?)), + permissions, + environment, }) } +} + +/// The `WasmtimeHostProvisioningState` implements everything needed to create a +/// compliant instance of `Execution`. +impl Execution for WasmtimeRuntimeState { + /// name of this execution. + fn name(&self) -> &str { + "Wasmtime Webassembly JIT engine with WASI support." + } /// Executes the entry point of the WASM program provisioned into the /// Veracruz host. @@ -250,873 +74,50 @@ impl WasmtimeRuntimeState { /// Otherwise, returns the return value of the entry point function of the /// program, along with a host state capturing the result of the program's /// execution. - pub(crate) fn invoke_engine(&self, binary: Vec) -> Result { + fn execute(&mut self, program_path: &Path) -> Result<()> { + info!("Initialize a wasmtime engine."); + let mut config = Config::default(); config.wasm_simd(true); - let engine = Engine::new(&config)?; - let module = Module::new(&engine, binary)?; + // https://docs.wasmtime.dev/examples-rust-wasi.html let mut linker = Linker::new(&engine); - - info!("Initialized Wasmtime engine."); - - // Link all WASI functions - let wasi_scope = WasiWrapper::WASI_SNAPSHOT_MODULE_NAME; - linker.func_wrap(wasi_scope, WasiAPIName::ARGS_GET.into(), Self::wasi_arg_get)?; - linker.func_wrap( - wasi_scope, - WasiAPIName::ARGS_SIZES_GET.into(), - Self::wasi_args_sizes_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::ENVIRON_GET.into(), - Self::wasi_environ_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::ENVIRON_SIZES_GET.into(), - Self::wasi_environ_size_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::CLOCK_RES_GET.into(), - Self::wasi_clock_res_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::CLOCK_TIME_GET.into(), - Self::wasi_clock_time_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_ADVISE.into(), - Self::wasi_fd_advise, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_ALLOCATE.into(), - Self::wasi_fd_allocate, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_CLOSE.into(), - Self::wasi_fd_close, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_DATASYNC.into(), - Self::wasi_fd_datasync, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_FDSTAT_GET.into(), - Self::wasi_fd_fdstat_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_FDSTAT_SET_FLAGS.into(), - Self::wasi_fd_fdstat_set_flags, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_FDSTAT_SET_RIGHTS.into(), - Self::wasi_fd_fdstat_set_rights, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_FILESTAT_GET.into(), - Self::wasi_fd_filestat_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_FILESTAT_SET_SIZE.into(), - Self::wasi_fd_filestat_set_size, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_FILESTAT_SET_TIMES.into(), - Self::wasi_fd_filestat_set_times, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_PREAD.into(), - Self::wasi_fd_pread, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_PRESTAT_GET.into(), - Self::wasi_fd_prestat_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_PRESTAT_DIR_NAME.into(), - Self::wasi_fd_prestat_dir_name, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_PWRITE.into(), - Self::wasi_fd_pwrite, - )?; - linker.func_wrap(wasi_scope, WasiAPIName::FD_READ.into(), Self::wasi_fd_read)?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_READDIR.into(), - Self::wasi_fd_readdir, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_RENUMBER.into(), - Self::wasi_fd_renumber, - )?; - linker.func_wrap(wasi_scope, WasiAPIName::FD_SEEK.into(), Self::wasi_fd_seek)?; - linker.func_wrap(wasi_scope, WasiAPIName::FD_SYNC.into(), Self::wasi_fd_sync)?; - linker.func_wrap(wasi_scope, WasiAPIName::FD_TELL.into(), Self::wasi_fd_tell)?; - linker.func_wrap( - wasi_scope, - WasiAPIName::FD_WRITE.into(), - Self::wasi_fd_write, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_CREATE_DIRECTORY.into(), - Self::wasi_path_create_directory, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_FILESTAT_GET.into(), - Self::wasi_path_filestat_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_FILESTAT_SET_TIMES.into(), - Self::wasi_path_filestat_set_times, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_LINK.into(), - Self::wasi_path_link, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_OPEN.into(), - Self::wasi_path_open, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_READLINK.into(), - Self::wasi_path_readlink, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_REMOVE_DIRECTORY.into(), - Self::wasi_path_remove_directory, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_RENAME.into(), - Self::wasi_path_rename, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_SYMLINK.into(), - Self::wasi_path_symlink, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PATH_UNLINK_FILE.into(), - Self::wasi_path_unlink_file, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::POLL_ONEOFF.into(), - Self::wasi_poll_oneoff, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PROC_EXIT.into(), - Self::wasi_proc_exit, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::PROC_RAISE.into(), - Self::wasi_proc_raise, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::SCHED_YIELD.into(), - Self::wasi_sched_yield, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::RANDOM_GET.into(), - Self::wasi_random_get, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::SOCK_RECV.into(), - Self::wasi_sock_recv, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::SOCK_SEND.into(), - Self::wasi_sock_send, - )?; - linker.func_wrap( - wasi_scope, - WasiAPIName::SOCK_SHUTDOWN.into(), - Self::wasi_sock_shutdown, - )?; - - // link Veracruz custom functions - linker.func_wrap( - WasiWrapper::VERACRUZ_SI_MODULE_NAME, - VeracruzAPIName::FD_CREATE.into(), - Self::veracruz_si_fd_create, - )?; - - info!("Link external functions."); - - // TODO: change - let mut store = Store::new(&engine, self.filesystem.clone()); - let instance = linker.instantiate(&mut store, &module)?; - - info!("Linker instantiates."); - - let export = instance - .get_export(&mut store, WasiWrapper::ENTRY_POINT_NAME) - .ok_or(FatalEngineError::NoProgramEntryPoint)?; - - info!("Get the main function."); - - let return_from_main = match check_main(&export.ty(&store)) { - EntrySignature::ArgvAndArgc => instance - .get_typed_func::<(i32, i32), ()>(&mut store, WasiWrapper::ENTRY_POINT_NAME)? - .call(&mut store, (0, 0)), - EntrySignature::NoParameters => instance - .get_typed_func::<(), ()>(&mut store, WasiWrapper::ENTRY_POINT_NAME)? - .call(&mut store, ()), - EntrySignature::NoEntryFound => { - return Err(anyhow!(FatalEngineError::NoProgramEntryPoint)) - } - }; + wasmtime_wasi::add_to_linker(&mut linker, |s| s)?; + + let wasm_build = WasiCtxBuilder::new() + // https://docs.wasmtime.dev/api/wasmtime_wasi/sync/struct.WasiCtxBuilder.html#method.args + .inherit_stdio() + .envs(&self.environment.environment_variables)? + .args(&self.environment.program_arguments)? + .inherit_env()? + .inherit_args()?; + + let wasm_build = self.permissions.keys().fold(Ok(wasm_build), |acc : Result, path| { + let wasm_build = acc?; + create_dir_all(path)?; + let file = File::open(&path)?; + info!("pre-opened directory {:?} created if necessary and opened", path); + Ok(wasm_build.preopened_dir(Dir::from_std_file(file), path)?) + })?; + + let wasi = wasm_build.build(); + let mut store = Store::new(&engine, wasi); + let module = Module::from_file(&engine, program_path)?; + linker.module(&mut store, "", &module)?; + + info!("Engine readies."); + + linker + .get_default(&mut store, "")? + .typed::<(), ()>(&store)? + .call(&mut store, ()) + .map_err(|e| { + info!("Engine return error: {:?}", e); + e + })?; info!("Execution returns."); - // NOTE: Surpress the trap, if `proc_exit` is called. - // In this case, the error code is in .exit_code(). - // - let exit_code = store - .into_data() - .lock() - .map_err(|_| anyhow!(FatalEngineError::FailedLockEngine))? - .exit_code(); - info!("Exit code {:?}", exit_code); - match exit_code { - Some(e) => Ok(e), - // If proc_exit is not call, return possible error and trap, - // otherwise the actual return code or default success code `0`. - None => { - info!( - "The return trace: {:?}, (`proc_exit` is not called).", - return_from_main - ); - return_from_main?; - Ok(0) - } - } - } - - fn convert_to_errno(input: FileSystemResult<()>) -> u32 { - let errno = match input { - Ok(_) => ErrNo::Success, - Err(e) => e, - }; - errno as u32 - } - - fn wasi_arg_get( - mut caller: CallerWrapper<'_>, - string_ptr_address: u32, - buf_address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.args_get(&mut caller, string_ptr_address, buf_address)) - } - - fn wasi_args_sizes_get( - mut caller: CallerWrapper<'_>, - count_address: u32, - size_address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.args_sizes_get(&mut caller, count_address, size_address)) - } - - fn wasi_environ_get( - mut caller: CallerWrapper<'_>, - string_ptr_address: u32, - buf_address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.environ_get(&mut caller, string_ptr_address, buf_address)) - } - - fn wasi_environ_size_get( - mut caller: CallerWrapper<'_>, - environc_address: u32, - environ_buf_size_address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.environ_sizes_get( - &mut caller, - environc_address, - environ_buf_size_address, - )) - } - - fn wasi_clock_res_get(mut caller: CallerWrapper<'_>, clock_id: u32, address: u32) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.clock_res_get(&mut caller, clock_id, address)) - } - - fn wasi_clock_time_get( - mut caller: CallerWrapper<'_>, - clock_id: u32, - precision: u64, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.clock_time_get(&mut caller, clock_id, precision, address)) - } - - fn wasi_fd_advise( - mut caller: CallerWrapper<'_>, - fd: u32, - offset: u64, - len: u64, - advice: u32, - ) -> u32 { - let advice = convert_wasi_arg!(advice, u8); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_advise(&mut caller, fd, offset, len, advice)) - } - - fn wasi_fd_allocate(mut caller: CallerWrapper<'_>, fd: u32, offset: u64, len: u64) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_allocate(&mut caller, fd, offset, len)) - } - - fn wasi_fd_close(caller: CallerWrapper<'_>, fd: u32) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_close(&caller, fd)) - } - - fn wasi_fd_datasync(mut caller: CallerWrapper<'_>, fd: u32) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_datasync(&mut caller, fd)) - } - - fn wasi_fd_fdstat_get(mut caller: CallerWrapper<'_>, fd: u32, address: u32) -> u32 { - let caller_data = caller.data().clone(); - let vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_fdstat_get(&mut caller, fd, address)) - } - - fn wasi_fd_fdstat_set_flags(mut caller: CallerWrapper<'_>, fd: u32, flag: u32) -> u32 { - let flag = convert_wasi_arg!(flag, u16); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_fdstat_set_flags(&mut caller, fd, flag)) - } - - fn wasi_fd_fdstat_set_rights( - mut caller: CallerWrapper<'_>, - fd: u32, - rights_base: u64, - rights_inheriting: u64, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_fdstat_set_rights( - &mut caller, - fd, - rights_base, - rights_inheriting, - )) - } - - fn wasi_fd_filestat_get(mut caller: CallerWrapper<'_>, fd: u32, address: u32) -> u32 { - let caller_data = caller.data().clone(); - let vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_filestat_get(&mut caller, fd, address)) - } - - fn wasi_fd_filestat_set_size(mut caller: CallerWrapper<'_>, fd: u32, size: u64) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_filestat_set_size(&mut caller, fd, size)) - } - - fn wasi_fd_filestat_set_times( - mut caller: CallerWrapper<'_>, - fd: u32, - atime: u64, - mtime: u64, - fst_flags: u32, - ) -> u32 { - let fst_flags = convert_wasi_arg!(fst_flags, u16); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_filestat_set_times(&mut caller, fd, atime, mtime, fst_flags)) - } - - fn wasi_fd_pread( - mut caller: CallerWrapper<'_>, - fd: u32, - iovec_base: u32, - iovec_count: u32, - offset: u64, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_pread( - &mut caller, - fd, - iovec_base, - iovec_count, - offset, - address, - )) - } - - fn wasi_fd_prestat_get(mut caller: CallerWrapper<'_>, fd: u32, address: u32) -> u32 { - info!("prestat_get called"); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - info!("succ lock"); - Self::convert_to_errno(vfs.fd_prestat_get(&mut caller, fd, address)) - } - - fn wasi_fd_prestat_dir_name( - mut caller: CallerWrapper<'_>, - fd: u32, - address: u32, - size: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_prestat_dir_name(&mut caller, fd, address, size)) - } - - fn wasi_fd_pwrite( - mut caller: CallerWrapper<'_>, - fd: u32, - iovec_base: u32, - iovec_number: u32, - offset: u64, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_pwrite( - &mut caller, - fd, - iovec_base, - iovec_number, - offset, - address, - )) - } - - fn wasi_fd_read( - mut caller: CallerWrapper<'_>, - fd: u32, - iovec_base: u32, - iovec_count: u32, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_read(&mut caller, fd, iovec_base, iovec_count, address)) - } - - fn wasi_fd_readdir( - mut caller: CallerWrapper<'_>, - fd: u32, - dirent_base: u32, - dirent_length: u32, - cookie: u64, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_readdir( - &mut caller, - fd, - dirent_base, - dirent_length, - cookie, - address, - )) - } - - fn wasi_fd_renumber(mut caller: CallerWrapper<'_>, fd: u32, to_fd: u32) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_renumber(&mut caller, fd, to_fd)) - } - - fn wasi_fd_seek( - mut caller: CallerWrapper<'_>, - fd: u32, - offset: i64, - whence: u32, - address: u32, - ) -> u32 { - let whence = convert_wasi_arg!(whence, u8); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_seek(&mut caller, fd, offset, whence, address)) - } - - fn wasi_fd_sync(mut caller: CallerWrapper<'_>, fd: u32) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_sync(&mut caller, fd)) - } - - fn wasi_fd_tell(mut caller: CallerWrapper<'_>, fd: u32, address: u32) -> u32 { - let caller_data = caller.data().clone(); - let vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_tell(&mut caller, fd, address)) - } - - fn wasi_fd_write( - mut caller: CallerWrapper<'_>, - fd: u32, - iovec_base: u32, - iovec_number: u32, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_write(&mut caller, fd, iovec_base, iovec_number, address)) - } - - fn wasi_path_create_directory( - mut caller: CallerWrapper<'_>, - fd: u32, - path: u32, - path_len: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_create_directory(&mut caller, fd, path, path_len)) - } - - fn wasi_path_filestat_get( - mut caller: CallerWrapper<'_>, - fd: u32, - flag: u32, - path: u32, - path_len: u32, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_filestat_get( - &mut caller, - fd, - flag, - path, - path_len, - address, - )) - } - - fn wasi_path_filestat_set_times( - mut caller: CallerWrapper<'_>, - fd: u32, - flag: u32, - path: u32, - path_len: u32, - atime: u64, - mtime: u64, - fst_flags: u32, - ) -> u32 { - let fst_flags = convert_wasi_arg!(fst_flags, u16); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_filestat_set_times( - &mut caller, - fd, - flag, - path, - path_len, - atime, - mtime, - fst_flags, - )) - } - - fn wasi_path_link( - mut caller: CallerWrapper<'_>, - old_fd: u32, - old_flags: u32, - old_address: u32, - old_path_len: u32, - new_fd: u32, - new_address: u32, - new_path_len: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_link( - &mut caller, - old_fd, - old_flags, - old_address, - old_path_len, - new_fd, - new_address, - new_path_len, - )) - } - - fn wasi_path_open( - mut caller: CallerWrapper<'_>, - fd: u32, - dir_flags: u32, - path_address: u32, - path_length: u32, - oflags: u32, - fs_rights_base: u64, - fs_rights_inheriting: u64, - fd_flags: u32, - address: u32, - ) -> u32 { - let oflags = convert_wasi_arg!(oflags, u16); - let fd_flags = convert_wasi_arg!(fd_flags, u16); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_open( - &mut caller, - fd, - dir_flags, - path_address, - path_length, - oflags, - fs_rights_base, - fs_rights_inheriting, - fd_flags, - address, - )) - } - - fn wasi_path_readlink( - mut caller: CallerWrapper<'_>, - fd: u32, - path: u32, - path_len: u32, - buf: u32, - buf_len: u32, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_readlink( - &mut caller, - fd, - path, - path_len, - buf, - buf_len, - address, - )) - } - - fn wasi_path_remove_directory( - mut caller: CallerWrapper<'_>, - fd: u32, - path: u32, - path_len: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_remove_directory(&mut caller, fd, path, path_len)) - } - - fn wasi_path_rename( - mut caller: CallerWrapper<'_>, - old_fd: u32, - old_path: u32, - old_len: u32, - new_fd: u32, - new_path: u32, - new_len: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_rename( - &mut caller, - old_fd, - old_path, - old_len, - new_fd, - new_path, - new_len, - )) - } - - fn wasi_path_symlink( - mut caller: CallerWrapper<'_>, - old_address: u32, - old_path_len: u32, - fd: u32, - new_address: u32, - new_path_len: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_symlink( - &mut caller, - old_address, - old_path_len, - fd, - new_address, - new_path_len, - )) - } - - fn wasi_path_unlink_file( - mut caller: CallerWrapper<'_>, - fd: u32, - path: u32, - path_len: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.path_unlink_file(&mut caller, fd, path, path_len)) - } - - fn wasi_poll_oneoff( - mut caller: CallerWrapper<'_>, - subscriptions: u32, - events: u32, - size: u32, - address: u32, - ) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.poll_oneoff(&mut caller, subscriptions, events, size, address)) - } - - fn wasi_proc_exit(mut caller: CallerWrapper<'_>, exit_code: u32) { - let caller_data = &caller.data().clone(); - let mut vfs = match caller_data.lock() { - Ok(v) => v, - Err(_) => panic!("unexpected failure"), - }; - - vfs.proc_exit(&mut caller, exit_code); - } - - fn wasi_proc_raise(mut caller: CallerWrapper<'_>, signal: u32) -> u32 { - let signal = convert_wasi_arg!(signal, u8); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.proc_raise(&mut caller, signal)) - } - - fn wasi_sched_yield(mut caller: CallerWrapper<'_>) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.sched_yield(&mut caller)) - } - - fn wasi_random_get(mut caller: CallerWrapper<'_>, address: u32, length: u32) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.random_get(&mut caller, address, length)) - } - - fn wasi_sock_recv( - mut caller: CallerWrapper<'_>, - socket: u32, - buf_address: u32, - buf_len: u32, - ri_flag: u32, - ro_data_len: u32, - ro_flag: u32, - ) -> u32 { - let ri_flag = convert_wasi_arg!(ri_flag, u16); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.sock_recv( - &mut caller, - socket, - buf_address, - buf_len, - ri_flag, - ro_data_len, - ro_flag, - )) - } - - fn wasi_sock_send( - mut caller: CallerWrapper<'_>, - socket: u32, - buf_address: u32, - buf_len: u32, - si_flag: u32, - ro_data_len: u32, - ) -> u32 { - let si_flag = convert_wasi_arg!(si_flag, u16); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.sock_send( - &mut caller, - socket, - buf_address, - buf_len, - si_flag, - ro_data_len, - )) - } - - fn wasi_sock_shutdown(mut caller: CallerWrapper, socket: u32, sd_flag: u32) -> u32 { - let sd_flag = convert_wasi_arg!(sd_flag, u8); - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.sock_shutdown(&mut caller, socket, sd_flag)) - } - - fn veracruz_si_fd_create(mut caller: CallerWrapper, address: u32) -> u32 { - let caller_data = caller.data().clone(); - let mut vfs = lock_vfs!(caller_data); - Self::convert_to_errno(vfs.fd_create(&mut caller, address)) - } -} - -/// The `WasmtimeHostProvisioningState` implements everything needed to create a -/// compliant instance of `ExecutionEngine`. -impl ExecutionEngine for WasmtimeRuntimeState { - /// ExecutionEngine wrapper of `invoke_engine`. Raises a panic if - /// the global Wasmtime host is unavailable. - #[inline] - fn invoke_entry_point(&mut self, program: Vec) -> Result { - self.invoke_engine(program) + Ok(()) } } diff --git a/crates/execution-engine/src/fs.rs b/crates/execution-engine/src/fs.rs deleted file mode 100644 index 7e5d4149b..000000000 --- a/crates/execution-engine/src/fs.rs +++ /dev/null @@ -1,2134 +0,0 @@ -//! A synthetic filesystem. -//! -//! This virtual file system(VFS) for Veracruz runtime and execution engine. -//! The VFS adopts most WASI API with *strict typing* and *Rust-style error handling*. -//! The Veracruz runtime will use this VFS directly, while any execution engine -//! can wrap all methods here to match the WASI API. -//! -//! ## Authors -//! -//! The Veracruz Development Team. -//! -//! ## Licensing and copyright notice -//! -//! See the `LICENSE.md` file in the Veracruz root directory for -//! information on licensing and copyright. - -#![allow(clippy::too_many_arguments)] - -use crate::native_module_manager::NativeModuleManager; -use policy_utils::{ - principal::{FileRights, NativeModule, NativeModuleType, Principal, RightsTable}, - CANONICAL_STDERR_FILE_PATH, CANONICAL_STDIN_FILE_PATH, CANONICAL_STDOUT_FILE_PATH, -}; -use std::{ - boxed::Box, - cmp::min, - collections::HashMap, - convert::{AsRef, TryFrom}, - fmt::Debug, - path::{Component, Path, PathBuf}, - string::String, - sync::{Arc, Mutex, MutexGuard}, - vec::Vec, -}; -use log::error; -use std::{ - ffi::OsString, - os::unix::ffi::{OsStrExt, OsStringExt}, -}; -use wasi_types::{ - Advice, DirCookie, DirEnt, ErrNo, Event, Fd, FdFlags, FdStat, FileDelta, FileSize, FileStat, - FileType, Inode, LookupFlags, OpenFlags, PreopenType, Prestat, RiFlags, Rights, RoFlags, - SdFlags, SetTimeFlags, SiFlags, Size, Subscription, Timestamp, Whence, -}; - -//////////////////////////////////////////////////////////////////////////////// -// Filesystem errors. -//////////////////////////////////////////////////////////////////////////////// - -/// Filesystem errors either return a result of type `T` or a defined error -/// code. The return code `ErrNo::Success` is implicit if `Ok(result)` is ever -/// returned from a filesystem function. The result `Err(ErrNo::Success)` -/// should never be returned. -pub type FileSystemResult = Result; - -/// Internal shared inode table. -type SharedInodeTable = Arc>; - -//////////////////////////////////////////////////////////////////////////////// -// INodes. -//////////////////////////////////////////////////////////////////////////////// - -/// INodes wrap the actual raw file data, and associate meta-data with that raw -/// data buffer. -#[derive(Clone, Debug)] -struct InodeEntry { - /// The status of this file. - file_stat: FileStat, - /// The content of the inode. - data: InodeImpl, -} - -impl InodeEntry { - /// Resize a file to `size`, fill with `fill_byte` if it grows, - /// and update the file status. - /// Return ErrNo::IsDir, if it is not a file - #[inline] - pub(self) fn resize_file(&mut self, size: FileSize, fill_byte: u8) -> FileSystemResult<()> { - self.data.resize_file(size, fill_byte)?; - self.file_stat.file_size = size; - Ok(()) - } - - /// Read maximum `max` bytes from the offset `offset`. - /// Return ErrNo::IsDir if it is not a file. - #[inline] - pub(self) fn read_file(&self, buf: &mut [u8], offset: FileSize) -> FileSystemResult { - self.data.read_file(buf, offset) - } - - /// Write `buf` to the file from the offset `offset`, - /// update the file status and return the number of written bytes. - /// Otherwise, return ErrNo::IsDir if it is not a file. - #[inline] - pub(self) fn write_file(&mut self, buf: &[u8], offset: FileSize) -> FileSystemResult { - let rst = self.data.write_file(buf, offset)?; - self.file_stat.file_size = self.data.len()?; - Ok(rst) - } - - /// Truncate the file. - /// Return ErrNo::IsDir if it is not a file. - #[inline] - pub(self) fn truncate_file(&mut self) -> FileSystemResult<()> { - self.data.truncate_file()?; - self.file_stat.file_size = 0u64; - Ok(()) - } - - /// Insert a file to the directory at `self`. - /// Return ErrNo:: NotDir if `self` is not a directory. - #[inline] - pub(self) fn insert>(&mut self, path: T, inode: Inode) -> FileSystemResult<()> { - self.data.insert(path, inode) - } - - /// Return the inode of `path`. - /// Return ErrNo:: NotDir if `self` is not a directory. - #[inline] - pub(self) fn get_inode_by_path>(&self, path: T) -> FileSystemResult { - self.data.get_inode_by_path(path) - } - - /// Check if the inode is a directory - #[inline] - pub(crate) fn is_dir(&self) -> bool { - self.data.is_dir() - } - - /// Read metadata of all files and sub-dirs in the dir and return a vec of DirEnt, - /// or return NotDir if `self` is not a dir - #[inline] - pub(self) fn read_dir( - &self, - inode_table: &InodeTable, - ) -> FileSystemResult)>> { - self.data.read_dir(inode_table) - } - - /// Return the number of bytes, if it is a file, - /// or the number of inodes, if it is a directory. - #[inline] - pub(self) fn len(&self) -> FileSystemResult { - self.data.len() - } - - /// Return if the current path corresponds is a service. - #[inline] - pub(self) fn is_service(&self) -> bool { - self.data.is_service() - } - - /// Return the service handler, and the current content of in the special file. - #[inline] - pub(crate) fn service_handler( - &self, - ) -> FileSystemResult<(Arc>>, Vec)> { - self.data.service_handler() - } -} - -/// The actual data of an inode, either a file or a directory. -#[derive(Clone, Debug)] -enum InodeImpl { - /// A special file that is bound to a native service. - /// Writing to the file triggers the execution of the service. - /// It treat the `Inode` as the input parameter and the result will be stored in Vec. - /// The services will use the FileSystem (handle) to access the VFS. - /// NOTE: Current design is only safe for SINGLE thread. - /// - The program is allowed to read the (input) content to the service; and the input - /// information, might be sensitive, is cleaned on the invocation `fd_closed`. - /// In single thread situation, it is fine. - /// - The output of the service is determined by the service itself. It can try to open - /// any file and write to it, as long as the service has enough capabilities in FileSystem. - NativeModule(Arc>>, Vec), - /// A file - File(Vec), - /// A directory. The `PathBuf` key is the relative path and must match the name inside the `Inode`. - Directory(HashMap), -} - -impl InodeImpl { - const CURRENT_PATH_STR: &'static str = "."; - const PARENT_PATH_STR: &'static str = ".."; - - /// Return a new Directory InodeImpl containing only current and parent paths - pub(crate) fn new_directory(current: Inode, parent: Inode) -> Self { - let mut dir = HashMap::new(); - dir.insert(PathBuf::from(Self::CURRENT_PATH_STR), current); - dir.insert(PathBuf::from(Self::PARENT_PATH_STR), parent); - Self::Directory(dir) - } - - /// Resize a file to `size`, and fill with `fill_byte` if it grows. - /// Otherwise, return ErrNo::IsDir if it is not a file. - #[inline] - pub(self) fn resize_file(&mut self, size: FileSize, fill_byte: u8) -> FileSystemResult<()> { - match self { - Self::NativeModule(.., file) | Self::File(file) => { - file.resize(<_>::try_from_or_errno(size)?, fill_byte); - Ok(()) - } - Self::Directory(_) => Err(ErrNo::IsDir), - } - } - - /// Read maximum `max` bytes from the offset `offset`. - /// Otherwise, return ErrNo::IsDir if it is a dir - /// or ErrNo::Again if it is a service and no output is available. - pub(self) fn read_file(&self, buf: &mut [u8], offset: FileSize) -> FileSystemResult { - match self { - Self::File(b) | Self::NativeModule(.., b) => { - Self::read_bytes_from_offset(b, buf, offset) - } - Self::Directory(_) => Err(ErrNo::IsDir), - } - } - - fn read_bytes_from_offset( - bytes: &[u8], - buf: &mut [u8], - offset: FileSize, - ) -> FileSystemResult { - // NOTE: It should be safe to convert a u64 to usize. - let offset = <_>::try_from_or_errno(offset)?; - // offset - // v - // --------------------------------------------- - // | .... | to_read | | - // --------------------------------------------- - // v ... read_length ... v - // ------------------------ - // | rst | - // ------------------------ - let (_, to_read) = bytes.split_at(offset); - let read_length = min(buf.len(), to_read.len()); - buf[..read_length].copy_from_slice(&to_read[..read_length]); - Ok(read_length) - } - - /// Write `buf` to the file from the offset `offset` and return the number of written bytes. - /// Otherwise, return ErrNo::IsDir if it is not a file. - pub(self) fn write_file(&mut self, buf: &[u8], offset: FileSize) -> FileSystemResult { - let bytes = match self { - Self::File(b) | Self::NativeModule(.., b) => b, - Self::Directory(_) => return Err(ErrNo::IsDir), - }; - // NOTE: It should be safe to convert a u64 to usize. - let offset = <_>::try_from_or_errno(offset)?; - // offset - // v .. remain_length .. v - // ---------------------------------------------- - // | .... | to_write 0 0 ... | - // ---------------------------------------------- - // v ... buf.len() ... v - // ---------------------------------- - // | buf | - // ---------------------------------- - if offset + buf.len() > bytes.len() { - bytes.resize(offset + buf.len(), 0); - } - let write_length = buf.len(); - bytes[offset..(offset + write_length)].copy_from_slice(&buf); - Ok(write_length) - } - - /// Truncate the file. - /// Return ErrNo::IsDir if it is a dir. - #[inline] - pub(self) fn truncate_file(&mut self) -> FileSystemResult<()> { - match self { - Self::File(b) | Self::NativeModule(.., b) => { - b.clear(); - Ok(()) - } - Self::Directory(_) => Err(ErrNo::IsDir), - } - } - - /// Insert a file to the directory at `self`. - /// Return ErrNo:: NotDir if `self` is not a directory. - #[inline] - pub(self) fn insert>(&mut self, path: T, inode: Inode) -> FileSystemResult<()> { - match self { - InodeImpl::Directory(path_table) => { - path_table.insert(path.as_ref().to_path_buf(), inode) - } - _otherwise => return Err(ErrNo::NotDir), - }; - Ok(()) - } - - /// Insert a file to the directory at `self`. - /// Return ErrNo:: NotDir if `self` is not a directory. - #[inline] - pub(self) fn get_inode_by_path>(&self, path: T) -> FileSystemResult { - match self { - InodeImpl::Directory(path_table) => { - Ok(*path_table.get(path.as_ref()).ok_or(ErrNo::NoEnt)?) - } - _otherwise => Err(ErrNo::NotDir), - } - } - - /// Return the number of the bytes, if it is a file, - /// or the number of inodes, if it it is a directory. - #[inline] - pub(self) fn len(&self) -> FileSystemResult { - let rst = match self { - Self::NativeModule(.., f) | Self::File(f) => f.len(), - Self::Directory(f) => f.len(), - }; - Ok(rst as FileSize) - } - - /// Check if it is a directory - #[inline] - pub(crate) fn is_dir(&self) -> bool { - match self { - Self::Directory(_) => true, - _ => false, - } - } - - /// Check if it is a service - #[inline] - pub(crate) fn is_service(&self) -> bool { - match self { - Self::NativeModule(..) => true, - _ => false, - } - } - - /// Return the service. - #[inline] - pub(crate) fn service_handler( - &self, - ) -> FileSystemResult<(Arc>>, Vec)> { - match self { - Self::NativeModule(service, input) => { - // NOTE: We copy out, particularly `input`, on purpose, as they are protected by a - // lock on the inote table. We have to release the lock allowing the service to - // access the FileSystem, unless we introduce lock ownership transition mechanism. - // A better way to organising the inode is using fine-grained locper entry - Ok((service.clone(), input.clone())) - } - _ => Err(ErrNo::Inval), - } - } - - /// Read metadata of files in the dir and return a vec of DirEnt, - /// or return NotDir if `self` is not a dir - pub(self) fn read_dir( - &self, - inode_table: &InodeTable, - ) -> FileSystemResult)>> { - let dir = match self { - InodeImpl::Directory(d) => d, - _otherwise => return Err(ErrNo::NotDir), - }; - let mut rst = Vec::new(); - for (index, (path, inode)) in dir.iter().enumerate() { - let path_byte = path.as_os_str().as_bytes().to_vec(); - let dir_ent = DirEnt { - next: (u64::try_from_or_errno(index)? + 1u64).into(), - inode: *inode, - name_len: <_>::try_from_or_errno(path_byte.len())?, - file_type: inode_table.get(&inode)?.file_stat.file_type, - }; - rst.push((dir_ent, path_byte)) - } - Ok(rst) - } -} - -struct InodeTable { - /// All inodes - table: HashMap, - /// The Right table for Principal, including participants and programs. - /// It will be used to create a new FileSystem (handler). - rights_table: RightsTable, - /// The inodes for stdin, stdout and stderr, respectively. - stdin: Inode, - stdout: Inode, - stderr: Inode, - /// We allocate inodes in the same way as we allocate file descriptors. Inode's are 64 bits - /// rather than 31 bits, so the artificial limit on inode allocations is 2^64. - next_inode_candidate: Inode, -} - -impl Debug for InodeTable { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "Inode Table:\n")?; - for (k, v) in self.table.iter() { - match &v.data { - InodeImpl::File(_) => write!(f, "\t{:?} -> file\n", k)?, - InodeImpl::NativeModule(service, _) => write!( - f, - "\t{:?} -> service {}\n", - k, - service - .try_lock() - .map_or_else(|_| "(failed to lock)".to_string(), |o| format!("{:?}", o)) - )?, - InodeImpl::Directory(d) => write!(f, "\t{:?} -> {:?}\n", k, d)?, - } - } - Ok(()) - } -} - -impl InodeTable { - /// The root directory name. It will be pre-opened for any wasm program. - pub(self) const ROOT_DIRECTORY: &'static str = "/"; - /// The root directory inode. It will be pre-opened for any wasm program. - /// File descriptors 0 to 2 are reserved for the standard streams. - pub(self) const ROOT_DIRECTORY_INODE: Inode = Inode(2); - - fn new(rights_table: RightsTable) -> FileSystemResult { - let mut rst = Self { - table: HashMap::new(), - stdin: Inode(0), - stdout: Inode(1), - stderr: Inode(2), - rights_table, - next_inode_candidate: Inode(Self::ROOT_DIRECTORY_INODE.0 + 1), - }; - // Add the root directory - rst.add_dir( - Self::ROOT_DIRECTORY_INODE, - Path::new(Self::ROOT_DIRECTORY), - Self::ROOT_DIRECTORY_INODE, - )?; - // Add the standard in out and err. - rst.install_standard_streams_inode()?; - Ok(rst) - } - - /// Install static and dynamic native modules. - /// Assume `path` is an absolute path to a (special) file. - /// NOTE: this function is intended to be called after the root filesystem (handler) is - /// created. - fn install_services(&mut self, native_modules: Vec) -> FileSystemResult<()> { - for native_module in native_modules { - let path = match native_module.r#type() { - NativeModuleType::Static { special_file } => Some(special_file), - NativeModuleType::Dynamic { special_file, .. } => Some(special_file), - _ => None, - }; - if path.is_some() { - let path = path.unwrap(); - let service = Arc::new(Mutex::new(Box::new(native_module.clone()))); - let new_inode = self.new_inode()?; - let path = strip_root_slash_path(path); - // Call the existing function to create general files. - self.add_file(Self::ROOT_DIRECTORY_INODE, path, new_inode, Vec::new())?; - // Manually uplift the general file to special file bound with the service. - self.table.get_mut(&new_inode).ok_or(ErrNo::Inval)?.data = - InodeImpl::NativeModule(service, Vec::new()); - } - } - Ok(()) - } - - /// Install standard streams (`stdin`, `stdout`, `stderr`). - fn install_standard_streams_inode(&mut self) -> FileSystemResult<()> { - self.stdin = self.new_inode()?; - self.add_file( - self.stdin, - CANONICAL_STDIN_FILE_PATH, - self.stdin, - Vec::new(), - )?; - - self.stdout = self.new_inode()?; - self.add_file( - self.stdout, - CANONICAL_STDOUT_FILE_PATH, - self.stdout, - Vec::new(), - )?; - - self.stderr = self.new_inode()?; - self.add_file( - self.stderr, - CANONICAL_STDERR_FILE_PATH, - self.stderr, - Vec::new(), - )?; - Ok(()) - } - - /// Return the inode for stdin - #[inline] - fn stdin(&self) -> Inode { - self.stdin - } - - /// Return the inode for stdout - #[inline] - fn stdout(&self) -> Inode { - self.stdout - } - - /// Return the inode for stderr - #[inline] - fn stderr(&self) -> Inode { - self.stderr - } - - /// Insert a new inode - #[inline] - fn insert(&mut self, inode: Inode, entry: InodeEntry) -> FileSystemResult<()> { - self.table.insert(inode, entry); - Ok(()) - } - - /// Return the inode entry associated to `inode` - #[inline] - fn get(&self, inode: &Inode) -> FileSystemResult<&InodeEntry> { - self.table.get(&inode).ok_or(ErrNo::NoEnt) - } - - /// Return the inode entry associated to `inode` - #[inline] - fn get_mut(&mut self, inode: &Inode) -> FileSystemResult<&mut InodeEntry> { - self.table.get_mut(&inode).ok_or(ErrNo::NoEnt) - } - - /// Return if the `inode` is a directory. - #[inline] - fn is_dir(&self, inode: &Inode) -> bool { - self.get(inode).map(|i| i.is_dir()).unwrap_or(false) - } - - /// Return if the `inode` is an empty directory. - #[inline] - fn is_dir_empty(&self, inode: &Inode) -> FileSystemResult { - let inode = self.get(inode); - match inode.map(|i| i.is_dir()).unwrap_or(false) { - true => Ok(inode?.read_dir(&self)?.iter().count() <= 2), - false => Ok(false), - } - } - - /// Return the rights table of `principal`. - #[inline] - fn get_rights(&self, principal: &Principal) -> FileSystemResult<&HashMap> { - self.rights_table.get(principal).ok_or(ErrNo::Access) - } - - /// Return the inode and the associated inode entry at the relative `path` in the parent - /// inode `parent_inode`. Return Error if `fd` is not a directory. - fn get_inode_by_inode_path>( - &self, - parent_inode: &Inode, - path: T, - ) -> FileSystemResult<(Inode, &InodeEntry)> { - let inode = path - .as_ref() - .components() - .fold(Ok(*parent_inode), |last, component| { - // If there is an error - let last = last?; - // Find the next inode - self.get(&last)?.get_inode_by_path(component) - })?; - //let inode = parent_inode_entry.get_inode_by_path(path.as_ref())?; - Ok((inode, self.get(&inode)?)) - } - - /// Pick a fresh inode. - fn new_inode(&mut self) -> FileSystemResult { - let cur = self.next_inode_candidate; - // Consume all possible Inodes, or the next inode is already used. - if self.table.contains_key(&cur) { - return Err(ErrNo::NFile); - } - // NOTE: we waste the max inode. - self.next_inode_candidate = match u64::from(cur).checked_add(1) { - Some(next) => Inode(next), - None => return Err(ErrNo::NFile), // Not quite accurate, but this may be the best fit - }; - Ok(cur) - } - - /// Install a directory with inode `new_inode` and attach it under the parent inode `parent`. - /// The `new_inode` MUST be fresh. - fn add_dir>( - &mut self, - parent: Inode, - path: T, - new_inode: Inode, - ) -> FileSystemResult<()> { - let file_stat = FileStat { - device: (0u64).into(), - inode: new_inode, - file_type: FileType::Directory, - num_links: 0, - file_size: 0u64, - atime: Timestamp::from_nanos(0), - mtime: Timestamp::from_nanos(0), - ctime: Timestamp::from_nanos(0), - }; - let path = path.as_ref().to_path_buf(); - let node = InodeEntry { - file_stat, - data: InodeImpl::new_directory(new_inode, parent), - }; - // NOTE: first add the inode to its parent inode, in the case of parent is not a directory, - // it causes error and no side effect will be made to the file system, i.e no island inode. - // If parent is not equal to new_inode, it means `new_inode` is not a ROOT, - // Hence, add the new inode into the parent inode dir. - if parent != new_inode { - self.table - .get_mut(&parent) - .ok_or(ErrNo::NoEnt)? - .insert(path, new_inode)?; - } - // Add the map from the new inode to inode implementation. - self.insert(new_inode, node)?; - Ok(()) - } - - /// Create all directories in the `path`, if necessary, e.g. `/path/to/a/new/dir`. - /// The last component in `path` will be treated a directory rather a file. - fn add_all_dir>( - &mut self, - mut parent: Inode, - path: T, - ) -> FileSystemResult { - // iterate over the path and create the directory if necessary. - for component in path.as_ref().components() { - if let Component::Normal(c) = component { - let new_parent = match self.get_inode_by_inode_path(&parent, c) { - Ok((o, _)) => o, - // Directory is not exist, hence create it. - Err(ErrNo::NoEnt) => { - let new_inode = self.new_inode()?; - self.add_dir(parent, c, new_inode)?; - new_inode - } - Err(e) => return Err(e), - }; - parent = new_parent; - } else { - return Err(ErrNo::Inval); - } - } - Ok(parent) - } - - /// Install a file with content `raw_file_data` and attach it to `inode`. - /// Create any missing directory in the path. - fn add_file>( - &mut self, - parent: Inode, - path: T, - new_inode: Inode, - raw_file_data: Vec, - ) -> FileSystemResult<()> { - let path = path.as_ref(); - // Create missing directories in the `parent` inode if the path contains directory, - // and shift the `parent` to the direct parent of the new file. - // Note that if the parent() return None, it means an empty `path` is passed in, hence it - // is an error. - let (parent, path) = { - let parent_path = path.parent().ok_or(ErrNo::Inval)?; - // No parent, directly add it - if parent_path == Path::new("") { - (parent, path) - } else { - let file_path = path.file_name().map(|s| s.as_ref()).ok_or(ErrNo::Inval)?; - self.add_all_dir(parent, parent_path)?; - ( - self.get_inode_by_inode_path(&parent, parent_path)?.0, - file_path, - ) - } - }; - let file_size = raw_file_data.len(); - let file_stat = FileStat { - device: 0u64.into(), - inode: new_inode, - file_type: FileType::RegularFile, - num_links: 0, - file_size: <_>::try_from_or_errno(file_size)?, - atime: Timestamp::from_nanos(0), - mtime: Timestamp::from_nanos(0), - ctime: Timestamp::from_nanos(0), - }; - let node = InodeEntry { - file_stat, - data: InodeImpl::File(raw_file_data), - }; - // Add the map from the new inode to inode implementation. - self.insert(new_inode, node)?; - // Add the new inode into the parent inode dir. If the parent == new_inode, it may be - // special inode, e.g. stdin stdout stderr - if parent != new_inode { - self.table - .get_mut(&parent) - .ok_or(ErrNo::NoEnt)? - .insert(path, new_inode)?; - } - Ok(()) - } -} - -//////////////////////////////////////////////////////////////////////////////// -// File-table entries. -//////////////////////////////////////////////////////////////////////////////// - -/// Each file table entry contains an index into the inode table, pointing to an -/// `InodeEntry`, where the static file data is stored. -#[derive(Clone, Debug)] -struct FdEntry { - /// The index to `inode_table` in FileSystem. - inode: Inode, - /// Metadata for the file descriptor. - fd_stat: FdStat, - /// The current offset of the file descriptor. - offset: FileSize, - /// Advice on how regions of the file are to be used. - advice: Vec<(FileSize, FileSize, Advice)>, -} - -//////////////////////////////////////////////////////////////////////////////// -// Filesystems. -//////////////////////////////////////////////////////////////////////////////// - -/// The filesystem proper, which collects together various tables and bits of -/// meta-data. -#[derive(Clone)] -pub struct FileSystem { - /// A table of file descriptor table entries. This is indexed by file - /// descriptors. - fd_table: HashMap, - /// In order to quickly allocate file descriptors, we keep track of a monotonically increasing - /// candidate, starting just above the reserved values. With this approach, file descriptors - /// can not be re-allocated after being freed, imposing an artificial limit of 2^31 file - /// descriptor allocations over the course of a program's execution. - next_fd_candidate: Fd, - /// The inode table, which points to the actual data associated with a file - /// and other metadata. This table is indexed by the Inode. - inode_table: SharedInodeTable, - /// Preopen FD table. Mapping the FD to dir name. - prestat_table: HashMap, - /// A list of native modules available for the computation. - native_modules: Vec, -} - -impl Debug for FileSystem { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "\tFD table:\n")?; - for (fd, fd_entry) in self.fd_table.iter() { - write!(f, "\t\t{:?} -> {:?}\n", fd, fd_entry)?; - } - write!(f, "\tpre open fd paths:\n")?; - for (fd, path) in self.fd_table.iter() { - write!(f, "\t\t{:?} -> {:?}\n", fd, path)?; - } - Ok(()) - } -} - -impl FileSystem { - //////////////////////////////////////////////////////////////////////////// - // Creating filesystems. - //////////////////////////////////////////////////////////////////////////// - - /// The first file descriptor. It will be pre-opened for any Wasm program. - pub const FIRST_FD: Fd = Fd(3); - /// The default initial rights on a newly created file. - pub const DEFAULT_RIGHTS: Rights = Rights::all(); - - /// Creates a new, empty `Filesystem` and returns the superuser handle, which - /// has all the capabilities on the entire filesystem. - /// - /// NOTE: the file descriptors `0`, `1`, and `2` are pre-allocated for `stdin` - /// and similar with respect to the parameter `std_streams_table`. Userspace - /// Wasm programs are going to expect that this is true, so we need to - /// preallocate some files corresponding to those, here. - pub fn new( - rights_table: RightsTable, - native_modules: Vec, - ) -> FileSystemResult { - let mut rst = Self { - fd_table: HashMap::new(), - next_fd_candidate: Self::FIRST_FD, - inode_table: Arc::new(Mutex::new(InodeTable::new(rights_table)?)), - prestat_table: HashMap::new(), - native_modules: native_modules.to_vec(), - }; - - let mut all_rights = HashMap::new(); - all_rights.insert(PathBuf::from("/"), Rights::all()); - all_rights.insert(PathBuf::from(CANONICAL_STDIN_FILE_PATH), Rights::all()); - all_rights.insert(PathBuf::from(CANONICAL_STDOUT_FILE_PATH), Rights::all()); - all_rights.insert(PathBuf::from(CANONICAL_STDERR_FILE_PATH), Rights::all()); - - rst.install_prestat::(&all_rights)?; - - rst.install_services(native_modules)?; - - Ok(rst) - } - - /// This is the *only* public API to create a new `FileSystem` (handler). - /// It returns a `FileSystem` where directories are pre-opened with appropriate - /// capabilities in relation to a principal, `principal`. Native modules are - /// inherited from the parent `FileSystem`. - pub fn spawn(&self, principal: &Principal) -> FileSystemResult { - let mut rst = Self { - fd_table: HashMap::new(), - next_fd_candidate: Self::FIRST_FD, - inode_table: self.inode_table.clone(), - prestat_table: HashMap::new(), - native_modules: self.native_modules.to_vec(), - }; - - // Must clone as `install_prestat` needs to lock the `inode_table` too - let rights_table = self.lock_inode_table()?.get_rights(principal)?.clone(); - rst.install_prestat::(&rights_table)?; - - Ok(rst) - } - - #[inline] - fn service_fs(&self) -> FileSystemResult { - Ok(self.clone()) - } - - /// Create a dummy filesystem - #[allow(dead_code)] - pub(crate) fn new_dummy() -> Self { - let mut rights_table = HashMap::new(); - rights_table.insert(Principal::NoCap, HashMap::new()); - Self { - fd_table: HashMap::new(), - next_fd_candidate: Self::FIRST_FD, - inode_table: Arc::new(Mutex::new(InodeTable::new(rights_table).unwrap())), - prestat_table: HashMap::new(), - native_modules: Vec::new(), - } - } - - //////////////////////////////////////////////////////////////////////// - // Internal auxiliary methods - //////////////////////////////////////////////////////////////////////// - - /// Lock the inode table - #[inline] - fn lock_inode_table(&self) -> FileSystemResult> { - self.inode_table.lock().map_err(|_| ErrNo::Busy) - } - - /// Install standard streams (`stdin`, `stdout`, `stderr`). - fn install_standard_streams_fd( - &mut self, - std_streams_table: &[FileRights], - ) -> FileSystemResult<()> { - for std_stream in std_streams_table { - // Map each standard stream to an fd and inode. - // Rights are assumed to be already configured by the execution engine in the rights table - // at that point. - // Base rights are ignored and replaced with the default rights - - let (fd_number, inode_number) = match std_stream.file_name() { - CANONICAL_STDIN_FILE_PATH => (Fd(0), self.lock_inode_table()?.stdin()), - CANONICAL_STDOUT_FILE_PATH => (Fd(1), self.lock_inode_table()?.stdout()), - CANONICAL_STDERR_FILE_PATH => (Fd(2), self.lock_inode_table()?.stderr()), - _otherwise => continue, - }; - let rights = Rights::from_bits(<_>::try_from_or_errno(*std_stream.rights())?) - .ok_or(ErrNo::Inval)?; - self.install_fd( - fd_number, - FileType::RegularFile, - inode_number, - &rights, - &rights, - ); - } - Ok(()) - } - - /// Install `stdin`, `stdout`, `stderr`, `$ROOT`, and all dir in `dir_paths`, - /// and then pre-open them. - fn install_prestat + std::cmp::Eq + std::hash::Hash + Sized>( - &mut self, - rights_table: &HashMap, - ) -> FileSystemResult<()> { - // construct the rights for stdin stdout and stderr. - let std_streams_table = rights_table - .iter() - .filter_map(|(k, v)| { - let file = k.as_ref().to_str(); - let rights = *v; - match file { - // Extract right associated to stdin stdout stderr - Some(path) - if path == CANONICAL_STDIN_FILE_PATH - || path == CANONICAL_STDOUT_FILE_PATH - || path == CANONICAL_STDERR_FILE_PATH => - { - let rights_u32 = match u32::try_from_or_errno(u64::from(rights)) { - Ok(o) => o, - Err(_) => return None, - }; - let file_rights = FileRights::new(String::from(path), rights_u32); - Some(file_rights) - } - _other => None, - } - }) - .collect::>(); - // Pre open the standard streams. - self.install_standard_streams_fd(&std_streams_table)?; - - let first_fd = Self::FIRST_FD.0; - - // Load all pre-opened directories. Create directories if necessary. - let rights_table_without_std = rights_table.iter().filter(|(k, _)| { - let k = k.as_ref(); - k != Path::new(CANONICAL_STDIN_FILE_PATH) - && k != Path::new(CANONICAL_STDOUT_FILE_PATH) - && k != Path::new(CANONICAL_STDERR_FILE_PATH) - }); - for (index, (path, rights)) in rights_table_without_std.enumerate() { - let new_fd = Fd(u32::try_from_or_errno(index)? + first_fd); - let path = path.as_ref(); - // strip off the root - let relative_path = strip_root_slash_path(path); - let new_inode = { - if relative_path == Path::new("") { - InodeTable::ROOT_DIRECTORY_INODE - } else { - self.lock_inode_table()? - .add_all_dir(InodeTable::ROOT_DIRECTORY_INODE, relative_path)? - } - }; - self.install_fd( - new_fd, - // We use unknown here as we allow pre install either file or dir - FileType::Unknown, - new_inode, - &rights, - &rights, - ); - self.prestat_table.insert(new_fd, path.to_path_buf()); - } - // Set the next_fd_candidate, it might waste few FDs. - self.next_fd_candidate = Fd(Self::FIRST_FD.0 + u32::try_from_or_errno(rights_table.len())?); - - Ok(()) - } - - fn install_services(&mut self, native_modules: Vec) -> FileSystemResult<()> { - self.lock_inode_table()?.install_services(native_modules) - } - - /// Install a `fd` to the file system. The fd will be of type RegularFile. - fn install_fd( - &mut self, - fd: Fd, - file_type: FileType, - inode: Inode, - rights_base: &Rights, - rights_inheriting: &Rights, - ) { - let fd_stat = FdStat { - file_type, - flags: FdFlags::empty(), - rights_base: *rights_base, - rights_inheriting: *rights_inheriting, - }; - - let fd_entry = FdEntry { - inode, - fd_stat, - offset: 0, - /// Advice on how regions of the file are to be used. - advice: Vec::new(), - }; - self.fd_table.insert(fd, fd_entry); - } - - /// Pick a fresh fd. - fn new_fd(&mut self) -> FileSystemResult { - let cur = self.next_fd_candidate; - // Consume all possible FDs, or the next FD is already used. - if u32::from(cur) & 1 << 31 != 0 || self.fd_table.contains_key(&cur) { - return Err(ErrNo::NFile); // Not quite accurate, but this may be the best fit - } - self.next_fd_candidate = Fd(u32::from(cur) + 1); - Ok(cur) - } - - /// Check if `rights` is allowed in `fd` - fn check_right(&self, fd: &Fd, rights: Rights) -> FileSystemResult<()> { - if self - .fd_table - .get(fd) - .ok_or(ErrNo::BadF)? - .fd_stat - .rights_base - .contains(rights) - { - Ok(()) - } else { - Err(ErrNo::Access) - } - } - - /// Return the inode and the associated inode entry, contained in file descriptor `fd` - #[inline] - fn get_inode_by_fd(&self, fd: &Fd) -> FileSystemResult { - Ok(self.fd_table.get(fd).ok_or(ErrNo::BadF)?.inode) - } - - /// Return the inode and the associated inode entry at the relative `path` in the file - /// descriptor `fd`. Return Error if `fd` is not a directory. - fn get_inode_by_fd_path>(&self, fd: &Fd, path: T) -> FileSystemResult { - let parent_inode = self.get_inode_by_fd(fd)?; - Ok(self - .lock_inode_table()? - .get_inode_by_inode_path(&parent_inode, path)? - .0) - } - - //////////////////////////////////////////////////////////////////////////// - // Operations on the filesystem. Rust style implementation of WASI API - //////////////////////////////////////////////////////////////////////////// - - /// Allows the programmer to declare how they intend to use various parts of - /// a file to the runtime. - #[inline] - pub(crate) fn fd_advise( - &mut self, - fd: Fd, - offset: FileSize, - len: FileSize, - adv: Advice, - ) -> FileSystemResult<()> { - self.check_right(&fd, Rights::FD_ADVISE)?; - let entry = self.fd_table.get_mut(&fd).ok_or(ErrNo::BadF)?; - entry.advice.push((offset, len, adv)); - Ok(()) - } - - /// The stub implementation of `fd_allocate`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn fd_allocate( - &mut self, - _fd: Fd, - _offset: FileSize, - _len: FileSize, - ) -> FileSystemResult<()> { - Err(ErrNo::NoSys) - } - - /// Implements the `fd_close` operation on the filesystem, which closes a - /// file descriptor. Returns `ErrNo::BadF`, if `fd` is not a current file-descriptor. - #[inline] - pub(crate) fn fd_close(&mut self, fd: Fd) -> FileSystemResult<()> { - let inode = self.get_inode_by_fd(&fd)?; - // Limit the scope of the lock - { - let mut inode_table = self.lock_inode_table()?; - let f = inode_table.get_mut(&inode)?; - if f.is_service() { - f.truncate_file()?; - } - } - self.fd_table.remove(&fd).ok_or(ErrNo::BadF)?; - Ok(()) - } - - /// The stub implementation of `fd_datasync`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn fd_datasync(&mut self, fd: Fd) -> FileSystemResult<()> { - self.check_right(&fd, Rights::FD_DATASYNC)?; - Err(ErrNo::NoSys) - } - - /// Return a copy of the status of the file descriptor, `fd`. - #[inline] - pub(crate) fn fd_fdstat_get(&self, fd: Fd) -> FileSystemResult { - Ok(self.fd_table.get(&fd).ok_or(ErrNo::BadF)?.fd_stat) - } - - /// Change the flag associated with the file descriptor, `fd`. - #[inline] - pub(crate) fn fd_fdstat_set_flags(&mut self, fd: Fd, flags: FdFlags) -> FileSystemResult<()> { - self.check_right(&fd, Rights::FD_FDSTAT_SET_FLAGS)?; - self.fd_table.get_mut(&fd).ok_or(ErrNo::BadF)?.fd_stat.flags = flags; - Ok(()) - } - - /// Change the right associated with the file descriptor, `fd`. - #[inline] - pub(crate) fn fd_fdstat_set_rights( - &mut self, - fd: Fd, - rights_base: Rights, - rights_inheriting: Rights, - ) -> FileSystemResult<()> { - let mut fd_stat = self.fd_table.get_mut(&fd).ok_or(ErrNo::BadF)?.fd_stat; - fd_stat.rights_base = rights_base; - fd_stat.rights_inheriting = rights_inheriting; - Ok(()) - } - - /// Return a copy of the status of the open file pointed by the file descriptor, `fd`. - pub(crate) fn fd_filestat_get(&self, fd: Fd) -> FileSystemResult { - let inode = self - .fd_table - .get(&fd) - .map(|fte| fte.inode) - .ok_or(ErrNo::BadF)?; - - Ok(self.lock_inode_table()?.get(&inode)?.file_stat) - } - - /// Change the size of the open file pointed by the file descriptor, `fd`. The extra bytes are - /// filled with ZERO. - pub(crate) fn fd_filestat_set_size(&mut self, fd: Fd, size: FileSize) -> FileSystemResult<()> { - self.check_right(&fd, Rights::FD_FILESTAT_SET_SIZE)?; - let inode = self - .fd_table - .get(&fd) - .map(|FdEntry { inode, .. }| *inode) - .ok_or(ErrNo::BadF)?; - - self.lock_inode_table()? - .get_mut(&inode)? - .resize_file(size, 0) - } - - /// Change the time of the open file pointed by the file descriptor, `fd`. If `fst_flags` - /// contains `ATIME_NOW` or `MTIME_NOW`, the method immediately returns unsupported error - /// `NoSys`. - pub(crate) fn fd_filestat_set_times( - &mut self, - fd: Fd, - atime: Timestamp, - mtime: Timestamp, - fst_flags: SetTimeFlags, - current_time: Timestamp, - ) -> FileSystemResult<()> { - self.check_right(&fd, Rights::FD_FILESTAT_SET_TIMES)?; - let inode = self - .fd_table - .get(&fd) - .map(|FdEntry { inode, .. }| *inode) - .ok_or(ErrNo::BadF)?; - - let mut inode_table = self.lock_inode_table()?; - let mut inode_impl = inode_table.get_mut(&inode)?; - if fst_flags.contains(SetTimeFlags::ATIME_NOW) { - inode_impl.file_stat.atime = current_time; - } else if fst_flags.contains(SetTimeFlags::MTIME_NOW) { - inode_impl.file_stat.mtime = current_time; - } else if fst_flags.contains(SetTimeFlags::ATIME) { - inode_impl.file_stat.atime = atime; - } else if fst_flags.contains(SetTimeFlags::MTIME) { - inode_impl.file_stat.mtime = mtime; - } - Ok(()) - } - - /// A rust-style implementation for `fd_pread`. - /// The actual WASI spec, requires, after `fd`, an extra parameter of type IoVec, - /// to which the content should be written. - /// Also the WASI requires the function returns the number of byte read. - /// However, the implementation of WASI spec of fd_pread depends on - /// how a particular execution engine handles the memory. - /// That is, different engines provide different API to interact the linear memory - /// space of WASM. Hence, the method here return the read bytes as `Vec`. - pub(crate) fn fd_pread>( - &self, - fd: Fd, - bufs: &mut [B], - offset: FileSize, - ) -> FileSystemResult { - self.check_right(&fd, Rights::FD_READ)?; - self.fd_pread_internal(fd, bufs, offset) - } - - /// A rust-style implementation for `fd_pread`, yet without rights check. - /// The actual WASI spec, requires, after `fd`, an extra parameter of type IoVec, - /// to which the content should be written. - /// Also the WASI requires the function returns the number of byte read. - /// However, the implementation of WASI spec of fd_pread depends on - /// how a particular execution engine handles the memory. - /// That is, different engines provide different API to interact the linear memory - /// space of WASM. Hence, the method here return the read bytes as `Vec`. - fn fd_pread_internal>( - &self, - fd: Fd, - bufs: &mut [B], - offset: FileSize, - ) -> FileSystemResult { - let inode = self.fd_table.get(&fd).ok_or(ErrNo::BadF)?.inode; - - let f = self.lock_inode_table()?; - let f = f.get(&inode)?; - - let mut offset = offset; - let mut len = 0; - for buf in bufs { - let delta = f.read_file(buf.as_mut(), offset)?; - offset += u64::try_from_or_errno(delta)?; - len += delta; - } - - Ok(len) - } - - /// Return the status of a pre-opened Fd `fd`. - #[inline] - pub(crate) fn fd_prestat_get(&mut self, fd: Fd) -> FileSystemResult { - let path = self.prestat_table.get(&fd).ok_or(ErrNo::BadF)?; - let resource_type = PreopenType::Dir { - name_len: <_>::try_from_or_errno(path.as_os_str().len())?, - }; - Ok(Prestat { resource_type }) - } - - /// Return the path of a pre-opened Fd `fd`. The path must be consistent with the status returned by `fd_prestat_get` - #[inline] - pub(crate) fn fd_prestat_dir_name(&mut self, fd: Fd) -> FileSystemResult { - let path = self.prestat_table.get(&fd).ok_or(ErrNo::BadF)?; - Ok(path.to_path_buf()) - } - - /// A rust-style implementation for `fd_pwrite`. - /// The actual WASI spec, requires that `ciovec` is of type Vec. - /// However, the implementation of WASI spec of fd_pread depends on - /// how a particular execution engine handles the memory. - /// That is, different engines provide different API to interact the linear memory - /// space of WASM. - pub(crate) fn fd_pwrite>( - &mut self, - fd: Fd, - bufs: &[B], - offset: FileSize, - ) -> FileSystemResult { - self.check_right(&fd, Rights::FD_WRITE)?; - let inode = self.fd_table.get(&fd).ok_or(ErrNo::BadF)?.inode; - - //// NOTE: Careful about the lock scope.,as a service may need to lock - //// the inode_table internally. - let (len, is_service) = { - let mut f = self.lock_inode_table()?; - let f = f.get_mut(&inode)?; - - let mut offset = offset; - let mut len = 0; - for buf in bufs { - let delta = f.write_file(buf.as_ref(), offset)?; - offset += u64::try_from_or_errno(delta)?; - len += delta; - } - (len, f.is_service()) - }; - - // If it is a service, call it. - // Warning: There is no input validity check performed here. It is the - // native module's responsibility to implement that. - if is_service { - let (service, exec_config) = self - .lock_inode_table()? - .get_mut(&inode)? - .service_handler()?; - let native_module = service.lock().map_err(|_| ErrNo::Busy)?; - - // Invoke native module manager - let mut native_module_manager = - NativeModuleManager::new(*native_module.clone(), self.service_fs()?); - // Invoke native module with execution configuration - native_module_manager.execute(exec_config)?; - } - Ok(len) - } - - /// A rust-style base implementation for `fd_read`. It directly calls `fd_pread` with the - /// current `offset` of Fd `fd` and then calls `fd_seek`. - pub(crate) fn fd_read>( - &mut self, - fd: Fd, - bufs: &mut [B], - ) -> FileSystemResult { - self.check_right(&fd, Rights::FD_READ)?; - let offset = self.fd_table.get(&fd).ok_or(ErrNo::BadF)?.offset; - - let read_len = self.fd_pread(fd, bufs, offset)?; - self.fd_seek(fd, read_len as i64, Whence::Current)?; - Ok(read_len) - } - - /// Function `fd_read_executable` reads an executable. This function should *only* be called - /// internally. It directly calls `fd_pread` with the - /// current `offset` of Fd `fd` and then calls `fd_seek`. - pub(crate) fn fd_read_executable>( - &mut self, - fd: Fd, - bufs: &mut [B], - ) -> FileSystemResult { - self.check_right(&fd, Rights::FD_EXECUTE)?; - let offset = self.fd_table.get(&fd).ok_or(ErrNo::BadF)?.offset; - - let read_len = self.fd_pread_internal(fd, bufs, offset)?; - self.fd_seek(fd, read_len as i64, Whence::Current)?; - Ok(read_len) - } - - /// The implementation of `fd_readdir`. - #[inline] - pub(crate) fn fd_readdir( - &mut self, - fd: Fd, - cookie: DirCookie, - ) -> FileSystemResult)>> { - self.check_right(&fd, Rights::FD_READDIR)?; - let dir_inode = self.get_inode_by_fd(&fd)?; - // limit lock scope - let mut dirs = { - let inode_table = self.lock_inode_table()?; - inode_table.get(&dir_inode)?.read_dir(&inode_table)? - }; - let cookie = <_>::try_from_or_errno(cookie.0)?; - if dirs.len() < cookie { - return Ok(Vec::new()); - } - let rst = dirs.split_off(cookie); - Ok(rst) - } - - /// Atomically renumbers the `old_fd` to the `new_fd`. Note that as - /// execution engine is single-threaded this is atomic from the WASM program's - /// point of view. - pub(crate) fn fd_renumber(&mut self, old_fd: Fd, new_fd: Fd) -> FileSystemResult<()> { - let entry = self.fd_table.get(&old_fd).ok_or(ErrNo::BadF)?.clone(); - if self.fd_table.get(&new_fd).is_none() { - self.fd_table.insert(new_fd, entry); - self.fd_table.remove(&old_fd); - Ok(()) - } else { - Err(ErrNo::BadF) - } - } - - /// Change the offset of Fd `fd`. - pub(crate) fn fd_seek( - &mut self, - fd: Fd, - delta: FileDelta, - whence: Whence, - ) -> FileSystemResult { - self.check_right(&fd, Rights::FD_SEEK)?; - let FdEntry { inode, offset, .. } = self.fd_table.get(&fd).ok_or(ErrNo::BadF)?; - let file_size = self.lock_inode_table()?.get(inode)?.file_stat.file_size; - - let new_base_offset = match whence { - Whence::Current => *offset, - Whence::End => file_size, - Whence::Start => 0, - }; - - // NOTE: Ensure the computation does not overflow. - let new_offset: FileSize = if delta >= 0 { - // It is safe to convert a positive i64 to u64. - let t_offset = new_base_offset + u64::try_from_or_errno(delta.abs())?; - // If offset is greater the file size, then expand the file. - if t_offset > file_size { - self.fd_filestat_set_size(fd, t_offset)?; - } - t_offset - } else { - // It is safe to convert a positive i64 to u64. - if u64::try_from_or_errno(delta.abs())? > new_base_offset { - return Err(ErrNo::SPipe); - } - new_base_offset - u64::try_from_or_errno(delta.abs())? - }; - - // Update the offset - self.fd_table.get_mut(&fd).ok_or(ErrNo::BadF)?.offset = new_offset; - Ok(new_offset) - } - - /// The stub implementation of `fd_sync`. It is a no-op now. - #[inline] - pub(crate) fn fd_sync(&mut self, fd: Fd) -> FileSystemResult<()> { - self.check_right(&fd, Rights::FD_SYNC)?; - Ok(()) - } - - /// Returns the current offset associated with the file descriptor. - #[inline] - pub(crate) fn fd_tell(&self, fd: Fd) -> FileSystemResult { - self.check_right(&fd, Rights::FD_TELL)?; - Ok(self.fd_table.get(&fd).ok_or(ErrNo::BadF)?.offset) - } - - /// A rust-style base implementation for `fd_write`. It directly calls `fd_pwrite` with the - /// current `offset` of Fd `fd` and then calls `fd_seek`. - pub(crate) fn fd_write>( - &mut self, - fd: Fd, - bufs: &[B], - ) -> FileSystemResult { - self.check_right(&fd, Rights::FD_WRITE)?; - let offset = self.fd_table.get(&fd).ok_or(ErrNo::BadF)?.offset; - - let rst = self.fd_pwrite(fd, bufs, offset)?; - self.fd_seek(fd, rst as i64, Whence::Current)?; - Ok(rst) - } - - /// The implementation of `path_create_directory`. - #[inline] - pub(crate) fn path_create_directory>( - &mut self, - fd: Fd, - path: T, - ) -> FileSystemResult<()> { - self.check_right(&fd, Rights::PATH_CREATE_DIRECTORY)?; - let parent_inode = self.get_inode_by_fd(&fd)?; - if !self.lock_inode_table()?.is_dir(&parent_inode) { - return Err(ErrNo::NotDir); - } - // The path exists - if self.get_inode_by_fd_path(&fd, path.as_ref()).is_ok() { - return Err(ErrNo::Exist); - } - // Create ALL missing dir in the path - // In each round, the `last` carries the current parent inode or an error - // and component is the next component in the path. - path.as_ref().components().fold( - Ok(parent_inode), - |last: FileSystemResult, component| { - // If there is an error - let last = last?; - let component_path = match component { - Component::Normal(p) => Ok(p), - _otherwise => Err(ErrNo::Inval), - }?; - let new_inode = self.lock_inode_table()?.new_inode()?; - self.lock_inode_table()? - .add_dir(last, component_path, new_inode)?; - // return the next inode, preparing for the next round. - Ok(new_inode) - }, - )?; - Ok(()) - } - - /// Return a copy of the status of the file at path `path`. We only support the searching from the root Fd. We ignore searching flag `flags`. - pub(crate) fn path_filestat_get>( - &mut self, - fd: Fd, - _flags: LookupFlags, - path: T, - ) -> FileSystemResult { - let path = path.as_ref(); - self.check_right(&fd, Rights::PATH_FILESTAT_GET)?; - let inode = self.get_inode_by_fd_path(&fd, path)?; - Ok(self.lock_inode_table()?.get(&inode)?.file_stat) - } - - /// Change the time of the open file at `path` If `fst_flags` - /// contains `ATIME_NOW` or `MTIME_NOW`, the method immediately returns unsupported error - /// `NoSys`. We only support searching from the root Fd. We ignore searching flag `flags`. - pub(crate) fn path_filestat_set_times>( - &mut self, - fd: Fd, - _flags: LookupFlags, - path: T, - atime: Timestamp, - mtime: Timestamp, - fst_flags: SetTimeFlags, - current_time: Timestamp, - ) -> FileSystemResult<()> { - let path = path.as_ref(); - self.check_right(&fd, Rights::PATH_FILESTAT_SET_TIMES)?; - - let inode = self.get_inode_by_fd_path(&fd, path)?; - let mut inode_table = self.lock_inode_table()?; - let mut inode_impl = inode_table.get_mut(&inode)?; - if fst_flags.contains(SetTimeFlags::ATIME_NOW) { - inode_impl.file_stat.atime = current_time; - } else if fst_flags.contains(SetTimeFlags::MTIME_NOW) { - inode_impl.file_stat.mtime = current_time; - } else if fst_flags.contains(SetTimeFlags::ATIME) { - inode_impl.file_stat.atime = atime; - } else if fst_flags.contains(SetTimeFlags::MTIME) { - inode_impl.file_stat.mtime = mtime; - } - Ok(()) - } - - /// A minimum functionality of opening a file or directory on behalf of the principal `principal`. - /// We only support search from the root Fd. We ignore the dir look up flag. - /// - /// The behaviour of `path_open` varies based on the open flags `oflags`: - /// * if no flag is set, open a file at the path, if exists, starting from the directory opened by the file descriptor `fd`; - /// * if `EXCL` is set, `path_open` fails if the path exists; - /// * if `CREATE` is set, create a new file at the path if the path does not exist; - /// * if `TRUNC` is set, the file at the path is truncated, that is, clean the content and set the file size to ZERO; and - /// * if `DIRECTORY` is set, `path_open` fails if the path is not a directory. - pub(crate) fn path_open>( - &mut self, - // The parent fd for searching - fd: Fd, - _dirflags: LookupFlags, - path: T, - oflags: OpenFlags, - rights_base: Rights, - rights_inheriting: Rights, - flags: FdFlags, - ) -> FileSystemResult { - let path = path.as_ref(); - // Check the right of the program on path_open - self.check_right(&fd, Rights::PATH_OPEN)?; - // Read the parent inode. - let parent_inode = self.get_inode_by_fd(&fd)?; - - if !self.lock_inode_table()?.is_dir(&parent_inode) { - return Err(ErrNo::NotDir); - } - // Intersect with the inheriting right from `fd` - let fd_inheriting = self - .fd_table - .get(&fd) - .ok_or(ErrNo::BadF)? - .fd_stat - .rights_inheriting; - let rights_base = rights_base & fd_inheriting; - let rights_inheriting = rights_inheriting & fd_inheriting; - // Several oflags logic, inc. `create`, `excl` and `directory`. - let inode = match self.get_inode_by_fd_path(&fd, path) { - Ok(inode) => { - // If file exists and `excl` is set, return `Exist` error. - if oflags.contains(OpenFlags::EXCL) { - return Err(ErrNo::Exist); - } - if oflags.contains(OpenFlags::DIRECTORY) && !self.lock_inode_table()?.is_dir(&inode) - { - return Err(ErrNo::NotDir); - } - inode - } - Err(e) => { - // If file does NOT exists and `create` is NOT set, return `NoEnt` error. - if !oflags.contains(OpenFlags::CREATE) { - return Err(e); - } - // Check the right of the program on create file - self.check_right(&fd, Rights::PATH_CREATE_FILE)?; - let new_inode = self.lock_inode_table()?.new_inode()?; - self.lock_inode_table()? - .add_file(parent_inode, path, new_inode, Vec::new())?; - new_inode - } - }; - // Truncate the file if `trunc` flag is set. - if oflags.contains(OpenFlags::TRUNC) { - // Check the right of the program on truncate - self.check_right(&fd, Rights::PATH_FILESTAT_SET_SIZE)?; - self.lock_inode_table()?.get_mut(&inode)?.truncate_file()?; - } - let new_fd = self.new_fd()?; - let FileStat { - file_type, - file_size, - .. - } = self.lock_inode_table()?.get(&inode)?.file_stat; - let fd_stat = FdStat { - file_type, - flags, - rights_base, - rights_inheriting, - }; - self.fd_table.insert( - new_fd, - FdEntry { - inode, - fd_stat, - offset: 0, - advice: vec![(0, file_size, Advice::Normal)], - }, - ); - Ok(new_fd) - } - - /// The stub implementation of `path_readlink`. Return unsupported error `NoSys`. - /// We only support the searching from the root Fd. - #[inline] - pub(crate) fn path_readlink>( - &mut self, - fd: Fd, - _path: T, - ) -> FileSystemResult> { - self.check_right(&fd, Rights::PATH_READLINK)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `path_remove_directory`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn path_remove_directory>( - &mut self, - fd: Fd, - _path: T, - ) -> FileSystemResult<()> { - self.check_right(&fd, Rights::PATH_REMOVE_DIRECTORY)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `path_rename`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn path_rename, R: AsRef>( - &mut self, - old_fd: Fd, - _old_path: T, - new_fd: Fd, - _new_path: R, - ) -> FileSystemResult<()> { - self.check_right(&old_fd, Rights::PATH_RENAME_SOURCE)?; - self.check_right(&new_fd, Rights::PATH_RENAME_TARGET)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `path_rename`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn path_link, R: AsRef>( - &mut self, - old_fd: Fd, - _old_flag: LookupFlags, - _old_path: T, - new_fd: Fd, - _new_path: R, - ) -> FileSystemResult<()> { - self.check_right(&old_fd, Rights::PATH_LINK_SOURCE)?; - self.check_right(&new_fd, Rights::PATH_LINK_TARGET)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `path_symlink`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn path_symlink, R: AsRef>( - &mut self, - _old_path: T, - fd: Fd, - _new_path: R, - ) -> FileSystemResult<()> { - self.check_right(&fd, Rights::PATH_SYMLINK)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `path_unlink_file`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn path_unlink_file>( - &mut self, - fd: Fd, - _path: T, - ) -> FileSystemResult<()> { - self.check_right(&fd, Rights::PATH_UNLINK_FILE)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `poll_oneoff`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn poll_oneoff( - &mut self, - _subscriptions: Vec, - _events: Vec, - ) -> FileSystemResult { - Err(ErrNo::NoSys) - } - - /// The stub implementation of `sock_recv`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn sock_recv>( - &mut self, - socket: Fd, - _bufs: &[B], - _ri_flags: RiFlags, - ) -> FileSystemResult<(Size, RoFlags)> { - self.check_right(&socket, Rights::FD_READ)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `sock_send`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn sock_send>( - &mut self, - socket: Fd, - _bufs: &[B], - _si_flags: SiFlags, - ) -> FileSystemResult { - self.check_right(&socket, Rights::FD_WRITE)?; - Err(ErrNo::NoSys) - } - - /// The stub implementation of `sock_shutdown`. Return unsupported error `NoSys`. - #[inline] - pub(crate) fn sock_shutdown(&mut self, socket: Fd, _flags: SdFlags) -> FileSystemResult<()> { - self.check_right(&socket, Rights::SOCK_SHUTDOWN)?; - Err(ErrNo::NoSys) - } - - /// This function, added for Veracruz, creates a new anonymous file. - /// It will return an Err if getrandom fails, but perhaps in no other - /// circumstances. - pub(crate) fn fd_create(&mut self) -> FileSystemResult { - let inode = self.lock_inode_table()?.new_inode()?; - let file_stat = FileStat { - device: 0u64.into(), - inode: inode.clone(), - file_type: FileType::RegularFile, - num_links: 0, - file_size: 0, - atime: Timestamp::from_nanos(0), - mtime: Timestamp::from_nanos(0), - ctime: Timestamp::from_nanos(0), - }; - let node = InodeEntry { - file_stat, - data: InodeImpl::File(Vec::new()), - }; - self.lock_inode_table()?.insert(inode, node)?; - - let new_fd = self.new_fd()?; - let file_type = FileType::RegularFile; - let flags = FdFlags::empty(); - let rights_base = Rights::all(); - let rights_inheriting = Rights::all(); - let fd_stat = FdStat { - file_type, - flags, - rights_base, - rights_inheriting, - }; - let fd_entry = FdEntry { - inode, - fd_stat, - offset: 0, - advice: vec![(0, 0, Advice::Normal)], - }; - self.fd_table.insert(new_fd, fd_entry); - Ok(new_fd) - } - - //////////////////////////////////////////////////////////////////////// - // Public interface for the filesystem. - // It will be used by the veracruz runtime. - //////////////////////////////////////////////////////////////////////// - - /// Return an appropriate prestat fd for the path - pub fn find_prestat>(&self, path: T) -> Result<(Fd, PathBuf), ErrNo> { - let path = path.as_ref(); - let (fd, parent_path) = path - .ancestors() - .find_map(|parent_path| { - self.prestat_table - .iter() - .find_map(|(prestat_fd, prestat_path)| { - if prestat_path == parent_path { - Some((prestat_fd, parent_path)) - } else { - None - } - }) - }) - .ok_or(ErrNo::Access)?; - - let path = path.strip_prefix(parent_path).map_err(|_| ErrNo::Inval)?; - Ok((*fd, path.to_path_buf())) - } - - /// Write to a file on path `file_name`. If `is_append` is set, `data` will be appended to `file_name`. - /// Otherwise this file will be truncated. The `principal` must have the right on `path_open`, - /// `fd_write` and `fd_seek`. - pub fn write_file_by_absolute_path>( - &mut self, - file_name: T, - data: Vec, - is_append: bool, - ) -> Result<(), ErrNo> { - let file_name = file_name.as_ref(); - let (fd, file_name) = self.find_prestat(file_name)?; - - let oflag = OpenFlags::CREATE - | if !is_append { - OpenFlags::TRUNC - } else { - OpenFlags::empty() - }; - let fd = self.path_open( - fd, - LookupFlags::empty(), - file_name, - oflag, - FileSystem::DEFAULT_RIGHTS, - FileSystem::DEFAULT_RIGHTS, - FdFlags::empty(), - )?; - if !self - .fd_table - .get(&fd) - .ok_or(ErrNo::BadF)? - .fd_stat - .rights_base - .contains(Rights::FD_WRITE | Rights::FD_SEEK) - { - return Err(ErrNo::Access); - } - if is_append { - self.fd_seek(fd, 0, Whence::End)?; - } - self.fd_write(fd, &[data])?; - self.fd_close(fd)?; - Ok(()) - } - - /// Read a file on path `file_name`. - /// The `principal` must have the right on `path_open`, - /// `fd_read` and `fd_seek`. - pub fn read_file_by_absolute_path>( - &mut self, - file_name: T, - ) -> Result, ErrNo> { - self.read_file_by_absolute_path_internal(file_name, false) - } - - /// Read a file on path `file_name`. - /// The `principal` must have the right on `path_open`, - /// `fd_read` and `fd_seek`. - pub fn read_executable_by_absolute_path>( - &mut self, - file_name: T, - ) -> Result, ErrNo> { - self.read_file_by_absolute_path_internal(file_name, true) - } - - fn read_file_by_absolute_path_internal>( - &mut self, - file_name: T, - is_reading_executable: bool, - ) -> Result, ErrNo> { - let expected_rights = Rights::FD_SEEK - | if is_reading_executable { - Rights::FD_EXECUTE - } else { - Rights::FD_READ - }; - let file_name = file_name.as_ref(); - let (fd, file_name) = self.find_prestat(file_name)?; - let fd = self.path_open( - fd, - LookupFlags::empty(), - file_name, - OpenFlags::empty(), - FileSystem::DEFAULT_RIGHTS, - FileSystem::DEFAULT_RIGHTS, - FdFlags::empty(), - )?; - if !self - .fd_table - .get(&fd) - .ok_or(ErrNo::BadF)? - .fd_stat - .rights_base - .contains(expected_rights) - { - error!( - "internal read denies, expected rights {:?}", - expected_rights - ); - return Err(ErrNo::Access); - } - let file_stat = self.fd_filestat_get(fd)?; - let mut vec = vec![0u8; file_stat.file_size as usize]; - let read_size = if is_reading_executable { - self.fd_read_executable(fd, &mut [&mut vec[..]])? - } else { - self.fd_read(fd, &mut [&mut vec[..]])? - }; - debug_assert_eq!(read_size, vec.len()); - self.fd_close(fd)?; - Ok(vec) - } - - /// Read all files recursively on path `path`. - /// The `principal` must have the right on `path_open`, - /// `fd_read` and `fd_seek`. - pub fn read_all_files_by_absolute_path>( - &mut self, - path: T, - ) -> Result)>, ErrNo> { - let path = path.as_ref(); - // Convert the absolute path to relative path and then find the inode - let inode = self - .lock_inode_table()? - .get_inode_by_inode_path( - &InodeTable::ROOT_DIRECTORY_INODE, - strip_root_slash_path(path), - )? - .0; - let mut rst = Vec::new(); - if self.lock_inode_table()?.is_dir(&inode) { - // Limit the lock scope - let all_dir = { - let inode_table = self.lock_inode_table()?; - inode_table.get(&inode)?.read_dir(&inode_table)? - }; - for (_, sub_relative_path) in all_dir.iter() { - let sub_relative_path = - PathBuf::from(OsString::from_vec(sub_relative_path.to_vec())); - // Ignore the path for current and parent directories. - if sub_relative_path != PathBuf::from(".") - && sub_relative_path != PathBuf::from("..") - { - let mut sub_absolute_path = path.to_path_buf(); - sub_absolute_path.push(sub_relative_path); - rst.append(&mut self.read_all_files_by_absolute_path(sub_absolute_path)?); - } - } - } else { - let buf = self.read_file_by_absolute_path(path)?; - rst.push((path.to_path_buf(), buf)); - } - - Ok(rst) - } - - /// Similarly to `read_all_files_by_absolute_path()`, recursively read all - /// files under the specified `path`. - /// The `principal` must have the right on `path_open`, `fd_read` and - /// `fd_seek`, though read errors on leaf files are tolerated. - /// Returns two vectors: - /// - A list of leaf files, along with their data, that the `principal` can - /// read. Also includes empty directories, just in case the native module - /// is expecting them; in that case the associated data is set to `None` - /// - A list of top-level files immediately under the root. This allows the - /// native module manager to mount the filesystem into the sandbox, since - /// Sandbox2 doesn't allow mapping a directory to `/`. - /// This function is used by the native module manager to duplicate the - /// VFS before running native modules. - pub fn read_all_files_and_dirs_by_absolute_path>( - &mut self, - path: T, - ) -> Result<(Vec<(PathBuf, Option>)>, Vec), ErrNo> { - let path = path.as_ref(); - // Ignore special files. This avoids permission errors and deadlocks - // when respectively reading and writing to special files. - if path == PathBuf::from("/services") { - return Ok((vec![], vec![])); - } - // Convert the absolute path to relative path and then find the inode - let inode = self - .lock_inode_table()? - .get_inode_by_inode_path( - &InodeTable::ROOT_DIRECTORY_INODE, - strip_root_slash_path(path), - )? - .0; - let mut rst = Vec::new(); - let mut top_level_files = Vec::new(); - if self.lock_inode_table()?.is_dir(&inode) { - // Limit the lock scope - let (all_dir, is_dir_empty) = { - let inode_table = self.lock_inode_table()?; - let inode_entry = inode_table.get(&inode)?; - ( - inode_entry.read_dir(&inode_table)?, - inode_table.is_dir_empty(&inode), - ) - }; - if is_dir_empty? { - // Directory is empty (current and parent directories don't - // count) - rst.push((path.to_path_buf(), None)); - } else { - for (_, sub_relative_path) in all_dir.iter() { - let sub_relative_path = - PathBuf::from(OsString::from_vec(sub_relative_path.to_vec())); - // Ignore the path for current and parent directories. - if sub_relative_path != PathBuf::from(".") - && sub_relative_path != PathBuf::from("..") - { - let mut sub_absolute_path = path.to_path_buf(); - sub_absolute_path.push(sub_relative_path); - let (mut list, _) = - self.read_all_files_and_dirs_by_absolute_path(&sub_absolute_path)?; - rst.append(&mut list); - if path == Path::new("/") { - top_level_files.push(sub_absolute_path); - } - } - } - } - } else { - // Ignore unreadable files - match self.read_file_by_absolute_path(path) { - Ok(b) => rst.push((path.to_path_buf(), Some(b))), - Err(_) => (), - } - } - - Ok((rst, top_level_files)) - } - - /// Check if a `file_name` exists. - /// Note: this function *has* side effect! - /// It will try to open the file and then close it. - pub fn file_exists>(&mut self, file_name: T) -> Result { - let file_name = file_name.as_ref(); - let (fd, file_name) = self.find_prestat(file_name)?; - match self.path_open( - fd, - LookupFlags::empty(), - file_name, - OpenFlags::empty(), - FileSystem::DEFAULT_RIGHTS, - FileSystem::DEFAULT_RIGHTS, - FdFlags::empty(), - ) { - Ok(new_fd) => { - self.fd_close(new_fd)?; - Ok(true) - } - Err(ErrNo::Access) => Err(ErrNo::Access), - Err(_) => Ok(false), - } - } - - /// A public API for writing to stdin. - #[inline] - pub fn write_stdin(&mut self, buf: &[u8]) -> FileSystemResult { - self.fd_write(Fd(0), &[buf]) - } - - /// A public API for reading from stdout. - #[inline] - pub fn read_stdout(&mut self) -> FileSystemResult> { - self.read_std_stream(Fd(1)) - } - - /// A public API for writing to stdout. - #[inline] - pub fn write_stdout(&mut self, buf: &[u8]) -> FileSystemResult { - self.fd_write(Fd(1), &[buf]) - } - - /// A public API for reading from stderr. - #[inline] - pub fn read_stderr(&mut self) -> FileSystemResult> { - self.read_std_stream(Fd(2)) - } - - /// A public API for writing to stderr. - #[inline] - pub fn write_stderr(&mut self, buf: &[u8]) -> FileSystemResult { - self.fd_write(Fd(2), &[buf]) - } - - /// Read from std streaming. - fn read_std_stream(&mut self, fd: Fd) -> FileSystemResult> { - // read the length of a stream - let inode = self.get_inode_by_fd(&fd)?; - let len = self.lock_inode_table()?.get(&inode)?.len()?; - let mut vec = vec![0u8; len as usize]; - let read_len = self.fd_read(fd, &mut [&mut vec[..]])?; - debug_assert_eq!(read_len, vec.len()); - Ok(vec) - } - - /// Return whether the given path can be executed by the given principal. - /// Since files inherit their parent's rights, granting execution to a - /// parent directory is enough to grant execution to every file under it. - /// Fails if the principal can't access the path with `path_open()`. - pub fn is_executable>( - &mut self, - principal: &Principal, - path: T, - ) -> FileSystemResult { - let path = path.as_ref(); - let mut vfs = self.spawn(principal)?; - - // Open path on behalf of the principal - let (fd, file_name) = vfs.find_prestat(path)?; - let fd = vfs.path_open( - fd, - LookupFlags::empty(), - file_name, - OpenFlags::empty(), - FileSystem::DEFAULT_RIGHTS, - FileSystem::DEFAULT_RIGHTS, - FdFlags::empty(), - )?; - - vfs.check_right(&fd, Rights::FD_EXECUTE)?; - - Ok(true) - } -} - -pub(crate) trait TryFromOrErrNo: Sized { - fn try_from_or_errno(t: T) -> FileSystemResult; -} - -impl TryFromOrErrNo for U -where - U: TryFrom + Sized, -{ - fn try_from_or_errno(t: T) -> FileSystemResult { - Self::try_from(t).map_err(|_| ErrNo::Inval) - } -} - -pub(crate) fn strip_root_slash_path(path: &Path) -> &Path { - path.strip_prefix("/").unwrap_or(path) -} - -pub(crate) fn strip_root_slash_str(path: &str) -> &str { - match &path[0..1] { - "/" => &path[1..], - _ => path, - } -} diff --git a/crates/execution-engine/src/lib.rs b/crates/execution-engine/src/lib.rs index cd5d67b83..c63075967 100644 --- a/crates/execution-engine/src/lib.rs +++ b/crates/execution-engine/src/lib.rs @@ -19,34 +19,29 @@ #[macro_use] extern crate std; -#[macro_use] -extern crate num_derive; - mod engines; -pub mod fs; -mod native_module_manager; -mod native_modules; +mod service; mod pipeline; -// Expose the error to the external. -pub use engines::common::FatalEngineError; -use crate::fs::FileSystem; -use policy_utils::{pipeline::Expr, principal::ExecutionStrategy}; + +use policy_utils::{pipeline::Expr, principal::{PrincipalPermission, ExecutionStrategy, Service}}; use std::boxed::Box; -/// Runtime options for a program. +/// Runtime environment for a program. #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Default)] -pub struct Options { +pub struct Environment { /// The environment variables currently set, and their bindings. pub environment_variables: Vec<(String, String)>, /// The program arguments of the executable being executed. pub program_arguments: Vec, - /// Whether clock-related functionality is enabled for the program. If not - /// enabled, clock- and time-related WASI host-calls return an unimplemented - /// status code. - pub enable_clock: bool, - /// Whether strace-like output is enabled. - pub enable_strace: bool, +} + +pub trait Execution: Send { + /// name of this execution. + fn name(&self) -> &str; + + /// Entry point of this execution, it can be a path to a particular file or a dir + fn execute(&mut self, program_path: &std::path::Path) -> anyhow::Result<()>; } /// The top-level function executes the pipeline of programs, `pipeline`, on @@ -62,16 +57,11 @@ pub struct Options { /// such as `freestanding-execution-engine` and `runtime-manager` can rely on. pub fn execute( strategy: &ExecutionStrategy, - mut caller_filesystem: FileSystem, - pipepine_filesystem: FileSystem, + caller_permissions: &PrincipalPermission, + execution_permissions: &PrincipalPermission, + services: &[Service], pipeline: Box, - options: &Options, -) -> anyhow::Result { - Ok(pipeline::execute_pipeline( - strategy, - &mut caller_filesystem, - &pipepine_filesystem, - pipeline, - options, - )?) + env: &Environment, +) -> anyhow::Result<()> { + pipeline::execute_pipeline(strategy, caller_permissions, execution_permissions, services, pipeline, env) } diff --git a/crates/execution-engine/src/native_module_manager.rs b/crates/execution-engine/src/native_module_manager.rs index 40f67ee6e..8d050cd7c 100644 --- a/crates/execution-engine/src/native_module_manager.rs +++ b/crates/execution-engine/src/native_module_manager.rs @@ -33,25 +33,21 @@ //! See the `LICENSE.md` file in the Veracruz root directory for //! information on licensing and copyright. -use crate::{ - fs::{strip_root_slash_path, strip_root_slash_str, FileSystem, FileSystemResult}, - native_modules::common::STATIC_NATIVE_MODULES, -}; +use anyhow::{anyhow, Result}; use log::info; -#[cfg(feature = "std")] -use nix::sys::signal; -use policy_utils::principal::{NativeModule, NativeModuleType}; +use policy_utils::principal::NativeModule; use std::{ - fs::{create_dir, create_dir_all, read_dir, remove_dir_all, File}, - io::{Read, Write}, - path::{Path, PathBuf}, - process::Command, + fs::{File, remove_dir_all}, + io::{Write}, + path::PathBuf, + process::Command }; -use wasi_types::{ErrNo, FdFlags, LookupFlags, OpenFlags}; +#[cfg(feature = "std")] +use nix::sys::signal; /// Path to the native module's manager sysroot on the kernel filesystem. Native /// module directories are created under this directory. -const NATIVE_MODULE_MANAGER_SYSROOT: &str = "/tmp/nmm"; +const NATIVE_MODULE_MANAGER_SYSROOT: &str = "/tmp/nmm/"; /// Path to the native module sandboxer. This is the program that actually prepares /// the sandbox environment and runs the native module in it. @@ -65,21 +61,16 @@ const EXECUTION_CONFIGURATION_FILE: &str = "execution_config"; pub struct NativeModuleManager { /// Native module to execute. native_module: NativeModule, - /// Native module's view of the VFS. This is used to copy files from the VFS - /// to the kernel filesystem. - native_module_vfs: FileSystem, /// Native module directory. Gets mounted into the sandbox environment /// before the native module is executed. native_module_directory: PathBuf, } impl NativeModuleManager { - pub fn new(native_module: NativeModule, native_module_vfs: FileSystem) -> Self { - let native_module_directory = PathBuf::from(NATIVE_MODULE_MANAGER_SYSROOT) - .join(strip_root_slash_str(native_module.name())); + pub fn new(native_module: NativeModule) -> Self { + let native_module_directory = PathBuf::from(NATIVE_MODULE_MANAGER_SYSROOT).join(native_module.name()); Self { native_module, - native_module_vfs, native_module_directory, } } @@ -89,245 +80,104 @@ impl NativeModuleManager { /// Takes a list of unprefixed paths, i.e. not including the path to the /// native module's directory. /// Returns the mappings as a string. - fn build_mappings(&self, unprefixed_files: Vec) -> FileSystemResult { + fn build_mappings(&self, unprefixed_files: Vec) -> Result { let mut mappings = String::new(); for f in unprefixed_files { let mapping = self .native_module_directory - .join(strip_root_slash_path(&f)) + .join(&f) .to_str() - .ok_or(ErrNo::Inval)? + .ok_or(anyhow!("Failed to convert native_module_directory to str"))? .to_owned() + "=>" - + &f.to_str().ok_or(ErrNo::Inval)?.to_owned(); + + &f.to_str() + .ok_or(anyhow!("Failed to convert {:?} to str",f))? + .to_owned(); mappings = mappings + &mapping + ","; } // Add the execution configuration file mappings = mappings - + &self - .native_module_directory - .join(strip_root_slash_str(EXECUTION_CONFIGURATION_FILE)) - .to_str() - .ok_or(ErrNo::Inval)? - .to_owned() - + "=>/" - + EXECUTION_CONFIGURATION_FILE; + + &self.native_module_directory + .join(EXECUTION_CONFIGURATION_FILE) + .to_str() + .ok_or(anyhow!("Failed to convert {} to str", EXECUTION_CONFIGURATION_FILE))? + .to_owned() + + "=>/" + + EXECUTION_CONFIGURATION_FILE; Ok(mappings) } - /// Prepare native module's filesystem by copying to the kernel filesystem - /// all the part of the VFS visible to the native module. - /// Returns a list of top-level files, i.e. files immediately under the - /// root, that should be copied to the kernel filesystem. - /// Fails if creating a new file or directory or writing to a file fails. - /// To be useful, this function must be called after provisioning files to - /// the VFS, and maybe even after the WASM program invokes the native module. - fn prepare_fs(&mut self) -> FileSystemResult> { - create_dir_all(self.native_module_directory.as_path()).map_err(|_| ErrNo::Access)?; - let (visible_files_and_dirs, top_level_files) = self - .native_module_vfs - .read_all_files_and_dirs_by_absolute_path("/")?; - for (path, buffer) in visible_files_and_dirs { - let path = self - .native_module_directory - .join(strip_root_slash_path(&path)); - - // Create parent directories - let parent_path = path.parent().ok_or(ErrNo::NoEnt)?; - create_dir_all(parent_path)?; - - match buffer { - Some(b) => { - let mut file = File::create(path)?; - file.write_all(&b)?; - } - None => create_dir(path)?, - } - } - - // Make sure all top-level files exist on the kernel filesystem to avoid - // potential mount errors later on. - // This is a workaround. Ideally, only files accessible to the principal - // should be mounted, however these can't be easily identified. - // Let's assume every top-level file is a directory. We don't care if - // this results in errors later, since the native module is not supposed - // to access these files - for f in &top_level_files { - let path = self.native_module_directory.join(strip_root_slash_path(&f)); - let _ = create_dir(path); - } - - Ok(top_level_files) - } - - /// Recursively copy a `path` under the native module's directory to the - /// VFS. - /// Takes an unprefixed path, i.e. not including the path to the native - /// module's directory. - /// Access errors are ignored. - /// This function should be called after the native module's execution to - /// reflect the side effects of execution onto the VFS. - fn copy_fs_to_vfs(&mut self, path_unprefixed: &Path) -> FileSystemResult<()> { - let path_prefixed = self - .native_module_directory - .join(strip_root_slash_path(&path_unprefixed)); - if path_prefixed.is_dir() { - for entry in read_dir(path_prefixed)? { - let entry = entry?; - let path_prefixed = entry.path(); - let path_unprefixed = path_prefixed - .strip_prefix(&self.native_module_directory) - .map_err(|_| ErrNo::Access)?; - - // Ignore execution configuration file - if path_unprefixed == PathBuf::from(EXECUTION_CONFIGURATION_FILE) { - continue; - } - - let path_unprefixed = PathBuf::from("/").join(path_unprefixed); - if path_prefixed.is_dir() { - // Create directory on the VFS with `path_open()` - let prestat = self.native_module_vfs.find_prestat(&path_unprefixed); - if prestat.is_ok() { - let (fd, file_name) = prestat?; - self.native_module_vfs.path_open( - fd, - LookupFlags::empty(), - file_name, - OpenFlags::CREATE, - FileSystem::DEFAULT_RIGHTS, - FileSystem::DEFAULT_RIGHTS, - FdFlags::empty(), - )?; - self.copy_fs_to_vfs(&path_unprefixed)?; - } - } else { - // Read file on the kernel fileystem by chunks of 1MiB - let mut f = File::open(&path_prefixed)?; - let mut buf: [u8; 1048576] = [0; 1048576]; - - // Copy file to the VFS. First truncate the VFS file then - // append to it. If the principal doesn't have write access, - // just ignore it - if self - .native_module_vfs - .write_file_by_absolute_path(&path_unprefixed, vec![], false) - .is_ok() - { - loop { - let n = f.read(&mut buf)?; - if n == 0 { - break; - } - self.native_module_vfs.write_file_by_absolute_path( - &path_unprefixed, - buf[..n].to_vec(), - true, - )?; - } - } - } - } - } - Ok(()) - } - /// Delete native module's filesystem on the kernel filesystem. /// As of now, there is no point in doing this, since native modules have /// read and write access to the entire program's VFS, potentially making /// native module executions stateful. In the future, we might consider /// giving native modules access to only a subset of the program's VFS with /// limited permissions. - fn teardown_fs(&self) -> FileSystemResult<()> { + fn teardown_fs(&self) -> Result<()> { remove_dir_all(self.native_module_directory.as_path())?; Ok(()) } /// Run the native module. The input is passed by the WASM program via the /// native module's special file. - pub fn execute(&mut self, input: Vec) -> FileSystemResult<()> { - if self.native_module.is_static() { - // Look up native module in the static native modules table - let mut nm = STATIC_NATIVE_MODULES.lock().map_err(|_| ErrNo::Inval)?; - let nm = nm - .get_mut(&self.native_module.name().to_string()) - .ok_or(ErrNo::Inval)?; - if nm.try_parse(&input)? { - nm.serve(&mut self.native_module_vfs, &input)?; - } - } else { - info!("Preparing the native module's filesystem..."); - let top_level_files = self.prepare_fs()?; - info!("OK"); - - // Inject execution configuration into the native module's directory - let mut file = File::create( - self.native_module_directory - .join(strip_root_slash_str(EXECUTION_CONFIGURATION_FILE)), - )?; - file.write_all(&input)?; - - // Enable SIGCHLD handling in order to synchronously execute the - // sandboxer. - // This is necessary as Veracruz-Server (Linux) disables SIGCHLD - // handling, which is inherited by the runtime manager - #[cfg(feature = "std")] - unsafe { - signal::sigaction( - signal::Signal::SIGCHLD, - &signal::SigAction::new( - signal::SigHandler::SigDfl, - signal::SaFlags::empty(), - signal::SigSet::empty(), - ), - ) - .expect("sigaction failed"); - } - - let mount_mappings = self.build_mappings(top_level_files)?; - let entry_point_tmp; - let entry_point = match self.native_module.r#type() { - NativeModuleType::Dynamic { - special_file: _, - entry_point, - } => entry_point.to_str().ok_or(ErrNo::Inval)?, - NativeModuleType::Provisioned { entry_point } => { - entry_point_tmp = self - .native_module_directory - .join(strip_root_slash_path(entry_point)); - entry_point_tmp.to_str().ok_or(ErrNo::Inval)? - } - _ => panic!("should not happen"), - }; - - // Make sure the entry point is executable. - // This is a temporary workaround that only works on Linux. - Command::new("chmod").args(["500", entry_point]).output()?; - - info!("Calling sandboxer..."); - let output = Command::new(NATIVE_MODULE_MANAGER_SANDBOXER_PATH) - .args([ - "--sandbox2tool_resolve_and_add_libraries", - "--sandbox2tool_mount_tmp", - "--sandbox2tool_additional_bind_mounts", - &mount_mappings, - "--sandbox2tool_file_size_creation_limit", - "1048576", - "--sandbox2tool_need_networking", - entry_point, - ]) - .output()?; - - info!("Propagating side effects to the VFS (access errors are ignored)..."); - self.copy_fs_to_vfs(&PathBuf::from(""))?; - let _ = self.native_module_vfs.write_stdout(&output.stdout); - let _ = self.native_module_vfs.write_stderr(&output.stderr); - info!("OK"); - - self.teardown_fs()?; + pub fn execute(&mut self, input: Vec) -> Result<()> { + //if self.native_module.is_static() { + //} else { + + // XXX Create file in kernel + // Inject execution configuration into the native module's directory + let mut file = File::create(self.native_module_directory.join(EXECUTION_CONFIGURATION_FILE))?; + file.write_all(&input)?; + + // Enable SIGCHLD handling in order to synchronously execute the + // sandboxer. + // This is necessary as Veracruz-Server (Linux) disables SIGCHLD + // handling, which is inherited by the runtime manager + #[cfg(feature = "std")] + unsafe { + signal::sigaction( + signal::Signal::SIGCHLD, + &signal::SigAction::new( + signal::SigHandler::SigDfl, + signal::SaFlags::empty(), + signal::SigSet::empty(), + ), + ) + .expect("sigaction failed"); } + // TODO change in the future + let mount_mappings = self.build_mappings(vec!["/".into()])?; + //let entry_point = match self.native_module.r#type() { + //// directly mounted in the kernel file system + //NativeModuleType::Dynamic { entry_point } => entry_point.clone(), + //NativeModuleType::Provisioned { entry_point } => self.native_module_directory.join(entry_point), + ////_ => panic!("should not happen"), + //}; + let entry_point = &self.native_module.entry_point; + let entry_point = entry_point.to_str().ok_or(anyhow!("Failed to convert entry point to str"))?; + + // Make sure the entry point is executable. + // This is a temporary workaround that only works on Linux. + Command::new("chmod").args(["500", entry_point]).output()?; + + info!("Calling sandboxer..."); + Command::new(NATIVE_MODULE_MANAGER_SANDBOXER_PATH) + .args([ + "--sandbox2tool_resolve_and_add_libraries", + "--sandbox2tool_mount_tmp", + "--sandbox2tool_additional_bind_mounts", + &mount_mappings, + "--sandbox2tool_file_size_creation_limit", + "1048576", + entry_point, + ]) + .output()?; + + self.teardown_fs()?; + //} + Ok(()) } } diff --git a/crates/execution-engine/src/native_modules/common.rs b/crates/execution-engine/src/native_modules/common.rs deleted file mode 100644 index 3b41b98d6..000000000 --- a/crates/execution-engine/src/native_modules/common.rs +++ /dev/null @@ -1,48 +0,0 @@ -//! Native modules for Execution Engine. -//! -//! ## Authors -//! -//! The Veracruz Development Team. -//! -//! ## Licensing and copyright notice -//! -//! See the `LICENSE.md` file in the Veracruz root directory for -//! information on licensing and copyright. - -use crate::{ - fs::{FileSystem, FileSystemResult}, - native_modules::{aead::AeadService, aes::AesCounterModeService, postcard::PostcardService}, -}; -use lazy_static::lazy_static; -use std::{collections::HashMap, sync::Mutex}; - -/// Specifications for static native module crates. -/// See `policy_utils::principal::NativeModule` and `generate-policy` for more -/// details on static native modules. -pub trait StaticNativeModule: Send { - fn name(&self) -> &str; - //fn configure(&mut self, config: Self::Configuration) -> FileSystemResult<()>; - // The FS will prepare the Input and call the serve function at an appropriate time. - // Result may depend on the configure. - fn serve(&mut self, fs: &mut FileSystem, input: &[u8]) -> FileSystemResult<()>; - // try_parse may buffer any result, hence we pass a mutable self here. - fn try_parse(&mut self, input: &[u8]) -> FileSystemResult; -} - -// Static native modules table. -// Note that only the ones specified in the policy will actually be exposed to -// WASM programs over the VFS. -lazy_static! { - pub static ref STATIC_NATIVE_MODULES: Mutex>> = { - let mut h = HashMap::>::new(); - let list: Vec> = vec![ - Box::new(AeadService::new()), - Box::new(AesCounterModeService::new()), - Box::new(PostcardService::new()), - ]; - for nm in list { - h.insert(nm.name().to_string(), nm); - } - Mutex::new(h) - }; -} diff --git a/crates/execution-engine/src/pipeline.rs b/crates/execution-engine/src/pipeline.rs index 103dc262d..804bcdbc4 100644 --- a/crates/execution-engine/src/pipeline.rs +++ b/crates/execution-engine/src/pipeline.rs @@ -17,19 +17,19 @@ #[cfg(feature = "std")] use crate::engines::wasmtime::WasmtimeRuntimeState; -use crate::Options; use crate::{ - engines::{common::ExecutionEngine, wasmi::WASMIRuntimeState}, - fs::FileSystem, - native_module_manager::NativeModuleManager, + Environment, + Execution, + service::common::initial_service, + engines::sandbox::Sandbox, }; use anyhow::{anyhow, Result}; use log::info; use policy_utils::{ pipeline::Expr, - principal::{ExecutionStrategy, NativeModule, NativeModuleType}, + principal::{PrincipalPermission, FilePermissions, ExecutionStrategy, check_permission, Service}, }; -use std::{boxed::Box, path::PathBuf}; +use std::{boxed::Box, path::Path}; /// Returns whether the given path corresponds to a WASM binary. fn is_wasm_binary(path_string: &String) -> bool { @@ -39,93 +39,48 @@ fn is_wasm_binary(path_string: &String) -> bool { /// Execute `pipeline`. Program will be read with the `caller_filesystem`, who should have /// `FD_EXECUTE` and `FD_SEEK` permissions and executed with `pipeline_filesystem`. /// The function will return the error code. -pub fn execute_pipeline( +pub(crate) fn execute_pipeline( strategy: &ExecutionStrategy, - caller_filesystem: &mut FileSystem, - pipeline_filesystem: &FileSystem, + caller_permissions: &PrincipalPermission, + execution_permissions: &PrincipalPermission, + services: &[Service], pipeline: Box, - options: &Options, -) -> Result { + env: &Environment, +) -> Result<()> { + // Iniital internal services + initial_service(services)?; use policy_utils::pipeline::Expr::*; match *pipeline { - Literal(mut path_string) => { - // Turn a relative path into an absolute path. - if &path_string[0..1] != "/" { - path_string.insert(0, '/'); + Literal(path) => { + info!("Literal {:?}", path); + // checker permission + if !check_permission(&caller_permissions, path.clone(), &FilePermissions{read: false, write: false, execute: true}) { + return Err(anyhow!("Permission denies")); } - info!("Literal {:?}", path_string); - if is_wasm_binary(&path_string) { + if is_wasm_binary(&path) { + info!("Invoke wasm binary: {path}"); // Read and call execute_WASM program - let binary = caller_filesystem.read_executable_by_absolute_path(path_string)?; - info!("Successful to read binary"); - let return_code = - execute_program(strategy, pipeline_filesystem.clone(), binary, options)?; - Ok(return_code) - } else { - // Treat program as a provisioned native module - let native_module = NativeModule::new( - path_string.clone(), - NativeModuleType::Provisioned { - entry_point: PathBuf::from(&path_string), - }, - ); - - // Invoke native module in the native module manager with no input. - // The execution principal (native module) should have read access - // to the directory containing the execution artifacts (binaries and - // shared libraries), or the native module manager won't be able to - // prepare the sandbox - let mut native_module_manager = - NativeModuleManager::new(native_module, pipeline_filesystem.clone()); - native_module_manager - .execute(vec![]) - .map(|_| 0) - .map_err(|err| anyhow!(err)) + execute_wasm(strategy, execution_permissions, &Path::new(&path), env) + } else { // Sandbox + info!("Invoke native binary: {path}"); + execute_native_binary(execution_permissions, &Path::new(&path)) } } Seq(vec) => { info!("Seq {:?}", vec); for expr in vec { - let return_code = execute_pipeline( - strategy, - caller_filesystem, - pipeline_filesystem, - expr, - options, - )?; - - // An error occurs - if return_code != 0 { - return Ok(return_code); - } + execute_pipeline(strategy, caller_permissions, execution_permissions, services, expr, env)?; } - - // default return_code is zero. - Ok(0) + Ok(()) } IfElse(cond, true_branch, false_branch) => { - info!( - "IfElse {:?} true -> {:?} false -> {:?}", - cond, true_branch, false_branch - ); - let return_code = if caller_filesystem.file_exists(cond)? { - execute_pipeline( - strategy, - caller_filesystem, - pipeline_filesystem, - true_branch, - options, - )? + info!("IfElse {:?} true -> {:?} false -> {:?}", cond, true_branch, false_branch); + let return_code = if Path::new(&cond).exists() { + execute_pipeline(strategy, caller_permissions, execution_permissions, services, true_branch, env)? } else { match false_branch { - Some(f) => execute_pipeline( - strategy, - caller_filesystem, - pipeline_filesystem, - f, - options, - )?, - None => 0, + Some(f) => execute_pipeline(strategy, caller_permissions, execution_permissions, services, f, env)?, + None => (), } }; Ok(return_code) @@ -134,25 +89,37 @@ pub fn execute_pipeline( } /// Execute the `program`. All I/O operations in the program are through at `filesystem`. -fn execute_program( +fn execute_wasm( strategy: &ExecutionStrategy, - filesystem: FileSystem, - program: Vec, - options: &Options, -) -> Result { - let mut engine: Box = match strategy { + execution_permissions: &PrincipalPermission, + program_path: &Path, + env: &Environment, +) -> Result<()> { + info!("Execute program with permissions {:?}", execution_permissions); + let mut engine: Box = match strategy { ExecutionStrategy::Interpretation => { - Box::new(WASMIRuntimeState::new(filesystem, options.clone())?) + return Err(anyhow!("No interpretation engine.")); } ExecutionStrategy::JIT => { cfg_if::cfg_if! { if #[cfg(any(feature = "std", feature = "nitro"))] { - Box::new(WasmtimeRuntimeState::new(filesystem, options.clone())?) + info!("JIT engine initialising"); + Box::new(WasmtimeRuntimeState::new(execution_permissions.clone(), env.clone())?) + } else { - return Err(anyhow::anyhow!(crate::engines::common::FatalEngineError::EngineIsNotReady)); + return Err(anyhow!("No JIT enine.")); } } } }; - engine.invoke_entry_point(program) + info!("engine call"); + engine.execute(program_path) +} + +fn execute_native_binary( + execution_permissions: &PrincipalPermission, + program_path: &Path +) -> Result<()> { + let program_name = program_path.file_name().and_then(|os_str| os_str.to_str()).ok_or(anyhow!("Failed to extract program name from program path to a native binary."))?; + Sandbox::new(execution_permissions.clone(), &program_name).execute(program_path) } diff --git a/crates/execution-engine/src/native_modules/aead.rs b/crates/execution-engine/src/service/aead.rs similarity index 70% rename from crates/execution-engine/src/native_modules/aead.rs rename to crates/execution-engine/src/service/aead.rs index c894e88a9..9f234ed41 100644 --- a/crates/execution-engine/src/native_modules/aead.rs +++ b/crates/execution-engine/src/service/aead.rs @@ -9,12 +9,11 @@ //! See the `LICENSE.md` file in the Veracruz root directory for //! information on licensing and copyright. -use crate::fs::{FileSystem, FileSystemResult}; -use crate::native_modules::common::StaticNativeModule; +use anyhow::Result; +use crate::Execution; use mbedtls::cipher::{Authenticated, Cipher, Decryption, Encryption, Fresh}; use serde::Deserialize; -use std::path::PathBuf; -use wasi_types::ErrNo; +use std::{path::{Path, PathBuf}, fs::{write, read}}; #[derive(Deserialize, Debug)] pub(crate) struct AeadService { @@ -33,38 +32,33 @@ pub(crate) struct AeadService { is_encryption: bool, } -impl StaticNativeModule for AeadService { +impl Execution for AeadService { /// Return the name of this service fn name(&self) -> &str { - "AEAD Service" + Self::NAME } /// Triggers the service. The details of the service can be found in function /// `encryption_decryption`. /// Here is the enter point. It also erase the state unconditionally afterwards. - fn serve(&mut self, fs: &mut FileSystem, _input: &[u8]) -> FileSystemResult<()> { + fn execute(&mut self, dir: &Path) -> Result<()> { + let input = dir.join("input"); + let output = dir.join("output"); + let buf = read(input)?; + let deserialized_input: AeadService = postcard::from_bytes(&buf)?; + *self = deserialized_input; // when reaching here, the `input` bytes are already parsed. - let result = self.encryption_decryption(fs); + let result = self.encryption_decryption(); // NOTE: erase all the states. self.reset(); + // Write an output to inform the callee + let _ = write(output, "0"); result } - - /// For the purpose of demonstration, we always return true. In reality, - /// this function may check validity of the `input`, and even buffer the result - /// for further uses. - fn try_parse(&mut self, input: &[u8]) -> FileSystemResult { - let deserialized_input: AeadService = - match postcard::from_bytes(&input).map_err(|_| ErrNo::Canceled) { - Ok(o) => o, - Err(_) => return Ok(false), - }; - *self = deserialized_input; - Ok(true) - } } impl AeadService { + pub(crate) const NAME: &'static str = "AEAD Service"; /// Create a new service, with empty internal state. pub fn new() -> Self { Self { @@ -79,7 +73,7 @@ impl AeadService { /// The core service. It encrypts or decrypts, depending on the flag `is_encryption`, the input read /// from the path `input_path` using the `key` and `iv`, and writes the result to the file at `output_path`. - fn encryption_decryption(&mut self, fs: &mut FileSystem) -> FileSystemResult<()> { + fn encryption_decryption(&mut self) -> Result<()> { let tag_len = 16; // standard default let AeadService { key, @@ -91,7 +85,7 @@ impl AeadService { } = self; // Read the input. The service must have the permission. - let input = fs.read_file_by_absolute_path(&input_path)?; + let input = read(&input_path)?; let mut output = Vec::new(); @@ -100,36 +94,31 @@ impl AeadService { mbedtls::cipher::raw::CipherId::Aes, mbedtls::cipher::raw::CipherMode::GCM, key.len() as u32 * 8, - ) - .map_err(|_| ErrNo::Canceled)?; + )?; output.resize(input.len() + tag_len, 0); let (n, _) = cypher - .set_key_iv(&key[..], &iv[..]) - .map_err(|_| ErrNo::Canceled)? - .encrypt_auth(&aad, &input, &mut output[..], tag_len) - .map_err(|_| ErrNo::Canceled)?; + .set_key_iv(&key[..], &iv[..])? + .encrypt_auth(&aad, &input, &mut output[..], tag_len)?; output.resize(n, 0); } else { let cypher: Cipher = mbedtls::cipher::Cipher::new( mbedtls::cipher::raw::CipherId::Aes, mbedtls::cipher::raw::CipherMode::GCM, key.len() as u32 * 8, - ) - .map_err(|_| ErrNo::Canceled)?; + )?; output.resize(input.len() + tag_len, 0); let (n, _) = cypher - .set_key_iv(&key[..], &iv[..]) - .map_err(|_| ErrNo::Canceled)? - .decrypt_auth(&aad, &input, &mut output, tag_len) - .map_err(|_| ErrNo::Canceled)?; + .set_key_iv(&key[..], &iv[..])? + .decrypt_auth(&aad, &input, &mut output, tag_len)?; output.resize(n, 0); } - fs.write_file_by_absolute_path(&output_path, output, true) + write(&output_path, output)?; + Ok(()) } /// Reset the state, and erase the sensitive information. diff --git a/crates/execution-engine/src/native_modules/aes.rs b/crates/execution-engine/src/service/aes.rs similarity index 70% rename from crates/execution-engine/src/native_modules/aes.rs rename to crates/execution-engine/src/service/aes.rs index f1710667c..d3c41015e 100644 --- a/crates/execution-engine/src/native_modules/aes.rs +++ b/crates/execution-engine/src/service/aes.rs @@ -9,12 +9,11 @@ //! See the `LICENSE.md` file in the Veracruz root directory for //! information on licensing and copyright. -use crate::fs::{FileSystem, FileSystemResult}; -use crate::native_modules::common::StaticNativeModule; +use anyhow::Result; +use crate::Execution; use mbedtls::cipher::{Cipher, Decryption, Encryption, Fresh, Traditional}; use serde::Deserialize; -use std::path::PathBuf; -use wasi_types::ErrNo; +use std::{path::{Path, PathBuf}, fs::{write, read}}; /// The interface between of the Counter mode AES module. #[derive(Deserialize, Debug)] @@ -32,38 +31,33 @@ pub(crate) struct AesCounterModeService { is_encryption: bool, } -impl StaticNativeModule for AesCounterModeService { +impl Execution for AesCounterModeService { /// Return the name of this service fn name(&self) -> &str { - "Counter mode AES Service" + Self::NAME } /// Triggers the service. The details of the service can be found in function /// `encryption_decryption`. /// Here is the enter point. It also erase the state unconditionally afterwards. - fn serve(&mut self, fs: &mut FileSystem, _input: &[u8]) -> FileSystemResult<()> { + fn execute(&mut self, dir: &Path) -> Result<()> { + let input = dir.join("input"); + let output = dir.join("output"); + let buf = read(input)?; + let deserialized_input: AesCounterModeService = postcard::from_bytes(&buf)?; + *self = deserialized_input; // when reaching here, the `input` bytes are already parsed. - let result = self.encryption_decryption(fs); + let result = self.encryption_decryption(); // NOTE: erase all the states. self.reset(); + // Write an output to inform the callee + let _ = write(output, "0"); result } - - /// For the purpose of demonstration, we always return true. In reality, - /// this function may check validity of the `input`, and even buffer the result - /// for further uses. - fn try_parse(&mut self, input: &[u8]) -> FileSystemResult { - let deserialized_input: AesCounterModeService = - match postcard::from_bytes(&input).map_err(|_| ErrNo::Canceled) { - Ok(o) => o, - Err(_) => return Ok(false), - }; - *self = deserialized_input; - Ok(true) - } } impl AesCounterModeService { + pub(crate) const NAME: &'static str = "Counter mode AES Service"; /// Create a new service, with empty internal state. pub fn new() -> Self { Self { @@ -77,7 +71,7 @@ impl AesCounterModeService { /// The core service. It encrypts or decrypts, depending on the flag `is_encryption`, the input read /// from the path `input_path` using the `key` and `iv`, and writes the result to the file at `output_path`. - fn encryption_decryption(&mut self, fs: &mut FileSystem) -> FileSystemResult<()> { + fn encryption_decryption(&mut self) -> Result<()> { let AesCounterModeService { key, iv, @@ -87,7 +81,7 @@ impl AesCounterModeService { } = self; // Read the input. The service must have the permission. - let input = fs.read_file_by_absolute_path(&input_path)?; + let input = read(&input_path)?; let mut output = Vec::new(); @@ -96,8 +90,7 @@ impl AesCounterModeService { mbedtls::cipher::raw::CipherId::Aes, mbedtls::cipher::raw::CipherMode::CTR, key.len() as u32 * 8, - ) - .map_err(|_| ErrNo::Canceled)?; + )?; let block_size = cypher.block_size(); // Mbed TLS requires the output buffer to be at least `ilen + block_size` long. @@ -106,17 +99,14 @@ impl AesCounterModeService { output.resize(padded_size, 0); cypher - .set_key_iv(&key[..], &iv[..]) - .map_err(|_| ErrNo::Canceled)? - .encrypt(&input, &mut output) - .map_err(|_| ErrNo::Canceled)?; + .set_key_iv(&key[..], &iv[..])? + .encrypt(&input, &mut output)?; } else { let cypher: Cipher = mbedtls::cipher::Cipher::new( mbedtls::cipher::raw::CipherId::Aes, mbedtls::cipher::raw::CipherMode::CTR, key.len() as u32 * 8, - ) - .map_err(|_| ErrNo::Canceled)?; + )?; let block_size = cypher.block_size(); // Mbed TLS requires the output buffer to be at least `ilen + block_size` long. @@ -125,15 +115,14 @@ impl AesCounterModeService { output.resize(padded_size, 0); cypher - .set_key_iv(&key[..], &iv[..]) - .map_err(|_| ErrNo::Canceled)? - .decrypt(&input, &mut output) - .map_err(|_| ErrNo::Canceled)?; + .set_key_iv(&key[..], &iv[..])? + .decrypt(&input, &mut output)?; } // We only need as many bytes from the output as the input: output.resize(input.len(), 0); - fs.write_file_by_absolute_path(&output_path, output, true) + write(&output_path, output)?; + Ok(()) } /// Reset the state, and erase the sensitive information. diff --git a/crates/execution-engine/src/service/common.rs b/crates/execution-engine/src/service/common.rs new file mode 100644 index 000000000..6521d1a37 --- /dev/null +++ b/crates/execution-engine/src/service/common.rs @@ -0,0 +1,127 @@ +//! Native modules for Execution Engine. +//! +//! ## Authors +//! +//! The Veracruz Development Team. +//! +//! ## Licensing and copyright notice +//! +//! See the `LICENSE.md` file in the Veracruz root directory for +//! information on licensing and copyright. + +use anyhow::Result; +use crate::{ + Execution, + service::{echo::EchoService, postcard::PostcardService, aes::AesCounterModeService, aead::AeadService} +}; +use std::{fs::{create_dir_all, remove_file}, sync::Once, path::{Path, PathBuf}, thread::{spawn, JoinHandle}, collections::HashMap}; +use log::info; +use nix::{unistd, sys::stat}; + +/// Static native modules table. +pub static mut SERVICES: Services = Services::new(); +static INIT_SERVICES: Once = Once::new(); + +/// Default input name pipeline file name. +static INPUT_FILE_NAME: &'static str = "input"; +/// Default output name pipeline file name. +static OUTPUT_FILE_NAME: &'static str = "output"; + +fn remove_tmp_file(dir: &PathBuf) { + let input_path = dir.join(INPUT_FILE_NAME); + let output_path = dir.join(OUTPUT_FILE_NAME); + + let _ = remove_file(input_path.clone()); + let _ = remove_file(output_path.clone()); +} + +pub(crate) struct Service { + dir: PathBuf, + // Use the Option trick, allowing us to join the handle in `drop` function + service: Option>>, +} + +impl Service { + pub(crate) fn new(dir: PathBuf, mut service: Box) -> Result { + create_dir_all(&dir)?; + let dir_copy = dir.clone(); + + let service = spawn(move || { + remove_tmp_file(&dir_copy); + + let input_path = dir_copy.join(INPUT_FILE_NAME); + let output_path = dir_copy.join(OUTPUT_FILE_NAME); + + info!("Bind a {:?} on input {input_path:?} and output {output_path:?}", service.name()); + // create new fifo and give read, write and execute rights to the owner + let _ = unistd::mkfifo(&input_path, stat::Mode::S_IRWXU)?; + let _ = unistd::mkfifo(&output_path, stat::Mode::S_IRWXU)?; + + loop{ + let _ = service.execute(dir_copy.as_path()); + } + }); + + Ok(Self {dir, service: Some(service)}) + } + +} + +impl Drop for Service { + fn drop(&mut self) { + if let Some(handler) = self.service.take() { + let _ = handler.join(); + } + + remove_tmp_file(&self.dir); + } +} + +pub struct Services { + pub(crate) services: Vec, +} + +impl Services { + pub const fn new() -> Self { + Self{services: Vec::new()} + } + + pub fn register>(&mut self, dir: T, service: Box) -> Result<()> { + self.services.push(Service::new(dir.as_ref().to_path_buf(), service)?); + Ok(()) + } +} + +pub fn initial_service(services: &[policy_utils::principal::Service]) -> Result<()> { + let mut existing_services = HashMap::<&str, Box>::new(); + existing_services.insert(EchoService::NAME, Box::new(EchoService::new())); + existing_services.insert(PostcardService::NAME, Box::new(PostcardService::new())); + existing_services.insert(AesCounterModeService::NAME, Box::new(AesCounterModeService::new())); + existing_services.insert(AeadService::NAME, Box::new(AeadService::new())); + + + // We will consume `existing_services` by using `into_iter`. + // It is needed for later extract the `Box`. + let mounted_services = existing_services.into_iter().filter_map(|(name, execution)|{ + services.iter().find(|x| match x.source() { + // find the service where the `name` that match the `Internal(s)` + policy_utils::principal::ServiceSource::Internal(n) => n == name, + _ => false, + }) + // if we find a matching, extract the dir information and pair with execution + .map(|s|{ + (s.dir(), execution) + }) + }); + + unsafe { + INIT_SERVICES.call_once(||{ + mounted_services.for_each(|(dir, execution)|{ + SERVICES.register(dir, execution).unwrap(); + }) + }); + } + info!("Initialised service"); + Ok(()) +} + diff --git a/crates/execution-engine/src/service/echo.rs b/crates/execution-engine/src/service/echo.rs new file mode 100644 index 000000000..e6440d7f7 --- /dev/null +++ b/crates/execution-engine/src/service/echo.rs @@ -0,0 +1,26 @@ +use crate::Execution; +use anyhow::Result; +use std::{path::Path, fs::{read, write}}; + +pub(crate) struct EchoService; + +impl Execution for EchoService { + fn name(&self) -> &str { + Self::NAME + } + + fn execute(&mut self, dir: &Path) -> Result<()> { + let input = dir.join("input"); + let output = dir.join("output"); + let buf = read(input)?; + write(output, buf)?; + Ok(()) + } +} + +impl EchoService { + pub(crate) const NAME: &'static str = "Echo Service"; + pub(crate) fn new() -> Self { + Self {} + } +} diff --git a/crates/execution-engine/src/native_modules/mod.rs b/crates/execution-engine/src/service/mod.rs similarity index 94% rename from crates/execution-engine/src/native_modules/mod.rs rename to crates/execution-engine/src/service/mod.rs index 6b7978faf..ac7972ede 100644 --- a/crates/execution-engine/src/native_modules/mod.rs +++ b/crates/execution-engine/src/service/mod.rs @@ -13,3 +13,4 @@ pub(crate) mod aead; pub(crate) mod aes; pub(crate) mod common; pub(crate) mod postcard; +pub(crate) mod echo; diff --git a/crates/execution-engine/src/native_modules/postcard.rs b/crates/execution-engine/src/service/postcard.rs similarity index 66% rename from crates/execution-engine/src/native_modules/postcard.rs rename to crates/execution-engine/src/service/postcard.rs index 60c3fd816..5bacd98ac 100644 --- a/crates/execution-engine/src/native_modules/postcard.rs +++ b/crates/execution-engine/src/service/postcard.rs @@ -10,11 +10,11 @@ //! See the `LICENSE.md` file in the Veracruz root directory for //! information on licensing and copyright. -use crate::fs::{FileSystem, FileSystemResult}; -use crate::native_modules::common::StaticNativeModule; +use anyhow::Result; +use crate::Execution; use postcard::from_bytes; use serde::{Deserialize, Serialize}; -use wasi_types::ErrNo; +use std::{path::Path, fs::{read, write}}; pub(crate) struct PostcardService; @@ -70,33 +70,29 @@ pub struct Struct3 { e3: Enum2, } -impl StaticNativeModule for PostcardService { +impl Execution for PostcardService { fn name(&self) -> &str { - "Postcard Service" + Self::NAME } - fn serve(&mut self, fs: &mut FileSystem, inputs: &[u8]) -> FileSystemResult<()> { - let v = from_bytes::>(inputs).map_err(|_| ErrNo::Inval)?; - fs.write_file_by_absolute_path( - "/services/postcard_result.dat", - serde_json::to_string(&v) - .map_err(|_| ErrNo::Inval)? + fn execute(&mut self, dir: &Path) -> Result<()> { + let input = dir.join("input"); + let output = dir.join("output"); + let buf = read(input)?; + let v = from_bytes::>(&buf)?; + + write( + output, + serde_json::to_string(&v)? .as_bytes() .to_vec(), - false, )?; Ok(()) } - - /// For the purpose of demonstration, we always return true. In reality, - /// this function may check validity of the `input`, and even buffer the result - /// for further uses. - fn try_parse(&mut self, _input: &[u8]) -> FileSystemResult { - Ok(true) - } } impl PostcardService { + pub(crate) const NAME: &'static str = "Postcard Service"; pub(crate) fn new() -> Self { Self {} } diff --git a/crates/freestanding-execution-engine/Cargo.toml b/crates/freestanding-execution-engine/Cargo.toml index f07f9a7e9..0e5b369e3 100644 --- a/crates/freestanding-execution-engine/Cargo.toml +++ b/crates/freestanding-execution-engine/Cargo.toml @@ -7,7 +7,7 @@ version = "0.3.0" [dependencies] anyhow = "1" -clap = "4" +clap = { version = "4", features = ["derive"] } env_logger = "0.10.0" execution-engine = { path = "../execution-engine", features = ["std"] } log = "0.4.13" diff --git a/crates/freestanding-execution-engine/src/main.rs b/crates/freestanding-execution-engine/src/main.rs index a03734275..febcbd3d9 100644 --- a/crates/freestanding-execution-engine/src/main.rs +++ b/crates/freestanding-execution-engine/src/main.rs @@ -23,26 +23,22 @@ //! See the file `LICENSE.md` in the Veracruz root directory for licensing //! and copyright information. -use anyhow::anyhow; -use clap::{Arg, ArgAction}; -use execution_engine::{execute, fs::FileSystem, Options}; +use clap::Parser; +use execution_engine::{execute, Environment}; use log::*; use policy_utils::{ - parsers::{enforce_leading_slash, parse_pipeline}, - pipeline::Expr, - principal::{ExecutionStrategy, NativeModule, NativeModuleType, Principal}, - CANONICAL_STDERR_FILE_PATH, CANONICAL_STDIN_FILE_PATH, CANONICAL_STDOUT_FILE_PATH, + parsers::parse_pipeline, + pipeline::Expr, + principal::{FilePermissions, ExecutionStrategy, Service, ServiceSource}, }; use std::{ collections::HashMap, error::Error, - fs::{create_dir_all, File}, - io::{Read, Write}, - path::{Path, PathBuf}, + path::PathBuf, time::Instant, vec::Vec, }; -use wasi_types::Rights; +use anyhow::{anyhow, Result}; //////////////////////////////////////////////////////////////////////////////// // Constants. @@ -59,301 +55,53 @@ const APPLICATION_NAME: &str = "freestanding-execution-engine"; const AUTHORS: &str = "The Veracruz Development Team. See the file `AUTHORS.md` in the \ Veracruz `docs` subdirectory for detailed authorship information."; /// Application version number. -const VERSION: &str = "pre-alpha"; +const VERSION: &str = "alpha"; //////////////////////////////////////////////////////////////////////////////// // Command line options and parsing. //////////////////////////////////////////////////////////////////////////////// /// A struct capturing all of the command line options passed to the program. +#[derive(Debug, Parser)] +#[command(name = APPLICATION_NAME, author = AUTHORS, version = VERSION, about = ABOUT, long_about = None, rename_all = "kebab-case")] struct CommandLineOptions { /// The list of file names passed as input data-sources. - input_sources: Vec, - /// The list of file names passed as output. - output_sources: Vec, + #[arg(short = 'i', long, value_name = "PATH")] + input_source: Vec, /// The execution strategy to use when performing the computation. + #[arg(long, short = 'e', value_name = "Interpretation | JIT", default_value = "JIT")] execution_strategy: ExecutionStrategy, - /// Whether the contents of `stdout` should be dumped before exiting. - dump_stdout: bool, - /// Whether the contents of `stderr` should be dumped before exiting. - dump_stderr: bool, - /// Whether clock functions (`clock_getres()`, `clock_gettime()`) should be - /// enabled. - enable_clock: bool, /// Environment variables for the program. - environment_variables: Vec<(String, String)>, - /// Whether strace is enabled. - enable_strace: bool, - /// A list of native module names. - native_modules_names: Vec, - /// A list of paths to native module entry points. - native_modules_entry_points: Vec, - /// A list of paths to native module special files. - native_modules_special_files: Vec, - /// The conditional pipeline of programs to execute. + #[arg(long, value_name = "PATH", value_parser=env_parser)] + env: Vec<(String, String)>, + #[arg(long, value_name = "SERVICE => DIR", value_parser = service_parser)] + service: Vec, + #[arg(short = 'r', long, value_name = "PATH", value_parser=pipeline_parser)] pipeline: Box, } -/// Parses the command line options, building a `CommandLineOptions` struct out -/// of them. If required options are not present, or if any options are -/// malformed, this will abort the program. -fn parse_command_line() -> Result> { - let matches = clap::Command::new(APPLICATION_NAME) - .version(VERSION) - .author(AUTHORS) - .about(ABOUT) - .arg( - Arg::new("input") - .short('i') - .long("input-source") - .value_name("DIRECTORIES") - .help( - "Space-separated paths to the input directories on disk. The directories are \ - copied into the root directory in Veracruz space. All programs are granted \ - with read capabilities.", - ) - .num_args(0..), - ) - .arg( - Arg::new("output") - .short('o') - .long("output-source") - .value_name("DIRECTORIES") - .help( - "Space-separated paths to the output directories. The directories are copied \ - into disk on the host. All program are granted with write capabilities.", - ) - .num_args(0..), - ) - .arg( - Arg::new("native-module-name") - .long("native-module-name") - .value_name("NAME") - .help("Specifies the name of the native module to use for the computation. \ -This must be of the form \"--native-module-name name\". Multiple --native-module-name flags may be provided.") - .num_args(1) - .action(ArgAction::Append), - ) - .arg( - Arg::new("native-module-entry-point") - .long("native-module-entry-point") - .value_name("FILE") - .help("Specifies the path to the entry point of the native module to use for the computation. \ -This must be of the form \"--native-module-entry-point path\". Multiple --native-module-entry-point flags may be provided. \ -If the value is an empty string, the native module is assumed to be static, i.e. part of the Veracruz runtime, \ -and is looked up by name in the static native modules table.") - .num_args(1) - .action(ArgAction::Append), - ) - .arg( - Arg::new("native-module-special-file") - .long("native-module-special-file") - .value_name("FILE") - .help("Specifies the path to the special file of the native module to use for the computation. \ -This must be of the form \"--native-module-special-file path\". Multiple --native-module-special-file flags may be provided.") - .num_args(1) - .action(ArgAction::Append), - ) - .arg( - Arg::new("pipeline") - .short('r') - .long("pipeline") - .value_name("PIPELINE") - .help("The conditional pipeline of programs to be executed.") - .required(true), - ) - .arg( - Arg::new("execution-strategy") - .short('x') - .long("execution-strategy") - .value_name("interp | jit") - .default_value("jit") - .help( - "Selects the execution strategy to use: interpretation or JIT (defaults to \ - interpretation).", - ), - ) - .arg( - Arg::new("dump-stdout") - .short('d') - .long("dump-stdout") - .help("Whether the contents of stdout should be dumped before exiting") - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new("dump-stderr") - .short('e') - .long("dump-stderr") - .help("Whether the contents of stderr should be dumped before exiting") - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new("enable-clock") - .short('c') - .long("enable-clock") - .help( - "Whether clock functions (`clock_getres()`, `clock_gettime()`) should be \ - enabled.", - ) - .action(ArgAction::SetTrue), - ) - .arg( - Arg::new("env") - .long("env") - .help("Specify an environment variable and value (VAR=VAL).") - .value_name("VAR=VAL") - .num_args(1) - .action(ArgAction::Append), - ) - .arg( - Arg::new("strace") - .long("strace") - .help("Enable strace-like output for WASI calls.") - .action(ArgAction::SetTrue), - ) - .get_matches(); - - info!("Parsed command line."); - - let execution_strategy = { - let strategy = matches - .get_one::("execution-strategy") - .ok_or("jit")? - .as_str(); - - match strategy { - "interp" => { - info!("Selecting interpretation as the execution strategy."); - ExecutionStrategy::Interpretation - } - "jit" => { - info!("Selecting JITting as the execution strategy."); - ExecutionStrategy::JIT - } - _ => { - return Err(format!( - "Expecting 'interp' or 'jit' as selectable execution strategies, but found {}", - strategy - ) - .into()); - } +fn service_parser(input: &str) -> Result { + match input.splitn(2,"=>").collect::>().as_slice() { + [source, dir] => { + // TODO distinguish internal and provisional + Ok(Service::new(ServiceSource::Internal(source.trim().to_string()), PathBuf::from(dir.trim()))) } - }; - - // Read all native module names - let native_modules_names = matches - .get_many::("native-module-name") - .map_or(Vec::new(), |p| p.map(|s| s.to_string()).collect::>()); - - // Read all native module entry points - let native_modules_entry_points = matches - .get_many::("native-module-entry-point") - .map_or(Vec::new(), |p| { - p.map(|s| PathBuf::from(s)).collect::>() - }); - - // Read all native module special files - let native_modules_special_files = matches - .get_many::("native-module-special-file") - .map_or(Vec::new(), |p| { - p.map(|s| PathBuf::from(s)).collect::>() - }); - - let pipeline = if let Some(pipeline_string) = matches.get_one::("pipeline") { - parse_pipeline(pipeline_string)? - } else { - return Err("No executable pipeline provided".into()); - }; - - let input_sources = if let Some(data) = matches.get_many::("input") { - let input_sources: Vec = data.map(|e| e.to_string()).collect(); - info!( - "Selected {} data sources as input to computation.", - input_sources.len() - ); - input_sources - } else { - Vec::new() - }; - - let output_sources = if let Some(data) = matches.get_many::("output") { - let output_sources: Vec = data.map(|e| e.to_string()).collect(); - info!( - "Selected {} data sources as input to computation.", - output_sources.len() - ); - output_sources - } else { - Vec::new() - }; - - let enable_clock = matches.get_flag("enable-clock"); - let dump_stdout = matches.get_flag("dump-stdout"); - let dump_stderr = matches.get_flag("dump-stderr"); - - let environment_variables = match matches.get_many::("env") { - None => Vec::new(), - Some(x) => x - .map(|e| { - let n = e.find('=').unwrap(); - (e[0..n].to_string(), e[n + 1..].to_string()) - }) - .collect(), - }; - - let enable_strace = matches.get_flag("strace"); - - Ok(CommandLineOptions { - input_sources, - output_sources, - execution_strategy, - dump_stdout, - dump_stderr, - enable_clock, - environment_variables, - enable_strace, - native_modules_names, - native_modules_entry_points, - native_modules_special_files, - pipeline, - }) -} - -/// Loads the specified data sources, as provided on the command line, for -/// reading and massages them into metadata frames, ready for -/// the computation. May abort the program if something goes wrong when reading -/// any data source. -fn load_input_sources( - input_sources: &[String], - vfs: &mut FileSystem, -) -> Result<(), Box> { - for file_path in input_sources.iter() { - let file_path = Path::new(file_path); - load_input_source(&file_path, vfs)?; + _ => Err(anyhow!("Error in parsing service")) } - Ok(()) } -fn load_input_source>( - file_path: T, - vfs: &mut FileSystem, -) -> Result<(), Box> { - let file_path = file_path.as_ref(); - info!("Loading data source '{:?}'.", file_path); - if file_path.is_file() { - let mut file = File::open(file_path)?; - let mut buffer = Vec::new(); - file.read_to_end(&mut buffer)?; - - vfs.write_file_by_absolute_path(&Path::new("/").join(file_path), buffer, false)?; - } else if file_path.is_dir() { - for dir in file_path.read_dir()? { - load_input_source(&dir?.path(), vfs)?; +fn env_parser(input: &str) -> Result<(String, String)> { + match input.splitn(2,"=").collect::>().as_slice() { + [var, value] => { + // TODO distinguish internal and provisional + Ok((var.to_string(), value.to_string())) } - } else { - return Err(format!("Error on load {:?}", file_path).into()); + _ => Err(anyhow!("Error in parsing environment variables")) } - Ok(()) +} + +fn pipeline_parser(input: &str) -> Result> { + parse_pipeline(input) } /// Entry: reads the static configuration and the command line parameters, @@ -361,129 +109,33 @@ fn load_input_source>( /// invoking the entry point. fn main() -> Result<(), Box> { env_logger::init(); - let cmdline = parse_command_line()?; + let cmdline = CommandLineOptions::parse(); info!("Command line read successfully."); - // Convert the program paths to absolute if needed. - - // Construct file table for all programs - - let mut file_table = HashMap::new(); - - let read_right = Rights::PATH_OPEN | Rights::FD_READ | Rights::FD_SEEK | Rights::FD_READDIR; - let write_right = read_right - | Rights::FD_WRITE - | Rights::PATH_CREATE_FILE - | Rights::PATH_FILESTAT_SET_SIZE - | Rights::PATH_CREATE_DIRECTORY; - - // Set up standard streams table - - file_table.insert(PathBuf::from(CANONICAL_STDIN_FILE_PATH), read_right); - file_table.insert(PathBuf::from(CANONICAL_STDOUT_FILE_PATH), write_right); - file_table.insert(PathBuf::from(CANONICAL_STDERR_FILE_PATH), write_right); - - // Set up services - - file_table.insert(PathBuf::from("/services"), read_right); - file_table.insert(PathBuf::from("/services"), write_right); - - // Add read permission to input path - - for file_path in cmdline.input_sources.iter() { - // NOTE: inject the root path. - file_table.insert(Path::new("/").join(file_path), read_right); - } - - // Add write permission to output path - - for file_path in cmdline.output_sources.iter() { - // NOTE: inject the root path. - file_table.insert(Path::new("/").join(file_path), write_right); - } - - // Construct the rights table - - let mut right_table = HashMap::new(); - - // Insert the file right for all programs - - // Grant the super user read access to any file under the root. This is - // used internally to read the program on behalf of the executing party - - let mut su_read_rights = HashMap::new(); - su_read_rights.insert(PathBuf::from("/"), write_right); - right_table.insert(Principal::InternalSuperUser, su_read_rights); - - info!("The final rights table: {:?}", right_table); - - // Construct the native module table - info!("Serializing native modules."); - - assert_eq!( - cmdline.native_modules_names.len(), - cmdline.native_modules_entry_points.len() - ); - assert_eq!( - cmdline.native_modules_entry_points.len(), - cmdline.native_modules_special_files.len() - ); - - let mut native_modules = Vec::new(); - for ((name, entry_point_path), special_file) in cmdline - .native_modules_names - .iter() - .zip(&cmdline.native_modules_entry_points) - .zip(&cmdline.native_modules_special_files) - { - // Add a backslash (VFS requirement) - let special_file = enforce_leading_slash( - special_file - .to_str() - .ok_or(anyhow!("Fail to convert special_file to str."))?, - ) - .into_owned(); - - let nm_type = if entry_point_path == &PathBuf::from("") { - NativeModuleType::Static { - special_file: PathBuf::from(special_file), - } - } else { - NativeModuleType::Dynamic { - special_file: PathBuf::from(special_file), - entry_point: entry_point_path.to_path_buf(), - } - }; - native_modules.push(NativeModule::new(name.to_string(), nm_type)); - } - - let mut vfs = FileSystem::new(right_table, native_modules)?; - load_input_sources(&cmdline.input_sources, &mut vfs)?; + let permission = cmdline.input_source.iter().map(|s| (PathBuf::from(s), FilePermissions{read: true, write: true, execute: true})).collect::>(); info!("Data sources loaded."); - // Execute the pipeline with the supplied options - - let options = Options { - enable_clock: cmdline.enable_clock, - enable_strace: cmdline.enable_strace, - environment_variables: cmdline.environment_variables, + // Execute the pipeline with the supplied environment + let env = Environment { + environment_variables: cmdline.env, ..Default::default() }; info!( - "Invoking pipeline {:?} with options {:?}.", - cmdline.pipeline, options + "Invoking pipeline {:?} with environment {:?}.", + cmdline.pipeline, env ); let main_time = Instant::now(); let return_code = execute( &cmdline.execution_strategy, - vfs.clone(), - vfs.clone(), + &permission, + &permission, + &cmdline.service, cmdline.pipeline.clone(), - &options, + &env, )?; info!( @@ -497,63 +149,5 @@ fn main() -> Result<(), Box> { main_time.elapsed().as_micros() ); - // Dump the contents of the 'stdout' file - - if cmdline.dump_stdout { - let buf = vfs.read_stdout()?; - let stdout_dump = std::str::from_utf8(&buf)?; - - print!( - "---- stdout dump ----\n{}---- stdout dump end ----\n", - stdout_dump - ); - - std::io::stdout().flush()?; - } - - // Dump the contents of the 'stderr' file - - if cmdline.dump_stderr { - let buf = vfs.read_stderr()?; - let stderr_dump = std::str::from_utf8(&buf)?; - - eprint!( - "---- stderr dump ----\n{}---- stderr dump end ----\n", - stderr_dump - ); - - std::io::stderr().flush()?; - } - - // Map all output directories - - for file_path in cmdline.output_sources.iter() { - for (output_path, buf) in vfs - .read_all_files_by_absolute_path(Path::new("/").join(file_path))? - .iter() - { - let output_path = output_path.strip_prefix("/").unwrap_or(output_path); - - if let Some(parent_path) = output_path.parent() { - if parent_path != Path::new("") { - create_dir_all(parent_path)?; - } - } - - let mut to_write = File::create(output_path)?; - to_write.write_all(&buf)?; - - // Try to decode - let decode: String = match postcard::from_bytes(buf) { - Ok(o) => o, - Err(_) => match std::str::from_utf8(buf) { - Ok(oo) => oo.to_string(), - Err(_) => "(Cannot parse as a UTF-8 string)".to_string(), - }, - }; - - info!("{:?}: {:?}", output_path, decode); - } - } Ok(()) } diff --git a/crates/generate-policy/Cargo.toml b/crates/generate-policy/Cargo.toml index 6c83c0512..e9df1705b 100644 --- a/crates/generate-policy/Cargo.toml +++ b/crates/generate-policy/Cargo.toml @@ -8,13 +8,12 @@ version = "0.1.0" [dependencies] anyhow = "1" chrono = { version = "0.4.19", default-features = false, features = ["clock", "std"] } -clap = "4" +clap = { version = "4", features = ["derive"] } data-encoding = "2.3.2" env_logger = "0.10.0" log = "0.4.13" policy-utils = { path = "../policy-utils", features = ["std"] } -regex = "1.5.5" serde = { version = "1.0.185", features = ["std"] } serde_json = { version = "1.0", features = ["std"] } veracruz-utils = { path = "../veracruz-utils", features = ["std"] } -wasi-types = { path = "../third-party/wasi-types" } +lazy_static = "*" diff --git a/crates/generate-policy/src/main.rs b/crates/generate-policy/src/main.rs index 764ca8d6c..8badc2cba 100644 --- a/crates/generate-policy/src/main.rs +++ b/crates/generate-policy/src/main.rs @@ -10,32 +10,28 @@ //! and copyright information. use anyhow::{anyhow, Result}; -use chrono::{DateTime, Datelike, FixedOffset, Timelike}; -use clap::{Arg, ArgAction}; +use chrono::{DateTime, Datelike, Timelike}; +use clap::Parser; use data_encoding::HEXLOWER; use log::{info, warn}; use policy_utils::{ expiry::Timepoint, - parsers::{enforce_leading_slash, parse_renamable_paths}, + parsers::parse_renamable_path, policy::Policy, - principal::{ - ExecutionStrategy, FileHash, FileRights, Identity, NativeModule, NativeModuleType, - Pipeline, Program, - }, + principal::{ExecutionStrategy, FileHash, FilePermissions, Identity, Service, ServiceSource, Pipeline, Program}, }; -use regex::Regex; use serde_json::{json, to_string_pretty, Value}; use std::{ - convert::TryFrom, fmt::Debug, fs::{read_to_string, File}, io::{Read, Write}, net::SocketAddr, path::PathBuf, - str::FromStr, + collections::HashMap, + sync::{Mutex, atomic::{AtomicU32, Ordering}}, }; use veracruz_utils::sha256::sha256; -use wasi_types::Rights; +use lazy_static::lazy_static; //////////////////////////////////////////////////////////////////////////////// // Miscellaneous useful functions. @@ -48,6 +44,11 @@ fn pretty_digest(buf: &[u8]) -> String { HEXLOWER.encode(&digest) } +lazy_static!{ + /// A global buffer to hold all the programs and their hashes during the parsing. + static ref PROG_HASH : Mutex> = Mutex::new(Vec::new()); +} + //////////////////////////////////////////////////////////////////////////////// // Constants. //////////////////////////////////////////////////////////////////////////////// @@ -82,72 +83,68 @@ const DEFAULT_MAX_MEMORY_MIB: u32 = 256; //////////////////////////////////////////////////////////////////////////////// /// A structure collating all of the arguments passed to the executable. -#[derive(Debug)] +#[derive(Debug, Parser)] +#[command(name = APPLICATION_NAME, author = AUTHORS, version = VERSION, about = ABOUT, long_about = None, rename_all = "kebab-case")] struct Arguments { /// The filenames of cryptographic certificates associated to each principal /// in the computation. - certificates: Vec, - /// The capabilities associated to each principal and program in the computation. - /// Note that the length of this vector MUST match the total length of `certificates` and `program_binary` - /// as each principal and program has an accompanying capability table. - certificate_capabilities: Vec>, - binary_capabilities: Vec>, - pipeline_capabilities: Vec>, + #[arg(short = 'c', long, value_name = "PATH => PERMISSION", value_parser=participant_parser)] + certificate: Vec>, /// The socket address (IP and port) of the Veracruz server instance. + #[arg(long, short = 's', value_name = "IP ADDRESS")] veracruz_server_ip: SocketAddr, /// The socket address (IP and port) of the Veracruz proxy attestation instance. + #[arg(long, short = 't', value_name = "IP ADDRESS")] proxy_attestation_server_ip: SocketAddr, /// The filename of the Proxy Attestation Service certificate - proxy_service_cert: PathBuf, + #[arg(long, value_name = "PATH", value_parser=reading_file_parser)] + proxy_attestation_server_cert: String, /// The filename of the Runtime Manager CSS file for SGX measurement. This is /// optional. + #[arg(long, short = 'b', value_name = "PATH")] css_file: Option, /// The filename of the Runtime Manager PRCR0 file for Nitro Enclave /// measurement. This is optional. + #[arg(long, short = 'l', value_name = "PATH")] pcr0_file: Option, /// The hash of the SEV SNP image. This is optional + #[arg(long, value_name = "HASH")] sevsnp_hash: Option, /// The filename of the output policy file. + #[arg(long, short = 'o', default_value = DEFAULT_OUTPUT_FILENAME, value_name = "PATH")] output_policy_file: PathBuf, /// The expiry timepoint of the server certificate. This is not optional, /// we use the value of `None` as a marker indicating that the field has not /// yet been initialized, due to `DateTime` not really having an obvious /// default value. Past command-line parsing, any value of `None` in this /// field is an internal invariant failure. - certificate_expiry: DateTime, + #[arg(long, short = 'x', value_name = "RFC2822 TIMEPOINT", value_parser = certificate_expiry_parser)] + certificate_expiry: Timepoint, /// The filename of the WASM program. - /// /// Note this is an array of string+path pairs, since a string enclave path /// can be provided along with the local file path. - program_binaries: Vec<(String, PathBuf)>, - /// A list of native module names. - native_modules_names: Vec, - /// A list of paths to native module entry points. - native_modules_entry_points: Vec, - /// A list of paths to native module special files. - native_modules_special_files: Vec, + #[arg(long, short = 'w', value_name = "PATH[=LOCAL_PATH] => PERMISSION", value_parser=binary_parser)] + program_binary: Vec, + #[arg(long, value_name = "SERVICE => DIR", value_parser = service_parser)] + service: Vec, /// The conditional pipeline of programs to execute. We parse this eagerly /// to check for parsing issues before writing the string to the policy /// file. However, this string is then re-parsed by the Veracruz runtime /// as we have no way of writing the binary AST into JSON. - pipelines: Vec, + #[arg(long, value_name = "SCRIPT => PERMISSION", value_parser=pipeline_parser)] + pipeline: Vec, /// The hash of files. - /// /// Note this is an array of string+path pairs, since a string enclave path /// can be provided along with the local file path. - hashes: Vec<(String, PathBuf)>, - /// Whether the enclave will be started in debug mode, with reduced - /// protections against snooping and interference, and with the ability to - /// write to the host's `stdout`. - enclave_debug_mode: bool, + #[arg(long, value_name = "PATH[=LOCAL_PATH]", value_parser=file_hash_parser)] + hash: Vec, /// Describes the execution strategy (interpretation or JIT) that will be /// used for the computation. - execution_strategy: String, - /// Whether clock functions (`clock_getres()`, `clock_gettime()`) should be - /// enabled. - enable_clock: bool, + #[arg(long, short = 'e', value_name = "Interpretation | JIT", default_value = DEFAULT_EXECUTION_STRATEGY)] + execution_strategy: ExecutionStrategy, /// The maximum amount of memory in MiB available to the isolate. Only /// enforced in Nitro for now. + #[arg(long, short = 'm', value_name = "SIZE", default_value_t = DEFAULT_MAX_MEMORY_MIB)] max_memory_mib: u32, } @@ -156,391 +153,33 @@ impl Arguments { /// of them. If required options are not present, or if any options are /// malformed, this will abort the program. fn parse_command_line() -> Result { - let matches = clap::Command::new(APPLICATION_NAME) - .version(VERSION) - .author(AUTHORS) - .about(ABOUT) - .disable_help_flag(true) - .arg( - Arg::new("certificate") - .short('c') - .long("certificate") - .value_name("FILE") - .help("The filename of a cryptographic certificate identifying a computation participant.") - .required(true) - .num_args(1) - .action(ArgAction::Append) - ) - .arg( - Arg::new("capability") - .short('p') - .long("capability") - .value_name("CAPABILITIES") - .help("The capability table of a client or a program of the form 'output:rw,input-0:w,program.wasm:w' where each entry is separated by ','. These may be either some combination of 'r' and 'w' for reading and writing permissions respectively, or an integer containing the bitwise-or of the low-level WASI capabilities.") - .required(true) - .num_args(1) - .action(ArgAction::Append) - ) - .arg( - Arg::new("veracruz-server-ip") - .short('s') - .long("veracruz-server-ip") - .value_name("IP ADDRESS") - .help("IP address of the Veracruz server.") - .num_args(1) - .required(true) - ) - .arg( - Arg::new("proxy-attestation-server-ip") - .short('t') - .long("proxy-attestation-server-ip") - .value_name("IP ADDRESS") - .help("IP address of the Veracruz proxy attestation server.") - .num_args(1) - .required(true) - ) - .arg( - Arg::new("proxy-attestation-server-cert") - .long("proxy-attestation-server-cert") - .value_name("PROXY_CERT") - .help("CA Certificate that the proxy attestation service uses to create and sign certificates") - .num_args(1) - .required(true) - ) - .arg( - Arg::new("css-file") - .short('b') - .long("css-file") - .value_name("FILE") - .help("Filename of the CSS file for the Runtime Manager enclave for SGX measurement.") - .num_args(1) - .required(false) - ) - .arg( - Arg::new("pcr-file") - .short('l') - .long("pcr-file") - .value_name("FILE") - .help("Filename of the PCR0 file for the Runtime Manager enclave for AWS Nitro Enclave measurement.") - .num_args(1) - .required(false) - ) - .arg( - Arg::new("sevsnp-hash") - .long("sevsnp-hash") - .value_name("HASH") - .help("Hash of the SEV SNP measurment") - .required(false), - ) - .arg( - Arg::new("output-policy-file") - .short('o') - .long("output-policy-file") - .value_name("FILE") - .help("Filename of the generated policy file.") - .num_args(1) - ) - .arg( - Arg::new("certificate-expiry") - .short('x') - .long("certificate-expiry") - .value_name("RFC2822 TIMEPOINT") - .help( - "The expiry point of the server certificate, expressed \ - as an RFC-2822 formatted timepoint.", - ) - .num_args(1) - .required(true) - ) - .arg( - Arg::new("program-binary") - .short('w') - .long("program-binary") - .value_name("FILE") - .help("Specifies the filename of the WASM binary to use for the computation. \ - This can be of the form \"--program-binary name\" or \"--program-binary enclave_name=path\" if you want to \ - supply the file as a different name in the enclave. Multiple --program-binary flags or a comma-separated \ - list of files may be provided.") - .num_args(1) - .required(true) - .action(ArgAction::Append) - ) - .arg( - Arg::new("native-module-name") - .long("native-module-name") - .value_name("NAME") - .help("Specifies the name of the native module to use for the computation. \ - This must be of the form \"--native-module-name name\". Multiple --native-module-name flags may be provided.") - .required(false) - .action(ArgAction::Append) - ) - .arg( - Arg::new("native-module-entry-point") - .long("native-module-entry-point") - .value_name("FILE") - .help("Specifies the path to the entry point of the native module to use for the computation. \ - This must be of the form \"--native-module-entry-point path\". Multiple --native-module-entry-point flags may be provided. \ - If the value is an empty string, the native module is assumed to be static, i.e. part of the Veracruz runtime, \ - and is looked up by name in the static native modules table.") - .required(false) - .action(ArgAction::Append) - ) - .arg( - Arg::new("native-module-special-file") - .long("native-module-special-file") - .value_name("FILE") - .help("Specifies the path to the special file of the native module to use for the computation. \ - This must be of the form \"--native-module-special-file path\". Multiple --native-module-special-file flags may be provided.") - .required(false) - .action(ArgAction::Append) - ) - .arg( - Arg::new("pipeline") - //.short('i') - .long("pipeline") - .value_name("SCRIPT") - .help("Script for executing several programs.") - .required(false) - .action(ArgAction::Append) - ) - .arg( - Arg::new("debug") - .short('d') - .long("enclave-debug-mode") - .help( - "Specifies whether the Veracruz trusted runtime should allow debugging \ - information to be produced by the executing WASM binary.", - ) - .action(ArgAction::SetTrue) - ) - .arg( - Arg::new("execution-strategy") - .short('e') - .long("execution-strategy") - .value_name("Interpretation | JIT") - .help( - "Specifies whether to use interpretation or JIT execution for the WASM \ - binary.", - ) - ) - .arg( - Arg::new("enable-clock") - .short('n') - .long("enable-clock") - .help( - "Specifies whether the Veracruz trusted runtime should allow the WASM \ - binary to call clock functions (`clock_getres()`, `clock_gettime()`).", - ) - .action(ArgAction::SetTrue) - ) - .arg( - Arg::new("max-memory-mib") - .short('m') - .long("max-memory-mib") - .value_name("SIZE") - .help( - "Specifies the maximum amount of memory in MiB available to the isolate. \ - Only enforced in Nitro for now.", - ) - ) - .arg( - Arg::new("hash") - .short('h') - .long("hashes") - .value_name("FILE") - .help("Specifies the filename of any (local) file that must match a hash. \ - This can be of the form \"--hash name\" or \"--hash enclave_name=path\" if you want to \ - supply the file as a different name in the enclave. Multiple --hash flags or a comma-separated \ - list of files may be provided.") - .action(ArgAction::Append) - ) - .get_matches(); - - info!("Parsed command line."); - - // Read all clients' certificates - let certificates = matches - .get_many::("certificate") - .ok_or(anyhow!( - "No certificates were passed as command line parameters." - ))? - .map(|c| PathBuf::from(c)) - .collect::>(); - - // Read all program paths - let mut program_binaries = Vec::new(); - for path_raw in matches - .get_many::("program-binary") - .ok_or(anyhow!("No program binary filename passed as an argument."))? - { - program_binaries - .append(&mut parse_renamable_paths(path_raw).map_err(|e| anyhow!("{:?}", e))?); - } - - // Use the program paths as the base of hashes - // and append the extra hashes - let mut hashes = program_binaries.clone(); - if let Some(hashes_raw) = matches.get_many::("hash") { - for hash_raw in hashes_raw { - hashes - .append(&mut parse_renamable_paths(hash_raw).map_err(|e| anyhow!("{:?}", e))?); - } - } - - // Read all native module names - let native_modules_names = matches - .get_many::("native-module-name") - .map_or(Vec::new(), |p| p.map(|s| s.to_string()).collect::>()); - - // Read all native module entry points - let native_modules_entry_points = matches - .get_many::("native-module-entry-point") - .map_or(Vec::new(), |p| { - p.map(|s| PathBuf::from(s)).collect::>() - }); - - // Read all native module special files - let native_modules_special_files = matches - .get_many::("native-module-special-file") - .map_or(Vec::new(), |p| { - p.map(|s| PathBuf::from(s)).collect::>() - }); - - // Read all the pipelines - let pipelines = matches - .get_many::("pipeline") - .map_or(Vec::new(), |pipelines| { - pipelines.map(|b| b.to_string()).collect::>() - }); - - // Check all the capabilities. This includes (1) format and (2) length. - let mut capabilities = matches - .get_many::("capability") - .ok_or(anyhow!( - "No capabilities were passed as command line parameters." - ))? - .map(|s| s.split(",").map(|s| String::from(s)).collect::>()) - .collect::>(); - check_capability(&capabilities)?; - - if certificates.len() + program_binaries.len() + pipelines.len() != capabilities.len() { - return Err(anyhow!("The number of capabilities attributes differ from the total number of certificate and program binary attributes.")); - } - - // Split the capabilities into three groups, certificate, program, and pipeline. - let mut binary_capabilities = capabilities.split_off(certificates.len()); - let certificate_capabilities = capabilities; - let pipeline_capabilities = binary_capabilities.split_off(program_binaries.len()); - - let veracruz_server_ip = - SocketAddr::from_str(matches.get_one::("veracruz-server-ip").ok_or( - anyhow!("No Veracruz server IP address was passed as a command line parameter."), - )?)?; - - let proxy_attestation_server_ip = SocketAddr::from_str(matches.get_one::("proxy-attestation-server-ip").ok_or(anyhow!("No Veracruz proxy attestation server IP address was passed as a command line parameter."))?)?; - - let proxy_service_cert = PathBuf::from(matches.get_one::("proxy-attestation-server-cert").ok_or(anyhow!("No Proxy Attestation Server certificate filename was passed as a command line parameter."))?); - - let output_policy_file = PathBuf::from( - matches - .get_one::("output-policy-file") - .map_or(DEFAULT_OUTPUT_FILENAME, |fname| fname), - ); - - let css_file = matches - .get_one::("css-file") - .map(|fname| PathBuf::from(fname)); - let pcr0_file = matches - .get_one::("pcr-file") - .map(|fname| PathBuf::from(fname)); - let sevsnp_hash = matches - .get_one::("sevsnp-hash") - .map(|value| value.to_string()); - if css_file.is_none() && pcr0_file.is_none() && sevsnp_hash.is_none() { - return Err(anyhow!( - "Either the CSS.bin, sevsnp_hash, or the PCR0 file must be provided as a \ - command-line parameter.", - )); - } - - let certificate_expiry = DateTime::parse_from_rfc2822( - matches - .get_one::("certificate-expiry") - .ok_or(anyhow!("No certificate lifetime passed as an argument."))?, - )?; - - let execution_strategy = String::from( - matches - .get_one::("execution-strategy") - .map_or(DEFAULT_EXECUTION_STRATEGY, |strategy| strategy), - ); - check_execution_strategy(&execution_strategy)?; - - let enclave_debug_mode = matches.get_flag("debug"); - let enable_clock = matches.get_flag("enable-clock"); - - let max_memory_mib = - if let Some(max_memory_mib) = matches.get_one::("max-memory-mib") { - max_memory_mib.parse().map_err(|e| { - anyhow!(format!( - "Failed to parse max memory. Error produced: {}.", - e - )) - })? - } else { - info!("No maximum amount of memory passed as an argument. Using a default."); - DEFAULT_MAX_MEMORY_MIB - }; - - info!("Successfully extracted command line arguments."); - - Ok(Self { - certificates, - certificate_capabilities, - binary_capabilities, - pipeline_capabilities, - veracruz_server_ip, - proxy_attestation_server_ip, - proxy_service_cert, - css_file, - pcr0_file, - sevsnp_hash, - output_policy_file, - certificate_expiry, - program_binaries, - native_modules_names, - native_modules_entry_points, - native_modules_special_files, - pipelines, - hashes, - enclave_debug_mode, - execution_strategy, - enable_clock, - max_memory_mib, - }) + Ok(Arguments::parse()) } /// Serializes the Veracruz policy file as a JSON value. - fn serialize_json(&self) -> Result { + fn serialize_json(mut self) -> Result { info!("Serializing JSON policy file."); + let linux_hash = self.compute_linux_enclave_hash()?; + let nitro_hash = self.compute_nitro_enclave_hash()?; + + let mut prog_hash = PROG_HASH.lock().map_err(|e| anyhow!("{e}"))?; + self.hash.append(&mut prog_hash); let policy = Policy::new( - self.serialize_identities()?, - self.serialize_binaries()?, - self.serialize_native_modules()?, - self.serialize_pipeline()?, + self.certificate, + self.program_binary, + self.service, + self.pipeline, format!("{}", self.veracruz_server_ip), - self.serialize_enclave_certificate_timepoint()?, + self.certificate_expiry, POLICY_CIPHERSUITE.to_string(), - self.compute_linux_enclave_hash()?, - self.compute_nitro_enclave_hash()?, + linux_hash, + nitro_hash, self.sevsnp_hash.clone(), format!("{}", self.proxy_attestation_server_ip), - self.serialize_proxy_service_certificate()?, - self.enclave_debug_mode, - self.serialize_execution_strategy()?, - self.serialize_file_hash()?, - self.enable_clock, + self.proxy_attestation_server_cert, + self.execution_strategy, + self.hash, self.max_memory_mib, ) .map_err(|_| anyhow!("Failed to instantiate a (struct) policy"))?; @@ -548,149 +187,6 @@ impl Arguments { Ok(json!(policy)) } - /// Serializes the identities of all principals in the Veracruz computation into - /// a vec of VeracruzIdentity. - fn serialize_identities(&self) -> Result>> { - info!("Serializing identities of computation Principals."); - - assert_eq!(self.certificates.len(), self.certificate_capabilities.len()); - - let mut values = Vec::new(); - - for (id, (cert, capability)) in self - .certificates - .iter() - .zip(&self.certificate_capabilities) - .enumerate() - { - let mut file = File::open(cert) - .map_err(|_| anyhow!("Could not open certificate file {:?}.", cert))?; - let mut content = String::new(); - - file.read_to_string(&mut content) - .expect("Failed to read file."); - - let certificates = content - .replace("\n", "") - .replace( - "-----BEGIN CERTIFICATE-----", - "-----BEGIN CERTIFICATE-----\n", - ) - .replace("-----END CERTIFICATE-----", "\n-----END CERTIFICATE-----"); - let file_permissions = serialize_capability(capability)?; - - values.push(Identity::new(certificates, id as u32, file_permissions)); - } - Ok(values) - } - - /// Serializes the identities of all principals in the Veracruz computation into - /// a vec of VeracruzProgram. - fn serialize_binaries(&self) -> Result> { - info!("Serializing programs."); - - assert_eq!(self.program_binaries.len(), self.binary_capabilities.len()); - - let mut result = Vec::new(); - for (id, ((program_file_name, _), capability)) in self - .program_binaries - .iter() - .zip(&self.binary_capabilities) - .enumerate() - { - let file_permissions = serialize_capability(capability)?; - let program_file_name = enforce_leading_slash(program_file_name).into_owned(); - - result.push(Program::new(program_file_name, id as u32, file_permissions)); - } - Ok(result) - } - - /// Serializes the native modules used in the computation into a vector. - fn serialize_native_modules(&self) -> Result> { - info!("Serializing native modules."); - - assert_eq!( - self.native_modules_names.len(), - self.native_modules_entry_points.len() - ); - assert_eq!( - self.native_modules_entry_points.len(), - self.native_modules_special_files.len() - ); - - let mut result = Vec::new(); - for ((name, entry_point_path), special_file) in self - .native_modules_names - .iter() - .zip(&self.native_modules_entry_points) - .zip(&self.native_modules_special_files) - { - // Add a backslash (VFS requirement) - let special_file = enforce_leading_slash( - special_file - .to_str() - .ok_or(anyhow!("Fail to convert special_file to str."))?, - ) - .into_owned(); - - let nm_type = if entry_point_path == &PathBuf::from("") { - NativeModuleType::Static { - special_file: PathBuf::from(special_file), - } - } else { - NativeModuleType::Dynamic { - special_file: PathBuf::from(special_file), - entry_point: entry_point_path.to_path_buf(), - } - }; - result.push(NativeModule::new(name.to_string(), nm_type)); - } - Ok(result) - } - - /// Serializes the identities of all pipelines. - fn serialize_pipeline(&self) -> Result> { - info!("Serializing pipelines."); - - assert_eq!(self.pipelines.len(), self.pipeline_capabilities.len()); - - let mut result = Vec::new(); - for (id, (preparsed_pipeline, capability)) in self - .pipelines - .iter() - .zip(&self.pipeline_capabilities) - .enumerate() - { - let file_permissions = serialize_capability(capability)?; - - result.push(Pipeline::new( - id.to_string(), - id as u32, - preparsed_pipeline.to_string(), - file_permissions, - )?); - } - Ok(result) - } - - /// Serializes the enclave server certificate expiry timepoint to a JSON value, - /// computing the time when the certificate will expire as a point relative to - /// the current time. - fn serialize_enclave_certificate_timepoint(&self) -> Result { - info!("Serializing enclave certificate expiry timepoint."); - - let timepoint = self.certificate_expiry; - - Ok(Timepoint::new( - timepoint.year() as u32, - timepoint.month() as u8, - timepoint.day() as u8, - timepoint.hour() as u8, - timepoint.minute() as u8, - )?) - } - /// Computes the Linux hash of the Runtime Manager enclave using a SHA256 /// digest of the runtime manager binary's content. fn compute_linux_enclave_hash(&self) -> Result> { @@ -740,71 +236,8 @@ impl Arguments { Ok(Some(content)) } - /// Serializes the proxy attestation service certificate (basically reads the - /// string from the file and returns that - fn serialize_proxy_service_certificate(&self) -> Result { - Ok(read_to_string(self.proxy_service_cert.to_str().ok_or( - anyhow!("Fail to convert proxy_service_cert to str."), - )?)?) - } - - fn serialize_execution_strategy(&self) -> Result { - match self.execution_strategy.as_str() { - "Interpretation" => Ok(ExecutionStrategy::Interpretation), - "JIT" => Ok(ExecutionStrategy::JIT), - _otherwise => Err(anyhow!("Could not parse execution strategy argument.")), - } - } - - fn serialize_file_hash(&self) -> Result> { - info!("Serializing standard streams."); - let mut result = Vec::new(); - for (file_name, file_path) in self.hashes.iter() { - let hash = compute_file_hash(file_path)?; - let file_name = enforce_leading_slash(file_name).into_owned(); - - result.push(FileHash::new(file_name, hash)); - } - Ok(result) - } -} - -/// Checks that the string `strategy` matches either "Interpretation" or "JIT", -/// and if not prints an error message and aborts. -fn check_execution_strategy(strategy: &str) -> Result<()> { - match strategy { - "Interpretation" | "JIT" => Ok(()), - _otherwise => Err(anyhow!("Could not parse execution strategy argument.")), - } } -/// Checks that all strings appearing in all vectors in the `capabilities` argument are -/// valid Veracruz capabilities: of the form "[FILE_NAME]:[Right_number]". -fn check_capability(capabilities: &[Vec]) -> Result<()> { - if !capabilities.iter().all(|v| { - v.iter().all(|s| { - let mut split = s.split(':'); - //skip the filename - split.next(); - let cap_check = match split.next() { - None => false, - Some(cap) => cap.parse::().is_ok(), - }; - //The length must be 2 hence it must be none. - cap_check || split.next().is_none() - }) - }) { - return Err(anyhow!( - "Could not parse the capability command line arguments." - )); - } - Ok(()) -} - -//////////////////////////////////////////////////////////////////////////////// -// JSON serialization. -//////////////////////////////////////////////////////////////////////////////// - /// Executes the hashing program on a file, returning the computed /// SHA256 hash as a string. fn compute_file_hash(argument: &PathBuf) -> Result { @@ -823,78 +256,122 @@ fn compute_file_hash(argument: &PathBuf) -> Result { Ok(pretty_digest(&mut buffer)) } -#[inline] -fn serialize_capability(cap_string: &[String]) -> Result> { - let mut result = Vec::new(); - for c in cap_string.iter() { - result.push(serialize_capability_entry(c.as_str())?); - } - Ok(result) +//////////////////////////////////////////////////////////////////////////////// +// Parser. +//////////////////////////////////////////////////////////////////////////////// + +fn reading_file_parser(input: &str) -> Result { + Ok(read_to_string(input.trim())?) } -fn serialize_capability_entry(cap_string: &str) -> Result { - // common shorthand (r = read, w = write, rw = read + write) - #[allow(non_snake_case)] - let READ_RIGHTS = Rights::PATH_OPEN | Rights::FD_READ | Rights::FD_SEEK | Rights::FD_READDIR; - - #[allow(non_snake_case)] - let WRITE_RIGHTS: Rights = Rights::FD_WRITE - | Rights::PATH_CREATE_FILE - | Rights::PATH_FILESTAT_SET_SIZE - | Rights::FD_SEEK - | Rights::PATH_OPEN - | Rights::PATH_CREATE_DIRECTORY; - - #[allow(non_snake_case)] - let EXECUTE_RIGHTS = Rights::PATH_OPEN | Rights::FD_EXECUTE | Rights::FD_SEEK; - - let mut split = cap_string.split(':'); - let file_name = enforce_leading_slash( - split - .next() - .expect(&format!("Failed to parse {}, empty string", cap_string)) - .trim(), - ) - .into_owned(); - let string_number = split - .next() - .expect(&format!( - "Failed to parse `{}`, contains no `:`", - cap_string - )) - .trim(); - - let re = Regex::new(r"[rwx]+")?; - let rights = { - if re.is_match(string_number) { - let mut rights = Rights::empty(); - if string_number.contains("r") { - rights = rights | READ_RIGHTS; - } - if string_number.contains("w") { - rights = rights | WRITE_RIGHTS; - } - if string_number.contains("x") { - rights = rights | EXECUTE_RIGHTS; +/// Parse the permission "(DIR:PERMISSION)[,(DIR:PERMISSION)]*" +fn parse_permission(input: &str) -> Result> { + input + .split(",") + .fold(Ok(HashMap::new()), |acc, c|{ + let mut acc = acc?; + let (k,v) = parse_permission_entry(c)?; + acc.insert(k,v); + Ok(acc) + }) +} + +fn parse_permission_entry(cap_string: &str) -> Result<(PathBuf, FilePermissions)> { + match cap_string.splitn(2,':').collect::>().as_slice() { + [file_name, permission] => { + // If the the cap contains char more than "rwx", the `all` call returns false. + if !permission.trim().chars().all(|c| c == 'r' || c == 'w' || c == 'x') { + return Err(anyhow!("Failed to parse permission entry")); } - rights - } else { - // parse raw WASI rights - let number = string_number - .parse::() - .expect(&format!("Failed to parse {}, not a u64", string_number)); - // check if this is a valid number - Rights::from_bits(number as u64).expect(&format!( - "Failed to parse {}, not a u64 representing WASI Right", - number - )) + + Ok((PathBuf::from(file_name.trim()), FilePermissions { + read: permission.contains("r"), + write: permission.contains("w"), + execute: permission.contains("x"), + })) + + } + _ => Err(anyhow!("Failed to parse permission entry")), + } +} + +fn participant_parser(input: &str) -> Result> { + static COUNTER: AtomicU32 = AtomicU32::new(0); + match input.splitn(2,"=>").collect::>().as_slice() { + [cert, permission] => { + let certificate = read_to_string(cert.trim())? + .replace("\n", "") + .replace( + "-----BEGIN CERTIFICATE-----", + "-----BEGIN CERTIFICATE-----\n", + ) + .replace( + "-----END CERTIFICATE-----", + "\n-----END CERTIFICATE-----" + ); + let file_permissions = parse_permission(permission.trim())?; + Ok(Identity::new(certificate, COUNTER.fetch_add(1, Ordering::SeqCst), file_permissions)) } - }; + _ => Err(anyhow!("Error in parsing participant")) + } +} + +fn binary_parser(input: &str) -> Result { + static COUNTER: AtomicU32 = AtomicU32::new(0); + match input.splitn(2,"=>").collect::>().as_slice() { + [path, permission] => { + let (path, local) = parse_renamable_path(path.trim())?; + let file_permissions = parse_permission(permission.trim())?; + PROG_HASH.lock().map_err(|e| anyhow!("{e}"))?.push(FileHash::new(path.clone(), compute_file_hash(&local)?)); + Ok(Program::new(path.to_string(), COUNTER.fetch_add(1, Ordering::SeqCst), file_permissions)) + } + _ => Err(anyhow!("Error in parsing binary")) + } +} + +fn pipeline_parser(input: &str) -> Result { + static COUNTER: AtomicU32 = AtomicU32::new(0); + match input.splitn(2,"=>").collect::>().as_slice() { + [pipeline, permission] => { + let file_permissions = parse_permission(permission.trim())?; + let id = COUNTER.fetch_add(1, Ordering::SeqCst); + Pipeline::new( + id.to_string(), + id, + pipeline.to_string(), + file_permissions, + ) + } + _ => Err(anyhow!("Error in parsing binary")) + } +} + +fn service_parser(input: &str) -> Result { + match input.splitn(2,"=>").collect::>().as_slice() { + [source, dir] => { + // TODO distinguish internal and provisional + Ok(Service::new(ServiceSource::Internal(source.trim().to_string()), PathBuf::from(dir.trim()))) + } + _ => Err(anyhow!("Error in parsing service")) + } +} + +fn certificate_expiry_parser(input: &str) -> Result { + let timepoint = DateTime::parse_from_rfc2822(input)?; + Ok(Timepoint::new( + timepoint.year() as u32, + timepoint.month() as u8, + timepoint.day() as u8, + timepoint.hour() as u8, + timepoint.minute() as u8, + )?) +} + +fn file_hash_parser(input: &str) -> Result { + let (path, local) = parse_renamable_path(input)?; + let hash = compute_file_hash(&local)?; + Ok(FileHash::new(path.clone(), hash)) - Ok(FileRights::new( - file_name, - u32::try_from(rights.bits()).expect("capability could not fit into u32"), - )) } //////////////////////////////////////////////////////////////////////////////// diff --git a/crates/io-utils/Cargo.toml b/crates/io-utils/Cargo.toml index 197981cb7..832e5562a 100644 --- a/crates/io-utils/Cargo.toml +++ b/crates/io-utils/Cargo.toml @@ -6,19 +6,15 @@ name = "io-utils" version = "0.3.0" [features] -linux = ["bincode", "byteorder", "base64/std"] -nitro = ["serde_json/std", "base64/std", "nix", "byteorder"] +linux = ["bincode"] +nitro = ["nix"] [dependencies] anyhow = "1" -base64 = { version = "0.13.0", default-features = false, optional = true } +base64 = "0.13.0" bincode = { version = "1.2.1", default-features = false, optional = true } -byteorder = { version = "1.4.3", optional = true } +byteorder = "1.4.3" err-derive = "0.2" log = "0.4.13" nix = { version = "0.26", optional = true } serde = { version = "1.0.185", features = ["derive"] } -serde_json = { version = "1.0", default-features = false, optional = true } -stringreader = "0.1" -transport-protocol = { path = "../transport-protocol" } -uuid = { version = "1.1.2", features = ["serde"] } diff --git a/crates/libveracruz/Cargo.toml b/crates/libveracruz/Cargo.toml deleted file mode 100644 index 51cd87670..000000000 --- a/crates/libveracruz/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "libveracruz" -version = "0.3.0" -description = "Utility library for Veracruz applications" -authors = ["The Veracruz Development Team"] -edition = "2021" - -[dependencies] diff --git a/crates/libveracruz/src/lib.rs b/crates/libveracruz/src/lib.rs deleted file mode 100644 index 7a816d590..000000000 --- a/crates/libveracruz/src/lib.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! -//! ## Authors -//! -//! The Veracruz Development Team. -//! -//! ## Licensing and copyright notice -//! -//! See the `LICENSE.md` file in the Veracruz root directory -//! for information on licensing and copyright. - -use std::fs::File; -use std::os::wasi::io::{FromRawFd, RawFd}; - -mod veracruz_si_import { - #[link(wasm_import_module = "veracruz_si")] - extern "C" { - pub fn fd_create(x: u32) -> u32; - } -} - -mod veracruz_si { - pub fn fd_create(fd: *mut crate::RawFd) -> u32 { - unsafe { crate::veracruz_si_import::fd_create(fd as u32) } - } -} - -/// Return a file descriptor for a newly created temporary file, -/// for which there is no file path. There are no failure modes. -pub fn fd_create() -> std::io::Result { - let mut fd: RawFd = 0; - let ret = veracruz_si::fd_create(&mut fd); - if ret == 0 { - Ok(unsafe { File::from_raw_fd(fd) }) - } else { - // Insert code to convert error code here, - // though fd_create should never fail. - panic!("unexpected") - } -} diff --git a/crates/linux-runtime-manager/Cargo.toml b/crates/linux-runtime-manager/Cargo.toml index acf1576a9..6566d42e4 100644 --- a/crates/linux-runtime-manager/Cargo.toml +++ b/crates/linux-runtime-manager/Cargo.toml @@ -6,8 +6,8 @@ edition = "2018" [dependencies] anyhow = "1" clap = "4" -env_logger = { version = "0.10.0" } -hex = { version = "0.4.2" } +env_logger = "0.10.0" +hex = "0.4.2" io-utils = { path = "../io-utils" } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } log = "0.4.13" diff --git a/crates/linux-veracruz-server/Cargo.toml b/crates/linux-veracruz-server/Cargo.toml index 10bc5b44e..8af1521e3 100644 --- a/crates/linux-veracruz-server/Cargo.toml +++ b/crates/linux-veracruz-server/Cargo.toml @@ -6,15 +6,15 @@ edition = "2018" [dependencies] anyhow = "1" clap = { version = "4", features = ["derive"]} -data-encoding = { version = "2.3.2" } -env_logger = { version = "0.10.0" } +data-encoding = "2.3.2" +env_logger = "0.10.0" io-utils = { path = "../io-utils", features = ["linux"] } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } log = "0.4.13" -nix = { version = "0.26" } +nix = "0.26" policy-utils = { path = "../policy-utils", features = ["std", ] } proxy-attestation-client = { git = "https://github.com/veracruz-project/proxy-attestation-client", tag = "v0.4" } rand = "0.8.3" -tempfile = { version = "3.2.0" } +tempfile = "3.2.0" veracruz-server = { path = "../veracruz-server", features = ["linux"]} veracruz-utils = { path = "../veracruz-utils", features = ["linux"] } diff --git a/crates/nitro-runtime-manager/Cargo.toml b/crates/nitro-runtime-manager/Cargo.toml index 3297fe31e..f9492ee71 100644 --- a/crates/nitro-runtime-manager/Cargo.toml +++ b/crates/nitro-runtime-manager/Cargo.toml @@ -8,7 +8,7 @@ version = "0.3.0" [dependencies] anyhow = "1" log = "0.4.13" -nix = { version = "0.26" } +nix = "0.26" nsm_api = { package = "aws-nitro-enclaves-nsm-api", version = "0.3.0" } raw-fd = { git = "https://github.com/veracruz-project/nitro-enclave", tag = "v0.3" } runtime-manager = { path = "../runtime-manager", features = ["nitro"] } diff --git a/crates/nitro-veracruz-server/Cargo.toml b/crates/nitro-veracruz-server/Cargo.toml index 7d6372c73..6626bbb2a 100644 --- a/crates/nitro-veracruz-server/Cargo.toml +++ b/crates/nitro-veracruz-server/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" anyhow = "1" bincode = { version = "1.2.1", default-features = false } clap = { version = "4", features = ["derive"]} -env_logger = { version = "0.10.0" } +env_logger = "0.10.0" log = "0.4.13" nitro-enclave = { git = "https://github.com/veracruz-project/nitro-enclave", tag = "v0.3" } policy-utils = { path = "../policy-utils", features = ["std"] } diff --git a/crates/platform-services/Cargo.toml b/crates/platform-services/Cargo.toml index 6511da42e..4386d725b 100644 --- a/crates/platform-services/Cargo.toml +++ b/crates/platform-services/Cargo.toml @@ -6,11 +6,10 @@ name = "platform-services" version = "0.3.0" [features] -default = [] -nitro = ["nix", "nsm_api"] -std = ["getrandom", "nix"] +std = ["getrandom"] +nitro = ["nsm_api"] [dependencies] getrandom = { version = "0.2", optional = true } -nix = { version = "0.26", optional = true } +nix = "0.26" nsm_api = { package = "aws-nitro-enclaves-nsm-api", version = "0.3.0", optional = true } diff --git a/crates/platform-services/Xargo.toml b/crates/platform-services/Xargo.toml deleted file mode 100644 index a99ffe189..000000000 --- a/crates/platform-services/Xargo.toml +++ /dev/null @@ -1,9 +0,0 @@ - -[patch.crates-io] -compiler_builtins = { git = "https://github.com/veracruz-project/compiler-builtins.git", branch = "veracruz" } -libc = { git = "https://github.com/veracruz-project/libc.git", branch = "veracruz" } -rustc-std-workspace-alloc = { git = "https://github.com/veracruz-project/rust.git", branch = "veracruz" } -rustc-std-workspace-core = { git = "https://github.com/veracruz-project/rust.git", branch = "veracruz" } -[dependencies.std] -branch = "veracruz" -git = "https://github.com/veracruz-project/rust.git" diff --git a/crates/policy-utils/Cargo.toml b/crates/policy-utils/Cargo.toml index 48ae8bbef..28172178d 100644 --- a/crates/policy-utils/Cargo.toml +++ b/crates/policy-utils/Cargo.toml @@ -11,24 +11,21 @@ nitro = [ "veracruz-utils/nitro", ] std = [ - "hex/std", - "serde/std", - "serde_json/std", "veracruz-utils/std", ] [dependencies] anyhow = "1" err-derive = { version = "0.2", default-features = false } -hex = { version = "0.4.2" } -lalrpop-util = { version = "0.19.12", features = ["lexer"] } +hex = "0.4.2" +lalrpop-util = { version = "0.20.0", features = ["lexer"] } lexical-core = { version = "0.8.2", default-features = false } mbedtls = { path = "../third-party/rust-mbedtls/mbedtls", default-features = false, features = ["std", "aesni", "padlock", "tls13"] } regex = "1" serde = { version = "1.0.185", features = ["derive"] } serde_json = { version = "1.0", default-features = false } veracruz-utils = { path = "../veracruz-utils" } -wasi-types = { path = "../third-party/wasi-types" } +log="*" [build-dependencies] -lalrpop = { version = "0.19.12", features = ["lexer"] } +lalrpop = { version = "0.20.0", features = ["lexer"] } diff --git a/crates/policy-utils/src/parsers.rs b/crates/policy-utils/src/parsers.rs index 2e92bc8de..e656e3352 100644 --- a/crates/policy-utils/src/parsers.rs +++ b/crates/policy-utils/src/parsers.rs @@ -15,12 +15,11 @@ #![allow(dead_code)] -#[cfg(feature = "std")] -use super::{CANONICAL_STDERR_FILE_PATH, CANONICAL_STDIN_FILE_PATH, CANONICAL_STDOUT_FILE_PATH}; use crate::pipeline::Expr; use lalrpop_util::lalrpop_mod; #[cfg(feature = "std")] -use std::{borrow::Cow, path}; +use std::path; +use anyhow::Result; lalrpop_mod!(pipeline); @@ -33,10 +32,10 @@ lalrpop_mod!(pipeline); /// sort of mistakes should still be caught by a later /// "file-not-found" error. #[cfg(feature = "std")] -pub fn parse_renamable_path(s: &str) -> Result<(String, path::PathBuf), &'static str> { +pub fn parse_renamable_path(s: &str) -> Result<(String, path::PathBuf)> { match s.splitn(2, '=').collect::>().as_slice() { - [name, path] => Ok((String::from(*name), path::PathBuf::from(*path))), - [path] => Ok((String::from(*path), path::PathBuf::from(*path))), + [name, path] => Ok((String::from(name.trim()), path::PathBuf::from(path.trim()))), + [path] => Ok((String::from(path.trim()), path::PathBuf::from(path.trim()))), _ => unreachable!(), } } @@ -52,30 +51,12 @@ pub fn parse_renamable_path(s: &str) -> Result<(String, path::PathBuf), &'static /// sort of mistakes should still be caught by a later /// "file-not-found" error. #[cfg(feature = "std")] -pub fn parse_renamable_paths(s: &str) -> Result, &'static str> { +pub fn parse_renamable_paths(s: &str) -> Result> { s.split(',') .map(|s| parse_renamable_path(s.as_ref())) .collect::, _>>() } -/// Insert a slash (/) if the path does not already have one -/// -/// Veracruz currently doesn't have a concept of "current directory", so -/// the "current directory" is always the root. This avoids easy typing -/// mistakes. -#[cfg(feature = "std")] -pub fn enforce_leading_slash(path: &str) -> Cow { - let is_special_file = path == CANONICAL_STDIN_FILE_PATH - || path == CANONICAL_STDOUT_FILE_PATH - || path == CANONICAL_STDERR_FILE_PATH; - - if !path.starts_with('/') && !is_special_file { - Cow::Owned(format!("/{}", path)) - } else { - Cow::Borrowed(path) - } -} - /// Parse a pineline string `pipeline_str` and return the syntax tree. pub fn parse_pipeline(pipeline_str: &str) -> anyhow::Result> { let engine = pipeline::ExprsParser::new(); diff --git a/crates/policy-utils/src/policy.rs b/crates/policy-utils/src/policy.rs index 0a57153d5..d124eb3f0 100644 --- a/crates/policy-utils/src/policy.rs +++ b/crates/policy-utils/src/policy.rs @@ -37,10 +37,7 @@ use super::{ error::PolicyError, expiry::Timepoint, - principal::{ - ExecutionStrategy, FileHash, Identity, NativeModule, Pipeline, Principal, Program, - RightsTable, - }, + principal::{PrincipalPermission, ExecutionStrategy, FileHash, Identity, Service, Pipeline, Principal, Program}, Platform, }; use anyhow::{anyhow, Result}; @@ -52,7 +49,7 @@ use std::{ vec::Vec, }; use veracruz_utils::sha256::sha256; -use wasi_types::Rights; +use log::info; //////////////////////////////////////////////////////////////////////////////// // Veracruz policies, proper. @@ -70,7 +67,7 @@ pub struct Policy { /// The candidate programs that can be loaded in the execution engine. programs: Vec, /// The candidate native modules that can be loaded. - native_modules: Vec, + native_modules: Vec, /// The list of files, e.g. binaries and configurations, that must match given hashes. file_hashes: Vec, /// The list of pipelines. @@ -95,15 +92,8 @@ pub struct Policy { /// The PEM encoded certificate for the proxy service that matches the chosen /// platform constraints for the policy proxy_service_cert: String, - /// The debug configuration flag. This dictates whether the WASM program - /// will be able to print debug configuration messages to `stdout` on the - /// host's machine. - debug: bool, /// The execution strategy that will be used to execute the WASM binary. execution_strategy: ExecutionStrategy, - /// The clock flag. This dictates whether the WASM program will be able to - /// call clock functions to e.g. get a clock's time or resolution. - enable_clock: bool, /// The maximum amount of memory in MiB available to the isolate. Only /// enforced in Nitro for now. max_memory_mib: u32, @@ -120,7 +110,7 @@ impl Policy { pub fn new( identities: Vec>, programs: Vec, - native_modules: Vec, + native_modules: Vec, mut pipelines: Vec, veracruz_server_url: String, enclave_cert_expiry: Timepoint, @@ -130,10 +120,8 @@ impl Policy { runtime_manager_hash_sevsnp: Option, proxy_attestation_server_url: String, proxy_service_cert: String, - debug: bool, execution_strategy: ExecutionStrategy, file_hashes: Vec, - enable_clock: bool, max_memory_mib: u32, ) -> Result { for p in pipelines.iter_mut() { @@ -153,9 +141,7 @@ impl Policy { runtime_manager_hash_nitro, runtime_manager_hash_sevsnp, proxy_attestation_server_url, - debug, execution_strategy, - enable_clock, max_memory_mib, policy_hash: None, file_hashes, @@ -171,6 +157,7 @@ impl Policy { /// Returns `Ok(policy)` iff these well-formedness checks pass. pub fn from_json(json: &str) -> Result { // parse json + info!("from_json:{:?}", json); let mut policy: Self = serde_json::from_str(json)?; for p in policy.pipelines.iter_mut() { @@ -188,24 +175,24 @@ impl Policy { /// Returns the identities associated with this policy. #[inline] - pub fn identities(&self) -> &Vec> { + pub fn identities(&self) -> &[Identity] { &self.identities } /// Returns the native modules associated with this policy. #[inline] - pub fn native_modules(&self) -> &Vec { + pub fn services(&self) -> &[Service] { &self.native_modules } /// Returns the URL of the Veracruz server associated with this policy. #[inline] - pub fn veracruz_server_url(&self) -> &String { + pub fn veracruz_server_url(&self) -> &str { &self.veracruz_server_url } /// Returns the proxy service certificate associated with this policy - pub fn proxy_service_cert(&self) -> &String { + pub fn proxy_service_cert(&self) -> &str { &self.proxy_service_cert } /// Returns the enclave certificate expiry moment associated with this @@ -218,14 +205,14 @@ impl Policy { /// Returns the permissible ciphersuites for TLS links associated with this /// policy. #[inline] - pub fn ciphersuite(&self) -> &String { + pub fn ciphersuite(&self) -> &str { &self.ciphersuite } /// Returns the hash of the trusted Veracruz runtime, associated with this /// policy. #[inline] - pub fn runtime_manager_hash(&self, platform: &Platform) -> Result<&String> { + pub fn runtime_manager_hash(&self, platform: &Platform) -> Result<&str> { let hash = match platform { Platform::Linux => self .runtime_manager_hash_linux @@ -250,28 +237,16 @@ impl Policy { /// Returns the URL of the proxy attestation service, associated with this /// policy. #[inline] - pub fn proxy_attestation_server_url(&self) -> &String { + pub fn proxy_attestation_server_url(&self) -> &str { &self.proxy_attestation_server_url } - /// Returns the debug configuration flag associated with this policy. - #[inline] - pub fn debug(&self) -> &bool { - &self.debug - } - /// Returns the execution strategy associated with this policy. #[inline] pub fn execution_strategy(&self) -> &ExecutionStrategy { &self.execution_strategy } - /// Returns the clock flag associated with this policy. - #[inline] - pub fn enable_clock(&self) -> &bool { - &self.enable_clock - } - /// Returns the maximum amount of memory available to the isolate associated /// with this policy. #[inline] @@ -294,10 +269,10 @@ impl Policy { identity.assert_valid()?; // check IDs of all the participants - if client_ids.contains(identity.id()) { + if client_ids.contains(&identity.id()) { return Err(anyhow!(PolicyError::FormatError)); } - client_ids.push(*identity.id()); + client_ids.push(identity.id()); } // Check the ciphersuite @@ -316,12 +291,10 @@ impl Policy { /// of requesting a shutdown of the computation. At the moment, only the /// principals who can request the result can also request shutdown. pub fn expected_shutdown_list(&self) -> Vec { - self.identities() + self.identities .iter() - .fold(Vec::new(), |mut acc, identity| { - acc.push(*identity.id() as u64); - acc - }) + .map(|identity| identity.id_u64()) + .collect() } /// Returns `Ok(identity)` if a principal with a certificate matching the @@ -329,9 +302,9 @@ impl Policy { /// identities/principals associated with this policy. Otherwise, returns /// an error. pub fn check_client_id(&self, cert: &str) -> Result { - for identity in self.identities().iter() { + for identity in self.identities.iter() { if identity.certificate().as_str() == cert { - return Ok(*identity.id() as u64); + return Ok(identity.id_u64()); } } Err(anyhow!(PolicyError::InvalidClientCertificateError( @@ -339,26 +312,26 @@ impl Policy { ))) } - /// Return the CapabilityTable in this policy. It contains capabilities related to all - /// participants and programs. - pub fn get_rights_table(&self) -> RightsTable { - let mut table = HashMap::new(); - for identity in self.identities() { - let id = Principal::Participant(*identity.id() as u64); - let right_map = identity.file_rights_map(); - table.insert(id, right_map); - } - for program in &self.programs { - let id = Principal::Program(program.program_file_name().to_string()); - let right_map = program.file_rights_map(); - table.insert(id, right_map); - } - for program in &self.pipelines { - let id = Principal::Pipeline(program.name().to_string()); - let right_map = program.file_rights_map(); - table.insert(id, right_map); + pub fn get_permission(&self, principal: &Principal) -> Result { + match principal { + Principal::InternalSuperUser | Principal::NoCap => return Err(anyhow!("SuperUser or NoCap")), + Principal::Participant(id) => { + if let Some(principal) = self.identities.iter().find(|x| *id == x.id_u64()) { + return Ok(principal.file_rights_map()) + } + }, + Principal::Program(path) => { + if let Some(principal) = self.programs.iter().find(|x| path == x.program_file_name()) { + return Ok(principal.file_rights_map()) + } + }, + Principal::Pipeline(name) | Principal::NativeModule(name) => { + if let Some(principal) = self.pipelines.iter().find(|x| name == x.name()) { + return Ok(principal.file_rights_map()) + } + }, } - table + Err(anyhow!("Cannot find {:?}", principal)) } /// Return the file hash table, mapping filenames to their expected hashes. @@ -374,39 +347,10 @@ impl Policy { Ok(table) } - /// Return the program input table, mapping program filenames to their expected input filenames. - pub fn get_input_table(&self) -> Result>> { - let mut table = HashMap::new(); - for program in &self.programs { - let program_file_name = program.program_file_name(); - let file_rights_map = program.file_rights_map(); - table.insert( - program_file_name.to_string(), - Self::get_required_inputs(&file_rights_map), - ); - } - Ok(table) - } - /// Return the pipeline of `pipeline_id` pub fn get_pipeline(&self, pipeline_id: usize) -> Result<&Pipeline> { self.pipelines .get(pipeline_id) .ok_or(anyhow!("Failed to find pipeline {}", pipeline_id)) } - - /// Extract the input filenames from a right_map. If a program has rights call - /// fd_read and path_open, it is considered as an input file. - fn get_required_inputs(right_map: &HashMap) -> Vec { - let mut rst = right_map - .iter() - .fold(Vec::new(), |mut acc, (file_name, right)| { - if right.contains(Rights::FD_READ | Rights::PATH_OPEN) { - acc.push(file_name.into()); - } - acc - }); - rst.sort(); - rst - } } diff --git a/crates/policy-utils/src/principal.rs b/crates/policy-utils/src/principal.rs index 8096efc8f..6422ff609 100644 --- a/crates/policy-utils/src/principal.rs +++ b/crates/policy-utils/src/principal.rs @@ -15,9 +15,10 @@ use super::error::PolicyError; use crate::{parsers::parse_pipeline, pipeline::Expr}; use anyhow::{anyhow, Result}; -use serde::{Deserialize, Serialize}; -use std::{collections::HashMap, fmt::Debug, path::PathBuf, string::String, vec::Vec}; -use wasi_types::Rights; +use serde::{Deserialize, Serialize, Serializer, Deserializer}; +use std::{collections::HashMap, fmt::Debug, path::{Path, PathBuf}, string::String, str::FromStr}; + + //////////////////////////////////////////////////////////////////////////////// // File operation and capabilities. @@ -40,48 +41,102 @@ pub enum Principal { NoCap, } -/// The Right Table, contains the `Right`, i.e. -/// the allowed operations of a Principal on a file -pub type RightsTable = HashMap>; +/// The Permission Table, i.e. the allowed operations, `rwx`, of a Principal on directories. +pub type PrincipalPermission = HashMap; +pub type PermissionTable = HashMap; + +/// Check if the `target_path` is allowed to perform `target_permission` in the `table`. +pub fn check_permission>( + table: &PrincipalPermission, + target_path: T, + target_permission: &FilePermissions, +) -> bool { + table + .iter() + // Find the permission corresponding to the longest prefix. + .fold((0, false), |(max_length, result), (path, permission)|{ + if !target_path.as_ref().starts_with(path){ + // prefix of target_path does not match path + // return the previous result + return (max_length, result); + } + + let size = path.as_os_str().len(); + + if size <= max_length { + // The matched path is shorted than previous one + // return the previous result + return (max_length, result); + } + + // If reaching here, find a longer prefix match + (size, permission.allows(target_permission)) + + }).1 +} /// Defines a file entry in the policy, containing the name and `Right`, the allowed op. -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub struct FileRights { - /// The file name - file_name: String, - /// The associated right, when someone open the file - rights: u32, +#[derive(Clone, Debug, PartialEq)] +pub struct FilePermissions { + pub read: bool, + pub write: bool, + pub execute: bool, } -impl FileRights { +impl FilePermissions { /// Creates a new file permission. #[inline] - pub fn new(file_name: String, rights: u32) -> Self { - Self { file_name, rights } + pub fn new(read: bool, write: bool, execute: bool) -> Self { + Self { read, write, execute } } - /// Returns the file_name. - #[inline] - pub fn file_name(&self) -> &str { - self.file_name.as_str() + /// Check if the current permission allows `request` + pub fn allows(&self, request: &Self) -> bool { + // request -> (logic imply) self + // This means, if `request` needs a true, + // then check the permission in `self`. Otherwise, `request` + // is false and the entire formulae is true. + // + // Noting that A -> B is logically equivalent to + // ~(A /\ ~B) where ~ means negation and /\ means logical and. + !(request.read & !self.read) + & !(request.write & !self.write) + & !(request.execute & !self.execute) } +} - /// Returns the rights. - #[inline] - pub fn rights(&self) -> &u32 { - &self.rights +/// Custom serialize and deserialize to "rwx" +impl Serialize for FilePermissions { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut permission = String::new(); + if self.read { + permission.push('r'); + } + if self.write { + permission.push('w'); + } + if self.execute { + permission.push('x'); + } + + serializer.serialize_str(&permission) } +} - /// Convert a vec of FileRights to a Hashmap from filenames to Rights. - #[inline] - pub fn compute_right_map(file_right_vec: &[FileRights]) -> HashMap { - file_right_vec.iter().fold( - HashMap::new(), - |mut acc, FileRights { file_name, rights }| { - acc.insert(file_name.into(), Rights::from_bits_truncate(*rights as u64)); - acc - }, - ) +impl<'de> Deserialize<'de> for FilePermissions { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s: &str = Deserialize::deserialize(deserializer)?; + Ok(Self { + read: s.contains('r'), + write: s.contains('w'), + execute: s.contains('x'), + }) } } @@ -96,7 +151,7 @@ pub struct Program { /// The program ID id: u32, /// The file permission that specifies the program's ability to read, write and execute files. - file_rights: Vec, + file_rights: PrincipalPermission, } impl Program { @@ -105,7 +160,7 @@ impl Program { pub fn new>( program_file_name: String, id: T, - file_rights: Vec, + file_rights: PrincipalPermission, ) -> Self { Self { program_file_name, @@ -128,89 +183,45 @@ impl Program { /// Return file rights map associated to the program. #[inline] - pub fn file_rights_map(&self) -> HashMap { - FileRights::compute_right_map(&self.file_rights) + pub fn file_rights_map(&self) -> PrincipalPermission { + self.file_rights.clone() } } -/// Defines a native module type. -#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)] -pub enum NativeModuleType { - /// Native module that is part of the Veracruz runtime and invoked as a - /// function call by a WASM program via a write to the native module's - /// special file on the VFS. - /// This type does not define an entry point, it is looked up by name in the - /// static native modules table. - /// Despite its static behaviour, a static native module must be explicitly - /// declared in the policy file to be used in a computation. See - /// `generate-policy` for more details. - Static { special_file: PathBuf }, - /// Native module that is a separate binary built independently from - /// Veracruz and residing on the kernel's filesystem. - /// Defines an entry point, i.e. path to the main binary relative to the - /// native module's root directory. - /// Invoked by a WASM program via a write to the native module's special - /// file on the VFS and executed in a sandbox environment on the kernel's - /// filesystem. The environment's filesystem is copied back to the VFS after - /// execution. - /// Dynamic linking is supported if the shared libraries can be found. - Dynamic { - special_file: PathBuf, - entry_point: PathBuf, - }, - /// Native module that is provisioned to the enclave and executed just like - /// a regular WASM program, i.e. via a result request from a participant. - /// Dynamic linking is supported if the shared libraries can be found. - /// The execution principal corresponding to the native module should have - /// read access to every directory containing the execution artifacts - /// (binary and optional shared libraries). - Provisioned { entry_point: PathBuf }, -} - /// Defines a native module that can be loaded directly (provisioned native /// module) or indirectly (static and dynamic native modules) in the execution /// environment. -#[derive(Clone, PartialEq, Serialize, Deserialize)] -pub struct NativeModule { - /// Native module's name - name: String, - /// Native's module type - r#type: NativeModuleType, - // TODO: add sandbox policy +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Service { + /// The source (executable) of the service + pub source: ServiceSource, + /// The root directory used by this service + pub special_dir: PathBuf, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum ServiceSource { + Internal(String), + Provision(PathBuf), } -impl NativeModule { +impl Service { /// Creates a Veracruz native module. #[inline] - pub fn new(name: String, r#type: NativeModuleType) -> Self { - Self { name, r#type } + pub fn new(source: ServiceSource, special_dir: PathBuf) -> Self { + Self { source, special_dir } } /// Return the name. #[inline] - pub fn name(&self) -> &str { - self.name.as_str() + pub fn source(&self) -> &ServiceSource { + &self.source } - /// Return the type. + /// return the dir where the service should be mounted. #[inline] - pub fn r#type(&self) -> &NativeModuleType { - &self.r#type - } - - /// Return whether the native module is static - #[inline] - pub fn is_static(&self) -> bool { - match self.r#type { - NativeModuleType::Static { .. } => true, - _ => false, - } - } -} - -impl Debug for NativeModule { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "\"{}\" {:?}", self.name(), self.r#type) + pub fn dir(&self) -> &PathBuf { + &self.special_dir } } @@ -233,7 +244,7 @@ pub struct Pipeline { /// The pipeline ID id: u32, /// The file permission that specifies the program's ability to read, write and execute files. - file_rights: Vec, + file_rights: PrincipalPermission, } impl Pipeline { @@ -243,7 +254,7 @@ impl Pipeline { name: String, id: T, preparsed_pipeline: String, - file_rights: Vec, + file_rights: PrincipalPermission, ) -> Result { let parsed_pipeline = Some(parse_pipeline(&preparsed_pipeline)?); Ok(Self { @@ -272,8 +283,8 @@ impl Pipeline { /// Return file rights map associated to the program. #[inline] - pub fn file_rights_map(&self) -> HashMap { - FileRights::compute_right_map(&self.file_rights) + pub fn file_rights_map(&self) -> PrincipalPermission { + self.file_rights.clone() } /// Return the pipeline AST. @@ -299,6 +310,20 @@ pub enum ExecutionStrategy { JIT, } + +impl FromStr for ExecutionStrategy { + type Err = anyhow::Error; + + // Required method + fn from_str(s: &str) -> Result { + match s { + "Interpretation" => Ok(ExecutionStrategy::Interpretation), + "JIT" => Ok(ExecutionStrategy::JIT), + _otherwise => Err(anyhow!("Could not parse execution strategy argument.")), + } + } +} + //////////////////////////////////////////////////////////////////////////////// // Identities. //////////////////////////////////////////////////////////////////////////////// @@ -321,14 +346,14 @@ pub struct Identity { id: u32, /// The file capabilities that specifies this principal's ability to read, /// write and execute files. - file_rights: Vec, + file_rights: PrincipalPermission, } impl Identity { /// Creates a new identity from a certificate, and identifier. Initially, /// we keep the set of roles empty. #[inline] - pub fn new(certificate: U, id: T, file_rights: Vec) -> Self + pub fn new(certificate: U, id: T, file_rights: PrincipalPermission) -> Self where T: Into, { @@ -341,14 +366,8 @@ impl Identity { /// Return file rights map associated to the program. #[inline] - pub fn file_rights(&self) -> &Vec { - &self.file_rights - } - - /// Return file rights map associated to the program. - #[inline] - pub fn file_rights_map(&self) -> HashMap { - FileRights::compute_right_map(&self.file_rights) + pub fn file_rights_map(&self) -> PrincipalPermission { + self.file_rights.clone() } /// Returns the certificate associated with this identity. @@ -359,8 +378,14 @@ impl Identity { /// Returns the ID associated with this identity. #[inline] - pub fn id(&self) -> &u32 { - &self.id + pub fn id(&self) -> u32 { + self.id + } + + /// Returns the ID associated with this identity. + #[inline] + pub fn id_u64(&self) -> u64 { + self.id as u64 } } diff --git a/crates/runtime-manager/Cargo.toml b/crates/runtime-manager/Cargo.toml index 1b0470c20..835bba3dd 100644 --- a/crates/runtime-manager/Cargo.toml +++ b/crates/runtime-manager/Cargo.toml @@ -7,12 +7,9 @@ version = "0.3.0" resolver = "2" [features] -default = [] linux = [ "execution-engine/std", "io-utils/linux", - "nix", - "policy-utils/std", "psa-attestation/linux", "session-manager/std", "veracruz-utils/linux", @@ -21,8 +18,6 @@ nitro = [ "execution-engine/std", "execution-engine/nitro", "io-utils/nitro", - "policy-utils/std", - "nix", "nsm_api", "session-manager/nitro", "veracruz-utils/nitro", @@ -32,17 +27,16 @@ nitro = [ anyhow = "1" bincode = { version = "1.2.1", default-features = false } err-derive = "0.2" -execution-engine = { path = "../execution-engine" } -hex = { version = "0.4.2" } -io-utils = { path = "../io-utils", optional = true } +execution-engine = { path = "../execution-engine", features = ["std"] } +hex = "0.4.2" +io-utils = { path = "../io-utils" } lazy_static = { version = "1.4.0", features = ["spin_no_std"] } log = "0.4.13" -nix = { version = "0.26", optional = true } +nix = "0.26" nsm_api = { package = "aws-nitro-enclaves-nsm-api", version = "0.3.0", optional = true } -policy-utils = { path = "../policy-utils" } +policy-utils = { path = "../policy-utils", features = ["std"] } protobuf = "3.2.0" psa-attestation = { path = "../psa-attestation", optional = true } -serde = { version = "1.0.185", default-features = false, features = ["alloc", "derive"], optional = true } serde_json = "1.0" session-manager = { path = "../session-manager" } transport-protocol = { path = "../transport-protocol" } diff --git a/crates/runtime-manager/src/managers/error.rs b/crates/runtime-manager/src/managers/error.rs index c4d493f1b..1029a34d0 100644 --- a/crates/runtime-manager/src/managers/error.rs +++ b/crates/runtime-manager/src/managers/error.rs @@ -20,8 +20,8 @@ pub enum RuntimeManagerError { #[cfg(feature = "linux")] #[error(display = "RuntimeManager: CommandLineArguments")] CommandLineArguments, - #[error(display = "RuntimeManager: FileSystem Error: {:?}.", _0)] - FileSystemError(#[error(source)] wasi_types::ErrNo), + #[error(display = "RuntimeManager: FileSystem Access Denial Error.")] + FileSystemAccessDenialError, #[error(display = "RuntimeManager: Uninitialized session in function {}.", _0)] UninitializedSessionError(&'static str), #[cfg(feature = "linux")] diff --git a/crates/runtime-manager/src/managers/execution_engine_manager.rs b/crates/runtime-manager/src/managers/execution_engine_manager.rs index 2c6240ed1..f7aee541d 100644 --- a/crates/runtime-manager/src/managers/execution_engine_manager.rs +++ b/crates/runtime-manager/src/managers/execution_engine_manager.rs @@ -20,6 +20,7 @@ use transport_protocol::{ }, TransportProtocolError, }; +use log::info; //////////////////////////////////////////////////////////////////////////////// // Protocol response messages. @@ -143,6 +144,7 @@ fn dispatch_on_request(client_id: u64, request: MESSAGE) -> ProvisioningResult { .as_mut() .ok_or(anyhow!(RuntimeManagerError::UninitializedProtocolState))?; + info!("Runtime dispatch on incoming a request."); match request { MESSAGE::WriteFile(data) => dispatch_on_write(protocol_state, data, client_id), MESSAGE::AppendFile(data) => dispatch_on_append(protocol_state, data, client_id), diff --git a/crates/runtime-manager/src/managers/mod.rs b/crates/runtime-manager/src/managers/mod.rs index 0349b9010..c7310aa59 100644 --- a/crates/runtime-manager/src/managers/mod.rs +++ b/crates/runtime-manager/src/managers/mod.rs @@ -10,24 +10,25 @@ //! information on licensing and copyright. use anyhow::{anyhow, Result}; -use execution_engine::{execute, fs::FileSystem}; +use execution_engine::execute; use lazy_static::lazy_static; use log::info; use policy_utils::{ - pipeline::Expr, policy::Policy, principal::Principal, CANONICAL_STDIN_FILE_PATH, + pipeline::Expr, policy::Policy, principal::{Principal, FilePermissions, check_permission}, }; use std::{ collections::HashMap, - path::PathBuf, + path::{Path, PathBuf}, string::String, sync::{ - atomic::{AtomicBool, AtomicU32, Ordering}, + atomic::AtomicU32, Mutex, }, vec::Vec, + fs::{self, OpenOptions}, + io::Write, }; use veracruz_utils::sha256::sha256; -use wasi_types::{ErrNo, Rights}; pub mod error; pub mod execution_engine_manager; @@ -45,7 +46,6 @@ lazy_static! { static ref SESSIONS: Mutex> = Mutex::new(HashMap::new()); static ref PROTOCOL_STATE: Mutex> = Mutex::new(None); - static ref DEBUG_FLAG: AtomicBool = AtomicBool::new(false); } //////////////////////////////////////////////////////////////////////////////// @@ -72,8 +72,6 @@ pub(crate) struct ProtocolState { /// The list of clients (their IDs) that can request shutdown of the /// Veracruz platform. expected_shutdown_sources: Vec, - /// The ref to the VFS, this is a FS handler with super user capability. - vfs: FileSystem, /// Digest table. Certain files must match the digest before writing to /// the filesystem. digest_table: HashMap>, @@ -86,23 +84,13 @@ impl ProtocolState { pub fn new(global_policy: Policy, global_policy_hash: String) -> Result { let expected_shutdown_sources = global_policy.expected_shutdown_list(); - let mut rights_table = global_policy.get_rights_table(); - - // Grant the super user read access to any file under the root. This is - // used internally to read the program on behalf of the executing party - let mut su_read_rights = HashMap::new(); - su_read_rights.insert(PathBuf::from("/"), Rights::all()); - rights_table.insert(Principal::InternalSuperUser, su_read_rights); - let digest_table = global_policy.get_file_hash_table()?; - let native_modules = global_policy.native_modules(); - let vfs = FileSystem::new(rights_table, native_modules.to_vec())?; + //let native_modules = global_policy.native_modules(); Ok(ProtocolState { global_policy, global_policy_hash, expected_shutdown_sources, - vfs, digest_table, }) } @@ -118,52 +106,74 @@ impl ProtocolState { //////////////////////////////////////////////////////////////////////////// /// Check if a client has capability to write to a file, and then overwrite it with new `data`. - pub(crate) fn write_file( + pub(crate) fn write_file>( &mut self, client_id: &Principal, - file_name: &str, + path: T, data: Vec, ) -> Result<()> { // Check the digest, if necessary - if let Some(digest) = self.digest_table.get(&PathBuf::from(file_name)) { + let path = path.as_ref(); + info!("write_file to path {:?}", path); + if let Some(digest) = self.digest_table.get(&PathBuf::from(path)) { let incoming_digest = sha256(&data); if incoming_digest.len() != digest.len() { - return Err(anyhow!(RuntimeManagerError::FileSystemError(ErrNo::Access))); + return Err(anyhow!(RuntimeManagerError::FileSystemAccessDenialError)); } for (lhs, rhs) in digest.iter().zip(incoming_digest.iter()) { if lhs != rhs { - return Err(anyhow!(RuntimeManagerError::FileSystemError(ErrNo::Access))); + return Err(anyhow!(RuntimeManagerError::FileSystemAccessDenialError)); } } } + + if !self.check_permission(client_id, path, FilePermissions{read: false, write: true, execute: false})? { + return Err(anyhow!(RuntimeManagerError::FileSystemAccessDenialError)) + } - if file_name == CANONICAL_STDIN_FILE_PATH { - self.vfs.spawn(client_id)?.write_stdin(&data)?; - } else { - self.vfs - .spawn(client_id)? - .write_file_by_absolute_path(file_name, data, false)?; + if let Some(parent_path) = path.parent() { + if !parent_path.try_exists()? { + fs::create_dir_all(parent_path)?; + } } + info!("write_file to path {:?} after create dir", path); + fs::write(path, data)?; + Ok(()) } /// Check if a client has capability to write to a file, and then overwrite it with new `data`. - pub(crate) fn append_file( + pub(crate) fn append_file>( &mut self, client_id: &Principal, - file_name: &str, + path: T, data: Vec, ) -> Result<()> { // If a file must match a digest, e.g. a program, // it is not permitted to append the file. - if self.digest_table.contains_key(&PathBuf::from(file_name)) { - return Err(anyhow!(RuntimeManagerError::FileSystemError(ErrNo::Access))); + let path = path.as_ref(); + if self.digest_table.contains_key(&PathBuf::from(path)) { + return Err(anyhow!(RuntimeManagerError::FileSystemAccessDenialError)); } - self.vfs.spawn(client_id)?.write_file_by_absolute_path( - file_name, data, // set the append flag to true - true, - )?; + + if !self.check_permission(client_id, path, FilePermissions{read: false, write: true, execute: false})? { + return Err(anyhow!(RuntimeManagerError::FileSystemAccessDenialError)) + } + + if let Some(parent_path) = path.parent() { + if !parent_path.try_exists()? { + fs::create_dir_all(parent_path)?; + } + } + + let mut file = OpenOptions::new() + .create(true) + .append(true) + .open(path)?; + + file.write_all(&data)?; + Ok(()) } @@ -171,14 +181,14 @@ impl ProtocolState { pub(crate) fn read_file( &self, client_id: &Principal, - file_name: &str, + path: &str, ) -> Result>> { - let mut vfs = self.vfs.spawn(client_id)?; - let rst = match file_name { - "stderr" => vfs.read_stderr()?, - "stdout" => vfs.read_stdout()?, - _otherwise => vfs.read_file_by_absolute_path(file_name)?, - }; + + if !self.check_permission(client_id, path, FilePermissions{read: true, write: false, execute: false})? { + return Err(anyhow!(RuntimeManagerError::FileSystemAccessDenialError)) + } + + let rst = fs::read(path)?; if rst.len() == 0 { return Ok(None); } @@ -218,21 +228,25 @@ impl ProtocolState { caller_principal, execution_principal ); let execution_strategy = self.global_policy.execution_strategy(); - let options = execution_engine::Options { - enable_clock: *self.global_policy.enable_clock(), + let env = execution_engine::Environment { environment_variables, ..Default::default() }; - let return_code = execute( + let caller_permission = self.global_policy.get_permission(caller_principal)?; + let execution_permission = self.global_policy.get_permission(execution_principal)?; + let services = self.global_policy.services(); + + execute( &execution_strategy, - self.vfs.spawn(caller_principal)?, - self.vfs.spawn(execution_principal)?, + &caller_permission, + &execution_permission, + services, pipeline, - &options, + &env, )?; - let response = Self::response_error_code_returned(return_code); + let response = Self::response_error_code_returned(0); Ok(Some(response)) } @@ -245,39 +259,20 @@ impl ProtocolState { ) .unwrap_or_else(|err| panic!("{:?}", err)) } -} - -//////////////////////////////////////////////////////////////////////////////// -// Debug printing outside of the enclave. -//////////////////////////////////////////////////////////////////////////////// - -/// Prints a debug message, `message`, via our debug OCALL print mechanism, if -/// the debug configuration flat is set for the enclave. Has no effect, -/// otherwise. -pub fn debug_message(message: String) { - if DEBUG_FLAG.load(Ordering::SeqCst) { - print_message(message, 0); - } -} -/// Prints an error message, `message`, with a fixed error code, `error_code`, -/// via our debug OCALL print mechanism, if the debug configuration flat is set -/// for the enclave. Has no effect, otherwise. -pub fn error_message(message: String, error_code: u32) { - print_message(message, error_code); -} - -/// Base function for printing messages outside of the enclave. Note that this -/// should only print something to *stdout* on the host's machine if the debug -/// configuration flag is set in the Veracruz global policy. -fn print_message(#[allow(unused)] message: String, #[allow(unused)] code: u32) { - #[cfg(feature = "linux")] - if code == 0 { - eprintln!("Enclave debug message \"{}\"", message); - } else { - eprintln!( - "Enclave returns error code {} and message \"{}\"", - code, message - ); + /// Manually check permission on clients + pub(crate) fn check_permission>( + &self, + client_id: &Principal, + target_path: T, + target_permission: FilePermissions, + ) -> Result + { + let result = match client_id { + Principal::InternalSuperUser => true, + Principal::NoCap => false, + other => check_permission(&self.global_policy.get_permission(other)?, target_path, &target_permission), + }; + Ok(result) } } diff --git a/crates/runtime-manager/src/managers/session_manager.rs b/crates/runtime-manager/src/managers/session_manager.rs index 4cb2f0f56..9719d716c 100644 --- a/crates/runtime-manager/src/managers/session_manager.rs +++ b/crates/runtime-manager/src/managers/session_manager.rs @@ -16,6 +16,7 @@ use session_manager::SessionContext; use std::{sync::atomic::Ordering, vec::Vec}; use veracruz_utils::csr; use veracruz_utils::sha256::sha256; +use log::info; pub fn init_session_manager() -> Result<()> { let new_session_manager = SessionContext::new()?; @@ -28,13 +29,10 @@ pub fn init_session_manager() -> Result<()> { } pub fn load_policy(policy_json: &str) -> Result<()> { + info!("Load policy: {:?}", policy_json); let policy_hash = sha256(&policy_json.as_bytes()); let policy = Policy::from_json(policy_json)?; - if *policy.debug() { - super::DEBUG_FLAG.store(true, Ordering::SeqCst); - } - let state = ProtocolState::new(policy.clone(), hex::encode(policy_hash))?; *super::PROTOCOL_STATE .lock() diff --git a/crates/session-manager/Cargo.toml b/crates/session-manager/Cargo.toml index 36cdbd092..de9e2e0b1 100644 --- a/crates/session-manager/Cargo.toml +++ b/crates/session-manager/Cargo.toml @@ -8,11 +8,9 @@ version = "0.3.0" [features] nitro = [ "mbedtls/monitor_getrandom", - "policy-utils/std", "veracruz-utils/nitro", ] std = [ - "policy-utils/std", "veracruz-utils/std", ] @@ -21,5 +19,5 @@ anyhow = "1" err-derive = "0.2" mbedtls = { path = "../third-party/rust-mbedtls/mbedtls", default-features = false, features = ["std", "aesni", "padlock", "tls13"] } platform-services = { path = "../platform-services" } -policy-utils = { path = "../policy-utils" } +policy-utils = { path = "../policy-utils", features = ["std"] } veracruz-utils = { path = "../veracruz-utils" } diff --git a/crates/session-manager/src/session_context.rs b/crates/session-manager/src/session_context.rs index 344537e8f..e9a65bd08 100644 --- a/crates/session-manager/src/session_context.rs +++ b/crates/session-manager/src/session_context.rs @@ -113,8 +113,8 @@ impl SessionContext { let cert = convert_cert_buffer(identity.certificate())?; let principal = Principal::new( cert.clone(), - *identity.id(), - identity.file_rights().to_vec(), + identity.id(), + identity.file_rights_map(), ); root_certs.append(cert); @@ -124,7 +124,7 @@ impl SessionContext { // create the configuration let policy_ciphersuite = veracruz_utils::lookup_ciphersuite(&policy.ciphersuite()).ok_or(anyhow!( - SessionManagerError::TLSInvalidCiphersuiteError(policy.ciphersuite().clone()) + SessionManagerError::TLSInvalidCiphersuiteError(policy.ciphersuite().to_string()) ))?; self.cipher_suites = vec![policy_ciphersuite, 0]; diff --git a/crates/tests/tests/common/event.rs b/crates/tests/tests/common/event.rs index 2195d4c89..1e592cbee 100644 --- a/crates/tests/tests/common/event.rs +++ b/crates/tests/tests/common/event.rs @@ -79,7 +79,7 @@ impl TestEvent { result_path: Q, ) -> Vec { // Load the remote input path, otherwise use default `/input/` - let remote_dir_path = env::var("REMOTE_DATA_DIR").unwrap_or("/input/".to_string()); + let remote_dir_path = env::var("REMOTE_DATA_DIR").unwrap_or("./input/".to_string()); // Construct the TestEvent gradually and append to this vec. let mut rst = Vec::new(); diff --git a/crates/tests/tests/common/util.rs b/crates/tests/tests/common/util.rs index cba93b16c..d7f2ad662 100644 --- a/crates/tests/tests/common/util.rs +++ b/crates/tests/tests/common/util.rs @@ -40,14 +40,14 @@ pub fn data_dir>(filename: T) -> PathBuf { /// Add path prefix, `$REMOTE_PROGRAM_DIR` or the default `/program/`, to the program `filename`. pub fn runtime_program_dir>(filename: T) -> String { - let mut path_prefix = env::var("REMOTE_PROGRAM_DIR").unwrap_or("/program/".to_string()); + let mut path_prefix = env::var("REMOTE_PROGRAM_DIR").unwrap_or("./program/".to_string()); path_prefix.push_str(filename.as_ref()); path_prefix } /// Add path prefix, `$REMOTE_DATA_DIR` or the default `/input/`, to the program `filename`. pub fn runtime_data_dir>(filename: T) -> String { - let mut path_prefix = env::var("REMOTE_DATA_DIR").unwrap_or("/input/".to_string()); + let mut path_prefix = env::var("REMOTE_DATA_DIR").unwrap_or("./input/".to_string()); path_prefix.push_str(filename.as_ref()); path_prefix } diff --git a/crates/tests/tests/integration_test.rs b/crates/tests/tests/integration_test.rs index 18fae79a6..e64d5d5a6 100644 --- a/crates/tests/tests/integration_test.rs +++ b/crates/tests/tests/integration_test.rs @@ -70,7 +70,7 @@ fn veracruz_phase1_get_random_one_client() { vec![ (0, TestEvent::write_program(RANDOM_SOURCE_WASM)), (0, TestEvent::execute(RANDOM_SOURCE_WASM)), - (0, TestEvent::read_result("/output/random.dat")), + (0, TestEvent::read_result("./output/random.dat")), (0, TestEvent::ShutDown), ], ) @@ -90,7 +90,7 @@ fn veracruz_phase1_linear_regression_two_clients() { (0, TestEvent::write_program(LINEAR_REGRESSION_WASM)), (1, TestEvent::write_data(LINEAR_REGRESSION_DATA)), (0, TestEvent::execute(LINEAR_REGRESSION_WASM)), - (1, TestEvent::read_result("/output/linear-regression.dat")), + (1, TestEvent::read_result("./output/linear-regression.dat")), (0, TestEvent::ShutDown), ], ) @@ -111,8 +111,8 @@ fn veracruz_phase2_linear_regression_three_clients() { (0, TestEvent::write_program(LINEAR_REGRESSION_WASM)), (1, TestEvent::write_data(LINEAR_REGRESSION_DATA)), (0, TestEvent::execute(LINEAR_REGRESSION_WASM)), - (1, TestEvent::read_result("/output/linear-regression.dat")), - (2, TestEvent::read_result("/output/linear-regression.dat")), + (1, TestEvent::read_result("./output/linear-regression.dat")), + (2, TestEvent::read_result("./output/linear-regression.dat")), (0, TestEvent::ShutDown), ], ) @@ -146,7 +146,7 @@ fn veracruz_phase2_intersection_set_sum_three_clients() { ), ( 2, - TestEvent::read_result("/output/intersection-set-sum.dat"), + TestEvent::read_result("./output/intersection-set-sum.dat"), ), (0, TestEvent::ShutDown), ], @@ -172,7 +172,7 @@ fn veracruz_phase2_string_edit_distance_three_clients() { (0, TestEvent::execute(STRING_EDIT_DISTANCE_WASM)), ( 2, - TestEvent::read_result("/output/string-edit-distance.dat"), + TestEvent::read_result("./output/string-edit-distance.dat"), ), (0, TestEvent::ShutDown), ], @@ -199,7 +199,7 @@ fn veracruz_phase3_string_edit_distance_four_clients() { (0, TestEvent::execute(STRING_EDIT_DISTANCE_WASM)), ( 3, - TestEvent::read_result("/output/string-edit-distance.dat"), + TestEvent::read_result("./output/string-edit-distance.dat"), ), (0, TestEvent::ShutDown), ], @@ -216,7 +216,7 @@ fn veracruz_phase4_linear_regression_two_clients_parallel() { let policy = Policy::from_json(&policy_json).unwrap(); let _children = proxy_attestation_setup( - policy.proxy_attestation_server_url().clone(), + policy.proxy_attestation_server_url().to_string(), &env::var("VERACRUZ_DATA_DIR").unwrap_or("../test-collateral".to_string()), ); @@ -234,7 +234,7 @@ fn veracruz_phase4_linear_regression_two_clients_parallel() { info!("### program provider read binary."); let program_data = read_local_file(prog_path).unwrap(); info!("### program provider send binary."); - client.write_file("/program/linear-regression.wasm", &program_data)?; + client.write_file("./program/linear-regression.wasm", &program_data)?; Result::<()>::Ok(()) }); @@ -252,7 +252,7 @@ fn veracruz_phase4_linear_regression_two_clients_parallel() { info!("### data provider read input."); let data = read_local_file(&data_filename).unwrap(); info!("### data provider send input."); - client.write_file("/input/linear-regression.dat", &data)?; + client.write_file("./input/linear-regression.dat", &data)?; Result::<()>::Ok(()) }); @@ -268,8 +268,8 @@ fn veracruz_phase4_linear_regression_two_clients_parallel() { ) .unwrap(); - client.request_compute("/program/linear-regression.wasm")?; - client.read_file("/output/linear-regression.dat")?; + client.request_compute("./program/linear-regression.wasm")?; + client.read_file("./output/linear-regression.dat")?; info!("### data provider request shutdown."); client.request_shutdown()?; Ok(()) @@ -327,7 +327,7 @@ impl TestExecutor { // start the proxy attestation server let proxy_children = proxy_attestation_setup( - policy.proxy_attestation_server_url().clone(), + policy.proxy_attestation_server_url().to_string(), &env::var("VERACRUZ_DATA_DIR").unwrap_or("../test-collateral".to_string()), ); diff --git a/crates/tests/tests/server_test.rs b/crates/tests/tests/server_test.rs index 49d9a5b49..26112fcfc 100644 --- a/crates/tests/tests/server_test.rs +++ b/crates/tests/tests/server_test.rs @@ -48,8 +48,6 @@ use veracruz_utils::VERACRUZ_RUNTIME_HASH_EXTENSION_ID; // Policy files const POLICY: &'static str = "single_client.json"; -const POLICY_POSTCARD_NATIVE: &'static str = "single_client_postcard_native.json"; -const POLICY_AESCTR_NATIVE: &'static str = "single_client_aesctr_native.json"; const CLIENT_CERT: &'static str = "client_cert.pem"; const CLIENT_KEY: &'static str = "client_key.pem"; const UNAUTHORIZED_CERT: &'static str = "data_client_cert.pem"; @@ -64,7 +62,6 @@ const PERSON_SET_INTERSECTION_WASM: &'static str = "private-set-intersection.was const LOGISTICS_REGRESSION_WASM: &'static str = "idash2017-logistic-regression.wasm"; const MACD_WASM: &'static str = "moving-average-convergence-divergence.wasm"; const INTERSECTION_SET_SUM_WASM: &'static str = "private-set-intersection-sum.wasm"; -const FD_CREATE_RUST_WASM: &'static str = "fd-create.wasm"; const NUMBER_STREM_WASM: &'static str = "number-stream-accumulation.wasm"; const POSTCARD_NATIVE_WASM: &'static str = "postcard-native.wasm"; const AESCTR_NATIVE_WASM: &'static str = "aesctr-native.wasm"; @@ -96,7 +93,7 @@ fn basic_init_destroy_enclave() { timeout(Duration::from_secs(TIME_OUT_SECS), || { let (policy, policy_json, _) = read_policy(policy_dir(POLICY)).unwrap(); let _children = proxy_attestation_setup( - policy.proxy_attestation_server_url().clone(), + policy.proxy_attestation_server_url().to_string(), &env::var("VERACRUZ_DATA_DIR").unwrap_or("../test-collateral".to_string()), ); VeracruzServerEnclave::new(&policy_json).unwrap(); @@ -110,7 +107,7 @@ fn basic_new_session() { let (policy, policy_json, _) = read_policy(policy_dir(POLICY)).unwrap(); // start the proxy attestation server let _children = proxy_attestation_setup( - policy.proxy_attestation_server_url().clone(), + policy.proxy_attestation_server_url().to_string(), &env::var("VERACRUZ_DATA_DIR").unwrap_or("../test-collateral".to_string()), ); init_veracruz_server_and_tls_session(policy_json).unwrap(); @@ -125,8 +122,8 @@ fn basic_read_write_and_traverse() { TestEvent::write_program(READ_FILE_WASM), TestEvent::write_data(STRING_1_DATA), TestEvent::execute(READ_FILE_WASM), - TestEvent::read_result("/output/test/test.txt"), - TestEvent::read_result("/output/hello-world-1.dat"), + TestEvent::read_result("./output/test/test.txt"), + TestEvent::read_result("./output/hello-world-1.dat"), TestEvent::ShutDown, ]; @@ -141,21 +138,7 @@ fn basic_random_source() { TestEvent::CheckHash, TestEvent::write_program(RANDOM_SOURCE_WASM), TestEvent::execute(RANDOM_SOURCE_WASM), - TestEvent::read_result("/output/random.dat"), - TestEvent::ShutDown, - ]; - - TestExecutor::test_template(POLICY, CLIENT_CERT, CLIENT_KEY, events, TIME_OUT_SECS, true) - .unwrap(); -} - -#[test] -/// Custom external function `fd_create` -fn fd_create() { - let events = vec![ - TestEvent::write_program(FD_CREATE_RUST_WASM), - TestEvent::execute(FD_CREATE_RUST_WASM), - TestEvent::read_result("/output/pass"), + TestEvent::read_result("./output/random.dat"), TestEvent::ShutDown, ]; @@ -168,7 +151,7 @@ fn fd_create() { fn basic_execute_non_existent() { let events = vec![ TestEvent::execute(RANDOM_SOURCE_WASM), - TestEvent::read_result("/output/random.dat"), + TestEvent::read_result("./output/random.dat"), TestEvent::ShutDown, ]; @@ -187,7 +170,7 @@ fn basic_execute_non_existent() { /// A client attempts to read a non-existent file fn basic_client_read_non_existent() { let events = vec![ - TestEvent::ReadFile(String::from("/output/random.dat")), + TestEvent::ReadFile(String::from("./output/random.dat")), TestEvent::ShutDown, ]; @@ -288,17 +271,17 @@ fn basic_unauthorized_certificate_key_pair() { #[test] /// Test AES native module. -fn aesctr_native_module() { +fn basic_aesctr_native_module() { let events = vec![ TestEvent::CheckHash, TestEvent::write_program(AESCTR_NATIVE_WASM), TestEvent::execute(AESCTR_NATIVE_WASM), - TestEvent::read_result("/output/aesctr_native_pass.txt"), + TestEvent::read_result("./output/aesctr_native_pass.txt"), TestEvent::ShutDown, ]; TestExecutor::test_template( - POLICY_AESCTR_NATIVE, + POLICY, CLIENT_CERT, CLIENT_KEY, events, @@ -316,12 +299,12 @@ fn basic_postcard_native_module() { TestEvent::write_program(POSTCARD_NATIVE_WASM), TestEvent::write_data(POSTCARD_DATA), TestEvent::execute(POSTCARD_NATIVE_WASM), - TestEvent::read_result("/output/postcard_native.txt"), + TestEvent::read_result("./output/postcard_native.txt"), TestEvent::ShutDown, ]; TestExecutor::test_template( - POLICY_POSTCARD_NATIVE, + POLICY, CLIENT_CERT, CLIENT_KEY, events, @@ -343,7 +326,7 @@ fn basic_number_accumulation_batch_process() { events.append(&mut TestEvent::batch_process_events( data_dir(F64_STREAM_PATH), NUMBER_STREM_WASM, - "/output/accumulation.dat", + "./output/accumulation.dat", )); events.push(TestEvent::ShutDown); @@ -360,7 +343,7 @@ fn basic_pipeline() { TestEvent::write_program(RANDOM_U32_LIST_WASM), TestEvent::write_program(SORT_NUBMER_WASM), TestEvent::pipeline("0"), - TestEvent::read_result("/output/sorted_numbers.txt"), + TestEvent::read_result("./output/sorted_numbers.txt"), TestEvent::ShutDown, ]; TestExecutor::test_template(POLICY, CLIENT_CERT, CLIENT_KEY, events, TIME_OUT_SECS, true) @@ -379,7 +362,7 @@ fn integration_linear_regression() { TestEvent::write_program(LINEAR_REGRESSION_WASM), TestEvent::write_data(LINEAR_REGRESSION_DATA), TestEvent::execute(LINEAR_REGRESSION_WASM), - TestEvent::read_result("/output/linear-regression.dat"), + TestEvent::read_result("./output/linear-regression.dat"), TestEvent::ShutDown, ]; @@ -405,7 +388,7 @@ fn integration_intersection_sum() { TestEvent::write_data(INTERSECTION_SET_SUM_CUSTOMER_DATA), TestEvent::write_data(INTERSECTION_SET_SUM_ADVERTISEMENT_DATA), TestEvent::execute(CUSTOMER_ADS_INTERSECTION_SET_SUM_WASM), - TestEvent::read_result("/output/intersection-set-sum.dat"), + TestEvent::read_result("./output/intersection-set-sum.dat"), TestEvent::ShutDown, ]; @@ -423,7 +406,7 @@ fn integration_string_edit_distance() { TestEvent::write_data(STRING_1_DATA), TestEvent::write_data(STRING_2_DATA), TestEvent::execute(STRING_EDIT_DISTANCE_WASM), - TestEvent::read_result("/output/string-edit-distance.dat"), + TestEvent::read_result("./output/string-edit-distance.dat"), TestEvent::ShutDown, ]; @@ -443,7 +426,7 @@ fn integration_private_set_intersection() { TestEvent::write_data(PERSON_SET_1_DATA), TestEvent::write_data(PERSON_SET_2_DATA), TestEvent::execute(PERSON_SET_INTERSECTION_WASM), - TestEvent::read_result("/output/private-set.dat"), + TestEvent::read_result("./output/private-set.dat"), TestEvent::ShutDown, ]; @@ -453,12 +436,12 @@ fn integration_private_set_intersection() { #[test] /// Attempt to fetch result without enough stream data. -fn test_phase4_number_stream_accumulation_one_data_one_stream_with_attestation() { +fn integration_number_stream_accumulation_one_data_one_stream_with_attestation() { let events = vec![ TestEvent::CheckHash, TestEvent::write_program(NUMBER_STREM_WASM), TestEvent::write_data(SINGLE_F64_DATA), - TestEvent::read_result("/output/accumulation.dat"), + TestEvent::read_result("./output/accumulation.dat"), TestEvent::ShutDown, ]; @@ -481,7 +464,7 @@ fn integration_postcard_json() { TestEvent::write_program(POSTCARD_WASM), TestEvent::write_data(POSTCARD_DATA), TestEvent::execute(POSTCARD_WASM), - TestEvent::read_result("/output/postcard_wasm.txt"), + TestEvent::read_result("./output/postcard_wasm.txt"), TestEvent::ShutDown, ]; @@ -497,14 +480,14 @@ fn performance_idash2017() { let mut events = vec![TestEvent::write_program(LOGISTICS_REGRESSION_WASM)]; events.append(&mut TestEvent::write_all( data_dir(LOGISTICS_REGRESSION_DATA_PATH), - "/input/idash2017/", + "./input/idash2017/", )); events.append(&mut vec![ TestEvent::CheckHash, TestEvent::execute(LOGISTICS_REGRESSION_WASM), // only read two outputs - TestEvent::read_result("/output/idash2017/generate-data-0.dat"), - TestEvent::read_result("/output/idash2017/generate-data-1.dat"), + TestEvent::read_result("./output/idash2017/generate-data-0.dat"), + TestEvent::read_result("./output/idash2017/generate-data-1.dat"), TestEvent::ShutDown, ]); @@ -520,13 +503,13 @@ fn performance_macd() { let mut events = vec![TestEvent::write_program(MACD_WASM)]; events.append(&mut TestEvent::write_all( data_dir(MACD_DATA_PATH), - "/input/macd/", + "./input/macd/", )); events.append(&mut vec![ TestEvent::CheckHash, TestEvent::execute(MACD_WASM), // only read two outputs - TestEvent::read_result("/output/macd/generate-1000.dat"), + TestEvent::read_result("./output/macd/generate-1000.dat"), TestEvent::ShutDown, ]); @@ -541,13 +524,13 @@ fn performance_set_intersection_sum() { let mut events = vec![TestEvent::write_program(INTERSECTION_SET_SUM_WASM)]; events.append(&mut TestEvent::write_all( data_dir(PRIVATE_SET_INTER_SUM_DATA_PATH), - "/input/private-set-inter-sum/", + "./input/private-set-inter-sum/", )); events.append(&mut vec![ TestEvent::CheckHash, TestEvent::execute(INTERSECTION_SET_SUM_WASM), // only read two outputs - TestEvent::read_result("/output/private-set-inter-sum/data-2000-0"), + TestEvent::read_result("./output/private-set-inter-sum/data-2000-0"), TestEvent::ShutDown, ]); @@ -665,7 +648,7 @@ impl TestExecutor { if expect_success { panic!("There was an unexpected failure"); } else { - panic!("A failure was expected"); + info!("A failure was expected"); } } Ok(()) @@ -689,7 +672,7 @@ impl TestExecutor { // start the proxy attestation server let _proxy_children = proxy_attestation_setup( - policy.proxy_attestation_server_url().clone(), + policy.proxy_attestation_server_url().to_string(), &env::var("VERACRUZ_DATA_DIR").unwrap_or("../test-collateral".to_string()), ); diff --git a/crates/veracruz-client/Cargo.toml b/crates/veracruz-client/Cargo.toml index 99ac276ab..3b5ecbf3b 100644 --- a/crates/veracruz-client/Cargo.toml +++ b/crates/veracruz-client/Cargo.toml @@ -8,12 +8,8 @@ version = "0.3.0" [[bin]] name = "veracruz-client" path = "src/cli.rs" -required-features = ["cli"] [features] -# a feature to enable CLI-only dependencies -# https://stackoverflow.com/questions/35711044/how-can-i-specify-binary-only-dependencies -cli = ["clap", "env_logger"] linux = [] nitro = [ "mbedtls/monitor_getrandom", @@ -22,15 +18,14 @@ nitro = [ [dependencies] anyhow = "1" bincode = { version = "1.2.1", default-features = false } -clap = { version = "4", features = ["derive"], optional = true } -env_logger = { version = "0.10.0", optional = true } +clap = { version = "4", features = ["derive"] } +env_logger = "0.10.0" err-derive = "0.2" hex = "0.4.2" log = "0.4.13" mbedtls = { path = "../third-party/rust-mbedtls/mbedtls", default-features = false, features = ["std", "aesni", "padlock", "tls13"] } policy-utils = { path = "../policy-utils", features = ["std"] } rand = "0.8.3" -# The cargo patch mechanism does NOT work when we add function into a macro_rules! serde_json = "1.0" transport-protocol = { path = "../transport-protocol" } veracruz-utils = { path = "../veracruz-utils", features = ["std"] } diff --git a/crates/veracruz-client/src/cli.rs b/crates/veracruz-client/src/cli.rs index 14ac7da50..376d993a1 100644 --- a/crates/veracruz-client/src/cli.rs +++ b/crates/veracruz-client/src/cli.rs @@ -157,8 +157,8 @@ fn main() { }; qprintln!( opt, - "Loaded policy {} {}", - opt.policy_path.to_string_lossy(), + "Loaded policy {:?} {}", + opt.policy_path, policy.policy_hash().unwrap_or("???") ); @@ -183,8 +183,7 @@ fn main() { for (program_name, program_path) in opt.program.iter().flatten() { qprintln!( opt, - "Submitting /{} from {}", - program_name, + "Submitting {program_name} from {}", match program_path.to_string_lossy().as_ref() { "-" => "", path => path, @@ -224,7 +223,7 @@ fn main() { for (data_name, data_path) in opt.data.iter().flatten() { qprintln!( opt, - "Submitting /{} from {}", + "Submitting {} from {}", data_name, match data_path.to_string_lossy().as_ref() { "-" => "", @@ -263,7 +262,7 @@ fn main() { // request compute(s)? for compute_name in opt.compute { - qprintln!(opt, "Requesting compute of /{}", compute_name); + qprintln!(opt, "Requesting compute of {}", compute_name); did_something = true; match veracruz_client.request_compute(&compute_name) { @@ -279,8 +278,7 @@ fn main() { for (output_name, output_path) in opt.output.iter().flatten() { qprintln!( opt, - "Reading /{} into {}", - output_name, + "Reading {output_name} into {}", match output_path.to_string_lossy().as_ref() { "-" => "", path => path, diff --git a/crates/veracruz-client/src/veracruz_client.rs b/crates/veracruz-client/src/veracruz_client.rs index ded240f31..14498a2b8 100644 --- a/crates/veracruz-client/src/veracruz_client.rs +++ b/crates/veracruz-client/src/veracruz_client.rs @@ -13,7 +13,7 @@ use crate::error::VeracruzClientError; use anyhow::{anyhow, Result}; use log::{error, info}; use mbedtls::{alloc::List, pk::Pk, ssl::Context, x509::Certificate}; -use policy_utils::{parsers::enforce_leading_slash, policy::Policy, Platform}; +use policy_utils::{policy::Policy, Platform}; use std::{ io::{Read, Write}, net::TcpStream, @@ -149,7 +149,7 @@ impl VeracruzClient { Self::check_certificate_validity(&client_cert_filename, &mut client_priv_key)?; let proxy_service_cert = { - let mut certs_pem = policy.proxy_service_cert().clone(); + let mut certs_pem = policy.proxy_service_cert().to_string(); certs_pem.push('\0'); let certs = Certificate::from_pem_multiple(certs_pem.as_bytes())?; certs @@ -159,7 +159,7 @@ impl VeracruzClient { let mut config = Config::new(Endpoint::Client, Transport::Stream, Preset::Default); config.set_min_version(Version::Tls13)?; config.set_max_version(Version::Tls13)?; - let policy_ciphersuite = veracruz_utils::lookup_ciphersuite(policy.ciphersuite().as_str()) + let policy_ciphersuite = veracruz_utils::lookup_ciphersuite(policy.ciphersuite()) .ok_or(anyhow!(VeracruzClientError::UnexpectedCiphersuite))?; let cipher_suites: Vec = vec![policy_ciphersuite.into(), 0]; config.set_ciphersuites(Arc::new(cipher_suites)); @@ -187,11 +187,9 @@ impl VeracruzClient { data: &[u8], serialize_functor: fn(&[u8], &str) -> transport_protocol::TransportProtocolResult, ) -> Result { - let path = enforce_leading_slash( - path.as_ref() + let path = path.as_ref() .to_str() - .ok_or(VeracruzClientError::InvalidPath)?, - ); + .ok_or(VeracruzClientError::InvalidPath)?; let serialized_data = serialize_functor(data, &path)?; let response = self.send(&serialized_data)?; @@ -205,6 +203,7 @@ impl VeracruzClient { /// Request to write `data` to the `path` from the beginning. pub fn write_file>(&mut self, path: P, data: &[u8]) -> Result<()> { + info!("Client write file: {:?}", path.as_ref()); self.request_functor(path, data, transport_protocol::serialize_write_file)?; Ok(()) } diff --git a/crates/veracruz-server/Cargo.toml b/crates/veracruz-server/Cargo.toml index df11eabde..653c4c062 100644 --- a/crates/veracruz-server/Cargo.toml +++ b/crates/veracruz-server/Cargo.toml @@ -12,57 +12,41 @@ path = "src/lib.rs" [features] # a feature to enable CLI-only dependencies # https://stackoverflow.com/questions/35711044/how-can-i-specify-binary-only-dependencies -cli = [ - "clap", - "env_logger", - "policy-utils/std", -] debug = [] linux = [ - "data-encoding", "io-utils/linux", - "nix", - "policy-utils/std", "tempfile", "veracruz-utils/linux", ] nitro = [ "io-utils/nitro", "nitro-enclave", - "nix", - "policy-utils/std", "veracruz-utils/nitro", ] sev = [ - "io-utils", - "nix", - "policy-utils/std", + "io-utils/linux", ] [dependencies] anyhow = "1" base64 = "0.13.0" bincode = { version = "1.2.1", default-features = false } -clap = { version = "4", features = ["derive"], optional = true} -data-encoding = { version = "2.3.2", optional = true } -env_logger = { version = "0.10.0", optional = true } err-derive = "0.2" hex = "0.4.2" -io-utils = { path = "../io-utils", optional = true } +io-utils = { path = "../io-utils" } lazy_static = "1.4" log = "0.4.13" nitro-enclave = { git = "https://github.com/veracruz-project/nitro-enclave", tag = "v0.3", optional = true } -nix = { version = "0.26", optional = true } +nix = "0.26" postcard = "1.0.0" -policy-utils = { path = "../policy-utils" } +policy-utils = { path = "../policy-utils", features = ["std"] } proxy-attestation-client = { git = "https://github.com/veracruz-project/proxy-attestation-client", tag = "v0.4" } psa-attestation = { path = "../psa-attestation", optional = true } rand = "0.8.3" reqwest = { version = "0.11", default-features = false, features = ["blocking", "multipart", "rustls-tls"] } serde = { version = "1.0.185", default-features = false, features = ["derive"] } serde_json = "1.0" -signal-hook = { version = "0.3.13", optional = true } tempfile = { version = "3.2.0", optional = true } transport-protocol = { path = "../transport-protocol" } uuid = { version = "1.1.2", features = ["serde"] } diff --git a/crates/veracruz-server/src/server.rs b/crates/veracruz-server/src/server.rs index bf34b0a06..633bcac6d 100644 --- a/crates/veracruz-server/src/server.rs +++ b/crates/veracruz-server/src/server.rs @@ -59,8 +59,8 @@ fn handle_veracruz_server_request( } // Response this request - if let Some(x1) = output_data_option { - for x in x1 { + if let Some(data) = output_data_option { + for x in data { stream.write_all(&x)?; } } diff --git a/crates/veracruz-utils/Cargo.toml b/crates/veracruz-utils/Cargo.toml index 9186e0f96..90e46dcdb 100644 --- a/crates/veracruz-utils/Cargo.toml +++ b/crates/veracruz-utils/Cargo.toml @@ -7,31 +7,24 @@ version = "0.3.0" [features] linux = [ - "platform-services/std", - "serde/derive", - "serde_json/std", + "platform-services/std" ] nitro = [ "mbedtls/monitor_getrandom", - "platform-services/nitro", - "serde/derive", - "serde_json/std", + "platform-services/nitro" ] std = [ "chrono", - "platform-services/std", - "serde/std", - "serde_json/std", + "platform-services/std" ] [dependencies] anyhow = "1" -bincode = { version = "1.2.1", default-features = false, optional = true } chrono = { version = "0.4.19", default-features = false, features = ["clock", "std"], optional = true } err-derive = "0.2" mbedtls = { path = "../third-party/rust-mbedtls/mbedtls", default-features = false, features = ["std", "aesni", "padlock", "tls13"] } platform-services = { path = "../platform-services", optional = true } # The cargo patch mechanism does NOT work when we add function into a macro_rules! -serde = { version = "1.0.185", default-features = false, optional = true } +serde = { version = "1.0.185", default-features = false, features = ["derive"] } serde_json = { version = "1.0", default-features = false } uuid = { version = "1.1.2", features = ["serde"] } diff --git a/docs/CLI_QUICKSTART.md b/docs/CLI_QUICKSTART.md index 095531e95..09365fae6 100644 --- a/docs/CLI_QUICKSTART.md +++ b/docs/CLI_QUICKSTART.md @@ -63,6 +63,7 @@ Veracruz supports the direct execution of non-WebAssembly native code via the compile the example to WebAssembly, which Rust makes very easy for us: ``` bash +$ rustup target add wasm32-wasi $ cargo build \ --manifest-path=workspaces/applications/Cargo.toml \ --target wasm32-wasi \ @@ -178,18 +179,12 @@ $ vc-pgen \ --veracruz-server-ip 127.0.0.1:3017 \ --certificate-expiry "$(date --rfc-2822 -d 'now + 100 days')" \ --css-file workspaces/linux-runtime/target/debug/linux-runtime-manager \ - --certificate example/example-program-cert.pem \ - --capability "/program/:w" \ - --certificate example/example-data0-cert.pem \ - --capability "/input/:w" \ - --certificate example/example-data1-cert.pem \ - --capability "/input/:w" \ - --certificate example/example-data2-cert.pem \ - --capability "/input/:w" \ - --certificate example/example-result-cert.pem \ - --capability "/program/:x,/output/:r" \ - --program-binary /program/example-binary.wasm=example/example-binary.wasm \ - --capability "/input/:r,/output/:w" \ + --certificate "example/example-program-cert.pem => ./program/:w" \ + --certificate "example/example-data0-cert.pem => ./input/:w" \ + --certificate "example/example-data1-cert.pem => ./input/:w" \ + --certificate "example/example-data2-cert.pem => ./input/:w" \ + --certificate "example/example-result-cert.pem => ./program/:x,./output/:r" \ + --program-binary "./program/example-binary.wasm=example/example-binary.wasm => .:rw" \ --output-policy-file example/example-policy.json \ --max-memory-mib 256 ``` @@ -235,7 +230,7 @@ Server in the background: ``` bash $ vc-server example/example-policy.json & Veracruz Server running on 127.0.0.1:3017 -$ sleep 10 +$ sleep 30 ``` ## Running the Veracruz Client @@ -252,7 +247,7 @@ identity with the "ProgramProvider" role: $ vc-client example/example-policy.json \ --identity example/example-program-cert.pem \ --key example/example-program-key.pem \ - --program /program/example-binary.wasm=example/example-binary.wasm + --program ./program/example-binary.wasm=example/example-binary.wasm Loaded policy example/example-policy.json 645ae94ea86eaf15cfc04c07a17bd9b6a3b3b6c3558fae6fb93d8ee4c3e71241 Connecting to 127.0.0.1:3017 Submitting /example-binary.wasm from example/example-binary.wasm @@ -267,7 +262,7 @@ different devices: $ vc-client example/example-policy.json \ --identity example/example-data0-cert.pem \ --key example/example-data0-key.pem \ - --data /input/shamir-0.dat=<(echo "01dc061a7bdaf77616dd5915f3b4" | xxd -r -p) + --data ./input/shamir-0.dat=<(echo "01dc061a7bdaf77616dd5915f3b4" | xxd -r -p) Loaded policy example/example-policy.json 645ae94ea86eaf15cfc04c07a17bd9b6a3b3b6c3558fae6fb93d8ee4c3e71241 Connecting to 127.0.0.1:3017 Submitting /input/shamir-0.dat from /dev/fd/63 @@ -275,7 +270,7 @@ Submitting /input/shamir-0.dat from /dev/fd/63 $ vc-client example/example-policy.json \ --identity example/example-data1-cert.pem \ --key example/example-data1-key.pem \ - --data /input/shamir-1.dat=<(echo "027f38e27b5a02a288d064965364" | xxd -r -p) + --data ./input/shamir-1.dat=<(echo "027f38e27b5a02a288d064965364" | xxd -r -p) Loaded policy example/example-policy.json 645ae94ea86eaf15cfc04c07a17bd9b6a3b3b6c3558fae6fb93d8ee4c3e71241 Connecting to 127.0.0.1:3017 Submitting /input/shamir-1.dat from /dev/fd/63 @@ -283,7 +278,7 @@ Submitting /input/shamir-1.dat from /dev/fd/63 $ vc-client example/example-policy.json \ --identity example/example-data2-cert.pem \ --key example/example-data2-key.pem \ - --data /input/shamir-2.dat=<(echo "03eb5b946cefd583f17f51e781da" | xxd -r -p) + --data ./input/shamir-2.dat=<(echo "03eb5b946cefd583f17f51e781da" | xxd -r -p) Loaded policy example/example-policy.json 645ae94ea86eaf15cfc04c07a17bd9b6a3b3b6c3558fae6fb93d8ee4c3e71241 Connecting to 127.0.0.1:3017 Submitting /input/shamir-2.dat from /dev/fd/63 @@ -296,8 +291,8 @@ with the "RequestResult" role: $ vc-client example/example-policy.json \ --identity example/example-result-cert.pem \ --key example/example-result-key.pem \ - --compute /program/example-binary.wasm \ - --result /output/shamir.dat=- + --compute ./program/example-binary.wasm \ + --result ./output/shamir.dat=- Loaded policy example/example-policy.json 645ae94ea86eaf15cfc04c07a17bd9b6a3b3b6c3558fae6fb93d8ee4c3e71241 Connecting to 127.0.0.1:3017 Requesting compute of /example-binary.wasm diff --git a/rust-toolchain b/rust-toolchain index b6148bc0a..832e9afb6 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.66.0 +1.70.0 diff --git a/workspaces/applications/Cargo.lock b/workspaces/applications/Cargo.lock index 5cd78c819..8cd574375 100644 --- a/workspaces/applications/Cargo.lock +++ b/workspaces/applications/Cargo.lock @@ -181,14 +181,6 @@ dependencies = [ "zune-inflate", ] -[[package]] -name = "fd-create" -version = "0.3.0" -dependencies = [ - "anyhow", - "libveracruz", -] - [[package]] name = "fdeflate" version = "0.3.0" @@ -408,10 +400,6 @@ version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" -[[package]] -name = "libveracruz" -version = "0.3.0" - [[package]] name = "linear-regression" version = "0.3.0" diff --git a/workspaces/applications/Cargo.toml b/workspaces/applications/Cargo.toml index dd9da1889..aa31834f3 100644 --- a/workspaces/applications/Cargo.toml +++ b/workspaces/applications/Cargo.toml @@ -17,7 +17,6 @@ members = [ "crates/examples/rust-examples/aesctr-native", # "crates/examples/rust-examples/audio-event-triangulation", "crates/examples/rust-examples/darknet-inference-native", - "crates/examples/rust-examples/fd-create", "crates/examples/rust-examples/file-seek", "crates/examples/rust-examples/huffman-encoding", "crates/examples/rust-examples/idash2017-logistic-regression", diff --git a/workspaces/host/Cargo.lock b/workspaces/host/Cargo.lock index 09b7d80cf..62842e22b 100644 --- a/workspaces/host/Cargo.lock +++ b/workspaces/host/Cargo.lock @@ -31,6 +31,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -86,7 +92,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -96,7 +102,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -222,9 +228,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-buffer" @@ -247,6 +253,69 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cap-fs-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc48200a1a0fa6fba138b1802ad7def18ec1cdd92f7b2a04e21f1bd887f7b9" +dependencies = [ + "cap-primitives", + "cap-std", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "cap-primitives" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b6df5b295dca8d56f35560be8c391d59f0420f72e546997154e24e765e6451" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes 1.0.11", + "ipnet", + "maybe-owned", + "rustix 0.37.23", + "windows-sys 0.48.0", + "winx 0.35.1", +] + +[[package]] +name = "cap-rand" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25555efacb0b5244cf1d35833d55d21abc916fff0eaad254b8e2453ea9b8ab" +dependencies = [ + "ambient-authority", + "rand", +] + +[[package]] +name = "cap-std" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3373a62accd150b4fcba056d4c5f3b552127f0ec86d3c8c102d60b978174a012" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes 1.0.11", + "rustix 0.37.23", +] + +[[package]] +name = "cap-time-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e95002993b7baee6b66c8950470e59e5226a23b3af39fc59c47fe416dd39821a" +dependencies = [ + "cap-primitives", + "once_cell", + "rustix 0.37.23", + "winx 0.35.1", +] + [[package]] name = "cc" version = "1.0.81" @@ -302,6 +371,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" dependencies = [ "clap_builder", + "clap_derive", + "once_cell", ] [[package]] @@ -316,6 +387,18 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_derive" +version = "4.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "clap_lex" version = "0.5.0" @@ -369,18 +452,18 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c289b8eac3a97329a524e953b5fd68a8416ca629e1a37287f12d9e0760aadbc" +checksum = "0ebf2f2c0abc3a31cda70b20bae56b9aeb6ad0de00c3620bfef1a7e26220edfb" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bf07ba80f53fa7f7dc97b11087ea867f7ae4621cfca21a909eca92c0b96c7d9" +checksum = "46d414ddd870ebce9b55eed9e803ef063436bd4d64160dd8e811ccbeb2c914f0" dependencies = [ "bumpalo", "cranelift-bforest", @@ -399,42 +482,42 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a7ca088173130c5c033e944756e3e441fbf3f637f32b4f6eb70252580c6dd4" +checksum = "d1b0065250c0c1fae99748aadc6003725e588542650886d76dd234eca8498598" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0114095ec7d2fbd658ed100bd007006360bc2530f57c6eee3d3838869140dbf9" +checksum = "27320b5159cfa5eadcbebceda66ac145c0aa5cb7a31948550b9636f77924081b" [[package]] name = "cranelift-control" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d56031683a55a949977e756d21826eb17a1f346143a1badc0e120a15615cd38" +checksum = "26bb54d1e129d6d3cf0e2a191ec2ba91aec1c290a048bc7595490a275d729d7a" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6565198b5684367371e2b946ceca721eb36965e75e3592fad12fc2e15f65d7b" +checksum = "4d5656cb48246a511ab1bd22431122d8d23553b7c5f7f5ccff5569f47c0b708c" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f28cc44847c8b98cb921e6bfc0f7b228f4d27519376fea724d181da91709a6" +checksum = "f5321dc54f0f4e19f85d8e68543c63edfc255171cc5910c8b9a48e6210ffcdf2" dependencies = [ "cranelift-codegen", "log", @@ -444,15 +527,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b658177e72178c438f7de5d6645c56d97af38e17fcb0b500459007b4e05cc5" +checksum = "adff1f9152fd9970ad9cc14e0d4e1b0089a75d19f8538c4dc9e19aebbd53fe60" [[package]] name = "cranelift-native" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1c7de7221e6afcc5e13ced3b218faab3bc65b47eac67400046a05418aecd6a" +checksum = "809bfa1db0b982b1796bc8c0002ab6bab959664df16095c289e567bdd22ade6f" dependencies = [ "cranelift-codegen", "libc", @@ -461,9 +544,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b0d28ebe8edb6b503630c489aa4669f1e2d13b97bec7271a0fcb0e159be3ad" +checksum = "892f9273ee0c7709e839fcee769f9db1630789be5dbdfa429d84e0de8ec3dd41" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -471,7 +554,7 @@ dependencies = [ "itertools", "log", "smallvec", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-types", ] @@ -549,16 +632,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ctor" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "data-encoding" version = "2.4.0" @@ -600,6 +673,15 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -611,10 +693,10 @@ dependencies = [ ] [[package]] -name = "dirs-sys-next" -version = "0.1.2" +name = "dirs-sys" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -622,10 +704,15 @@ dependencies = [ ] [[package]] -name = "downcast-rs" -version = "1.2.0" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] [[package]] name = "either" @@ -642,6 +729,15 @@ dependencies = [ "log", ] +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -656,13 +752,10 @@ dependencies = [ ] [[package]] -name = "erased-serde" -version = "0.3.28" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" -dependencies = [ - "serde", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "err-derive" @@ -686,7 +779,7 @@ checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -704,27 +797,19 @@ name = "execution-engine" version = "0.3.0" dependencies = [ "anyhow", - "byteorder", "cfg-if", - "err-derive", "lazy_static", "log", "mbedtls", "nix", - "num", - "num-derive", - "num-traits", "platform-services", "policy-utils", "postcard", "serde", "serde_json", - "strum", - "strum_macros", - "typetag", "wasi-types", - "wasmi", "wasmtime", + "wasmtime-wasi", ] [[package]] @@ -733,6 +818,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fd-lock" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93f7a0db71c99f68398f80653ed05afb0b00e062e1a20c7ff849c4edfabbbcc" +dependencies = [ + "cfg-if", + "rustix 0.38.25", + "windows-sys 0.52.0", +] + [[package]] name = "file-per-thread-logger" version = "0.2.0" @@ -772,6 +868,17 @@ dependencies = [ "wasi-types", ] +[[package]] +name = "fs-set-times" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d167b646a876ba8fda6b50ac645cfd96242553cbaf0ca4fccaa39afcbf0801f" +dependencies = [ + "io-lifetimes 1.0.11", + "rustix 0.38.25", + "windows-sys 0.48.0", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -787,7 +894,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "debugid", "fxhash", "serde", @@ -803,13 +910,12 @@ dependencies = [ "clap", "data-encoding", "env_logger", + "lazy_static", "log", "policy-utils", - "regex", "serde", "serde_json", "veracruz-utils", - "wasi-types", ] [[package]] @@ -833,17 +939,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "ghost" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba330b70a5341d3bc730b8e205aaee97ddab5d9c448c4f51a7c2d924266fa8f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - [[package]] name = "gimli" version = "0.27.3" @@ -851,7 +946,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] @@ -891,6 +986,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heapless" version = "0.7.16" @@ -980,13 +1081,23 @@ dependencies = [ ] [[package]] -name = "inventory" -version = "0.2.3" +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + +[[package]] +name = "io-extras" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84344c6e0b90a9e2b6f3f9abe5cc74402684e348df7b32adca28747e0cef091a" +checksum = "fde93d48f0d9277f977a333eca8313695ddd5301dc96f7e02aeddcb0dd99096f" dependencies = [ - "ctor", - "ghost", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", ] [[package]] @@ -997,9 +1108,21 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "is-terminal" version = "0.4.7" @@ -1007,9 +1130,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi", - "io-lifetimes", - "rustix", - "windows-sys", + "io-lifetimes 1.0.11", + "rustix 0.37.23", + "windows-sys 0.48.0", ] [[package]] @@ -1067,9 +1190,9 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", @@ -1079,8 +1202,9 @@ dependencies = [ "itertools", "lalrpop-util", "petgraph", + "pico-args", "regex", - "regex-syntax", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -1089,9 +1213,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" dependencies = [ "regex", ] @@ -1137,9 +1261,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.144" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -1152,16 +1276,16 @@ dependencies = [ ] [[package]] -name = "libm" -version = "0.2.7" +name = "linux-raw-sys" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" @@ -1188,6 +1312,12 @@ dependencies = [ "libc", ] +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "mbedtls" version = "0.10.0" @@ -1242,7 +1372,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix", + "rustix 0.37.23", ] [[package]] @@ -1272,12 +1402,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1419,7 +1543,7 @@ checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" dependencies = [ "crc32fast", "hashbrown 0.13.2", - "indexmap", + "indexmap 1.9.3", "memchr", ] @@ -1429,12 +1553,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "parity-wasm" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1455,7 +1573,7 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec", - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -1483,7 +1601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -1495,6 +1613,18 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + [[package]] name = "pin-utils" version = "0.1.0" @@ -1526,12 +1656,12 @@ dependencies = [ "lalrpop", "lalrpop-util", "lexical-core", + "log", "mbedtls", "regex", "serde", "serde_json", "veracruz-utils", - "wasi-types", ] [[package]] @@ -1731,7 +1861,7 @@ checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] @@ -1740,6 +1870,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "rs-libc" version = "0.2.4" @@ -1779,10 +1915,25 @@ checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags 1.3.2", "errno", - "io-lifetimes", + "io-lifetimes 1.0.11", + "itoa", + "libc", + "linux-raw-sys 0.3.8", + "once_cell", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +dependencies = [ + "bitflags 2.4.1", + "errno", "libc", - "linux-raw-sys", - "windows-sys", + "linux-raw-sys 0.4.12", + "windows-sys 0.48.0", ] [[package]] @@ -1870,6 +2021,15 @@ dependencies = [ "digest", ] +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + [[package]] name = "shlex" version = "1.1.0" @@ -1946,25 +2106,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - [[package]] name = "syn" version = "1.0.109" @@ -1999,6 +2140,22 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-interface" +version = "0.25.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10081a99cbecbc363d381b9503563785f0b02735fccbb0d4c1a2cb3d39f7e7fe" +dependencies = [ + "bitflags 2.4.1", + "cap-fs-ext", + "cap-std", + "fd-lock", + "io-lifetimes 2.0.3", + "rustix 0.38.25", + "windows-sys 0.48.0", + "winx 0.36.3", +] + [[package]] name = "target-lexicon" version = "0.12.11" @@ -2079,35 +2236,43 @@ dependencies = [ ] [[package]] -name = "typenum" -version = "1.16.0" +name = "tracing" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] [[package]] -name = "typetag" -version = "0.1.8" +name = "tracing-attributes" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4080564c5b2241b5bff53ab610082234e0c57b0417f4bd10596f183001505b8a" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", + "proc-macro2", + "quote", + "syn 2.0.28", ] [[package]] -name = "typetag-impl" -version = "0.1.8" +name = "tracing-core" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60147782cc30833c05fba3bab1d9b5771b2685a2557672ac96fa5d154099c0e" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "once_cell", ] +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + [[package]] name = "unicase" version = "2.6.0" @@ -2181,7 +2346,6 @@ name = "veracruz-utils" version = "0.3.0" dependencies = [ "anyhow", - "bincode", "chrono", "err-derive", "mbedtls", @@ -2203,6 +2367,50 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi-cap-std-sync" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b22cf4595ee2af2c728a3ad5e90961556df7870e027bb054c59e0747f3533edb" +dependencies = [ + "anyhow", + "async-trait", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "io-lifetimes 1.0.11", + "is-terminal", + "once_cell", + "rustix 0.37.23", + "system-interface", + "tracing", + "wasi-common", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasi-common" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8dbf50f7f86c73af7eeb9a00d342fe20a6a2460bd7737d8db6b65e9a8216cd" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "cap-rand", + "cap-std", + "io-extras", + "log", + "rustix 0.37.23", + "thiserror", + "tracing", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + [[package]] name = "wasi-types" version = "0.1.6" @@ -2271,67 +2479,66 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" -version = "0.31.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41763f20eafed1399fff1afb466496d3a959f58241436cfdc17e3f5ca954de16" +checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" dependencies = [ "leb128", ] [[package]] -name = "wasmi" -version = "0.13.2" +name = "wasm-encoder" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41763f20eafed1399fff1afb466496d3a959f58241436cfdc17e3f5ca954de16" dependencies = [ - "parity-wasm", - "serde", - "typetag", - "wasmi-validation", - "wasmi_core", + "leb128", ] [[package]] -name = "wasmi-validation" -version = "0.5.0" +name = "wasmparser" +version = "0.107.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" dependencies = [ - "parity-wasm", + "indexmap 1.9.3", + "semver", ] [[package]] -name = "wasmi_core" -version = "0.2.1" +name = "wasmparser" +version = "0.118.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" dependencies = [ - "downcast-rs", - "libm", - "memory_units", - "num-rational", - "num-traits", - "serde", - "typetag", + "indexmap 2.1.0", + "semver", ] [[package]] -name = "wasmparser" -version = "0.107.0" +name = "wasmprinter" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +checksum = "3d027eb8294904fc715ac0870cebe6b0271e96b90605ee21511e7565c4ce568c" dependencies = [ - "indexmap", - "semver", + "anyhow", + "wasmparser 0.118.1", ] [[package]] name = "wasmtime" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd02b992d828b91efaf2a7499b21205fe4ab3002e401e3fe0f227aaeb4001d93" +checksum = "028253baf4df6e0823481845a380117de2b7f42166261551db7d097d60cfc685" dependencies = [ "anyhow", "async-trait", "bincode", "bumpalo", "cfg-if", + "encoding_rs", "fxprof-processed-profile", - "indexmap", + "indexmap 1.9.3", "libc", "log", "object", @@ -2342,32 +2549,34 @@ dependencies = [ "serde", "serde_json", "target-lexicon", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-cache", "wasmtime-component-macro", + "wasmtime-component-util", "wasmtime-cranelift", "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit", "wasmtime-runtime", + "wasmtime-winch", "wat", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-asm-macros" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284466ef356ce2d909bc0ad470b60c4d0df5df2de9084457e118131b3c779b92" +checksum = "e76c6e968fb3df273a8140bb9e02693b17da1f53a3bbafa0a5811e8ef1031cd8" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-cache" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc78cfe1a758d1336f447a47af6ec05e0df2c03c93440d70faf80e17fbb001e" +checksum = "34308e5033adb530c18de06f6f2d1de2c0cb6dc19e9c13451acf97ec4e07b30a" dependencies = [ "anyhow", "base64", @@ -2375,19 +2584,19 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix", + "rustix 0.37.23", "serde", "sha2", "toml", - "windows-sys", + "windows-sys 0.48.0", "zstd", ] [[package]] name = "wasmtime-component-macro" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e916103436a6d84faa4c2083e2e98612a323c2cc6147ec419124f67c764c9c" +checksum = "1631a5fed4e162edf7e0604845e6150903f17099970e1a0020f540831d0f8479" dependencies = [ "anyhow", "proc-macro2", @@ -2400,15 +2609,15 @@ dependencies = [ [[package]] name = "wasmtime-component-util" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f20a5135ec5ef01080e674979b02d6fa5eebaa2b0c2d6660513ee9956a1bf624" +checksum = "31bd6b1c6d8ece2aa852bf5dad0ea91be63e81c7571d7bcf24238b05405adb70" [[package]] name = "wasmtime-cranelift" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1aa99cbf3f8edb5ad8408ba380f5ab481528ecd8a5053acf758e006d6727fd" +checksum = "696333ffdbd9fabb486d8a5ee82c75fcd22d199446d3df04935a286fcbb40100" dependencies = [ "anyhow", "cranelift-codegen", @@ -2422,16 +2631,16 @@ dependencies = [ "object", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-cranelift-shared", "wasmtime-environ", ] [[package]] name = "wasmtime-cranelift-shared" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce31fd55978601acc103acbb8a26f81c89a6eae12d3a1c59f34151dfa609484" +checksum = "434899162f65339ae7710f6fba91083b86e707cb618a8f4e8b037b8d46223d56" dependencies = [ "anyhow", "cranelift-codegen", @@ -2445,41 +2654,44 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f9e58e0ee7d43ff13e75375c726b16bce022db798d3a099a65eeaa7d7a544b" +checksum = "1189b2fa0e7fbf71a06c7c909ae7f8f0085f8f4e4365926d6ff1052e024effe9" dependencies = [ "anyhow", "cranelift-entity", "gimli", - "indexmap", + "indexmap 1.9.3", "log", "object", "serde", "target-lexicon", "thiserror", - "wasmparser", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", + "wasmprinter", + "wasmtime-component-util", "wasmtime-types", ] [[package]] name = "wasmtime-fiber" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14309cbdf2c395258b124a24757c727403070c0465a28bcc780c4f82f4bca5ff" +checksum = "e0e22d42113a1181fee3477f96639fd88c757b303f7083e866691f47a06065c5" dependencies = [ "cc", "cfg-if", - "rustix", + "rustix 0.37.23", "wasmtime-asm-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-jit" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0f2eaeb01bb67266416507829bd8e0bb60278444e4cbd048e280833ebeaa02" +checksum = "b3b904e4920c5725dae5d2445c5923092f1d0dead3a521bd7f4218d7a9496842" dependencies = [ "addr2line", "anyhow", @@ -2491,48 +2703,49 @@ dependencies = [ "log", "object", "rustc-demangle", - "rustix", + "rustix 0.37.23", "serde", "target-lexicon", "wasmtime-environ", "wasmtime-jit-debug", "wasmtime-jit-icache-coherence", "wasmtime-runtime", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-jit-debug" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f42e59d62542bfb73ce30672db7eaf4084a60b434b688ac4f05b287d497de082" +checksum = "c7228ed7aaedec75d6bd298f857e42f4626cffdb7b577c018eb2075c65d44dcf" dependencies = [ "object", "once_cell", - "rustix", + "rustix 0.37.23", ] [[package]] name = "wasmtime-jit-icache-coherence" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b49ceb7e2105a8ebe5614d7bbab6f6ef137a284e371633af60b34925493081f" +checksum = "517750d84b6ebdb2c32226cee412c7e6aa48e4cebbb259d9a227b4317426adc6" dependencies = [ "cfg-if", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-runtime" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5de4762421b0b2b19e02111ca403632852b53e506e03b4b227ffb0fbfa63c2" +checksum = "c89ef7f9d70f30fc5dfea15b61b65b81363bf8b3881ab76de3a7b24905c4e83a" dependencies = [ "anyhow", "cc", "cfg-if", - "indexmap", + "encoding_rs", + "indexmap 1.9.3", "libc", "log", "mach", @@ -2540,38 +2753,91 @@ dependencies = [ "memoffset 0.8.0", "paste", "rand", - "rustix", + "rustix 0.37.23", "sptr", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit-debug", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-types" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb7c138f797192f46afdd3ec16f85ef007c3bb45fa8e5174031f17b0be4c4a" +checksum = "2ac19aadf941ad333cbb0307121482700d925a99624d4110859d69b7f658b69d" dependencies = [ "cranelift-entity", "serde", "thiserror", - "wasmparser", + "wasmparser 0.107.0", +] + +[[package]] +name = "wasmtime-wasi" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2214bfed500d91f2cf020c085bbdac431b27ab5e683000a65ede93c9b1fd7c14" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 1.3.2", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "libc", + "rustix 0.37.23", + "system-interface", + "thiserror", + "tracing", + "wasi-cap-std-sync", + "wasi-common", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-winch" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa0f80e89ec9671a6efc1507c37a3748a63b2566033d7d0993fa711696c4b24" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "object", + "target-lexicon", + "wasmparser 0.107.0", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "winch-codegen", ] [[package]] name = "wasmtime-wit-bindgen" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3334b0466a4d340de345cda83474d1d2c429770c3d667877971407672bc618a" +checksum = "aed98de4b3e68b1abe60f0dc59ecd74b757d70a39459d500a727a8cab3311bbb" dependencies = [ "anyhow", "heck", "wit-parser", ] +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", +] + [[package]] name = "wast" version = "62.0.1" @@ -2581,7 +2847,7 @@ dependencies = [ "leb128", "memchr", "unicode-width", - "wasm-encoder", + "wasm-encoder 0.31.1", ] [[package]] @@ -2590,7 +2856,7 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "842e15861d203fb4a96d314b0751cdeaf0f6f8b35e8d81d2953af2af5e44e637" dependencies = [ - "wast", + "wast 62.0.1", ] [[package]] @@ -2604,6 +2870,48 @@ dependencies = [ "once_cell", ] +[[package]] +name = "wiggle" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "947e89009051ddc4e58a2d653103165147e1aee5737603044160d9bc4847aab1" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 1.3.2", + "thiserror", + "tracing", + "wasmtime", + "wiggle-macro", +] + +[[package]] +name = "wiggle-generate" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7344729841849d8841ef22164fe848ed6fce8b5eb74ab8b3739296146e10af5" +dependencies = [ + "anyhow", + "heck", + "proc-macro2", + "quote", + "shellexpand", + "syn 1.0.109", + "witx", +] + +[[package]] +name = "wiggle-macro" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93acdd0b56b3e78a272fa937135d515ea9b690f94cb452b5165ac3ae614341ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wiggle-generate", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2635,13 +2943,29 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winch-codegen" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a1a53444157fc27c3f3e98e5e19a1717efad8749959a3d493d0f6bbf0f0b3d" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "regalloc2", + "smallvec", + "target-lexicon", + "wasmparser 0.107.0", + "wasmtime-environ", +] + [[package]] name = "windows" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -2650,7 +2974,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -2659,13 +2992,28 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -2674,42 +3022,105 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winx" +version = "0.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c52a121f0fbf9320d5f2a9a5d82f6cb7557eda5e8b47fc3e7f359ec866ae960" +dependencies = [ + "bitflags 1.3.2", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "wit-parser" version = "0.8.0" @@ -2718,7 +3129,7 @@ checksum = "6daec9f093dbaea0e94043eeb92ece327bbbe70c86b1f41aca9bbfefd7f050f0" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 1.9.3", "log", "pulldown-cmark", "semver", @@ -2726,6 +3137,18 @@ dependencies = [ "url", ] +[[package]] +name = "witx" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" +dependencies = [ + "anyhow", + "log", + "thiserror", + "wast 35.0.2", +] + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/workspaces/host/Cargo.toml b/workspaces/host/Cargo.toml index de974bb90..d5aec0a6d 100644 --- a/workspaces/host/Cargo.toml +++ b/workspaces/host/Cargo.toml @@ -16,6 +16,7 @@ cargo-features = ["resolver"] exclude = [ "crates/third-party/rust-mbedtls", "crates/third-party/wasmi", + "crates/wasmi", ] members = [ "crates/freestanding-execution-engine", diff --git a/workspaces/linux-host/Cargo.lock b/workspaces/linux-host/Cargo.lock index 140d2389e..fe8c96bd3 100644 --- a/workspaces/linux-host/Cargo.lock +++ b/workspaces/linux-host/Cargo.lock @@ -868,10 +868,6 @@ dependencies = [ "log", "nix", "serde", - "serde_json", - "stringreader", - "transport-protocol", - "uuid", ] [[package]] @@ -918,9 +914,9 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", @@ -930,8 +926,9 @@ dependencies = [ "itertools", "lalrpop-util", "petgraph", + "pico-args", "regex", - "regex-syntax", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -940,9 +937,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" dependencies = [ "regex", ] @@ -1195,20 +1192,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -1220,26 +1203,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-complex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -1250,29 +1213,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.16" @@ -1352,6 +1292,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.10" @@ -1383,12 +1329,12 @@ dependencies = [ "lalrpop", "lalrpop-util", "lexical-core", + "log", "mbedtls", "regex", "serde", "serde_json", "veracruz-utils", - "wasi-types", ] [[package]] @@ -1617,7 +1563,7 @@ checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] @@ -1626,6 +1572,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1880,16 +1832,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1970,12 +1912,6 @@ dependencies = [ "precomputed-hash", ] -[[package]] -name = "stringreader" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913e7b03d63752f6cdd2df77da36749d82669904798fe8944b9ec3d23f159905" - [[package]] name = "strsim" version = "0.8.0" @@ -2367,9 +2303,6 @@ dependencies = [ "anyhow", "base64 0.13.1", "bincode", - "clap 4.3.19", - "data-encoding", - "env_logger 0.10.0", "err-derive", "hex", "io-utils", @@ -2385,7 +2318,6 @@ dependencies = [ "reqwest", "serde", "serde_json", - "signal-hook", "tempfile", "transport-protocol", "uuid", @@ -2397,7 +2329,6 @@ name = "veracruz-utils" version = "0.3.0" dependencies = [ "anyhow", - "bincode", "chrono", "err-derive", "mbedtls", @@ -2438,18 +2369,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi-types" -version = "0.1.6" -dependencies = [ - "bitflags", - "err-derive", - "num", - "num-derive", - "num-traits", - "serde", -] - [[package]] name = "wasm-bindgen" version = "0.2.87" diff --git a/workspaces/linux-host/src/linux-host/Cargo.toml b/workspaces/linux-host/src/linux-host/Cargo.toml index 33c09bcf1..655021e0e 100644 --- a/workspaces/linux-host/src/linux-host/Cargo.toml +++ b/workspaces/linux-host/src/linux-host/Cargo.toml @@ -7,5 +7,5 @@ version = "0.3.0" [dependencies] tests = { path = "../../crates/tests", features = [ "linux" ] } -veracruz-client = { path = "../../crates/veracruz-client", features = [ "linux", "cli" ] } -veracruz-server = { path = "../../crates/veracruz-server", features = [ "linux", "cli" ] } +veracruz-client = { path = "../../crates/veracruz-client", features = [ "linux" ] } +veracruz-server = { path = "../../crates/veracruz-server", features = [ "linux" ] } diff --git a/workspaces/linux-runtime/Cargo.lock b/workspaces/linux-runtime/Cargo.lock index ac83b52f7..ac0027db1 100644 --- a/workspaces/linux-runtime/Cargo.lock +++ b/workspaces/linux-runtime/Cargo.lock @@ -31,6 +31,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -86,7 +92,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -96,7 +102,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -228,9 +234,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-buffer" @@ -253,6 +259,69 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cap-fs-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc48200a1a0fa6fba138b1802ad7def18ec1cdd92f7b2a04e21f1bd887f7b9" +dependencies = [ + "cap-primitives", + "cap-std", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "cap-primitives" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b6df5b295dca8d56f35560be8c391d59f0420f72e546997154e24e765e6451" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes 1.0.11", + "ipnet", + "maybe-owned", + "rustix 0.37.23", + "windows-sys 0.48.0", + "winx 0.35.1", +] + +[[package]] +name = "cap-rand" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25555efacb0b5244cf1d35833d55d21abc916fff0eaad254b8e2453ea9b8ab" +dependencies = [ + "ambient-authority", + "rand", +] + +[[package]] +name = "cap-std" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3373a62accd150b4fcba056d4c5f3b552127f0ec86d3c8c102d60b978174a012" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes 1.0.11", + "rustix 0.37.23", +] + +[[package]] +name = "cap-time-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e95002993b7baee6b66c8950470e59e5226a23b3af39fc59c47fe416dd39821a" +dependencies = [ + "cap-primitives", + "once_cell", + "rustix 0.37.23", + "winx 0.35.1", +] + [[package]] name = "cc" version = "1.0.81" @@ -375,18 +444,18 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c289b8eac3a97329a524e953b5fd68a8416ca629e1a37287f12d9e0760aadbc" +checksum = "0ebf2f2c0abc3a31cda70b20bae56b9aeb6ad0de00c3620bfef1a7e26220edfb" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bf07ba80f53fa7f7dc97b11087ea867f7ae4621cfca21a909eca92c0b96c7d9" +checksum = "46d414ddd870ebce9b55eed9e803ef063436bd4d64160dd8e811ccbeb2c914f0" dependencies = [ "bumpalo", "cranelift-bforest", @@ -405,42 +474,42 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a7ca088173130c5c033e944756e3e441fbf3f637f32b4f6eb70252580c6dd4" +checksum = "d1b0065250c0c1fae99748aadc6003725e588542650886d76dd234eca8498598" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0114095ec7d2fbd658ed100bd007006360bc2530f57c6eee3d3838869140dbf9" +checksum = "27320b5159cfa5eadcbebceda66ac145c0aa5cb7a31948550b9636f77924081b" [[package]] name = "cranelift-control" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d56031683a55a949977e756d21826eb17a1f346143a1badc0e120a15615cd38" +checksum = "26bb54d1e129d6d3cf0e2a191ec2ba91aec1c290a048bc7595490a275d729d7a" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6565198b5684367371e2b946ceca721eb36965e75e3592fad12fc2e15f65d7b" +checksum = "4d5656cb48246a511ab1bd22431122d8d23553b7c5f7f5ccff5569f47c0b708c" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f28cc44847c8b98cb921e6bfc0f7b228f4d27519376fea724d181da91709a6" +checksum = "f5321dc54f0f4e19f85d8e68543c63edfc255171cc5910c8b9a48e6210ffcdf2" dependencies = [ "cranelift-codegen", "log", @@ -450,15 +519,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b658177e72178c438f7de5d6645c56d97af38e17fcb0b500459007b4e05cc5" +checksum = "adff1f9152fd9970ad9cc14e0d4e1b0089a75d19f8538c4dc9e19aebbd53fe60" [[package]] name = "cranelift-native" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1c7de7221e6afcc5e13ced3b218faab3bc65b47eac67400046a05418aecd6a" +checksum = "809bfa1db0b982b1796bc8c0002ab6bab959664df16095c289e567bdd22ade6f" dependencies = [ "cranelift-codegen", "libc", @@ -467,9 +536,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b0d28ebe8edb6b503630c489aa4669f1e2d13b97bec7271a0fcb0e159be3ad" +checksum = "892f9273ee0c7709e839fcee769f9db1630789be5dbdfa429d84e0de8ec3dd41" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -477,7 +546,7 @@ dependencies = [ "itertools", "log", "smallvec", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-types", ] @@ -555,16 +624,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ctor" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "debugid" version = "0.8.0" @@ -600,6 +659,15 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -611,10 +679,10 @@ dependencies = [ ] [[package]] -name = "dirs-sys-next" -version = "0.1.2" +name = "dirs-sys" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -622,10 +690,15 @@ dependencies = [ ] [[package]] -name = "downcast-rs" -version = "1.2.0" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] [[package]] name = "either" @@ -642,6 +715,15 @@ dependencies = [ "log", ] +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -656,13 +738,10 @@ dependencies = [ ] [[package]] -name = "erased-serde" -version = "0.3.28" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" -dependencies = [ - "serde", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "err-derive" @@ -686,7 +765,7 @@ checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -704,27 +783,19 @@ name = "execution-engine" version = "0.3.0" dependencies = [ "anyhow", - "byteorder", "cfg-if", - "err-derive", "lazy_static", "log", "mbedtls", "nix", - "num", - "num-derive", - "num-traits", "platform-services", "policy-utils", "postcard", "serde", "serde_json", - "strum", - "strum_macros", - "typetag", "wasi-types", - "wasmi", "wasmtime", + "wasmtime-wasi", ] [[package]] @@ -742,6 +813,17 @@ dependencies = [ "instant", ] +[[package]] +name = "fd-lock" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93f7a0db71c99f68398f80653ed05afb0b00e062e1a20c7ff849c4edfabbbcc" +dependencies = [ + "cfg-if", + "rustix 0.38.25", + "windows-sys 0.52.0", +] + [[package]] name = "file-per-thread-logger" version = "0.2.0" @@ -767,6 +849,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-set-times" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d167b646a876ba8fda6b50ac645cfd96242553cbaf0ca4fccaa39afcbf0801f" +dependencies = [ + "io-lifetimes 1.0.11", + "rustix 0.38.25", + "windows-sys 0.48.0", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -782,7 +875,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "debugid", "fxhash", "serde", @@ -810,17 +903,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "ghost" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba330b70a5341d3bc730b8e205aaee97ddab5d9c448c4f51a7c2d924266fa8f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - [[package]] name = "gimli" version = "0.27.3" @@ -828,7 +910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] @@ -868,6 +950,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heapless" version = "0.7.16" @@ -906,7 +994,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -965,6 +1053,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + [[package]] name = "instant" version = "0.1.12" @@ -975,13 +1073,13 @@ dependencies = [ ] [[package]] -name = "inventory" -version = "0.2.3" +name = "io-extras" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84344c6e0b90a9e2b6f3f9abe5cc74402684e348df7b32adca28747e0cef091a" +checksum = "fde93d48f0d9277f977a333eca8313695ddd5301dc96f7e02aeddcb0dd99096f" dependencies = [ - "ctor", - "ghost", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", ] [[package]] @@ -992,9 +1090,15 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + [[package]] name = "io-utils" version = "0.3.0" @@ -1007,12 +1111,14 @@ dependencies = [ "log", "nix", "serde", - "serde_json", - "stringreader", - "transport-protocol", - "uuid", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "is-terminal" version = "0.4.7" @@ -1020,9 +1126,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi", - "io-lifetimes", - "rustix", - "windows-sys", + "io-lifetimes 1.0.11", + "rustix 0.37.23", + "windows-sys 0.48.0", ] [[package]] @@ -1080,9 +1186,9 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", @@ -1092,8 +1198,9 @@ dependencies = [ "itertools", "lalrpop-util", "petgraph", + "pico-args", "regex", - "regex-syntax", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -1102,9 +1209,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" dependencies = [ "regex", ] @@ -1150,9 +1257,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.144" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -1165,16 +1272,16 @@ dependencies = [ ] [[package]] -name = "libm" -version = "0.2.7" +name = "linux-raw-sys" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "linux-runtime-manager" @@ -1219,6 +1326,12 @@ dependencies = [ "libc", ] +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "mbedtls" version = "0.10.0" @@ -1273,7 +1386,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix", + "rustix 0.37.23", ] [[package]] @@ -1303,12 +1416,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1450,7 +1557,7 @@ checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" dependencies = [ "crc32fast", "hashbrown 0.13.2", - "indexmap", + "indexmap 1.9.3", "memchr", ] @@ -1460,12 +1567,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "parity-wasm" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1486,7 +1587,7 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec", - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -1514,7 +1615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -1526,6 +1627,18 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + [[package]] name = "pin-utils" version = "0.1.0" @@ -1557,12 +1670,12 @@ dependencies = [ "lalrpop", "lalrpop-util", "lexical-core", + "log", "mbedtls", "regex", "serde", "serde_json", "veracruz-utils", - "wasi-types", ] [[package]] @@ -1664,7 +1777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49" dependencies = [ "anyhow", - "indexmap", + "indexmap 1.9.3", "log", "protobuf", "protobuf-support", @@ -1833,7 +1946,7 @@ checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] @@ -1842,6 +1955,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1914,10 +2033,25 @@ checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags 1.3.2", "errno", - "io-lifetimes", + "io-lifetimes 1.0.11", + "itoa", "libc", - "linux-raw-sys", - "windows-sys", + "linux-raw-sys 0.3.8", + "once_cell", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.12", + "windows-sys 0.48.0", ] [[package]] @@ -2017,6 +2151,15 @@ dependencies = [ "digest", ] +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + [[package]] name = "shlex" version = "1.1.0" @@ -2087,37 +2230,12 @@ dependencies = [ "precomputed-hash", ] -[[package]] -name = "stringreader" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913e7b03d63752f6cdd2df77da36749d82669904798fe8944b9ec3d23f159905" - [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - [[package]] name = "syn" version = "1.0.109" @@ -2152,6 +2270,22 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-interface" +version = "0.25.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10081a99cbecbc363d381b9503563785f0b02735fccbb0d4c1a2cb3d39f7e7fe" +dependencies = [ + "bitflags 2.4.1", + "cap-fs-ext", + "cap-std", + "fd-lock", + "io-lifetimes 2.0.3", + "rustix 0.38.25", + "windows-sys 0.48.0", + "winx 0.36.3", +] + [[package]] name = "target-lexicon" version = "0.12.11" @@ -2245,6 +2379,38 @@ dependencies = [ "serde", ] +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "transport-protocol" version = "0.3.0" @@ -2263,30 +2429,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "typetag" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4080564c5b2241b5bff53ab610082234e0c57b0417f4bd10596f183001505b8a" -dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", -] - -[[package]] -name = "typetag-impl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60147782cc30833c05fba3bab1d9b5771b2685a2557672ac96fa5d154099c0e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "unicase" version = "2.6.0" @@ -2360,7 +2502,6 @@ name = "veracruz-utils" version = "0.3.0" dependencies = [ "anyhow", - "bincode", "chrono", "err-derive", "mbedtls", @@ -2382,6 +2523,50 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi-cap-std-sync" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b22cf4595ee2af2c728a3ad5e90961556df7870e027bb054c59e0747f3533edb" +dependencies = [ + "anyhow", + "async-trait", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "io-lifetimes 1.0.11", + "is-terminal", + "once_cell", + "rustix 0.37.23", + "system-interface", + "tracing", + "wasi-common", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasi-common" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8dbf50f7f86c73af7eeb9a00d342fe20a6a2460bd7737d8db6b65e9a8216cd" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "cap-rand", + "cap-std", + "io-extras", + "log", + "rustix 0.37.23", + "thiserror", + "tracing", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + [[package]] name = "wasi-types" version = "0.1.6" @@ -2450,67 +2635,66 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" -version = "0.31.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41763f20eafed1399fff1afb466496d3a959f58241436cfdc17e3f5ca954de16" +checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" dependencies = [ "leb128", ] [[package]] -name = "wasmi" -version = "0.13.2" +name = "wasm-encoder" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41763f20eafed1399fff1afb466496d3a959f58241436cfdc17e3f5ca954de16" dependencies = [ - "parity-wasm", - "serde", - "typetag", - "wasmi-validation", - "wasmi_core", + "leb128", ] [[package]] -name = "wasmi-validation" -version = "0.5.0" +name = "wasmparser" +version = "0.107.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" dependencies = [ - "parity-wasm", + "indexmap 1.9.3", + "semver", ] [[package]] -name = "wasmi_core" -version = "0.2.1" +name = "wasmparser" +version = "0.118.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" dependencies = [ - "downcast-rs", - "libm", - "memory_units", - "num-rational", - "num-traits", - "serde", - "typetag", + "indexmap 2.1.0", + "semver", ] [[package]] -name = "wasmparser" -version = "0.107.0" +name = "wasmprinter" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +checksum = "3d027eb8294904fc715ac0870cebe6b0271e96b90605ee21511e7565c4ce568c" dependencies = [ - "indexmap", - "semver", + "anyhow", + "wasmparser 0.118.1", ] [[package]] name = "wasmtime" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd02b992d828b91efaf2a7499b21205fe4ab3002e401e3fe0f227aaeb4001d93" +checksum = "028253baf4df6e0823481845a380117de2b7f42166261551db7d097d60cfc685" dependencies = [ "anyhow", "async-trait", "bincode", "bumpalo", "cfg-if", + "encoding_rs", "fxprof-processed-profile", - "indexmap", + "indexmap 1.9.3", "libc", "log", "object", @@ -2521,32 +2705,34 @@ dependencies = [ "serde", "serde_json", "target-lexicon", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-cache", "wasmtime-component-macro", + "wasmtime-component-util", "wasmtime-cranelift", "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit", "wasmtime-runtime", + "wasmtime-winch", "wat", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-asm-macros" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284466ef356ce2d909bc0ad470b60c4d0df5df2de9084457e118131b3c779b92" +checksum = "e76c6e968fb3df273a8140bb9e02693b17da1f53a3bbafa0a5811e8ef1031cd8" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-cache" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc78cfe1a758d1336f447a47af6ec05e0df2c03c93440d70faf80e17fbb001e" +checksum = "34308e5033adb530c18de06f6f2d1de2c0cb6dc19e9c13451acf97ec4e07b30a" dependencies = [ "anyhow", "base64 0.21.2", @@ -2554,19 +2740,19 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix", + "rustix 0.37.23", "serde", "sha2", "toml", - "windows-sys", + "windows-sys 0.48.0", "zstd", ] [[package]] name = "wasmtime-component-macro" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e916103436a6d84faa4c2083e2e98612a323c2cc6147ec419124f67c764c9c" +checksum = "1631a5fed4e162edf7e0604845e6150903f17099970e1a0020f540831d0f8479" dependencies = [ "anyhow", "proc-macro2", @@ -2579,15 +2765,15 @@ dependencies = [ [[package]] name = "wasmtime-component-util" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f20a5135ec5ef01080e674979b02d6fa5eebaa2b0c2d6660513ee9956a1bf624" +checksum = "31bd6b1c6d8ece2aa852bf5dad0ea91be63e81c7571d7bcf24238b05405adb70" [[package]] name = "wasmtime-cranelift" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1aa99cbf3f8edb5ad8408ba380f5ab481528ecd8a5053acf758e006d6727fd" +checksum = "696333ffdbd9fabb486d8a5ee82c75fcd22d199446d3df04935a286fcbb40100" dependencies = [ "anyhow", "cranelift-codegen", @@ -2601,16 +2787,16 @@ dependencies = [ "object", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-cranelift-shared", "wasmtime-environ", ] [[package]] name = "wasmtime-cranelift-shared" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce31fd55978601acc103acbb8a26f81c89a6eae12d3a1c59f34151dfa609484" +checksum = "434899162f65339ae7710f6fba91083b86e707cb618a8f4e8b037b8d46223d56" dependencies = [ "anyhow", "cranelift-codegen", @@ -2624,41 +2810,44 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f9e58e0ee7d43ff13e75375c726b16bce022db798d3a099a65eeaa7d7a544b" +checksum = "1189b2fa0e7fbf71a06c7c909ae7f8f0085f8f4e4365926d6ff1052e024effe9" dependencies = [ "anyhow", "cranelift-entity", "gimli", - "indexmap", + "indexmap 1.9.3", "log", "object", "serde", "target-lexicon", "thiserror", - "wasmparser", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", + "wasmprinter", + "wasmtime-component-util", "wasmtime-types", ] [[package]] name = "wasmtime-fiber" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14309cbdf2c395258b124a24757c727403070c0465a28bcc780c4f82f4bca5ff" +checksum = "e0e22d42113a1181fee3477f96639fd88c757b303f7083e866691f47a06065c5" dependencies = [ "cc", "cfg-if", - "rustix", + "rustix 0.37.23", "wasmtime-asm-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-jit" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0f2eaeb01bb67266416507829bd8e0bb60278444e4cbd048e280833ebeaa02" +checksum = "b3b904e4920c5725dae5d2445c5923092f1d0dead3a521bd7f4218d7a9496842" dependencies = [ "addr2line", "anyhow", @@ -2670,48 +2859,49 @@ dependencies = [ "log", "object", "rustc-demangle", - "rustix", + "rustix 0.37.23", "serde", "target-lexicon", "wasmtime-environ", "wasmtime-jit-debug", "wasmtime-jit-icache-coherence", "wasmtime-runtime", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-jit-debug" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f42e59d62542bfb73ce30672db7eaf4084a60b434b688ac4f05b287d497de082" +checksum = "c7228ed7aaedec75d6bd298f857e42f4626cffdb7b577c018eb2075c65d44dcf" dependencies = [ "object", "once_cell", - "rustix", + "rustix 0.37.23", ] [[package]] name = "wasmtime-jit-icache-coherence" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b49ceb7e2105a8ebe5614d7bbab6f6ef137a284e371633af60b34925493081f" +checksum = "517750d84b6ebdb2c32226cee412c7e6aa48e4cebbb259d9a227b4317426adc6" dependencies = [ "cfg-if", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-runtime" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5de4762421b0b2b19e02111ca403632852b53e506e03b4b227ffb0fbfa63c2" +checksum = "c89ef7f9d70f30fc5dfea15b61b65b81363bf8b3881ab76de3a7b24905c4e83a" dependencies = [ "anyhow", "cc", "cfg-if", - "indexmap", + "encoding_rs", + "indexmap 1.9.3", "libc", "log", "mach", @@ -2719,38 +2909,91 @@ dependencies = [ "memoffset 0.8.0", "paste", "rand", - "rustix", + "rustix 0.37.23", "sptr", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit-debug", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-types" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb7c138f797192f46afdd3ec16f85ef007c3bb45fa8e5174031f17b0be4c4a" +checksum = "2ac19aadf941ad333cbb0307121482700d925a99624d4110859d69b7f658b69d" dependencies = [ "cranelift-entity", "serde", "thiserror", - "wasmparser", + "wasmparser 0.107.0", +] + +[[package]] +name = "wasmtime-wasi" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2214bfed500d91f2cf020c085bbdac431b27ab5e683000a65ede93c9b1fd7c14" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 1.3.2", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "libc", + "rustix 0.37.23", + "system-interface", + "thiserror", + "tracing", + "wasi-cap-std-sync", + "wasi-common", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-winch" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa0f80e89ec9671a6efc1507c37a3748a63b2566033d7d0993fa711696c4b24" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "object", + "target-lexicon", + "wasmparser 0.107.0", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "winch-codegen", ] [[package]] name = "wasmtime-wit-bindgen" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3334b0466a4d340de345cda83474d1d2c429770c3d667877971407672bc618a" +checksum = "aed98de4b3e68b1abe60f0dc59ecd74b757d70a39459d500a727a8cab3311bbb" dependencies = [ "anyhow", "heck", "wit-parser", ] +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", +] + [[package]] name = "wast" version = "62.0.1" @@ -2760,7 +3003,7 @@ dependencies = [ "leb128", "memchr", "unicode-width", - "wasm-encoder", + "wasm-encoder 0.31.1", ] [[package]] @@ -2769,7 +3012,7 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "842e15861d203fb4a96d314b0751cdeaf0f6f8b35e8d81d2953af2af5e44e637" dependencies = [ - "wast", + "wast 62.0.1", ] [[package]] @@ -2783,6 +3026,48 @@ dependencies = [ "once_cell", ] +[[package]] +name = "wiggle" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "947e89009051ddc4e58a2d653103165147e1aee5737603044160d9bc4847aab1" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 1.3.2", + "thiserror", + "tracing", + "wasmtime", + "wiggle-macro", +] + +[[package]] +name = "wiggle-generate" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7344729841849d8841ef22164fe848ed6fce8b5eb74ab8b3739296146e10af5" +dependencies = [ + "anyhow", + "heck", + "proc-macro2", + "quote", + "shellexpand", + "syn 1.0.109", + "witx", +] + +[[package]] +name = "wiggle-macro" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93acdd0b56b3e78a272fa937135d515ea9b690f94cb452b5165ac3ae614341ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wiggle-generate", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2814,13 +3099,29 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winch-codegen" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a1a53444157fc27c3f3e98e5e19a1717efad8749959a3d493d0f6bbf0f0b3d" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "regalloc2", + "smallvec", + "target-lexicon", + "wasmparser 0.107.0", + "wasmtime-environ", +] + [[package]] name = "windows" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -2829,7 +3130,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -2838,13 +3148,28 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -2853,42 +3178,105 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winx" +version = "0.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c52a121f0fbf9320d5f2a9a5d82f6cb7557eda5e8b47fc3e7f359ec866ae960" +dependencies = [ + "bitflags 1.3.2", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "wit-parser" version = "0.8.0" @@ -2897,7 +3285,7 @@ checksum = "6daec9f093dbaea0e94043eeb92ece327bbbe70c86b1f41aca9bbfefd7f050f0" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 1.9.3", "log", "pulldown-cmark", "semver", @@ -2905,6 +3293,18 @@ dependencies = [ "url", ] +[[package]] +name = "witx" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" +dependencies = [ + "anyhow", + "log", + "thiserror", + "wast 35.0.2", +] + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/workspaces/nitro-host/Cargo.lock b/workspaces/nitro-host/Cargo.lock index 95ec2a4f6..015ce29bd 100644 --- a/workspaces/nitro-host/Cargo.lock +++ b/workspaces/nitro-host/Cargo.lock @@ -868,10 +868,6 @@ dependencies = [ "log", "nix", "serde", - "serde_json", - "stringreader", - "transport-protocol", - "uuid", ] [[package]] @@ -918,9 +914,9 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", @@ -930,8 +926,9 @@ dependencies = [ "itertools", "lalrpop-util", "petgraph", + "pico-args", "regex", - "regex-syntax", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -940,9 +937,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" dependencies = [ "regex", ] @@ -1195,20 +1192,6 @@ dependencies = [ "minimal-lexical", ] -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.3" @@ -1220,26 +1203,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-complex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -1250,29 +1213,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.16" @@ -1352,6 +1292,12 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + [[package]] name = "pin-project-lite" version = "0.2.10" @@ -1383,12 +1329,12 @@ dependencies = [ "lalrpop", "lalrpop-util", "lexical-core", + "log", "mbedtls", "regex", "serde", "serde_json", "veracruz-utils", - "wasi-types", ] [[package]] @@ -1617,7 +1563,7 @@ checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] @@ -1626,6 +1572,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1880,16 +1832,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -1970,12 +1912,6 @@ dependencies = [ "precomputed-hash", ] -[[package]] -name = "stringreader" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913e7b03d63752f6cdd2df77da36749d82669904798fe8944b9ec3d23f159905" - [[package]] name = "strsim" version = "0.8.0" @@ -2367,9 +2303,6 @@ dependencies = [ "anyhow", "base64 0.13.1", "bincode", - "clap 4.3.19", - "data-encoding", - "env_logger 0.10.0", "err-derive", "hex", "io-utils", @@ -2385,7 +2318,6 @@ dependencies = [ "reqwest", "serde", "serde_json", - "signal-hook", "tempfile", "transport-protocol", "uuid", @@ -2397,7 +2329,6 @@ name = "veracruz-utils" version = "0.3.0" dependencies = [ "anyhow", - "bincode", "chrono", "err-derive", "mbedtls", @@ -2438,18 +2369,6 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "wasi-types" -version = "0.1.6" -dependencies = [ - "bitflags", - "err-derive", - "num", - "num-derive", - "num-traits", - "serde", -] - [[package]] name = "wasm-bindgen" version = "0.2.87" diff --git a/workspaces/nitro-host/src/nitro-host/Cargo.toml b/workspaces/nitro-host/src/nitro-host/Cargo.toml index 159dbb2ef..48333289a 100644 --- a/workspaces/nitro-host/src/nitro-host/Cargo.toml +++ b/workspaces/nitro-host/src/nitro-host/Cargo.toml @@ -7,5 +7,5 @@ version = "0.3.0" [dependencies] tests = { path = "../../crates/tests", features = [ "nitro" ] } -veracruz-client = { path = "../../crates/veracruz-client", features = [ "nitro", "cli" ] } -veracruz-server = { path = "../../crates/veracruz-server", features = [ "nitro", "cli" ] } +veracruz-client = { path = "../../crates/veracruz-client", features = [ "nitro" ] } +veracruz-server = { path = "../../crates/veracruz-server", features = [ "nitro" ] } diff --git a/workspaces/nitro-runtime/Cargo.lock b/workspaces/nitro-runtime/Cargo.lock index c4e5a6109..1c125386b 100644 --- a/workspaces/nitro-runtime/Cargo.lock +++ b/workspaces/nitro-runtime/Cargo.lock @@ -31,6 +31,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -179,9 +185,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-buffer" @@ -204,6 +210,69 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +[[package]] +name = "cap-fs-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58bc48200a1a0fa6fba138b1802ad7def18ec1cdd92f7b2a04e21f1bd887f7b9" +dependencies = [ + "cap-primitives", + "cap-std", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "cap-primitives" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4b6df5b295dca8d56f35560be8c391d59f0420f72e546997154e24e765e6451" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes 1.0.11", + "ipnet", + "maybe-owned", + "rustix 0.37.23", + "windows-sys 0.48.0", + "winx 0.35.1", +] + +[[package]] +name = "cap-rand" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d25555efacb0b5244cf1d35833d55d21abc916fff0eaad254b8e2453ea9b8ab" +dependencies = [ + "ambient-authority", + "rand", +] + +[[package]] +name = "cap-std" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3373a62accd150b4fcba056d4c5f3b552127f0ec86d3c8c102d60b978174a012" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes 1.0.11", + "rustix 0.37.23", +] + +[[package]] +name = "cap-time-ext" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e95002993b7baee6b66c8950470e59e5226a23b3af39fc59c47fe416dd39821a" +dependencies = [ + "cap-primitives", + "once_cell", + "rustix 0.37.23", + "winx 0.35.1", +] + [[package]] name = "cc" version = "1.0.81" @@ -293,18 +362,18 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c289b8eac3a97329a524e953b5fd68a8416ca629e1a37287f12d9e0760aadbc" +checksum = "0ebf2f2c0abc3a31cda70b20bae56b9aeb6ad0de00c3620bfef1a7e26220edfb" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bf07ba80f53fa7f7dc97b11087ea867f7ae4621cfca21a909eca92c0b96c7d9" +checksum = "46d414ddd870ebce9b55eed9e803ef063436bd4d64160dd8e811ccbeb2c914f0" dependencies = [ "bumpalo", "cranelift-bforest", @@ -323,42 +392,42 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a7ca088173130c5c033e944756e3e441fbf3f637f32b4f6eb70252580c6dd4" +checksum = "d1b0065250c0c1fae99748aadc6003725e588542650886d76dd234eca8498598" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0114095ec7d2fbd658ed100bd007006360bc2530f57c6eee3d3838869140dbf9" +checksum = "27320b5159cfa5eadcbebceda66ac145c0aa5cb7a31948550b9636f77924081b" [[package]] name = "cranelift-control" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d56031683a55a949977e756d21826eb17a1f346143a1badc0e120a15615cd38" +checksum = "26bb54d1e129d6d3cf0e2a191ec2ba91aec1c290a048bc7595490a275d729d7a" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6565198b5684367371e2b946ceca721eb36965e75e3592fad12fc2e15f65d7b" +checksum = "4d5656cb48246a511ab1bd22431122d8d23553b7c5f7f5ccff5569f47c0b708c" dependencies = [ "serde", ] [[package]] name = "cranelift-frontend" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25f28cc44847c8b98cb921e6bfc0f7b228f4d27519376fea724d181da91709a6" +checksum = "f5321dc54f0f4e19f85d8e68543c63edfc255171cc5910c8b9a48e6210ffcdf2" dependencies = [ "cranelift-codegen", "log", @@ -368,15 +437,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80b658177e72178c438f7de5d6645c56d97af38e17fcb0b500459007b4e05cc5" +checksum = "adff1f9152fd9970ad9cc14e0d4e1b0089a75d19f8538c4dc9e19aebbd53fe60" [[package]] name = "cranelift-native" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1c7de7221e6afcc5e13ced3b218faab3bc65b47eac67400046a05418aecd6a" +checksum = "809bfa1db0b982b1796bc8c0002ab6bab959664df16095c289e567bdd22ade6f" dependencies = [ "cranelift-codegen", "libc", @@ -385,9 +454,9 @@ dependencies = [ [[package]] name = "cranelift-wasm" -version = "0.97.1" +version = "0.98.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b0d28ebe8edb6b503630c489aa4669f1e2d13b97bec7271a0fcb0e159be3ad" +checksum = "892f9273ee0c7709e839fcee769f9db1630789be5dbdfa429d84e0de8ec3dd41" dependencies = [ "cranelift-codegen", "cranelift-entity", @@ -395,7 +464,7 @@ dependencies = [ "itertools", "log", "smallvec", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-types", ] @@ -473,16 +542,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ctor" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "debugid" version = "0.8.0" @@ -518,6 +577,15 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + [[package]] name = "dirs-next" version = "2.0.0" @@ -529,10 +597,10 @@ dependencies = [ ] [[package]] -name = "dirs-sys-next" -version = "0.1.2" +name = "dirs-sys" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -540,10 +608,15 @@ dependencies = [ ] [[package]] -name = "downcast-rs" -version = "1.2.0" +name = "dirs-sys-next" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] [[package]] name = "either" @@ -560,6 +633,15 @@ dependencies = [ "log", ] +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -574,13 +656,10 @@ dependencies = [ ] [[package]] -name = "erased-serde" -version = "0.3.28" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da96524cc884f6558f1769b6c46686af2fe8e8b4cd253bd5a3cdba8181b8e070" -dependencies = [ - "serde", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "err-derive" @@ -604,7 +683,7 @@ checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -622,27 +701,19 @@ name = "execution-engine" version = "0.3.0" dependencies = [ "anyhow", - "byteorder", "cfg-if", - "err-derive", "lazy_static", "log", "mbedtls", "nix", - "num", - "num-derive", - "num-traits", "platform-services", "policy-utils", "postcard", "serde", "serde_json", - "strum", - "strum_macros", - "typetag", "wasi-types", - "wasmi", "wasmtime", + "wasmtime-wasi", ] [[package]] @@ -660,6 +731,17 @@ dependencies = [ "instant", ] +[[package]] +name = "fd-lock" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93f7a0db71c99f68398f80653ed05afb0b00e062e1a20c7ff849c4edfabbbcc" +dependencies = [ + "cfg-if", + "rustix 0.38.25", + "windows-sys 0.52.0", +] + [[package]] name = "file-per-thread-logger" version = "0.2.0" @@ -685,6 +767,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-set-times" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d167b646a876ba8fda6b50ac645cfd96242553cbaf0ca4fccaa39afcbf0801f" +dependencies = [ + "io-lifetimes 1.0.11", + "rustix 0.38.25", + "windows-sys 0.48.0", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -700,7 +793,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.1", "debugid", "fxhash", "serde", @@ -728,17 +821,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "ghost" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba330b70a5341d3bc730b8e205aaee97ddab5d9c448c4f51a7c2d924266fa8f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.28", -] - [[package]] name = "gimli" version = "0.27.3" @@ -746,7 +828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 1.9.3", "stable_deref_trait", ] @@ -786,6 +868,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heapless" version = "0.7.16" @@ -824,7 +912,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -883,6 +971,16 @@ dependencies = [ "serde", ] +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + [[package]] name = "instant" version = "0.1.12" @@ -893,13 +991,13 @@ dependencies = [ ] [[package]] -name = "inventory" -version = "0.2.3" +name = "io-extras" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84344c6e0b90a9e2b6f3f9abe5cc74402684e348df7b32adca28747e0cef091a" +checksum = "fde93d48f0d9277f977a333eca8313695ddd5301dc96f7e02aeddcb0dd99096f" dependencies = [ - "ctor", - "ghost", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", ] [[package]] @@ -910,9 +1008,15 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ "hermit-abi", "libc", - "windows-sys", + "windows-sys 0.48.0", ] +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + [[package]] name = "io-utils" version = "0.3.0" @@ -924,12 +1028,14 @@ dependencies = [ "log", "nix", "serde", - "serde_json", - "stringreader", - "transport-protocol", - "uuid", ] +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + [[package]] name = "is-terminal" version = "0.4.7" @@ -937,9 +1043,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi", - "io-lifetimes", - "rustix", - "windows-sys", + "io-lifetimes 1.0.11", + "rustix 0.37.23", + "windows-sys 0.48.0", ] [[package]] @@ -997,9 +1103,9 @@ dependencies = [ [[package]] name = "lalrpop" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1cbf952127589f2851ab2046af368fd20645491bb4b376f04b7f94d7a9837b" +checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" dependencies = [ "ascii-canvas", "bit-set", @@ -1009,8 +1115,9 @@ dependencies = [ "itertools", "lalrpop-util", "petgraph", + "pico-args", "regex", - "regex-syntax", + "regex-syntax 0.7.5", "string_cache", "term", "tiny-keccak", @@ -1019,9 +1126,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.19.12" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3c48237b9604c5a4702de6b824e02006c3214327564636aef27c1028a8fa0ed" +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" dependencies = [ "regex", ] @@ -1067,9 +1174,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.144" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" [[package]] name = "libloading" @@ -1082,16 +1189,16 @@ dependencies = [ ] [[package]] -name = "libm" -version = "0.2.7" +name = "linux-raw-sys" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.3.8" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" @@ -1118,6 +1225,12 @@ dependencies = [ "libc", ] +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "mbedtls" version = "0.10.0" @@ -1172,7 +1285,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffc89ccdc6e10d6907450f753537ebc5c5d3460d2e4e62ea74bd571db62c0f9e" dependencies = [ - "rustix", + "rustix 0.37.23", ] [[package]] @@ -1202,12 +1315,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memory_units" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8452105ba047068f40ff7093dd1d9da90898e63dd61736462e9cdda6a90ad3c3" - [[package]] name = "minimal-lexical" version = "0.2.1" @@ -1363,7 +1470,7 @@ checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" dependencies = [ "crc32fast", "hashbrown 0.13.2", - "indexmap", + "indexmap 1.9.3", "memchr", ] @@ -1373,12 +1480,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "parity-wasm" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1ad0aff30c1da14b1254fcb2af73e1fa9a28670e584a626f53a369d0e157304" - [[package]] name = "parking_lot" version = "0.12.1" @@ -1399,7 +1500,7 @@ dependencies = [ "libc", "redox_syscall 0.3.5", "smallvec", - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -1427,7 +1528,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.9.3", ] [[package]] @@ -1439,6 +1540,18 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pico-args" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + [[package]] name = "pin-utils" version = "0.1.0" @@ -1470,12 +1583,12 @@ dependencies = [ "lalrpop", "lalrpop-util", "lexical-core", + "log", "mbedtls", "regex", "serde", "serde_json", "veracruz-utils", - "wasi-types", ] [[package]] @@ -1577,7 +1690,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d39b14605eaa1f6a340aec7f320b34064feb26c93aec35d6a9a2272a8ddfa49" dependencies = [ "anyhow", - "indexmap", + "indexmap 1.9.3", "log", "protobuf", "protobuf-support", @@ -1736,7 +1849,7 @@ checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] @@ -1745,6 +1858,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1817,10 +1936,25 @@ checksum = "4d69718bf81c6127a49dc64e44a742e8bb9213c0ff8869a22c308f84c1d4ab06" dependencies = [ "bitflags 1.3.2", "errno", - "io-lifetimes", + "io-lifetimes 1.0.11", + "itoa", "libc", - "linux-raw-sys", - "windows-sys", + "linux-raw-sys 0.3.8", + "once_cell", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys 0.4.12", + "windows-sys 0.48.0", ] [[package]] @@ -1920,6 +2054,15 @@ dependencies = [ "digest", ] +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs", +] + [[package]] name = "shlex" version = "1.1.0" @@ -1990,31 +2133,6 @@ dependencies = [ "precomputed-hash", ] -[[package]] -name = "stringreader" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "913e7b03d63752f6cdd2df77da36749d82669904798fe8944b9ec3d23f159905" - -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - [[package]] name = "syn" version = "1.0.109" @@ -2049,6 +2167,22 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-interface" +version = "0.25.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10081a99cbecbc363d381b9503563785f0b02735fccbb0d4c1a2cb3d39f7e7fe" +dependencies = [ + "bitflags 2.4.1", + "cap-fs-ext", + "cap-std", + "fd-lock", + "io-lifetimes 2.0.3", + "rustix 0.38.25", + "windows-sys 0.48.0", + "winx 0.36.3", +] + [[package]] name = "target-lexicon" version = "0.12.11" @@ -2142,6 +2276,38 @@ dependencies = [ "serde", ] +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "transport-protocol" version = "0.3.0" @@ -2160,30 +2326,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" -[[package]] -name = "typetag" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4080564c5b2241b5bff53ab610082234e0c57b0417f4bd10596f183001505b8a" -dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", -] - -[[package]] -name = "typetag-impl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60147782cc30833c05fba3bab1d9b5771b2685a2557672ac96fa5d154099c0e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "unicase" version = "2.6.0" @@ -2251,7 +2393,6 @@ name = "veracruz-utils" version = "0.3.0" dependencies = [ "anyhow", - "bincode", "chrono", "err-derive", "mbedtls", @@ -2273,6 +2414,50 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi-cap-std-sync" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b22cf4595ee2af2c728a3ad5e90961556df7870e027bb054c59e0747f3533edb" +dependencies = [ + "anyhow", + "async-trait", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "io-lifetimes 1.0.11", + "is-terminal", + "once_cell", + "rustix 0.37.23", + "system-interface", + "tracing", + "wasi-common", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasi-common" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8dbf50f7f86c73af7eeb9a00d342fe20a6a2460bd7737d8db6b65e9a8216cd" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "cap-rand", + "cap-std", + "io-extras", + "log", + "rustix 0.37.23", + "thiserror", + "tracing", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + [[package]] name = "wasi-types" version = "0.1.6" @@ -2341,67 +2526,66 @@ checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "wasm-encoder" -version = "0.31.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41763f20eafed1399fff1afb466496d3a959f58241436cfdc17e3f5ca954de16" +checksum = "18c41dbd92eaebf3612a39be316540b8377c871cb9bde6b064af962984912881" dependencies = [ "leb128", ] [[package]] -name = "wasmi" -version = "0.13.2" +name = "wasm-encoder" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41763f20eafed1399fff1afb466496d3a959f58241436cfdc17e3f5ca954de16" dependencies = [ - "parity-wasm", - "serde", - "typetag", - "wasmi-validation", - "wasmi_core", + "leb128", ] [[package]] -name = "wasmi-validation" -version = "0.5.0" +name = "wasmparser" +version = "0.107.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" dependencies = [ - "parity-wasm", + "indexmap 1.9.3", + "semver", ] [[package]] -name = "wasmi_core" -version = "0.2.1" +name = "wasmparser" +version = "0.118.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" dependencies = [ - "downcast-rs", - "libm", - "memory_units", - "num-rational", - "num-traits", - "serde", - "typetag", + "indexmap 2.1.0", + "semver", ] [[package]] -name = "wasmparser" -version = "0.107.0" +name = "wasmprinter" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e3ac9b780c7dda0cac7a52a5d6d2d6707cc6e3451c9db209b6c758f40d7acb" +checksum = "3d027eb8294904fc715ac0870cebe6b0271e96b90605ee21511e7565c4ce568c" dependencies = [ - "indexmap", - "semver", + "anyhow", + "wasmparser 0.118.1", ] [[package]] name = "wasmtime" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd02b992d828b91efaf2a7499b21205fe4ab3002e401e3fe0f227aaeb4001d93" +checksum = "028253baf4df6e0823481845a380117de2b7f42166261551db7d097d60cfc685" dependencies = [ "anyhow", "async-trait", "bincode", "bumpalo", "cfg-if", + "encoding_rs", "fxprof-processed-profile", - "indexmap", + "indexmap 1.9.3", "libc", "log", "object", @@ -2412,32 +2596,34 @@ dependencies = [ "serde", "serde_json", "target-lexicon", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-cache", "wasmtime-component-macro", + "wasmtime-component-util", "wasmtime-cranelift", "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit", "wasmtime-runtime", + "wasmtime-winch", "wat", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-asm-macros" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284466ef356ce2d909bc0ad470b60c4d0df5df2de9084457e118131b3c779b92" +checksum = "e76c6e968fb3df273a8140bb9e02693b17da1f53a3bbafa0a5811e8ef1031cd8" dependencies = [ "cfg-if", ] [[package]] name = "wasmtime-cache" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc78cfe1a758d1336f447a47af6ec05e0df2c03c93440d70faf80e17fbb001e" +checksum = "34308e5033adb530c18de06f6f2d1de2c0cb6dc19e9c13451acf97ec4e07b30a" dependencies = [ "anyhow", "base64 0.21.2", @@ -2445,19 +2631,19 @@ dependencies = [ "directories-next", "file-per-thread-logger", "log", - "rustix", + "rustix 0.37.23", "serde", "sha2", "toml", - "windows-sys", + "windows-sys 0.48.0", "zstd", ] [[package]] name = "wasmtime-component-macro" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e916103436a6d84faa4c2083e2e98612a323c2cc6147ec419124f67c764c9c" +checksum = "1631a5fed4e162edf7e0604845e6150903f17099970e1a0020f540831d0f8479" dependencies = [ "anyhow", "proc-macro2", @@ -2470,15 +2656,15 @@ dependencies = [ [[package]] name = "wasmtime-component-util" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f20a5135ec5ef01080e674979b02d6fa5eebaa2b0c2d6660513ee9956a1bf624" +checksum = "31bd6b1c6d8ece2aa852bf5dad0ea91be63e81c7571d7bcf24238b05405adb70" [[package]] name = "wasmtime-cranelift" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1aa99cbf3f8edb5ad8408ba380f5ab481528ecd8a5053acf758e006d6727fd" +checksum = "696333ffdbd9fabb486d8a5ee82c75fcd22d199446d3df04935a286fcbb40100" dependencies = [ "anyhow", "cranelift-codegen", @@ -2492,16 +2678,16 @@ dependencies = [ "object", "target-lexicon", "thiserror", - "wasmparser", + "wasmparser 0.107.0", "wasmtime-cranelift-shared", "wasmtime-environ", ] [[package]] name = "wasmtime-cranelift-shared" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce31fd55978601acc103acbb8a26f81c89a6eae12d3a1c59f34151dfa609484" +checksum = "434899162f65339ae7710f6fba91083b86e707cb618a8f4e8b037b8d46223d56" dependencies = [ "anyhow", "cranelift-codegen", @@ -2515,41 +2701,44 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f9e58e0ee7d43ff13e75375c726b16bce022db798d3a099a65eeaa7d7a544b" +checksum = "1189b2fa0e7fbf71a06c7c909ae7f8f0085f8f4e4365926d6ff1052e024effe9" dependencies = [ "anyhow", "cranelift-entity", "gimli", - "indexmap", + "indexmap 1.9.3", "log", "object", "serde", "target-lexicon", "thiserror", - "wasmparser", + "wasm-encoder 0.29.0", + "wasmparser 0.107.0", + "wasmprinter", + "wasmtime-component-util", "wasmtime-types", ] [[package]] name = "wasmtime-fiber" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14309cbdf2c395258b124a24757c727403070c0465a28bcc780c4f82f4bca5ff" +checksum = "e0e22d42113a1181fee3477f96639fd88c757b303f7083e866691f47a06065c5" dependencies = [ "cc", "cfg-if", - "rustix", + "rustix 0.37.23", "wasmtime-asm-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-jit" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0f2eaeb01bb67266416507829bd8e0bb60278444e4cbd048e280833ebeaa02" +checksum = "b3b904e4920c5725dae5d2445c5923092f1d0dead3a521bd7f4218d7a9496842" dependencies = [ "addr2line", "anyhow", @@ -2561,48 +2750,49 @@ dependencies = [ "log", "object", "rustc-demangle", - "rustix", + "rustix 0.37.23", "serde", "target-lexicon", "wasmtime-environ", "wasmtime-jit-debug", "wasmtime-jit-icache-coherence", "wasmtime-runtime", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-jit-debug" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f42e59d62542bfb73ce30672db7eaf4084a60b434b688ac4f05b287d497de082" +checksum = "c7228ed7aaedec75d6bd298f857e42f4626cffdb7b577c018eb2075c65d44dcf" dependencies = [ "object", "once_cell", - "rustix", + "rustix 0.37.23", ] [[package]] name = "wasmtime-jit-icache-coherence" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b49ceb7e2105a8ebe5614d7bbab6f6ef137a284e371633af60b34925493081f" +checksum = "517750d84b6ebdb2c32226cee412c7e6aa48e4cebbb259d9a227b4317426adc6" dependencies = [ "cfg-if", "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-runtime" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5de4762421b0b2b19e02111ca403632852b53e506e03b4b227ffb0fbfa63c2" +checksum = "c89ef7f9d70f30fc5dfea15b61b65b81363bf8b3881ab76de3a7b24905c4e83a" dependencies = [ "anyhow", "cc", "cfg-if", - "indexmap", + "encoding_rs", + "indexmap 1.9.3", "libc", "log", "mach", @@ -2610,38 +2800,91 @@ dependencies = [ "memoffset 0.8.0", "paste", "rand", - "rustix", + "rustix 0.37.23", "sptr", "wasmtime-asm-macros", "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit-debug", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "wasmtime-types" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbb7c138f797192f46afdd3ec16f85ef007c3bb45fa8e5174031f17b0be4c4a" +checksum = "2ac19aadf941ad333cbb0307121482700d925a99624d4110859d69b7f658b69d" dependencies = [ "cranelift-entity", "serde", "thiserror", - "wasmparser", + "wasmparser 0.107.0", +] + +[[package]] +name = "wasmtime-wasi" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2214bfed500d91f2cf020c085bbdac431b27ab5e683000a65ede93c9b1fd7c14" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 1.3.2", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "libc", + "rustix 0.37.23", + "system-interface", + "thiserror", + "tracing", + "wasi-cap-std-sync", + "wasi-common", + "wasmtime", + "wiggle", + "windows-sys 0.48.0", +] + +[[package]] +name = "wasmtime-winch" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa0f80e89ec9671a6efc1507c37a3748a63b2566033d7d0993fa711696c4b24" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "object", + "target-lexicon", + "wasmparser 0.107.0", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "winch-codegen", ] [[package]] name = "wasmtime-wit-bindgen" -version = "10.0.1" +version = "11.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3334b0466a4d340de345cda83474d1d2c429770c3d667877971407672bc618a" +checksum = "aed98de4b3e68b1abe60f0dc59ecd74b757d70a39459d500a727a8cab3311bbb" dependencies = [ "anyhow", "heck", "wit-parser", ] +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", +] + [[package]] name = "wast" version = "62.0.1" @@ -2651,7 +2894,7 @@ dependencies = [ "leb128", "memchr", "unicode-width", - "wasm-encoder", + "wasm-encoder 0.31.1", ] [[package]] @@ -2660,7 +2903,7 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "842e15861d203fb4a96d314b0751cdeaf0f6f8b35e8d81d2953af2af5e44e637" dependencies = [ - "wast", + "wast 62.0.1", ] [[package]] @@ -2674,6 +2917,48 @@ dependencies = [ "once_cell", ] +[[package]] +name = "wiggle" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "947e89009051ddc4e58a2d653103165147e1aee5737603044160d9bc4847aab1" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 1.3.2", + "thiserror", + "tracing", + "wasmtime", + "wiggle-macro", +] + +[[package]] +name = "wiggle-generate" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7344729841849d8841ef22164fe848ed6fce8b5eb74ab8b3739296146e10af5" +dependencies = [ + "anyhow", + "heck", + "proc-macro2", + "quote", + "shellexpand", + "syn 1.0.109", + "witx", +] + +[[package]] +name = "wiggle-macro" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93acdd0b56b3e78a272fa937135d515ea9b690f94cb452b5165ac3ae614341ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "wiggle-generate", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2705,13 +2990,29 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winch-codegen" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1a1a53444157fc27c3f3e98e5e19a1717efad8749959a3d493d0f6bbf0f0b3d" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "regalloc2", + "smallvec", + "target-lexicon", + "wasmparser 0.107.0", + "wasmtime-environ", +] + [[package]] name = "windows" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", ] [[package]] @@ -2720,7 +3021,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.1", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -2729,13 +3039,28 @@ version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -2744,42 +3069,105 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + +[[package]] +name = "winx" +version = "0.35.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c52a121f0fbf9320d5f2a9a5d82f6cb7557eda5e8b47fc3e7f359ec866ae960" +dependencies = [ + "bitflags 1.3.2", + "io-lifetimes 1.0.11", + "windows-sys 0.48.0", +] + +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.1", + "windows-sys 0.52.0", +] + [[package]] name = "wit-parser" version = "0.8.0" @@ -2788,7 +3176,7 @@ checksum = "6daec9f093dbaea0e94043eeb92ece327bbbe70c86b1f41aca9bbfefd7f050f0" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 1.9.3", "log", "pulldown-cmark", "semver", @@ -2796,6 +3184,18 @@ dependencies = [ "url", ] +[[package]] +name = "witx" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" +dependencies = [ + "anyhow", + "log", + "thiserror", + "wast 35.0.2", +] + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/workspaces/shared.mk b/workspaces/shared.mk index fdb2c85ba..98a922e2b 100644 --- a/workspaces/shared.mk +++ b/workspaces/shared.mk @@ -33,7 +33,6 @@ WASM_PROG_LIST = random-source.wasm \ random-u32-list.wasm \ shamir-secret-sharing.wasm \ sort-numbers.wasm \ - fd-create.wasm \ aesctr-native.wasm WASM_PROG_FILES = $(patsubst %.wasm, $(OUT_DIR)/%.wasm, $(WASM_PROG_LIST)) @@ -101,43 +100,12 @@ datasets: $(OUT_DIR) $(CERTS) $(KEYS) $(CA_KEY) $(CA_CRT) ################################################### # Generate Policy Files -# Numbers for wasi rights -FD_DATASYNC := $(shell echo "2^0" | bc) -FD_READ := $(shell echo "2^1" | bc) -FD_SEEK := $(shell echo "2^2" | bc) -FD_FDSTAT_SET_FLAGS := $(shell echo "2^3" | bc) -FD_SYNC := $(shell echo "2^4" | bc) -FD_TELL := $(shell echo "2^5" | bc) -FD_WRITE := $(shell echo "2^6" | bc) -FD_ADVISE := $(shell echo "2^7" | bc) -FD_ALLOCATE := $(shell echo "2^8" | bc) -PATH_CREATE_DIRECTORY := $(shell echo "2^9" | bc) -PATH_CREATE_FILE := $(shell echo "2^10" | bc) -PATH_LINK_SOURCE := $(shell echo "2^11" | bc) -PATH_LINK_TARGET := $(shell echo "2^12" | bc) -PATH_OPEN := $(shell echo "2^13" | bc) -FD_READDIR := $(shell echo "2^14" | bc) -PATH_READLINK := $(shell echo "2^15" | bc) -PATH_RENAME_SOURCE := $(shell echo "2^16" | bc) -PATH_RENAME_TARGET := $(shell echo "2^17" | bc) -PATH_FILESTAT_GET := $(shell echo "2^18" | bc) -PATH_FILESTAT_SET_SIZE := $(shell echo "2^19" | bc) -PATH_FILESTAT_SET_TIMES := $(shell echo "2^20" | bc) -FD_FILESTAT_GET := $(shell echo "2^21" | bc) -FD_FILESTAT_SET_SIZE := $(shell echo "2^22" | bc) -FD_FILESTAT_SET_TIMES := $(shell echo "2^23" | bc) -PATH_SYMLINK := $(shell echo "2^24" | bc) -PATH_REMOVE_DIRECTORY := $(shell echo "2^25" | bc) -PATH_UNLINK_FILE := $(shell echo "2^26" | bc) -POLL_FD_READWRITE := $(shell echo "2^27" | bc) -SOCK_SHUTDOWN := $(shell echo "2^28" | bc) -FD_EXECUTE := $(shell echo "2^29" | bc) # Common rights -READ_RIGHT := $(shell echo $(FD_READ) + $(FD_SEEK) + $(PATH_OPEN) + $(FD_READDIR) | bc) -WRITE_RIGHT := $(shell echo $(FD_WRITE) + $(PATH_CREATE_FILE) + $(PATH_FILESTAT_SET_SIZE) + $(FD_SEEK) + $(PATH_OPEN) + $(PATH_CREATE_DIRECTORY) | bc) -READ_WRITE_RIGHT := $(shell echo $(FD_READ) + $(FD_SEEK) + $(PATH_OPEN) + $(FD_READDIR) + $(FD_WRITE) + $(PATH_CREATE_FILE) + $(PATH_FILESTAT_SET_SIZE) + $(PATH_CREATE_DIRECTORY) | bc) -OPEN_EXECUTE_RIGHT := $(shell echo $(PATH_OPEN) + $(FD_EXECUTE) + $(FD_SEEK) | bc) -WRITE_EXECUTE_RIGHT := $(shell echo $(FD_WRITE) + $(PATH_CREATE_FILE) + $(PATH_FILESTAT_SET_SIZE) + $(FD_SEEK) + $(PATH_OPEN) + $(PATH_CREATE_DIRECTORY) + $(FD_EXECUTE) | bc) +READ_RIGHT := r +WRITE_RIGHT := w +READ_WRITE_RIGHT := rw +OPEN_EXECUTE_RIGHT := rx +WRITE_EXECUTE_RIGHT := wx ifeq ($(PLATFORM), Darwin) CERTIFICATE_EXPIRY := "$(shell date -Rf +100d)" @@ -149,15 +117,12 @@ endif POLICY_FILES ?= \ single_client.json \ - single_client_no_debug.json \ dual_policy.json \ dual_parallel_policy.json \ triple_policy_1.json \ triple_policy_2.json \ triple_policy_4.json \ - quadruple_policy.json \ - single_client_postcard_native.json \ - single_client_aesctr_native.json + quadruple_policy.json PGEN = $(WORKSPACE_DIR)/host/target/$(PROFILE_PATH)/generate-policy @@ -168,81 +133,73 @@ $(PGEN): $(WORKSPACE_DIR)/host/crates/generate-policy/src/main.rs \ policy-files: $(OUT_DIR) measurement-file $(patsubst %.json, $(OUT_DIR)/%.json, $(POLICY_FILES)) @echo $(INFO_COLOR)"GEN => $(POLICY_FILES)"$(RESET_COLOR) -PROGRAM_DIR = /program/ +PROGRAM_DIR = ./program/ CREDENTIALS = $(CA_CRT) $(CLIENT_CRT) $(PROGRAM_CRT) $(DATA_CRT) $(RESULT_CRT) $(MEASUREMENT_FILE) -PGEN_COMMON_PARAMS = --proxy-attestation-server-cert $(CA_CRT) $(MEASUREMENT_PARAMETER) \ - --certificate-expiry $(CERTIFICATE_EXPIRY) --execution-strategy Interpretation +PGEN_COMMON_PARAMS = + +CLIENT_WRITE_PROG_CAPABILITY = "./input/:$(WRITE_RIGHT),./output/:$(READ_RIGHT),$(PROGRAM_DIR):$(WRITE_EXECUTE_RIGHT),/tmp/:$(READ_WRITE_RIGHT)" +CLIENT_READ_PROG_CAPABILITY = "./input/:$(WRITE_RIGHT),./output/:$(READ_RIGHT),$(PROGRAM_DIR):$(OPEN_EXECUTE_RIGHT),/tmp/:$(READ_WRITE_RIGHT)" +DEFAULT_PROGRAM_LIST = $(foreach prog_name,$(WASM_PROG_FILES),--program-binary "$(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) => ./input/:$(READ_RIGHT),./output/:$(READ_WRITE_RIGHT),/tmp/:$(READ_WRITE_RIGHT)") +DEFAULT_NATIVE_MODULE_LIST = --service "Postcard Service => /tmp/postcard/" --service "Echo Service => /tmp/echo/" --service "Counter mode AES Service => /tmp/aes/" MAX_MEMORY_MIB = 256 +DEFAULT_FLAGS = --proxy-attestation-server-ip 127.0.0.1:3010 \ + --proxy-attestation-server-cert $(CA_CRT) $(MEASUREMENT_PARAMETER) \ + --certificate-expiry $(CERTIFICATE_EXPIRY) \ + --execution-strategy JIT \ + --max-memory-mib $(MAX_MEMORY_MIB) $(OUT_DIR)/single_client.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) - cd $(OUT_DIR) ; $(PGEN) --certificate $(CLIENT_CRT) \ - --capability "/input/: $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT), /services/ : $(READ_WRITE_RIGHT)") \ - --pipeline "$(PROGRAM_DIR)random-u32-list.wasm ; if /output/unsorted_numbers.txt { $(PROGRAM_DIR)sort-numbers.wasm ; }" --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT), /services/ : $(READ_WRITE_RIGHT)" \ - --veracruz-server-ip 127.0.0.1:3011 --proxy-attestation-server-ip 127.0.0.1:3010 \ - --enclave-debug-mode $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) --output-policy-file $@ - -$(OUT_DIR)/single_client_no_debug.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) - cd $(OUT_DIR) ; $(PGEN) --certificate $(CLIENT_CRT) \ - --capability "/input/: $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT), /services/ : $(READ_WRITE_RIGHT)") \ - --veracruz-server-ip 127.0.0.1:3011 --proxy-attestation-server-ip 127.0.0.1:3010 \ - $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) --output-policy-file $@ + cd $(OUT_DIR) ; $(PGEN) --certificate "$(CLIENT_CRT) => $(CLIENT_WRITE_PROG_CAPABILITY)" \ + $(DEFAULT_PROGRAM_LIST) \ + --pipeline "$(PROGRAM_DIR)random-u32-list.wasm ; if ./output/unsorted_numbers.txt { $(PROGRAM_DIR)sort-numbers.wasm ; } => ./input/:$(READ_RIGHT),./output/:$(READ_WRITE_RIGHT),/tmp/:$(READ_WRITE_RIGHT)" \ + $(DEFAULT_NATIVE_MODULE_LIST) \ + --veracruz-server-ip 127.0.0.1:3011 \ + $(DEFAULT_FLAGS) \ + --output-policy-file $@ $(OUT_DIR)/dual_policy.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) cd $(OUT_DIR) ; $(PGEN) \ - --certificate $(PROGRAM_CRT) --capability "$(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - --certificate $(DATA_CRT) --capability "/input/ : $(WRITE_RIGHT), /output/ : $(READ_RIGHT), stdin : $(WRITE_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT)") \ - --veracruz-server-ip 127.0.0.1:3012 --proxy-attestation-server-ip 127.0.0.1:3010 \ - --enable-clock $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) --output-policy-file $@ + --certificate "$(PROGRAM_CRT) => $(PROGRAM_DIR):$(WRITE_EXECUTE_RIGHT)" \ + --certificate "$(DATA_CRT) => ./input/:$(WRITE_RIGHT),./output/:$(READ_RIGHT)" \ + $(DEFAULT_PROGRAM_LIST) \ + $(DEFAULT_NATIVE_MODULE_LIST) \ + --veracruz-server-ip 127.0.0.1:3012 \ + $(DEFAULT_FLAGS) \ + --output-policy-file $@ $(OUT_DIR)/dual_parallel_policy.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) cd $(OUT_DIR) ; $(PGEN) \ - --certificate $(PROGRAM_CRT) --capability "$(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - --certificate $(DATA_CRT) --capability "/input/ : $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(OPEN_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT)") \ - --veracruz-server-ip 127.0.0.1:3013 --proxy-attestation-server-ip 127.0.0.1:3010 \ - --enable-clock $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) --output-policy-file $@ + --certificate "$(PROGRAM_CRT) => $(PROGRAM_DIR):$(WRITE_EXECUTE_RIGHT)" \ + --certificate "$(DATA_CRT) => $(CLIENT_READ_PROG_CAPABILITY)" \ + $(DEFAULT_PROGRAM_LIST) \ + $(DEFAULT_NATIVE_MODULE_LIST) \ + --veracruz-server-ip 127.0.0.1:3013 \ + $(DEFAULT_FLAGS) \ + --output-policy-file $@ # Generate all the triple policy but on different port. $(OUT_DIR)/triple_policy_%.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) cd $(OUT_DIR) ; $(PGEN) \ - --certificate $(PROGRAM_CRT) --capability "$(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - --certificate $(DATA_CRT) --capability "/input/ : $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(OPEN_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT)" \ - --certificate $(RESULT_CRT) --capability "/input/ : $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(OPEN_EXECUTE_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT)") \ - --veracruz-server-ip 127.0.0.1:$(shell echo "3020 + $*" | bc) \ - --proxy-attestation-server-ip 127.0.0.1:3010 \ - --enable-clock $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) --output-policy-file $@ + --certificate "$(PROGRAM_CRT) => $(PROGRAM_DIR):$(WRITE_EXECUTE_RIGHT)" \ + --certificate "$(DATA_CRT) => $(CLIENT_READ_PROG_CAPABILITY)" \ + --certificate "$(RESULT_CRT) => $(CLIENT_READ_PROG_CAPABILITY)" \ + $(DEFAULT_PROGRAM_LIST) \ + $(DEFAULT_NATIVE_MODULE_LIST) \ + --veracruz-server-ip 127.0.0.1:$(shell echo "3020 + $*" | bc) \ + $(DEFAULT_FLAGS) \ + --output-policy-file $@ $(OUT_DIR)/quadruple_policy.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) cd $(OUT_DIR) ; $(PGEN) \ - --certificate $(PROGRAM_CRT) --capability "$(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - --certificate $(DATA_CRT) --capability "/input/ : $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(OPEN_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT)" \ - --certificate $(NEVER_CRT) --capability "/input/ : $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(OPEN_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT)" \ - --certificate $(RESULT_CRT) --capability "/input/ : $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(OPEN_EXECUTE_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT)") \ - --veracruz-server-ip 127.0.0.1:3030 --proxy-attestation-server-ip 127.0.0.1:3010 \ - --enable-clock $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) --output-policy-file $@ - -$(OUT_DIR)/single_client_postcard_native.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) - cd $(OUT_DIR) ; $(PGEN) --certificate $(CLIENT_CRT) \ - --capability "/input/: $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT), /services/ : $(READ_WRITE_RIGHT)") \ - --veracruz-server-ip 127.0.0.1:3011 --proxy-attestation-server-ip 127.0.0.1:3010 \ - --enclave-debug-mode $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) \ - --native-module-name "Postcard Service" --native-module-special-file "/services/postcard_string.dat" --native-module-entry-point "" \ - --output-policy-file $@ - -$(OUT_DIR)/single_client_aesctr_native.json: $(PGEN) $(CREDENTIALS) $(WASM_PROG_FILES) $(RUNTIME_ENCLAVE_BINARY_PATH) - cd $(OUT_DIR) ; $(PGEN) --certificate $(CLIENT_CRT) \ - --capability "/input/: $(WRITE_RIGHT), /output/ : $(READ_RIGHT), $(PROGRAM_DIR) : $(WRITE_EXECUTE_RIGHT), stdin : $(WRITE_RIGHT), stderr : $(READ_RIGHT), stdout : $(READ_RIGHT)" \ - $(foreach prog_name,$(WASM_PROG_FILES),--program-binary $(PROGRAM_DIR)$(notdir $(prog_name))=$(prog_name) --capability "/input/ : $(READ_RIGHT), /output/ : $(READ_WRITE_RIGHT), stdin : $(READ_RIGHT), stderr : $(WRITE_RIGHT), stdout : $(WRITE_RIGHT), /services/ : $(READ_WRITE_RIGHT)") \ - --veracruz-server-ip 127.0.0.1:3011 --proxy-attestation-server-ip 127.0.0.1:3010 \ - --enclave-debug-mode $(PGEN_COMMON_PARAMS) --max-memory-mib $(MAX_MEMORY_MIB) \ - --native-module-name "Counter mode AES Service" --native-module-special-file "/services/aesctr.dat" --native-module-entry-point "" \ + --certificate "$(PROGRAM_CRT) => $(PROGRAM_DIR):$(WRITE_EXECUTE_RIGHT)" \ + --certificate "$(DATA_CRT) => $(CLIENT_READ_PROG_CAPABILITY)" \ + --certificate "$(NEVER_CRT) => $(CLIENT_READ_PROG_CAPABILITY)" \ + --certificate "$(RESULT_CRT) => $(CLIENT_READ_PROG_CAPABILITY)" \ + $(DEFAULT_PROGRAM_LIST) \ + $(DEFAULT_NATIVE_MODULE_LIST) \ + --veracruz-server-ip 127.0.0.1:3030 \ + $(DEFAULT_FLAGS) \ --output-policy-file $@