Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(backend): refine approach of funcs forbidding #4409

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
145 changes: 67 additions & 78 deletions core-backend/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ use gear_wasm_instrument::{
// we have requirement to pass function pointer for `gear_sandbox`
// so the only reason this macro exists is const function pointers are not stabilized yet
// so we create non-capturing closure that can be coerced into function pointer
#[rustfmt::skip]
macro_rules! wrap_syscall {
($func:ident) => {
|caller, args| FuncsHandler::execute(caller, args, FuncsHandler::$func)
($func:ident, $syscall:ident) => {
|caller, args| FuncsHandler::execute(caller, args, FuncsHandler::$func, $syscall)
};
}

Expand Down Expand Up @@ -117,7 +118,6 @@ where
// It makes adding functions to `EnvironmentDefinitionBuilder` shorter.
struct EnvBuilder<Ext: BackendExternalities> {
env_def_builder: EnvironmentDefinitionBuilder<HostState<Ext, BackendMemory<ExecutorMemory>>>,
forbidden_funcs: BTreeSet<SyscallName>,
funcs_count: usize,
}

Expand All @@ -133,12 +133,7 @@ where
name: SyscallName,
f: HostFuncType<HostState<Ext, BackendMemory<ExecutorMemory>>>,
) {
if self.forbidden_funcs.contains(&name) {
self.env_def_builder
.add_host_func("env", name.to_str(), wrap_syscall!(forbidden));
} else {
self.env_def_builder.add_host_func("env", name.to_str(), f);
}
self.env_def_builder.add_host_func("env", name.to_str(), f);

self.funcs_count += 1;
}
Expand Down Expand Up @@ -167,63 +162,69 @@ where
{
#[rustfmt::skip]
fn bind_funcs(builder: &mut EnvBuilder<Ext>) {
builder.add_func(EnvVars, wrap_syscall!(env_vars));
builder.add_func(BlockHeight, wrap_syscall!(block_height));
builder.add_func(BlockTimestamp,wrap_syscall!(block_timestamp));
builder.add_func(CreateProgram, wrap_syscall!(create_program));
builder.add_func(CreateProgramWGas, wrap_syscall!(create_program_wgas));
builder.add_func(Debug, wrap_syscall!(debug));
builder.add_func(Panic, wrap_syscall!(panic));
builder.add_func(OomPanic, wrap_syscall!(oom_panic));
builder.add_func(Exit, wrap_syscall!(exit));
builder.add_func(ReplyCode, wrap_syscall!(reply_code));
builder.add_func(SignalCode, wrap_syscall!(signal_code));
builder.add_func(ReserveGas, wrap_syscall!(reserve_gas));
builder.add_func(ReplyDeposit, wrap_syscall!(reply_deposit));
builder.add_func(UnreserveGas, wrap_syscall!(unreserve_gas));
builder.add_func(GasAvailable, wrap_syscall!(gas_available));
builder.add_func(Leave, wrap_syscall!(leave));
builder.add_func(MessageId, wrap_syscall!(message_id));
builder.add_func(ProgramId, wrap_syscall!(program_id));
builder.add_func(Random, wrap_syscall!(random));
builder.add_func(Read, wrap_syscall!(read));
builder.add_func(Reply, wrap_syscall!(reply));
builder.add_func(ReplyCommit, wrap_syscall!(reply_commit));
builder.add_func(ReplyCommitWGas, wrap_syscall!(reply_commit_wgas));
builder.add_func(ReplyPush, wrap_syscall!(reply_push));
builder.add_func(ReplyTo, wrap_syscall!(reply_to));
builder.add_func(SignalFrom, wrap_syscall!(signal_from));
builder.add_func(ReplyWGas, wrap_syscall!(reply_wgas));
builder.add_func(ReplyInput, wrap_syscall!(reply_input));
builder.add_func(ReplyPushInput, wrap_syscall!(reply_push_input));
builder.add_func(ReplyInputWGas, wrap_syscall!(reply_input_wgas));
builder.add_func(Send, wrap_syscall!(send));
builder.add_func(SendCommit, wrap_syscall!(send_commit));
builder.add_func(SendCommitWGas, wrap_syscall!(send_commit_wgas));
builder.add_func(SendInit, wrap_syscall!(send_init));
builder.add_func(SendPush, wrap_syscall!(send_push));
builder.add_func(SendWGas, wrap_syscall!(send_wgas));
builder.add_func(SendInput, wrap_syscall!(send_input));
builder.add_func(SendPushInput, wrap_syscall!(send_push_input));
builder.add_func(SendInputWGas, wrap_syscall!(send_input_wgas));
builder.add_func(Size, wrap_syscall!(size));
builder.add_func(Source, wrap_syscall!(source));
builder.add_func(Value, wrap_syscall!(value));
builder.add_func(ValueAvailable, wrap_syscall!(value_available));
builder.add_func(Wait, wrap_syscall!(wait));
builder.add_func(WaitFor, wrap_syscall!(wait_for));
builder.add_func(WaitUpTo, wrap_syscall!(wait_up_to));
builder.add_func(Wake, wrap_syscall!(wake));
builder.add_func(SystemReserveGas, wrap_syscall!(system_reserve_gas));
builder.add_func(ReservationReply, wrap_syscall!(reservation_reply));
builder.add_func(ReservationReplyCommit, wrap_syscall!(reservation_reply_commit));
builder.add_func(ReservationSend, wrap_syscall!(reservation_send));
builder.add_func(ReservationSendCommit, wrap_syscall!(reservation_send_commit));
builder.add_func(SystemBreak, wrap_syscall!(system_break));

builder.add_func(Alloc, wrap_syscall!(alloc));
builder.add_func(Free, wrap_syscall!(free));
builder.add_func(FreeRange, wrap_syscall!(free_range));
macro_rules! add_function {
($syscall:ident, $func:ident) => {
builder.add_func($syscall, wrap_syscall!($func, $syscall));
};
}

add_function!(EnvVars, env_vars);
add_function!(BlockHeight, block_height);
add_function!(BlockTimestamp, block_timestamp);
add_function!(CreateProgram, create_program);
add_function!(CreateProgramWGas, create_program_wgas);
add_function!(Debug, debug);
add_function!(Panic, panic);
add_function!(OomPanic, oom_panic);
add_function!(Exit, exit);
add_function!(ReplyCode, reply_code);
add_function!(SignalCode, signal_code);
add_function!(ReserveGas, reserve_gas);
add_function!(ReplyDeposit, reply_deposit);
add_function!(UnreserveGas, unreserve_gas);
add_function!(GasAvailable, gas_available);
add_function!(Leave, leave);
add_function!(MessageId, message_id);
add_function!(ProgramId, program_id);
add_function!(Random, random);
add_function!(Read, read);
add_function!(Reply, reply);
add_function!(ReplyCommit, reply_commit);
add_function!(ReplyCommitWGas, reply_commit_wgas);
add_function!(ReplyPush, reply_push);
add_function!(ReplyTo, reply_to);
add_function!(SignalFrom, signal_from);
add_function!(ReplyWGas, reply_wgas);
add_function!(ReplyInput, reply_input);
add_function!(ReplyPushInput, reply_push_input);
add_function!(ReplyInputWGas, reply_input_wgas);
add_function!(Send, send);
add_function!(SendCommit, send_commit);
add_function!(SendCommitWGas, send_commit_wgas);
add_function!(SendInit, send_init);
add_function!(SendPush, send_push);
add_function!(SendWGas, send_wgas);
add_function!(SendInput, send_input);
add_function!(SendPushInput, send_push_input);
add_function!(SendInputWGas, send_input_wgas);
add_function!(Size, size);
add_function!(Source, source);
add_function!(Value, value);
add_function!(ValueAvailable, value_available);
add_function!(Wait, wait);
add_function!(WaitFor, wait_for);
add_function!(WaitUpTo, wait_up_to);
add_function!(Wake, wake);
add_function!(SystemReserveGas, system_reserve_gas);
add_function!(ReservationReply, reservation_reply);
add_function!(ReservationReplyCommit, reservation_reply_commit);
add_function!(ReservationSend, reservation_send);
add_function!(ReservationSendCommit, reservation_send_commit);
add_function!(SystemBreak, system_break);

add_function!(Alloc, alloc);
add_function!(Free, free);
add_function!(FreeRange, free_range);
}
}

Expand Down Expand Up @@ -271,22 +272,10 @@ where
use EnvironmentError::*;
use SystemEnvironmentError::*;

let entry_forbidden = entry_point
.try_into_kind()
.as_ref()
.map(DispatchKind::forbidden_funcs)
.unwrap_or_default();

let mut store = Store::new(None);

let mut builder = EnvBuilder::<EnvExt> {
env_def_builder: EnvironmentDefinitionBuilder::new(),
forbidden_funcs: ext
.forbidden_funcs()
.iter()
.copied()
.chain(entry_forbidden)
.collect(),
funcs_count: 0,
};

Expand Down
19 changes: 9 additions & 10 deletions core-backend/src/funcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ use gear_core::{
use gear_core_errors::{MessageError, ReplyCode, SignalCode};
use gear_sandbox::{AsContextExt, ReturnValue, Value};
use gear_sandbox_env::{HostError, WasmReturnValue};
use gear_wasm_instrument::SystemBreakCode;
use gear_wasm_instrument::{SyscallName, SystemBreakCode};
use gsys::{
BlockNumberWithHash, ErrorBytes, ErrorWithGas, ErrorWithHandle, ErrorWithHash,
ErrorWithReplyCode, ErrorWithSignalCode, ErrorWithTwoHashes, Gas, Hash, HashWithValue,
Expand Down Expand Up @@ -148,6 +148,7 @@ pub(crate) trait Syscall<Caller, T = ()> {
self,
caller: &mut CallerWrap<Caller>,
ctx: Self::Context,
syscall_name: SyscallName,
) -> Result<(Gas, T), HostError>;
}

Expand Down Expand Up @@ -234,6 +235,7 @@ where
self,
caller: &mut CallerWrap<Caller>,
(): Self::Context,
_syscall_name: SyscallName,
) -> Result<(Gas, T), HostError> {
(self.0)(caller)
}
Expand Down Expand Up @@ -285,10 +287,11 @@ where
self,
caller: &mut CallerWrap<Caller>,
context: Self::Context,
syscall_name: SyscallName,
) -> Result<(Gas, ()), HostError> {
let Self { token, f, .. } = self;
let FallibleSyscallContext { gas, res_ptr } = context;
caller.run_fallible::<T, _, E>(gas, res_ptr, token, f)
caller.run_fallible::<T, _, E>(gas, res_ptr, token, syscall_name, f)
}
}

Expand Down Expand Up @@ -329,10 +332,11 @@ where
self,
caller: &mut CallerWrap<Caller>,
ctx: Self::Context,
syscall_name: SyscallName,
) -> Result<(Gas, T), HostError> {
let Self { token, f } = self;
let InfallibleSyscallContext { gas } = ctx;
caller.run_any::<T, _>(gas, token, f)
caller.run_any::<T, _>(gas, token, syscall_name, f)
}
}

Expand All @@ -352,6 +356,7 @@ where
caller: &mut Caller,
args: &[Value],
builder: Builder,
syscall_name: SyscallName,
) -> Result<WasmReturnValue, HostError>
where
Builder: SyscallBuilder<Caller, Args, Res, Call>,
Expand All @@ -365,7 +370,7 @@ where

let (ctx, args) = Call::Context::from_args(args)?;
let syscall = builder.build(args)?;
let (gas, value) = syscall.execute(&mut caller, ctx)?;
let (gas, value) = syscall.execute(&mut caller, ctx, syscall_name)?;
let value = value.into();

Ok(WasmReturnValue {
Expand Down Expand Up @@ -1378,12 +1383,6 @@ where
)
}

pub fn forbidden(_args: &[Value]) -> impl Syscall<Caller> {
InfallibleSyscall::new(CostToken::Null, |_: &mut CallerWrap<Caller>| {
Err(ActorTerminationReason::Trap(TrapExplanation::ForbiddenFunction).into())
})
}

fn out_of_gas(ctx: &mut CallerWrap<Caller>) -> UndefinedTerminationReason {
let ext = ctx.ext_mut();
let current_counter = ext.current_counter_type();
Expand Down
4 changes: 4 additions & 0 deletions core-backend/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ pub struct MockExt {
reads: Vec<MemoryInterval>,
writes: Vec<MemoryInterval>,
_forbidden_funcs: BTreeSet<SyscallName>,
_endpoint_forbidden_funcs: BTreeSet<SyscallName>,
}

impl MockExt {
Expand Down Expand Up @@ -242,6 +243,9 @@ impl Externalities for MockExt {
fn forbidden_funcs(&self) -> &BTreeSet<SyscallName> {
&self._forbidden_funcs
}
fn endpoint_forbidden_funcs(&self) -> &BTreeSet<SyscallName> {
&self._endpoint_forbidden_funcs
}
fn reserve_gas(
&mut self,
_amount: u64,
Expand Down
28 changes: 26 additions & 2 deletions core-backend/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@
//! sp-sandbox runtime (here it's program execution state) realization.

use crate::{
error::{BackendAllocSyscallError, RunFallibleError, UndefinedTerminationReason},
error::{
ActorTerminationReason, BackendAllocSyscallError, RunFallibleError, TrapExplanation,
UndefinedTerminationReason,
},
memory::{BackendMemory, ExecutorMemory, MemoryAccessRegistry},
state::{HostState, State},
BackendExternalities,
};
use gear_core::{costs::CostToken, pages::WasmPage};
use gear_sandbox::{AsContextExt, HostError};
use gear_wasm_instrument::SyscallName;

pub(crate) struct CallerWrap<'a, Caller> {
pub caller: &'a mut Caller,
Expand Down Expand Up @@ -75,12 +79,30 @@ where
Ext: BackendExternalities + 'static,
{
#[track_caller]
pub fn run_any<U, F>(&mut self, gas: u64, token: CostToken, f: F) -> Result<(u64, U), HostError>
pub fn run_any<U, F>(
&mut self,
gas: u64,
token: CostToken,
syscall_name: SyscallName,
f: F,
) -> Result<(u64, U), HostError>
where
F: FnOnce(&mut Self) -> Result<U, UndefinedTerminationReason>,
{
self.state_mut().ext.decrease_current_counter_to(gas);

if self.ext_mut().forbidden_funcs().contains(&syscall_name)
|| self
.ext_mut()
.endpoint_forbidden_funcs()
.contains(&syscall_name)
{
self.set_termination_reason(
ActorTerminationReason::Trap(TrapExplanation::ForbiddenFunction).into(),
);
return Err(HostError);
}

let run = || {
self.state_mut().ext.charge_gas_for_token(token)?;
f(self)
Expand All @@ -100,6 +122,7 @@ where
gas: u64,
res_ptr: u32,
token: CostToken,
syscall_name: SyscallName,
f: F,
) -> Result<(u64, ()), HostError>
where
Expand All @@ -109,6 +132,7 @@ where
self.run_any(
gas,
token,
syscall_name,
|ctx: &mut Self| -> Result<_, UndefinedTerminationReason> {
let res = f(ctx);
let res = ctx.process_fallible_func_result(res)?;
Expand Down
10 changes: 10 additions & 0 deletions core-processor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ where
);
let value_counter = ValueCounter::new(value_available);

let endpoint_forbidden_funcs = kind.forbidden_funcs();

let context = ProcessorContext {
gas_counter,
gas_allowance_counter,
Expand All @@ -134,6 +136,7 @@ where
existential_deposit: settings.existential_deposit,
mailbox_threshold: settings.mailbox_threshold,
costs: settings.ext_costs,
endpoint_forbidden_funcs,
};

// Creating externalities.
Expand Down Expand Up @@ -307,6 +310,12 @@ where
)
.ok_or("Incorrect message store context: out of outgoing bytes limit")?;

let endpoint_forbidden_funcs = function
.try_into_kind()
.as_mut()
.map(|kind| kind.forbidden_funcs())
.unwrap_or_default();

let context = ProcessorContext {
gas_counter: GasCounter::new(gas_limit),
gas_allowance_counter: GasAllowanceCounter::new(gas_limit),
Expand All @@ -333,6 +342,7 @@ where
existential_deposit: Default::default(),
mailbox_threshold: Default::default(),
costs: Default::default(),
endpoint_forbidden_funcs,
};

// Creating externalities.
Expand Down
Loading
Loading