Skip to content
This repository was archived by the owner on Feb 18, 2026. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ede4113
Update the rust toolchain to 1.70.
ShaleXIONG Jul 25, 2023
b7eba4c
Update the lolrpop version.
ShaleXIONG Jul 25, 2023
e7de1ee
Update the wasmtime and wasmi version.
ShaleXIONG Jul 25, 2023
e4709b4
Use the kernal file system in wasmtime, and wire into freestanding ex…
ShaleXIONG Aug 22, 2023
49ecc60
Remove the vfs but use the kernel filesystem.
ShaleXIONG Sep 5, 2023
688e02d
update the example to use relative path.
ShaleXIONG Sep 28, 2023
e5b23f8
Rework on the engine and related, use the kernel file system.
ShaleXIONG Oct 2, 2023
e133c37
Update the makefiles for the new engine.
ShaleXIONG Oct 2, 2023
ffdb9a6
Remove appending the root `/` in veracruz client when calling write f…
ShaleXIONG Oct 3, 2023
f1fcfe6
Update the test suite on the engine rework.
ShaleXIONG Oct 3, 2023
fa0e80d
Fix a big in wrong import in freestanding.
ShaleXIONG Oct 3, 2023
02aa1d6
Temporarily comment out the test case for native module.
ShaleXIONG Oct 3, 2023
ec25967
Update all the cargo.toml file.
ShaleXIONG Oct 4, 2023
ade56f7
Rework on the permission check for (remote) clients.
ShaleXIONG Oct 6, 2023
b304a68
Remove dead code and unifies Cargo.toml.
ShaleXIONG Oct 6, 2023
a7aea77
Rework on the native module interface using the linux named pipeline.
ShaleXIONG Nov 1, 2023
b943904
Check the execution permission in the execution engine before running.
ShaleXIONG Nov 1, 2023
04fd9c2
Rework and simplify on the Sandbox for native binary.
ShaleXIONG Nov 24, 2023
67bd9ce
Fix a bug caused by type check of policy.
ShaleXIONG Nov 24, 2023
5a57695
Rework on the generate policy, use derive from clap.
ShaleXIONG Nov 24, 2023
f817133
Add the missing program hash when generating policy.
ShaleXIONG Nov 24, 2023
0e3054e
Update the generate policy script
ShaleXIONG Nov 24, 2023
445ce36
Fix a bug due to whitespace in policy generation.
ShaleXIONG Nov 24, 2023
8e3b2eb
Remove the application code for fd_create, which is no longer used.
ShaleXIONG Nov 27, 2023
786af80
Update the machnism to load internal native module by matching name.
ShaleXIONG Nov 28, 2023
0e12d5a
Generate the spec of the native service in the policy.
ShaleXIONG Nov 28, 2023
93913c3
Add the missing `Execution` Trait definition.
ShaleXIONG Nov 28, 2023
3f14c48
Remove an unused mod in execution-engine.
ShaleXIONG Nov 30, 2023
01caffe
Fix the quickstart test in the CI.
ShaleXIONG Dec 4, 2023
31f96a5
Update the shamir example.
ShaleXIONG Dec 4, 2023
8e1ee26
Update Cargo.lock.
ShaleXIONG Dec 8, 2023
7f66daf
TEST minor
ShaleXIONG Dec 7, 2023
258dc1f
Fix the directory mapping in Sandbox.
ShaleXIONG Jan 29, 2024
854c975
fix a merge mistake
ShaleXIONG Apr 2, 2024
dbea580
update cargo.lock
ShaleXIONG Apr 3, 2024
f825222
update the CI script.
ShaleXIONG Apr 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Rework on the permission check for (remote) clients.
  • Loading branch information
ShaleXIONG committed Apr 5, 2024
commit ade56f74469993ed75fddf426e7567a16d29c7d8
11 changes: 10 additions & 1 deletion crates/execution-engine/src/engines/wasmtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::{
fs::{create_dir_all, File},
};
use wasmtime::{Config, Engine, Linker, Module, Store};
use wasmtime_wasi::sync::{Dir, WasiCtxBuilder};
use wasmtime_wasi::sync::{Dir, WasiCtxBuilder, TcpListener};
use policy_utils::principal::PrincipalPermission;

////////////////////////////////////////////////////////////////////////////////
Expand All @@ -32,6 +32,8 @@ use policy_utils::principal::PrincipalPermission;
pub struct WasmtimeRuntimeState {
permissions: PrincipalPermission,
environment: Environment,
// Careful on the type name conflict, here we want the TcpListener from std.
sockets: Vec<(u32,std::net::TcpListener)>,
}

////////////////////////////////////////////////////////////////////////////////
Expand All @@ -45,6 +47,7 @@ impl WasmtimeRuntimeState {
Ok(Self {
permissions,
environment,
sockets: Vec::new(),
})
}
}
Expand Down Expand Up @@ -98,6 +101,12 @@ impl ExecutionEngine for WasmtimeRuntimeState {
Ok(wasm_build.preopened_dir(Dir::from_std_file(file), path)?)
})?;

let wasm_build = self.sockets.iter().fold(Ok(wasm_build), |acc : Result<WasiCtxBuilder>, (fd,listener)| {
let wasm_build = acc?;
info!("bind fd {:?}", fd);
Ok(wasm_build.preopened_socket(*fd, TcpListener::from_std(listener.try_clone()?))?)
})?;

let wasi = wasm_build.build();
let mut store = Store::new(&engine, wasi);
let module = Module::new(&engine, program)?;
Expand Down
10 changes: 5 additions & 5 deletions crates/execution-engine/src/pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn is_wasm_binary(path_string: &String) -> bool {
/// The function will return the error code.
pub fn execute_pipeline(
strategy: &ExecutionStrategy,
permissions: &PrincipalPermission,
execution_permissions: &PrincipalPermission,
pipeline: Box<Expr>,
env: &Environment,
) -> Result<u32> {
Expand All @@ -53,7 +53,7 @@ pub fn execute_pipeline(
// Read and call execute_WASM program
let binary = fs::read(path)?;
let return_code =
execute_program(strategy, permissions, binary, env)?;
execute_program(strategy, execution_permissions, binary, env)?;
Ok(return_code)
} else {
info!("Invoke native binary: {}", path);
Expand All @@ -79,7 +79,7 @@ pub fn execute_pipeline(
Seq(vec) => {
info!("Seq {:?}", vec);
for expr in vec {
let return_code = execute_pipeline(strategy, permissions, expr, env)?;
let return_code = execute_pipeline(strategy, execution_permissions, expr, env)?;

// An error occurs
if return_code != 0 {
Expand All @@ -93,10 +93,10 @@ pub fn execute_pipeline(
IfElse(cond, true_branch, false_branch) => {
info!("IfElse {:?} true -> {:?} false -> {:?}", cond, true_branch, false_branch);
let return_code = if Path::new(&cond).exists() {
execute_pipeline(strategy, permissions, true_branch, env)?
execute_pipeline(strategy, execution_permissions, true_branch, env)?
} else {
match false_branch {
Some(f) => execute_pipeline(strategy, permissions, f, env)?,
Some(f) => execute_pipeline(strategy, execution_permissions, f, env)?,
None => 0,
}
};
Expand Down
2 changes: 1 addition & 1 deletion crates/policy-utils/src/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use crate::pipeline::Expr;
use lalrpop_util::lalrpop_mod;
#[cfg(feature = "std")]
use std::{ffi, path};
use std::path;

lalrpop_mod!(pipeline);

Expand Down
61 changes: 32 additions & 29 deletions crates/policy-utils/src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
use super::{
error::PolicyError,
expiry::Timepoint,
principal::{PermissionTable, FilePermissions, ExecutionStrategy, FileHash, Identity, NativeModule, Pipeline, Principal, Program},
principal::{PrincipalPermission, FilePermissions, ExecutionStrategy, FileHash, Identity, NativeModule, Pipeline, Principal, Program},
Platform,
};
use anyhow::{anyhow, Result};
Expand Down Expand Up @@ -292,10 +292,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
Expand All @@ -314,49 +314,52 @@ 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<u64> {
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
/// X509 certificate, `cert`, is present within the list of
/// identities/principals associated with this policy. Otherwise, returns
/// an error.
pub fn check_client_id(&self, cert: &str) -> Result<u64> {
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(
cert.to_string()
)))
}

/// Return the CapabilityTable in this policy. It contains capabilities related to all
/// participants and programs.
pub fn get_rights_table(&self) -> PermissionTable {
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<PrincipalPermission> {
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) => {
if let Some(principal) = self.pipelines.iter().find(|x| name == x.name()) {
return Ok(principal.file_rights_map())
}
},
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.
Expand Down
56 changes: 53 additions & 3 deletions crates/policy-utils/src/principal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::error::PolicyError;
use crate::{parsers::parse_pipeline, pipeline::Expr};
use anyhow::{anyhow, Result};
use serde::{Deserialize, Serialize, Serializer, Deserializer};
use std::{collections::HashMap, fmt::Debug, path::PathBuf, string::String};
use std::{collections::HashMap, fmt::Debug, path::{Path, PathBuf}, string::String};


////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -44,6 +44,36 @@ pub enum Principal {
pub type PrincipalPermission = HashMap<PathBuf, FilePermissions>;
pub type PermissionTable = HashMap<Principal, PrincipalPermission>;

/// Check if the `target_path` is allowed to perform `target_permission` in the `table`.
pub fn check_permission<T: AsRef<Path>>(
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)]
pub struct FilePermissions {
Expand All @@ -58,6 +88,20 @@ impl FilePermissions {
pub fn new(read: bool, write: bool, execute: bool) -> Self {
Self { read, write, execute }
}

/// 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)
}
}

/// Custom serialize and deserialize to "rwx"
Expand Down Expand Up @@ -363,8 +407,14 @@ impl<U> Identity<U> {

/// 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
}
}

Expand Down
Loading