Commit 873a4eab authored by mbaxter's avatar mbaxter Committed by GitHub

cannon: Port audit fixes (#11697)

* cannon: Require boolean exited field to be encoded as 0 or 1

* cannon: Port mmap solidity tests for MTCannon

* cannon: Port srav solidity tests

* cannon: Run semver-lock, snapshot tasks

* cannon: Cut extra validation on thread.exited

* cannon: Run semver lock

* cannon: Update IMIPS2 interface
parent 85c79a55
...@@ -148,8 +148,8 @@ ...@@ -148,8 +148,8 @@
"sourceCodeHash": "0xb6e219e8c2d81d75c48a1459907609e9096fe032a7447c88cd3e0d134752ac8e" "sourceCodeHash": "0xb6e219e8c2d81d75c48a1459907609e9096fe032a7447c88cd3e0d134752ac8e"
}, },
"src/cannon/MIPS2.sol": { "src/cannon/MIPS2.sol": {
"initCodeHash": "0x36b7c32cf9eba05e6db44910a25c800b801c075f8e053eca9515c6e0e4d8a902", "initCodeHash": "0xf5e2bca4ba0c504ffa68f1ce5fbf4349b1fa892034777d77803d9111aed279fa",
"sourceCodeHash": "0xa307c44a2d67bc84e75f4b7341345ed236da2e63c1f3f442416f14cd262126bf" "sourceCodeHash": "0xe8d06d4e2c3cf6e0682e4c152429cd61f0fd963acb1190df1bba1727d90ef6b7"
}, },
"src/cannon/PreimageOracle.sol": { "src/cannon/PreimageOracle.sol": {
"initCodeHash": "0xce7a1c3265e457a05d17b6d1a2ef93c4639caac3733c9cf88bfd192eae2c5788", "initCodeHash": "0xce7a1c3265e457a05d17b6d1a2ef93c4639caac3733c9cf88bfd192eae2c5788",
......
...@@ -51,5 +51,10 @@ ...@@ -51,5 +51,10 @@
], ],
"stateMutability": "view", "stateMutability": "view",
"type": "function" "type": "function"
},
{
"inputs": [],
"name": "InvalidExitedValue",
"type": "error"
} }
] ]
\ No newline at end of file
...@@ -51,8 +51,8 @@ contract MIPS2 is ISemver { ...@@ -51,8 +51,8 @@ contract MIPS2 is ISemver {
} }
/// @notice The semantic version of the MIPS2 contract. /// @notice The semantic version of the MIPS2 contract.
/// @custom:semver 1.0.0-beta.5 /// @custom:semver 1.0.0-beta.6
string public constant version = "1.0.0-beta.5"; string public constant version = "1.0.0-beta.6";
/// @notice The preimage oracle contract. /// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE; IPreimageOracle internal immutable ORACLE;
...@@ -91,7 +91,7 @@ contract MIPS2 is ISemver { ...@@ -91,7 +91,7 @@ contract MIPS2 is ISemver {
unchecked { unchecked {
State memory state; State memory state;
ThreadState memory thread; ThreadState memory thread;
uint32 exited;
assembly { assembly {
if iszero(eq(state, STATE_MEM_OFFSET)) { if iszero(eq(state, STATE_MEM_OFFSET)) {
// expected state mem offset check // expected state mem offset check
...@@ -131,6 +131,7 @@ contract MIPS2 is ISemver { ...@@ -131,6 +131,7 @@ contract MIPS2 is ISemver {
c, m := putField(c, m, 4) // heap c, m := putField(c, m, 4) // heap
c, m := putField(c, m, 1) // exitCode c, m := putField(c, m, 1) // exitCode
c, m := putField(c, m, 1) // exited c, m := putField(c, m, 1) // exited
exited := mload(sub(m, 32))
c, m := putField(c, m, 8) // step c, m := putField(c, m, 8) // step
c, m := putField(c, m, 8) // stepsSinceLastContextSwitch c, m := putField(c, m, 8) // stepsSinceLastContextSwitch
c, m := putField(c, m, 4) // wakeup c, m := putField(c, m, 4) // wakeup
...@@ -139,6 +140,7 @@ contract MIPS2 is ISemver { ...@@ -139,6 +140,7 @@ contract MIPS2 is ISemver {
c, m := putField(c, m, 32) // rightThreadStack c, m := putField(c, m, 32) // rightThreadStack
c, m := putField(c, m, 4) // nextThreadID c, m := putField(c, m, 4) // nextThreadID
} }
st.assertExitedIsValid(exited);
if (state.exited) { if (state.exited) {
// thread state is unchanged // thread state is unchanged
...@@ -459,6 +461,7 @@ contract MIPS2 is ISemver { ...@@ -459,6 +461,7 @@ contract MIPS2 is ISemver {
/// @notice Computes the hash of the MIPS state. /// @notice Computes the hash of the MIPS state.
/// @return out_ The hashed MIPS state. /// @return out_ The hashed MIPS state.
function outputState() internal returns (bytes32 out_) { function outputState() internal returns (bytes32 out_) {
uint32 exited;
assembly { assembly {
// copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data // copies 'size' bytes, right-aligned in word at 'from', to 'to', incl. trailing data
function copyMem(from, to, size) -> fromOut, toOut { function copyMem(from, to, size) -> fromOut, toOut {
...@@ -481,7 +484,7 @@ contract MIPS2 is ISemver { ...@@ -481,7 +484,7 @@ contract MIPS2 is ISemver {
from, to := copyMem(from, to, 4) // heap from, to := copyMem(from, to, 4) // heap
let exitCode := mload(from) let exitCode := mload(from)
from, to := copyMem(from, to, 1) // exitCode from, to := copyMem(from, to, 1) // exitCode
let exited := mload(from) exited := mload(from)
from, to := copyMem(from, to, 1) // exited from, to := copyMem(from, to, 1) // exited
from, to := copyMem(from, to, 8) // step from, to := copyMem(from, to, 8) // step
from, to := copyMem(from, to, 8) // stepsSinceLastContextSwitch from, to := copyMem(from, to, 8) // stepsSinceLastContextSwitch
...@@ -516,6 +519,8 @@ contract MIPS2 is ISemver { ...@@ -516,6 +519,8 @@ contract MIPS2 is ISemver {
out_ := keccak256(start, sub(to, start)) out_ := keccak256(start, sub(to, start))
out_ := or(and(not(shl(248, 0xFF)), out_), shl(248, status)) out_ := or(and(not(shl(248, 0xFF)), out_), shl(248, status))
} }
st.assertExitedIsValid(exited);
} }
/// @notice Updates the current thread stack root via inner thread root in calldata /// @notice Updates the current thread stack root via inner thread root in calldata
......
...@@ -6,5 +6,7 @@ import { ISemver } from "src/universal/ISemver.sol"; ...@@ -6,5 +6,7 @@ import { ISemver } from "src/universal/ISemver.sol";
/// @title IMIPS2 /// @title IMIPS2
/// @notice Interface for the MIPS2 contract. /// @notice Interface for the MIPS2 contract.
interface IMIPS2 is ISemver { interface IMIPS2 is ISemver {
error InvalidExitedValue();
function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32); function step(bytes memory _stateData, bytes memory _proof, bytes32 _localContext) external returns (bytes32);
} }
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { InvalidExitedValue } from "src/cannon/libraries/CannonErrors.sol";
library MIPSState { library MIPSState {
struct CpuScalars { struct CpuScalars {
uint32 pc; uint32 pc;
...@@ -8,4 +10,10 @@ library MIPSState { ...@@ -8,4 +10,10 @@ library MIPSState {
uint32 lo; uint32 lo;
uint32 hi; uint32 hi;
} }
function assertExitedIsValid(uint32 exited) internal pure {
if (exited > 1) {
revert InvalidExitedValue();
}
}
} }
...@@ -65,7 +65,6 @@ contract MIPS_Test is CommonTest { ...@@ -65,7 +65,6 @@ contract MIPS_Test is CommonTest {
/// invalid (anything greater than 1). /// invalid (anything greater than 1).
/// @param _exited Value to set the exited field to. /// @param _exited Value to set the exited field to.
function testFuzz_step_invalidExitedValue_fails(uint8 _exited) external { function testFuzz_step_invalidExitedValue_fails(uint8 _exited) external {
// Assume
// Make sure the value of _exited is invalid. // Make sure the value of _exited is invalid.
_exited = uint8(bound(uint256(_exited), 2, type(uint8).max)); _exited = uint8(bound(uint256(_exited), 2, type(uint8).max));
...@@ -77,6 +76,7 @@ contract MIPS_Test is CommonTest { ...@@ -77,6 +76,7 @@ contract MIPS_Test is CommonTest {
// Compute the encoded state and manipulate it. // Compute the encoded state and manipulate it.
bytes memory enc = encodeState(state); bytes memory enc = encodeState(state);
assembly { assembly {
// Push offset by an additional 32 bytes (0x20) to account for length prefix
mstore8(add(add(enc, 0x20), 89), _exited) mstore8(add(add(enc, 0x20), 89), _exited)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment