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

Fix segfault in cs_option() on s390x #166

Merged
merged 2 commits into from
Jan 31, 2025

Conversation

iii-i
Copy link
Contributor

@iii-i iii-i commented Jan 14, 2025

capstone-rs crashes on s390x (also knows as SystemZ in the LLVM world)
as follows:

Thread 2 received signal SIGSEGV, Segmentation fault.
0x000002aa00a6a604 in cs_option (ud=140702726002672, type=CS_OPT_SYNTAX, value=2) at capstone/cs.c:782
782             return arch_configs[handle->arch].arch_option(handle, type, value);

(gdb) p/x handle->arch
$7 = 0x7ffb

handle->arch is clearly corrupted. It is assigned as follows in
cs_open():

   0x000002aa00a6a44a <+146>:   lgr     %r9,%r3
[...]
   0x000002aa00a6a468 <+176>:   rosbg   %r9,%r10,0,31,32
[...]
458                     ud->arch = arch;
459                     ud->mode = mode;
   0x000002aa00a6a47a <+194>:   stg     %r9,0(%r13)

Here the 32-bit arch value and the 32-bit mode value are placed into a
64-bit register and stored with one instruction.

The important part is that cs_mode is a 32-bit value passed in %r3, and
the code uses instructions with mnemonics ending with "g", which
operate on full 64-bit registers [1]. This is allowed because of the
s390x ABI [1]: it requires zero-extension of 4-byte int arguments.

Bitfield enums are currently generated like this:

#[repr(C)]
[...]
pub struct cs_mode(pub libc::c_uint);

which causes the problem above, because the ABI does not require
zero-extension of 4-byte struct arguments.

Starting from RustTarget::Stable_1_28, bindgen
generates #[repr(transparent)] instead of #[repr(C)], which is
designed to solve exactly this kind of problems [3].

capstone-rs' MSRV is 1.70, so it should be possible to go even further,
but be conservative and use the minimum version necessary to fix the
issue.

[1] https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf
[2] https://github.com/IBM/s390x-abi/releases
[3] https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent

@iii-i iii-i force-pushed the fix-segfault-in-cs-option-on-s390x branch from d751f07 to 0658209 Compare January 14, 2025 20:54
@iii-i
Copy link
Contributor Author

iii-i commented Jan 14, 2025

  • Fixed a couple typos.

@iii-i
Copy link
Contributor Author

iii-i commented Jan 16, 2025

  • (Hopefully) fixed a clippy warning in unrelated code.

iii-i added 2 commits January 16, 2025 23:21
capstone-rs crashes on s390x (also knows as SystemZ in the LLVM world)
as follows:

    Thread 2 received signal SIGSEGV, Segmentation fault.
    0x000002aa00a6a604 in cs_option (ud=140702726002672, type=CS_OPT_SYNTAX, value=2) at capstone/cs.c:782
    782             return arch_configs[handle->arch].arch_option(handle, type, value);

    (gdb) p/x handle->arch
    $7 = 0x7ffb

handle->arch is clearly corrupted. It is assigned as follows in
cs_open():

       0x000002aa00a6a44a <+146>:   lgr     %r9,%r3
    [...]
       0x000002aa00a6a468 <+176>:   rosbg   %r9,%r10,0,31,32
    [...]
    458                     ud->arch = arch;
    459                     ud->mode = mode;
       0x000002aa00a6a47a <+194>:   stg     %r9,0(%r13)

Here the 32-bit arch value and the 32-bit mode value are placed into a
64-bit register and stored with one instruction.

The important part is that cs_mode is a 32-bit value passed in %r3, and
the code uses instructions with mnemonics ending with "g", which
operate on full 64-bit registers [1]. This is allowed because of the
s390x ABI [1]: it requires zero-extension of 4-byte int arguments.

Bitfield enums are currently generated like this:

    #[repr(C)]
    [...]
    pub struct cs_mode(pub libc::c_uint);

which causes the problem above, because the ABI does not require
zero-extension of 4-byte struct arguments.

Starting from RustTarget::Stable_1_28, bindgen
generates #[repr(transparent)] instead of #[repr(C)], which is
designed to solve exactly this kind of problems [3].

capstone-rs' MSRV is 1.70, so it should be possible to go even further,
but be conservative and use the minimum version necessary to fix the
issue.

[1] https://publibfp.dhe.ibm.com/epubs/pdf/a227832d.pdf
[2] https://github.com/IBM/s390x-abi/releases
[3] https://doc.rust-lang.org/nomicon/other-reprs.html#reprtransparent
@iii-i iii-i force-pushed the fix-segfault-in-cs-option-on-s390x branch from ae8f3bc to 7c89f33 Compare January 16, 2025 22:21
@iii-i
Copy link
Contributor Author

iii-i commented Jan 16, 2025

  • Local testing with nightly has produced even more clippy warnings; fixed all of them.

@tmfink
Copy link
Member

tmfink commented Jan 24, 2025

Thanks for the PR! Your comments are very descriptive.
I'll try to review your changes, but no promises on the timeline.

@tmfink tmfink merged commit 0282aa5 into capstone-rust:master Jan 31, 2025
16 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.

3 participants