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

Sequencer suffers from TOCTOU issues #1318

Closed
SuperFluffy opened this issue Jul 31, 2024 · 1 comment · Fixed by #1332
Closed

Sequencer suffers from TOCTOU issues #1318

SuperFluffy opened this issue Jul 31, 2024 · 1 comment · Fixed by #1332
Assignees
Labels
bug Something isn't working sequencer pertaining to the astria-sequencer crate

Comments

@SuperFluffy
Copy link
Member

SuperFluffy commented Jul 31, 2024

Bug found by auditors:

Due to the way action handling is done, unexpected behaviors can be noted.

a transactions action's stateful checks are ran together in parallel. Then the actions are executed.

Action 1 -> check_stateful()
Action 2 -> check_stateful()
...
Action 1 -> Execute()
Action 2 -> Execute()

This means that certain actions could have unforseen consequences. Imagine 2 BridgeSudoChangeAction actions which have been bundled into 1 tx, they would both execute even if the first action changes the sudo address because the stateful checks of both actions are executed before the execute

    async fn check_stateless(&self) -> anyhow::Result<()> {
        ensure!(!self.actions.is_empty(), "must have at least one action");

        for action in &self.actions {
            match action {

┆Issue Number: ENG-666

@SuperFluffy
Copy link
Member Author

SuperFluffy commented Jul 31, 2024

Some thoughts I have for this:

Because check_stateless, check_stateful, and execute are split and run one after the other, this inherently creates ace conditions. The way to fix this is to move the checks into execute. Given their serial nature this addresses the problem.

Looking at the current state of cnidarium, I find that they changed their naming in cndiarium_component::ActionHandler to the following:

@SuperFluffy SuperFluffy added bug Something isn't working sequencer pertaining to the astria-sequencer crate labels Jul 31, 2024
@SuperFluffy SuperFluffy self-assigned this Jul 31, 2024
Fraser999 added a commit to Fraser999/astria that referenced this issue Aug 8, 2024
github-merge-queue bot pushed a commit that referenced this issue Aug 20, 2024
)

## Summary
Introduces `ActionHandler::check_and_execute`, replacing
`ActionHandler::check_stateful` and `ActionHandler::execute`.

## Background
Zelic found that separating execution into `check_stateful` and
`execute` lead to time-of-check-vs-time-of-use risks: while
`check_stateful` for two actions `A` and `B` might each pass, the
execution of action `A` might change the state such that a subsequent
execution of action `B` would now fail - or worse, lead to invalid
state.

This patch follows Penumbra (see issues linked at the bottom) in merging
them into one atomic operation (atomic in the sense that
`<Action>::check_and_execute` are run sequentially).

There is also a `ActionHandler::check_historic` trait method, which
however is currently not used. It is left for future work to go through
the individual checks and move them to `check_historic`, where
applicable (for example, checking address prefixes as long as changing
these is not possible after chain init).

## Changes
- change `ActionHandler` trait to merge `check_stateful` and `execute`
into `check_and_execute`.
- inject a transaction's signer into the ephemeral object store, setting
before and after a transaction is executed. Necessary because this
follows the `cnidarium_component::ActionHandler` convention, but also
allows simplifying
- remove the notion of bech32m addresses from many state writes and
reads: the prefix only matters at the boundary, not inside the system

## Testing
All tests were updated and pass.

NOTE: a useful test would be to craft a problematic transaction that
would be rejected with the newest change. However, crafting and
executing such a transaction so that it is rejected by the current
sequencer but leads to incorrect is left to a follow-up.

## Breaking Changelist
While no snapshots guarding against breaking app state were triggered,
this is still a breaking change: if supplied with a problematic payload,
a sequencer node without this patch will reach a different (and invalid)
state compared a node with the present patch.

## Related Issues

Original Penumbra issues and fix:
penumbra-zone/penumbra#3960
penumbra-zone/penumbra#3960

Closes #1318

---------

Co-authored-by: Fraser Hutchison <190532+Fraser999@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working sequencer pertaining to the astria-sequencer crate
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant