Not matching the (real) variadic declaration makes the interceptor take garbage inputs on AArch64.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
Not matching the (real) variadic declaration makes the interceptor take garbage inputs on AArch64.
Is this Darwin specific or does it apply to aarch64-linux as well?
compiler-rt/test/tsan/Darwin/variadic-open.cpp | ||
---|---|---|
1 ↗ | (On Diff #280630) | Is this Darwin specific or does it apply to aarch64-linux as well? |
compiler-rt/test/tsan/Darwin/variadic-open.cpp | ||
---|---|---|
1 ↗ | (On Diff #280630) | I believe this is Darwin specific. See https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html which explains that all variadic arguments are always passed on the stack. |
compiler-rt/test/tsan/Darwin/variadic-open.cpp | ||
---|---|---|
12 ↗ | (On Diff #280630) | Is that just a umask effect? Would a call to umask(0) help here? |
This fails on Linux/PPC64: http://lab.llvm.org:8011/builders/clang-ppc64be-linux/builds/52026/steps/ninja%20check%201/logs/FAIL%3A%20ThreadSanitizer-powerpc64%3A%3A%20variadic-open.cpp
I'm going to move the test back to the Darwin/ folder, as I don't have a good way to debug this.
@vitalybuka If you have suggestions how to make this reliably work on Linux, I'll be happy to add/move the test again.
Actually given the symptom, I'm thinking this could be a real problem with the variadic interceptor:
1: Hello world. 2: permissions = 07777
Would anyone with access to a Linux/PPC64 machine be willing to take a look if the open() syscall is receiving the right value (0600 from the testcase)?
I can provide you access to a PPC64LE machine or I can check the details myself if you can tell me exactly what to do and how.
I can provide you access to a PPC64LE machine or I can check the details myself if you can tell me exactly what to do and how.
What I would like to look into is: Build and run the testcase from this patch (variadic-open.cpp) *without* TSan, check that the resulting file permissions are 0600. Then build llvm+compiler-rt on PPC64, and build and run the testcase with the just-built clang *with* TSan on, and that should result with the file permissions reported as 07777? Then try to revert the code change from this patch (from tsan_interceptors_posix.cpp) and re-build and re-run the testcase *with* TSan. Does it now work correctly (report 0600)?
Let me know if think sounds too time-consuming and I can certainly do that myself with a remote access to a machine :)
Thanks!!!
...and could you also see if perhaps this change helps:
diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -137,7 +137,11 @@ const int PTHREAD_BARRIER_SERIAL_THREAD = -1; #endif const int MAP_FIXED = 0x10; typedef long long_t; +#if SANITIZER_MAC || SANITIZER_FREEBSD || SANITIZER_NETBSD typedef __sanitizer::u16 mode_t; +#else +typedef __sanitizer::u32 mode_t; +#endif // From /usr/include/unistd.h # define F_ULOCK 0 /* Unlock a previously locked region. */
I'll send you the results in a few minutes. Sorry about the delay - holiday here in Canada.
It would appear that this failure is not really related to this patch at all. Seems to fail with -O0/-O1 regardless of which patch is applied.
https://pastebin.com/1Mvz5KDz
Please let me know if there's something else I can help with.
At a very quick glance, the two versions call different interceptors.
The -O1 version calls __interceptor_fstat and the -O2 version calls __interceptor___fxstat.
I am not sure if that reveals anything further, but that seems to be the major difference between the two.
If I read the output right, it seems that even before this change, running with TSan messes up the permissions argument. I think this may be some latent bug in glibc that is only triggered in unusual environments (like TSan). I found this comment at https://lkml.org/lkml/2014/10/30/812:
... uses a conditional va_arg() to get
the third parameter *despite* not even being a variadic function (not
varargs, not stdarg). So it's not even portable or correct *anyway*,
Which sounds relevant. Just a guess, but maybe the varargs code in glibc is technically wrong, but under normal conditions, it just ends up being lucky and the right value ends up at the right register/stackslot?