Daohub-io / cap9

Capability-based security protocol for smart contracts
Apache License 2.0
22 stars 10 forks source link

Validation: Allow indirect calls #158

Open JakeOShannessy opened 5 years ago

JakeOShannessy commented 5 years ago

This is part of the validation process. WASM has a concept of indirect calls which we don't currently check for in the validation code. This should be just some extra logic but I'm making an issue for it so we don't forget. I want to get end-to-end tests working well before we worry about edge cases.

JakeOShannessy commented 5 years ago

This is loosely analogous to to the dynamic jump/call problem we had in EVM. In summary, an indirect call is "call one of the functions in this table, here is an index to choose which function". The index is determined dynamically, so we can't know statically what the end called function will be. I think the simplest and most robust option is to ensure that dcall is not accessible from the table.

For now I have regarded all indirect calls as a risk and forbidden them. This makes the validator safe, although it will consider some safe contracts unsafe until we allow for indirect calls.

Latrasis commented 5 years ago

Ok let's put this on hold for now.

JakeOShannessy commented 5 years ago

Tables can be filled one of two ways by the host (such as the parity node, we don't care about this we need to trust the node anyway) and via the element section.

If there are no elems then the contract is safe, as there is no way for dcall to be added to the table.

An elem segment is (elem $table_id $offset ($func1 $func2 ...)), where $func1 etc. are references to functions (including imports). As such, indirect calls are valid if dcall is not added to the table in this manner. Therefore:

A contract is a valid procedure iff there are no elems which reference the imported dcall.

JakeOShannessy commented 5 years ago

Ok, I just wanted to note that information. It looks pretty straightforward to add, we just iterate though elems the same way we iterate through codes to ensure that there are no references to dcall. From what I've read it will be pretty critical. For example traits in Rust use call_indirect. The kernel has 55 call_indirects.

Latrasis commented 5 years ago

@JakeOShannessy: Let's put this on hold for now, until preliminary issues are done. If not, we can skip it.

JakeOShannessy commented 5 years ago

I thought it already was on hold. We won't be able to skip it in the end because nothing will pass validation if we do.