VM: Enforce a call depth limit

This commit is contained in:
Aayush Rajasekaran 2020-10-19 13:26:07 -04:00
parent d8d2174104
commit 143dcafdb7
4 changed files with 26 additions and 21 deletions

View File

@ -18,7 +18,7 @@ func VersionForNetwork(version network.Version) Version {
switch version { switch version {
case network.Version0, network.Version1, network.Version2, network.Version3: case network.Version0, network.Version1, network.Version2, network.Version3:
return Version0 return Version0
case network.Version4, network.Version5: case network.Version4, network.Version5, network.Version6:
return Version2 return Version2
default: default:
panic(fmt.Sprintf("unsupported network version %d", version)) panic(fmt.Sprintf("unsupported network version %d", version))

View File

@ -405,7 +405,7 @@ func circSupply(ctx context.Context, vmi *vm.VM, maddr address.Address) abi.Toke
rt := unsafeVM.MakeRuntime(ctx, &types.Message{ rt := unsafeVM.MakeRuntime(ctx, &types.Message{
GasLimit: 1_000_000_000, GasLimit: 1_000_000_000,
From: maddr, From: maddr,
}, maddr, 0, 0, 0) })
return rt.TotalFilCircSupply() return rt.TotalFilCircSupply()
} }

View File

@ -72,6 +72,7 @@ type Runtime struct {
originNonce uint64 originNonce uint64
executionTrace types.ExecutionTrace executionTrace types.ExecutionTrace
depth uint64
numActorsCreated uint64 numActorsCreated uint64
allowInternal bool allowInternal bool
callerValidated bool callerValidated bool

View File

@ -38,6 +38,8 @@ import (
"github.com/filecoin-project/lotus/lib/bufbstore" "github.com/filecoin-project/lotus/lib/bufbstore"
) )
const MaxCallDepth = 4096
var log = logging.Logger("vm") var log = logging.Logger("vm")
var actorLog = logging.Logger("actors") var actorLog = logging.Logger("actors")
var gasOnActorExec = newGasCharge("OnActorExec", 0, 0) var gasOnActorExec = newGasCharge("OnActorExec", 0, 0)
@ -97,24 +99,37 @@ func (bs *gasChargingBlocks) Put(blk block.Block) error {
return nil return nil
} }
func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime { func (vm *VM) makeRuntime(ctx context.Context, msg *types.Message, parent *Runtime) *Runtime {
rt := &Runtime{ rt := &Runtime{
ctx: ctx, ctx: ctx,
vm: vm, vm: vm,
state: vm.cstate, state: vm.cstate,
origin: origin, origin: msg.From,
originNonce: originNonce, originNonce: msg.Nonce,
height: vm.blockHeight, height: vm.blockHeight,
gasUsed: usedGas, gasUsed: 0,
gasAvailable: msg.GasLimit, gasAvailable: msg.GasLimit,
numActorsCreated: nac, depth: 0,
numActorsCreated: 0,
pricelist: PricelistByEpoch(vm.blockHeight), pricelist: PricelistByEpoch(vm.blockHeight),
allowInternal: true, allowInternal: true,
callerValidated: false, callerValidated: false,
executionTrace: types.ExecutionTrace{Msg: msg}, executionTrace: types.ExecutionTrace{Msg: msg},
} }
if parent != nil {
rt.gasUsed = parent.gasUsed
rt.origin = parent.origin
rt.originNonce = parent.originNonce
rt.numActorsCreated = parent.numActorsCreated
rt.depth = parent.depth + 1
}
if rt.depth > MaxCallDepth && rt.NetworkVersion() >= network.Version6 {
rt.Abortf(exitcode.SysErrForbidden, "message execution exceeds call depth")
}
rt.cst = &cbor.BasicIpldStore{ rt.cst = &cbor.BasicIpldStore{
Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks}, Blocks: &gasChargingBlocks{rt.chargeGasFunc(2), rt.pricelist, vm.cst.Blocks},
Atlas: vm.cst.Atlas, Atlas: vm.cst.Atlas,
@ -148,8 +163,8 @@ type UnsafeVM struct {
VM *VM VM *VM
} }
func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message, origin address.Address, originNonce uint64, usedGas int64, nac uint64) *Runtime { func (vm *UnsafeVM) MakeRuntime(ctx context.Context, msg *types.Message) *Runtime {
return vm.VM.makeRuntime(ctx, msg, origin, originNonce, usedGas, nac) return vm.VM.makeRuntime(ctx, msg, nil)
} }
type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error) type CircSupplyCalculator func(context.Context, abi.ChainEpoch, *state.StateTree) (abi.TokenAmount, error)
@ -224,18 +239,7 @@ func (vm *VM) send(ctx context.Context, msg *types.Message, parent *Runtime,
st := vm.cstate st := vm.cstate
origin := msg.From rt := vm.makeRuntime(ctx, msg, parent)
on := msg.Nonce
var nac uint64 = 0
var gasUsed int64
if parent != nil {
gasUsed = parent.gasUsed
origin = parent.origin
on = parent.originNonce
nac = parent.numActorsCreated
}
rt := vm.makeRuntime(ctx, msg, origin, on, gasUsed, nac)
if EnableGasTracing { if EnableGasTracing {
rt.lastGasChargeTime = start rt.lastGasChargeTime = start
if parent != nil { if parent != nil {