Commit 95765dfc authored by mbaxter's avatar mbaxter Committed by GitHub

cannon: Handle unaligned futex addresses (#11929)

* cannon: Update tests for futex unaligned memory behavior

* cannon: Align futex-related addresses when they are set

* cannon: Run lint and semver tasks

* cannon: Add wakeup traversal tests with unaligend addresses

* cannon: Don't panic if ThreadState.FutexAddr is unaligned

* cannon: Run semver lock task

* cannon: Cleanup stray whitespace
parent 717330e9
...@@ -105,15 +105,16 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -105,15 +105,16 @@ func (m *InstrumentedState) handleSyscall() error {
return nil return nil
case exec.SysFutex: case exec.SysFutex:
// args: a0 = addr, a1 = op, a2 = val, a3 = timeout // args: a0 = addr, a1 = op, a2 = val, a3 = timeout
effAddr := a0 & 0xFFffFFfc
switch a1 { switch a1 {
case exec.FutexWaitPrivate: case exec.FutexWaitPrivate:
m.memoryTracker.TrackMemAccess(a0) m.memoryTracker.TrackMemAccess(effAddr)
mem := m.state.Memory.GetMemory(a0) mem := m.state.Memory.GetMemory(effAddr)
if mem != a2 { if mem != a2 {
v0 = exec.SysErrorSignal v0 = exec.SysErrorSignal
v1 = exec.MipsEAGAIN v1 = exec.MipsEAGAIN
} else { } else {
thread.FutexAddr = a0 thread.FutexAddr = effAddr
thread.FutexVal = a2 thread.FutexVal = a2
if a3 == 0 { if a3 == 0 {
thread.FutexTimeoutStep = exec.FutexNoTimeout thread.FutexTimeoutStep = exec.FutexNoTimeout
...@@ -126,7 +127,7 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -126,7 +127,7 @@ func (m *InstrumentedState) handleSyscall() error {
case exec.FutexWakePrivate: case exec.FutexWakePrivate:
// Trigger thread traversal starting from the left stack until we find one waiting on the wakeup // Trigger thread traversal starting from the left stack until we find one waiting on the wakeup
// address // address
m.state.Wakeup = a0 m.state.Wakeup = effAddr
// Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees. // Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees.
// The woken up thread should indicate this in userspace. // The woken up thread should indicate this in userspace.
v0 = 0 v0 = 0
...@@ -255,8 +256,9 @@ func (m *InstrumentedState) mipsStep() error { ...@@ -255,8 +256,9 @@ func (m *InstrumentedState) mipsStep() error {
m.onWaitComplete(thread, true) m.onWaitComplete(thread, true)
return nil return nil
} else { } else {
m.memoryTracker.TrackMemAccess(thread.FutexAddr) effAddr := thread.FutexAddr & 0xFFffFFfc
mem := m.state.Memory.GetMemory(thread.FutexAddr) m.memoryTracker.TrackMemAccess(effAddr)
mem := m.state.Memory.GetMemory(effAddr)
if thread.FutexVal == mem { if thread.FutexVal == mem {
// still got expected value, continue sleeping, try next thread. // still got expected value, continue sleeping, try next thread.
m.preemptThread(thread) m.preemptThread(thread)
......
...@@ -144,8 +144,8 @@ ...@@ -144,8 +144,8 @@
"sourceCodeHash": "0xba4674e1846afbbc708877332a38dfabd4b8d1e48ce07d8ebf0a45c9f27f16b0" "sourceCodeHash": "0xba4674e1846afbbc708877332a38dfabd4b8d1e48ce07d8ebf0a45c9f27f16b0"
}, },
"src/cannon/MIPS2.sol": { "src/cannon/MIPS2.sol": {
"initCodeHash": "0xdaed5d70cc84a53f224c28f24f8eef26d5d53dfba9fdc4f1b28c3b231b974e53", "initCodeHash": "0xd9da47f735b7a655a25ae0e867b467620a2cb537eb65d184a361f5ea4174d384",
"sourceCodeHash": "0x4026eb7ae7b303ec4c3c2880e14e260dbcfc0b4290459bcd22994cfed8655f80" "sourceCodeHash": "0x3a6d83a7d46eb267f6778f8ae116383fe3c14ad553d90b6c761fafeef22ae29c"
}, },
"src/cannon/PreimageOracle.sol": { "src/cannon/PreimageOracle.sol": {
"initCodeHash": "0x801e52f9c8439fcf7089575fa93272dfb874641dbfc7d82f36d979c987271c0b", "initCodeHash": "0x801e52f9c8439fcf7089575fa93272dfb874641dbfc7d82f36d979c987271c0b",
......
...@@ -57,8 +57,8 @@ contract MIPS2 is ISemver { ...@@ -57,8 +57,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.9 /// @custom:semver 1.0.0-beta.10
string public constant version = "1.0.0-beta.9"; string public constant version = "1.0.0-beta.10";
/// @notice The preimage oracle contract. /// @notice The preimage oracle contract.
IPreimageOracle internal immutable ORACLE; IPreimageOracle internal immutable ORACLE;
...@@ -175,7 +175,7 @@ contract MIPS2 is ISemver { ...@@ -175,7 +175,7 @@ contract MIPS2 is ISemver {
// Don't allow regular execution until we resolved if we have woken up any thread. // Don't allow regular execution until we resolved if we have woken up any thread.
if (state.wakeup != sys.FUTEX_EMPTY_ADDR) { if (state.wakeup != sys.FUTEX_EMPTY_ADDR) {
if (state.wakeup == thread.futexAddr) { if (state.wakeup == thread.futexAddr) {
// completed wake traverssal // completed wake traversal
// resume execution on woken up thread // resume execution on woken up thread
state.wakeup = sys.FUTEX_EMPTY_ADDR; state.wakeup = sys.FUTEX_EMPTY_ADDR;
return outputState(); return outputState();
...@@ -431,15 +431,15 @@ contract MIPS2 is ISemver { ...@@ -431,15 +431,15 @@ contract MIPS2 is ISemver {
return outputState(); return outputState();
} else if (syscall_no == sys.SYS_FUTEX) { } else if (syscall_no == sys.SYS_FUTEX) {
// args: a0 = addr, a1 = op, a2 = val, a3 = timeout // args: a0 = addr, a1 = op, a2 = val, a3 = timeout
uint32 effAddr = a0 & 0xFFffFFfc;
if (a1 == sys.FUTEX_WAIT_PRIVATE) { if (a1 == sys.FUTEX_WAIT_PRIVATE) {
uint32 mem = MIPSMemory.readMem( uint32 mem =
state.memRoot, a0 & 0xFFffFFfc, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1) MIPSMemory.readMem(state.memRoot, effAddr, MIPSMemory.memoryProofOffset(MEM_PROOF_OFFSET, 1));
);
if (mem != a2) { if (mem != a2) {
v0 = sys.SYS_ERROR_SIGNAL; v0 = sys.SYS_ERROR_SIGNAL;
v1 = sys.EAGAIN; v1 = sys.EAGAIN;
} else { } else {
thread.futexAddr = a0; thread.futexAddr = effAddr;
thread.futexVal = a2; thread.futexVal = a2;
thread.futexTimeoutStep = a3 == 0 ? sys.FUTEX_NO_TIMEOUT : state.step + sys.FUTEX_TIMEOUT_STEPS; thread.futexTimeoutStep = a3 == 0 ? sys.FUTEX_NO_TIMEOUT : state.step + sys.FUTEX_TIMEOUT_STEPS;
// Leave cpu scalars as-is. This instruction will be completed by `onWaitComplete` // Leave cpu scalars as-is. This instruction will be completed by `onWaitComplete`
...@@ -449,7 +449,7 @@ contract MIPS2 is ISemver { ...@@ -449,7 +449,7 @@ contract MIPS2 is ISemver {
} else if (a1 == sys.FUTEX_WAKE_PRIVATE) { } else if (a1 == sys.FUTEX_WAKE_PRIVATE) {
// Trigger thread traversal starting from the left stack until we find one waiting on the wakeup // Trigger thread traversal starting from the left stack until we find one waiting on the wakeup
// address // address
state.wakeup = a0; state.wakeup = effAddr;
// Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees. // Don't indicate to the program that we've woken up a waiting thread, as there are no guarantees.
// The woken up thread should indicate this in userspace. // The woken up thread should indicate this in userspace.
v0 = 0; v0 = 0;
......
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