This is an archive of the discontinued LLVM Phabricator instance.

[sanitizer] Use AT_EXECFN in ReExec() if available
ClosedPublic

Authored by bkramer on Nov 5 2018, 9:42 AM.

Details

Summary

execve("/proc/self/exe") will not work if the binary relies on
$EXEC_ORIGIN in an rpath. Query AT_EXECFN instead, which will give the
same string that the current binary was exec'd with.

Diff Detail

Event Timeline

bkramer created this revision.Nov 5 2018, 9:42 AM
Herald added subscribers: Restricted Project, delcypher, jlebar, kubamracek. · View Herald TranscriptNov 5 2018, 9:42 AM
jgorbe added a subscriber: jgorbe.Nov 5 2018, 10:10 AM

Is a test possible here?

bkramer updated this revision to Diff 172649.Nov 5 2018, 1:50 PM

Add test

In D54113#1287835, @kcc wrote:

Is a test possible here?

I thought it was only possible on PPC, but I can abuse the fact that MSAN re-execs on unlimited stacks. Test included.

vitalybuka added inline comments.Nov 5 2018, 2:48 PM
test/msan/Linux/reexec_unlimited_stack.cc
17

How this test triggers changed code?

bkramer added inline comments.Nov 5 2018, 2:59 PM
test/msan/Linux/reexec_unlimited_stack.cc
17

The idea is that the ulimit -s unlimited makes msan re-exec on startup. Currently this overwrites AT_EXECFN with /proc/self/exe. With this change it's preserved.

bkramer updated this revision to Diff 172669.Nov 5 2018, 3:01 PM
  • Add a comment to the test.
vitalybuka accepted this revision.Nov 5 2018, 4:41 PM
This revision is now accepted and ready to land.Nov 5 2018, 4:41 PM
This revision was automatically updated to reflect the committed changes.
This revision was automatically updated to reflect the committed changes.

$EXEC_ORIGIN ($ORIGIN without tracing the symlink) does not exist in vanilla glibc https://sourceware.org/ml/libc-alpha/2017-10/msg01109.html

This breaks TSanitizer-x86_64-Test-Nolibc as getauxval is a glibc symbol, which can be fixed by https://reviews.llvm.org/D54160

ld.lld: error: undefined symbol: getauxval
>>> referenced by sanitizer_linux.cc:646 (../projects/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc:646)
>>>               sanitizer_linux.cc.o:(__sanitizer::ReExec()) in archive libRTSanitizerCommon.test.nolibc.x86_64.a