This is an archive of the discontinued LLVM Phabricator instance.

[sanitizer-common] Run module msan init before early sigaction test
ClosedPublic

Authored by mysterymath on Jul 18 2023, 2:57 PM.

Details

Summary

MSAN wrappers can be inserted for e.g. the access to stderr in the
constructor of the test, which can segfault if the constructor function
runs before these data structures have been initialized.

Diff Detail

Event Timeline

mysterymath created this revision.Jul 18 2023, 2:57 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 18 2023, 2:57 PM
Herald added a subscriber: Enna1. · View Herald Transcript
mysterymath requested review of this revision.Jul 18 2023, 2:57 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 18 2023, 2:57 PM
Herald added a subscriber: Restricted Project. · View Herald Transcript

Can MSan initialize properly on its own?
Let's say this test is an actual user program and it crashes.

What is "access to stderr"? Is stderr a macro that is defined to a function call in this impl?

dvyukov accepted this revision.Jul 19 2023, 12:26 AM

Reading the other thread:

It dereferences some value that it picks out of the GOT, but that isn't mapped in the binary.

On Linux these global things should be initialized in the dynamic loader before constructors start.
.preinit_array callbacks can run when these are not intialized.
Though, docs say that priorities 0-100 are reserved for implementation so not guaranteed to work. So probably the change is fine as is (but Fuchsia will defintiely hit it in future on real programs out there).

Another option may be to change printf to write(STDERR_FILENO). But not sure if it's better.

This revision is now accepted and ready to land.Jul 19 2023, 12:26 AM
mysterymath added a comment.EditedJul 19 2023, 10:57 AM

Reading the other thread:

It dereferences some value that it picks out of the GOT, but that isn't mapped in the binary.

It looks like I was actually wrong about that; the access is to some MSAN-manipulated pointer that's read out of the GOT. Here's the disassembly ending at the segfault:

0000000000f86e8 <_Z4ctorv>:
   f86e8:       55                      push   %rbp
   f86e9:       48 89 e5                mov    %rsp,%rbp
   f86ec:       48 81 ec b0 00 00 00    sub    $0xb0,%rsp
   f86f3:       48 8b 05 66 a5 00 00    mov    0xa566(%rip),%rax        # 102c60 <stderr@GLIBC_2.2.5>
                        f86f6: R_X86_64_REX_GOTPCRELX   stderr-0x4
   f86fa:       48 8b 08                mov    (%rax),%rcx
   f86fd:       48 89 8d 60 ff ff ff    mov    %rcx,-0xa0(%rbp)
   f8704:       48 b9 00 00 00 00 00    movabs $0x500000000000,%rcx
   f870b:       50 00 00
   f870e:       48 31 c8                xor    %rcx,%rax
   f8711:       48 8b 00                mov    (%rax),%rax

So probably the change is fine as is (but Fuchsia will defintiely hit it in future on real programs out there).

Ah, I should note that this change isn't happening on Fuchsia, it's happening on a Linux host when LLVM is configured to build the Fuchsia toolchain. The above disassembly is from a x86-64 Linux version of the compiled sigaction.cpp.