Skip to content
This repository has been archived by the owner on May 28, 2024. It is now read-only.

Commit

Permalink
[Addon] Enable whitelist command option
Browse files Browse the repository at this point in the history
  • Loading branch information
hydai authored and dm4 committed Apr 28, 2021
1 parent baf7ef9 commit 65457dc
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 21 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/external-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ jobs:
sudo apt-get install llvm-dev liblld-10-dev libboost-all-dev
npm i -g ssvmup
- name: Set Rust to required version
run: rustup override set 1.50.0

- name: Build and install SSVM-napi
uses: './ssvm-napi/.github/actions/build-from-source'
with:
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ jobs:
run: |
sudo apt-get install llvm-dev liblld-10-dev libboost-all-dev
- name: Set Rust to required version
run: rustup override set 1.50.0

- name: Build SSVM-napi with ${{ matrix.cc }}
uses: './.github/actions/build-from-source'
with:
Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ Please refer to [Tutorial: A standalone wasm32-wasi application](./Tutorial_Wasm
2. Wasm bytecode format which is the content of a wasm binary file (Uint8Array)
* `options`: An options object for setup the SSVM execution environment.
* `options` <JS Object>
* `args` <JS Array>: An array of strings that Wasm application will get as function arguments. Default: `[]`
* `env` <JS Object>: An object like `process.env` that Wasm application will get as its environment variables. Default: `{}`
* `preopens` <JS Object>: An object which maps '<guest_path>:<host_path>'. E.g. `{'/sandbox': '/some/real/path/that/wasm/can/access'}` Default: `{}`
* `EnableWasiStartFunction`: This option will disable wasm-bindgen mode and prepare the working environment for standalone wasm program. If you want to run an appliation with `main()`, you should set this to `true`. Default: `false`.
* `EnableAOT`: This option will enable ssvm aot mode. Default: `false`.
* `EnableMeasurement`: This option will enable measurement but decrease its performance. Default: `false`.
* `args` <JS Array>: An array of strings that Wasm application will get as function arguments. Default: `[]`.
* `env` <JS Object>: An object like `process.env` that Wasm application will get as its environment variables. Default: `{}`.
* `preopens` <JS Object>: An object which maps '<guest_path>:<host_path>'. E.g. `{'/sandbox': '/some/real/path/that/wasm/can/access'}` Default: `{}`.
* `EnableWasiStartFunction` <Boolean>: This option will disable wasm-bindgen mode and prepare the working environment for standalone wasm program. If you want to run an appliation with `main()`, you should set this to `true`. Default: `false`.
* `EnableAOT` <Boolean>: This option will enable ssvm aot mode. Default: `false`.
* `EnableMeasurement` <Boolean>: This option will enable measurement but decrease its performance. Default: `false`.
* `AllowCommands` <JS Array>: An array of strings that indicate what commands are allowed to execute in the SSVM Process Module. Default `[]`.
* `AllowAllCommands` <Boolean>: Allow users to call any command in the SSVM Process Module. This option will overwrite the `AllowCommands`. Default: `false`.
* Return value:
* `vm_instance`: A ssvm instance.

Expand Down Expand Up @@ -216,6 +218,7 @@ vm.RunXXX("Func", args);
* `InstructionCount` -> <Integer>: The number of executed instructions in this execution.
* `TotalGasCost` -> <Integer>: The cost of this execution.
* `InstructionPerSecond` -> <Float>: The instructions per second of this execution.

```javascript
let result = RunInt("Add", 1, 2);
// result should be 3
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.0",
"node-addon-api": "^3.0.0",
"npm": "^6.14.5"
"npm": "^7.11.1"
},
"devDependencies": {
"mocha": "^8.1.3",
"node-gyp-cache": "^0.2.1",
"ssvmup": "^0.1.17"
"ssvmup": "^0.1.21"
},
"scripts": {
"test": "cd test && ./test.sh",
Expand Down
51 changes: 39 additions & 12 deletions src/options.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,36 @@ bool parseWasiStartFlag(const Napi::Object &Options) {
return false;
}

bool parseAllowedCmds(std::vector<std::string> &AllowedCmds, const Napi::Object &Options) {
AllowedCmds.clear();
if (Options.Has(kAllowedCommandsString) && Options.Get(kAllowedCommandsString).IsArray()) {
Napi::Array Cmds = Options.Get(kAllowedCommandsString).As<Napi::Array>();
for (uint32_t I = 0; I < Cmds.Length(); I++) {
Napi::Value Cmd = Cmds[I];
if (Cmd.IsString()) {
AllowedCmds.push_back(Cmd.As<Napi::String>().Utf8Value());
} else {
// Invalid inputs
return false;
}
}
}
return true;
}

bool parseAllowedCmdsAll(const Napi::Object &Options) {
if (Options.Has(kAllowedCommandsAllString) && Options.Get(kAllowedCommandsAllString).IsBoolean()) {
return Options.Get(kAllowedCommandsAllString).As<Napi::Boolean>().Value();
}
return false;
}


bool parseCmdArgs(std::vector<std::string> &CmdArgs,
const Napi::Object &Options) {
CmdArgs.clear();
if (Options.Has("args") && Options.Get("args").IsArray()) {
Napi::Array Args = Options.Get("args").As<Napi::Array>();
if (Options.Has(kCmdArgsString) && Options.Get(kCmdArgsString).IsArray()) {
Napi::Array Args = Options.Get(kCmdArgsString).As<Napi::Array>();
for (uint32_t i = 0; i < Args.Length(); i++) {
Napi::Value Arg = Args[i];
if (Arg.IsNumber()) {
Expand All @@ -43,8 +68,8 @@ bool parseCmdArgs(std::vector<std::string> &CmdArgs,

bool parseDirs(std::vector<std::string> &Dirs, const Napi::Object &Options) {
Dirs.clear();
if (Options.Has("preopens") && Options.Get("preopens").IsObject()) {
Napi::Object Preopens = Options.Get("preopens").As<Napi::Object>();
if (Options.Has(kPreOpensString) && Options.Get(kPreOpensString).IsObject()) {
Napi::Object Preopens = Options.Get(kPreOpensString).As<Napi::Object>();
Napi::Array Keys = Preopens.GetPropertyNames();
for (uint32_t i = 0; i < Keys.Length(); i++) {
// Dir format: <guest_path>:<host_path>
Expand All @@ -69,8 +94,8 @@ bool parseDirs(std::vector<std::string> &Dirs, const Napi::Object &Options) {

bool parseEnvs(std::vector<std::string> &Envs, const Napi::Object &Options) {
Envs.clear();
if (Options.Has("env") && Options.Get("env").IsObject()) {
Napi::Object Environs = Options.Get("env").As<Napi::Object>();
if (Options.Has(kEnvString) && Options.Get(kEnvString).IsObject()) {
Napi::Object Environs = Options.Get(kEnvString).As<Napi::Object>();
Napi::Array Keys = Environs.GetPropertyNames();
for (uint32_t i = 0; i < Keys.Length(); i++) {
// Environ format: <KEY>=<VALUE>
Expand All @@ -94,16 +119,16 @@ bool parseEnvs(std::vector<std::string> &Envs, const Napi::Object &Options) {
}

bool parseAOTConfig(const Napi::Object &Options) {
if (Options.Has("EnableAOT") && Options.Get("EnableAOT").IsBoolean()) {
return Options.Get("EnableAOT").As<Napi::Boolean>().Value();
if (Options.Has(kEnableAOTString) && Options.Get(kEnableAOTString).IsBoolean()) {
return Options.Get(kEnableAOTString).As<Napi::Boolean>().Value();
}
return false;
}

bool parseMeasure(const Napi::Object &Options) {
if (Options.Has("EnableMeasurement") &&
Options.Get("EnableMeasurement").IsBoolean()) {
return Options.Get("EnableMeasurement").As<Napi::Boolean>().Value();
if (Options.Has(kEnableMeasurementString) &&
Options.Get(kEnableMeasurementString).IsBoolean()) {
return Options.Get(kEnableMeasurementString).As<Napi::Boolean>().Value();
}
return false;
}
Expand All @@ -113,12 +138,14 @@ bool parseMeasure(const Napi::Object &Options) {
bool SSVMOptions::parse(const Napi::Object &Options) {
if (!parseCmdArgs(getWasiCmdArgs(), Options) ||
!parseDirs(getWasiDirs(), Options) ||
!parseEnvs(getWasiEnvs(), Options)) {
!parseEnvs(getWasiEnvs(), Options) ||
!parseAllowedCmds(getAllowedCmds(), Options)) {
return false;
}
setReactorMode(!parseWasiStartFlag(Options));
setAOTMode(parseAOTConfig(Options));
setMeasure(parseMeasure(Options));
setAllowedCmdsAll(parseAllowedCmdsAll(Options));
return true;
}

Expand Down
18 changes: 17 additions & 1 deletion src/options.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,43 @@
namespace SSVM {
namespace NAPI {

static inline std::string kAllowedCommandsString [[maybe_unused]] = "AllowCommands";
static inline std::string kAllowedCommandsAllString [[maybe_unused]] = "AllowAllCommands";
static inline std::string kCmdArgsString [[maybe_unused]] = "args";
static inline std::string kPreOpensString [[maybe_unused]] = "preopens";
static inline std::string kEnvString [[maybe_unused]] = "env";
static inline std::string kEnableAOTString [[maybe_unused]] = "EnableAOT";
static inline std::string kEnableMeasurementString [[maybe_unused]] = "EnableMeasurement";

class SSVMOptions {
private:
bool ReactorMode;
bool AOTMode;
bool Measure;
std::vector<std::string> WasiCmdArgs, WasiDirs, WasiEnvs;
bool AllowedCmdsAll;
std::vector<std::string> WasiCmdArgs, WasiDirs, WasiEnvs, AllowedCmds;

public:
void setReactorMode(bool Value = true) { ReactorMode = Value; }
void setAOTMode(bool Value = true) { AOTMode = Value; }
void setMeasure(bool Value = true) { Measure = Value; }
void setAllowedCmdsAll(bool Value = true) { AllowedCmdsAll = Value; }
void setWasiCmdArgs(const std::vector<std::string> &WCA) {
WasiCmdArgs = WCA;
}
void setAllowedCmds(const std::vector<std::string> &AC) {
AllowedCmds = AC;
}
void setWasiDirs(const std::vector<std::string> &WD) { WasiDirs = WD; }
void setWasiEnvs(const std::vector<std::string> &WE) { WasiEnvs = WE; }
bool isReactorMode() const noexcept { return ReactorMode; }
bool isAOTMode() const noexcept { return AOTMode; }
bool isMeasuring() const noexcept { return Measure; }
bool isAllowedCmdsAll() const noexcept { return AllowedCmdsAll; }
const std::vector<std::string> &getWasiCmdArgs() const { return WasiCmdArgs; }
std::vector<std::string> &getWasiCmdArgs() { return WasiCmdArgs; }
const std::vector<std::string> &getAllowedCmds() const { return AllowedCmds; }
std::vector<std::string> &getAllowedCmds() { return AllowedCmds; }
const std::vector<std::string> &getWasiDirs() const { return WasiDirs; }
std::vector<std::string> &getWasiDirs() { return WasiDirs; }
const std::vector<std::string> &getWasiEnvs() const { return WasiEnvs; }
Expand Down
13 changes: 13 additions & 0 deletions src/ssvmaddon.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "common/log.h"
#include "common/span.h"
#include "loader/loader.h"
#include "host/ssvm_process/processmodule.h"
#include "host/wasi/wasimodule.h"
#include "utils.h"

#include <limits>
Expand Down Expand Up @@ -142,6 +144,17 @@ void SSVMAddon::InitVM(const Napi::CallbackInfo &Info) {

SSVM::Log::setErrorLoggingLevel();

SSVM::Host::SSVMProcessModule *ProcMod =
dynamic_cast<SSVM::Host::SSVMProcessModule *>(
VM->getImportModule(SSVM::VM::Configure::VMType::SSVM_Process));

if (Options.isAllowedCmdsAll()) {
ProcMod->getEnv().AllowedAll = true;
}
for (auto &Cmd : Options.getAllowedCmds()) {
ProcMod->getEnv().AllowedCmd.insert(Cmd);
}

Inited = true;
}

Expand Down

0 comments on commit 65457dc

Please sign in to comment.