From 2c9f1c7d6b5c87f6a6c8fcd6d3f550c19011faf9 Mon Sep 17 00:00:00 2001 From: Ilya Raykker Date: Thu, 29 Aug 2024 10:25:59 +0400 Subject: [PATCH] Apply wasmd-patch --- CHANGELOG.md | 5 +++++ x/compute/internal/keeper/handler_plugin.go | 15 ++++++++++++++ x/compute/internal/keeper/keeper.go | 23 +++++++++++++++++++++ x/compute/internal/types/context.go | 16 ++++++++++++++ x/compute/internal/types/errors.go | 3 +++ x/compute/internal/types/types.go | 1 + 6 files changed, 63 insertions(+) create mode 100644 x/compute/internal/types/context.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a60b4264..2fa15b1e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +# 1.14.0 + +- Fix CWA-2024-005 +- Bump ledger-cosmos-go from v0.12.2 to v0.12.4 + # 1.13.0 - Support DCAP attestation diff --git a/x/compute/internal/keeper/handler_plugin.go b/x/compute/internal/keeper/handler_plugin.go index fd57cea7e..aad6b0578 100644 --- a/x/compute/internal/keeper/handler_plugin.go +++ b/x/compute/internal/keeper/handler_plugin.go @@ -588,6 +588,21 @@ func (h SDKMessageHandler) handleSdkMessage(ctx sdk.Context, msg sdk.Msg) (*sdk. return nil, sdkerrors.ErrUnknownRequest.Wrapf("can't route message %+v", msg) } +// callDepthMessageHandler is a wrapper around a Messenger that checks the call depth before dispatching a message. +type callDepthMessageHandler struct { + Messenger + MaxCallDepth uint32 +} + +func (h callDepthMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg v1wasmTypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) { + ctx, err = checkAndIncreaseCallDepth(ctx, h.MaxCallDepth) + if err != nil { + return nil, nil, err + } + + return h.Messenger.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg) +} + // convertWasmIBCTimeoutHeightToCosmosHeight converts a wasm type ibc timeout height to ibc module type height func convertWasmIBCTimeoutHeightToCosmosHeight(ibcTimeoutBlock *v1wasmTypes.IBCTimeoutBlock) ibcclienttypes.Height { if ibcTimeoutBlock == nil { diff --git a/x/compute/internal/keeper/keeper.go b/x/compute/internal/keeper/keeper.go index b1da90857..3301e650d 100644 --- a/x/compute/internal/keeper/keeper.go +++ b/x/compute/internal/keeper/keeper.go @@ -86,6 +86,7 @@ type Keeper struct { messenger Messenger // queryGasLimit is the max wasm gas that can be spent on executing a query with a contract queryGasLimit uint64 + maxCallDepth uint32 HomeDir string // authZPolicy AuthorizationPolicy // paramSpace subspace.Subspace @@ -149,9 +150,13 @@ func NewKeeper( cdc, ), queryGasLimit: wasmConfig.SmartQueryGasLimit, + maxCallDepth: types.DefaultMaxCallDepth, HomeDir: homeDir, LastMsgManager: lastMsgManager, } + // always wrap the messenger, even if it was replaced by an option + keeper.messenger = callDepthMessageHandler{keeper.messenger, keeper.maxCallDepth} + keeper.queryPlugins = DefaultQueryPlugins(govKeeper, distKeeper, mintKeeper, bankKeeper, stakingKeeper, queryRouter, &keeper, channelKeeper).Merge(customPlugins) return keeper @@ -812,6 +817,24 @@ func (k Keeper) querySmartImpl(ctx sdk.Context, contractAddress sdk.AccAddress, return queryResult, nil } +func checkAndIncreaseCallDepth(ctx sdk.Context, maxCallDepth uint32) (sdk.Context, error) { + var callDepth uint32 + if size, ok := types.CallDepth(ctx); ok { + callDepth = size + } + + // increase + callDepth++ + + // did we go too far? + if callDepth > maxCallDepth { + return sdk.Context{}, types.ErrExceedMaxCallDepth + } + + // set updated stack size + return types.WithCallDepth(ctx, callDepth), nil +} + // We don't use this function since we have an encrypted state. It's here for upstream compatibility // QueryRaw returns the contract's state for give key. For a `nil` key a empty slice result is returned. func (k Keeper) QueryRaw(ctx sdk.Context, contractAddress sdk.AccAddress, key []byte) []types.Model { diff --git a/x/compute/internal/types/context.go b/x/compute/internal/types/context.go new file mode 100644 index 000000000..5443610aa --- /dev/null +++ b/x/compute/internal/types/context.go @@ -0,0 +1,16 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const contextKeyCallDepth contextKey = iota + +func WithCallDepth(ctx sdk.Context, counter uint32) sdk.Context { + return ctx.WithValue(contextKeyCallDepth, counter) +} + +func CallDepth(ctx sdk.Context) (uint32, bool) { + val, ok := ctx.Value(contextKeyCallDepth).(uint32) + return val, ok +} diff --git a/x/compute/internal/types/errors.go b/x/compute/internal/types/errors.go index 517e138b7..3c44424d2 100644 --- a/x/compute/internal/types/errors.go +++ b/x/compute/internal/types/errors.go @@ -72,6 +72,9 @@ var ( // ErrMaxIBCChannels error for maximum number of ibc channels reached ErrMaxIBCChannels = errors.Register(DefaultCodespace, 22, "max transfer channels") + + // ErrExceedMaxCallDepth error if max message stack size is exceeded + ErrExceedMaxCallDepth = errors.Register(DefaultCodespace, 30, "max call depth exceeded") ) func IsEncryptedErrorCode(code uint32) bool { diff --git a/x/compute/internal/types/types.go b/x/compute/internal/types/types.go index 1e529d8d7..6575c5af9 100644 --- a/x/compute/internal/types/types.go +++ b/x/compute/internal/types/types.go @@ -17,6 +17,7 @@ import ( ) const ( + DefaultMaxCallDepth = uint32(500) defaultLRUCacheSize = uint64(0) defaultEnclaveLRUCacheSize = uint16(100) defaultQueryGasLimit = uint64(10_000_000)