Skip to content

Conversation

aman4150
Copy link
Collaborator

generic-sandbox: Fix signal handling on macOS

ucontext_t is different on macOS and Linux. On macOS, SIGSEGV is not
sent for page faults, instead SIGBUS is sent. This commit updates the
signal handler to check for SIGBUS on macOS.

Finally, we also fix the page fault address extraction on macOS.

Signed-off-by: Aman <[email protected]>

generic-sandbox: Fix invalid jump detection on macOS / Rosetta 2

On Rosetta 2, indirect jump to a non-canonical address doesn't trigger
a page fault (SIGBUS) right away. Instead, it jumps to the address, and then
triggers a page fault (SIGBUS) when trying to fetch the instruction.

This means that previous program counter is now lost, and now we have no
way of detecting if the guest program triggered an invalid jump or not.

We fix this program by updating the vmctx before making the jump and in
the signal handler we check if the current program counter is non-canonical.

Signed-off-by: Aman <[email protected]>

ci: Run generic-sandbox tests in CI on aarch64 MacOS using Rosetta 2

Signed-off-by: Aman <[email protected]>

@aman4150 aman4150 force-pushed the macos-fixes-and-ci branch 2 times, most recently from 29a9d53 to c4ae795 Compare September 22, 2025 12:01
@aman4150 aman4150 requested a review from koute September 22, 2025 12:02

[dependencies]
log = { workspace = true }
paste = { workspace = true }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this.

We deliberately keep the number of dependencies to a minimum, especially dependencies which don't really bring any extra functionality and are just quality-of-life improvements like paste here it. Currently the only external dependency we have is the log crate, and I'd like to keep it that way. (The schnellru crate is my own crate, so it doesn't count. :P)

You should be able to do something like this instead of using the paste crate:

#[cfg(target_os = "macos")]
macro_rules! reg_field {
    (rax) => {__rax};
    (rbx) => {__rbx};
}

#[cfg(not(target_os = "macos"))]
macro_rules! reg_field {
    ($reg:ident) => {$reg};
}

And then use reg_field! in the fetch_reg.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

ucontext_t is different on macOS and Linux. On macOS, SIGSEGV is not
sent for page faults, instead SIGBUS is sent. This commit updates the
signal handler to check for SIGBUS on macOS.

Finally, we also fix the page fault address extraction on macOS.

Signed-off-by: Aman <[email protected]>
On Rosetta 2, indirect jump to a non-canonical address doesn't trigger
a page fault (SIGBUS) right away. Instead, it jumps to the address, and then
triggers a page fault (SIGBUS) when trying to fetch the instruction.

This means that previous program counter is now lost, and now we have no
way of detecting if the guest program triggered an invalid jump or not.

We fix this program by updating the vmctx before making the jump and in
the signal handler we check if the current program counter is non-canonical.

Signed-off-by: Aman <[email protected]>
@aman4150 aman4150 merged commit a9f31a3 into paritytech:master Sep 30, 2025
12 checks passed
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

Successfully merging this pull request may close these issues.

2 participants