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 5 commits 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
23 changes: 14 additions & 9 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 @@ -224,17 +225,22 @@ impl<F> RawSyscall<F> {
}
}

impl<T, F, Caller> Syscall<Caller, T> for RawSyscall<F>
impl<T, F, Caller, Ext> Syscall<Caller, T> for RawSyscall<F>
where
F: FnOnce(&mut CallerWrap<Caller>) -> Result<(Gas, T), HostError>,
Caller: AsContextExt<State = HostState<Ext, BackendMemory<ExecutorMemory>>>,
Ext: BackendExternalities + 'static,
{
type Context = ();

fn execute(
self,
caller: &mut CallerWrap<Caller>,
(): Self::Context,
syscall_name: SyscallName,
) -> Result<(Gas, T), HostError> {
caller.check_func_forbiddenness(syscall_name)?;

(self.0)(caller)
}
}
Expand Down Expand Up @@ -285,9 +291,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.check_func_forbiddenness(syscall_name)?;
caller.run_fallible::<T, _, E>(gas, res_ptr, token, f)
}
}
Expand Down Expand Up @@ -329,9 +337,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.check_func_forbiddenness(syscall_name)?;
caller.run_any::<T, _>(gas, token, f)
}
}
Expand All @@ -352,6 +362,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 +376,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 +1389,6 @@ where
)
}

pub fn forbidden(_args: &[Value]) -> impl Syscall<Caller> + use<Caller, Ext> {
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
5 changes: 4 additions & 1 deletion core-backend/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ use gear_core::{
gas::{ChargeError, CounterType, CountersOwner, GasAmount, GasCounter, GasLeft},
ids::{MessageId, ProgramId, ReservationId},
memory::{Memory, MemoryInterval},
message::{HandlePacket, InitPacket, ReplyPacket},
message::{DispatchKind, HandlePacket, InitPacket, ReplyPacket},
pages::WasmPage,
};
use gear_core_errors::{ReplyCode, SignalCode};
Expand Down Expand Up @@ -242,6 +242,9 @@ impl Externalities for MockExt {
fn forbidden_funcs(&self) -> &BTreeSet<SyscallName> {
&self._forbidden_funcs
}
fn endpoint_dispatch_kind(&self) -> DispatchKind {
Default::default()
}
fn reserve_gas(
&mut self,
_amount: u64,
Expand Down
22 changes: 21 additions & 1 deletion 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 @@ -160,4 +164,20 @@ where
},
}
}

pub fn check_func_forbiddenness(&mut self, syscall_name: SyscallName) -> Result<(), HostError> {
if self.ext_mut().forbidden_funcs().contains(&syscall_name)
|| self
.ext_mut()
.endpoint_dispatch_kind()
Comment on lines +171 to +172
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't it make more sense from where we take this value?

Suggested change
.ext_mut()
.endpoint_dispatch_kind()
.ext_mut()
.msg_ctx()
.dispatch_kind()
.forbids(x)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not like it belongs to endpoint

.forbids(syscall_name)
{
self.set_termination_reason(
ActorTerminationReason::Trap(TrapExplanation::ForbiddenFunction).into(),
);
return Err(HostError);
}

Ok(())
}
}
4 changes: 4 additions & 0 deletions core-processor/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1421,6 +1421,10 @@ impl<LP: LazyPagesInterface> Externalities for Ext<LP> {
fn forbidden_funcs(&self) -> &BTreeSet<SyscallName> {
&self.context.forbidden_funcs
}

fn endpoint_dispatch_kind(&self) -> DispatchKind {
self.context.message_context.kind()
}
}

#[cfg(test)]
Expand Down
5 changes: 4 additions & 1 deletion core/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
env_vars::EnvVars,
ids::{MessageId, ProgramId, ReservationId},
memory::Memory,
message::{HandlePacket, InitPacket, MessageContext, Payload, ReplyPacket},
message::{DispatchKind, HandlePacket, InitPacket, MessageContext, Payload, ReplyPacket},
pages::WasmPage,
};
use alloc::collections::BTreeSet;
Expand Down Expand Up @@ -391,4 +391,7 @@ pub trait Externalities {

/// Return the set of functions that are forbidden to be called.
fn forbidden_funcs(&self) -> &BTreeSet<SyscallName>;

/// Return the current dispatch kind.
fn endpoint_dispatch_kind(&self) -> DispatchKind;
}
5 changes: 5 additions & 0 deletions core/src/message/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ impl MessageContext {
&self.settings
}

/// Getter for inner dispatch kind
pub fn kind(&self) -> DispatchKind {
self.kind
}

fn check_reply_availability(&self) -> Result<(), ExecutionError> {
if !matches!(self.kind, DispatchKind::Init | DispatchKind::Handle) {
return Err(ExecutionError::IncorrectEntryForReply);
Expand Down
Loading
Loading