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

"Attenuate" call #573

Open
graydon opened this issue Nov 14, 2022 · 3 comments
Open

"Attenuate" call #573

graydon opened this issue Nov 14, 2022 · 3 comments

Comments

@graydon
Copy link
Contributor

graydon commented Nov 14, 2022

We currently ban re-entrant cross-contract calls, but we're expecting to add it as an option users can opt-in to allowing in a given call host function call, at some point.

One way of reducing the risk (and a few other possible cross-contract information-leakage risks such as we've been discussing in the PRNG PR) of this is to allow contracts to "attenuate" parts of the host before they make calls to other contracts, essentially giving up their ability to do various things in-the-future, either in a re-entered frame and/or the current frame once a call returns. Or possibly even in the callee contracts. This would be similar to the openBSD's pledge or linux's seccomp -- ways of limiting the damage one's own code could do if confused by a re-entrant call or return value from a malicious callee contract.

@leighmcculloch
Copy link
Member

leighmcculloch commented Nov 14, 2022

I think this is interesting but given the complexity I expect it would be to use it, it may be really difficult to wield it accurately enough to use it as a first line of defense.

Could you provide a narrower example of how this would be used?

@jayz22
Copy link
Contributor

jayz22 commented Nov 14, 2022

cc @sisuresh relating to contract reentry.

@graydon
Copy link
Contributor Author

graydon commented Nov 14, 2022

I think this is interesting but given the complexity I expect it would be to use it, it may be really difficult to wield it accurately enough to use it as a first line of defense.

Could you provide a narrower example of how this would be used?

Sure. The classic "reentry bugs" I've seen are mostly just rephrased classical concurrency anomalies, where the concurrent parties are "yourself" and "the re-entered version of yourself". For example your contract A does a ledger-entry read and determines that some balance for ledger entry X, preparing to send it to party Y, but before finishing A makes some call it hope is benign to contract B which calls C which then maliciously and unexpectedly calls A back and modifies X again, sending the balance to party Z.

This is a concurrency anomaly in that there are two copies of A running, sharing concurrent access to the ledger and fighting over the value of X in that store, the second A won and changed X underneath the first A, and now the first A a stale read of X. So when control returns to that A it will double-spend X.

You could avoid this by doing a suitable attenuate call in A that turns off subsequent ledger IO, either in the callback, or the current frame, or the entire rest of the transaction. So once attenuated you can get reentrant callbacks to cause you to emit events, say, or forward calls to other 3rd parties, but not to do more ledger modifications.

This is a bit hand-wavey but I think something like this might be helpful, essentially a way for contracts to mark a phase-transition in a transaction that either commits their changes or locks themselves (or other reentrant copies of themselves) out of making such changes, before handing over control to an unknown 3rd party (assuming we do the thing where we call first class methods on unknown 3rd party references, I gather that remains part of our design).

This arose in a conversation I was having earlier with @MonsieurNicolas where we were thinking of easy ways to limit the danger of reentry (and also try_call which as it stands allows you to call a contract and observe its failure and then call it again in the same tx, which might be an unintended information-channel). Some systems essentially only allow you to do a "tail call" from contract to contract, possibly passing a continuation or closure for re-entry, which is a more dramatic restriction than this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants
@graydon @leighmcculloch @jayz22 and others