This patch moves recv and recvfrom interceptors to sanitizer_common to enable them in ASan. This those, we would be able to catch CVE-2015-7547 with dynamic stack buffer overflow (https://groups.google.com/forum/#!topic/address-sanitizer/ttPxNhTK9TU).
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
I think this should go into sanitizer_common, to also cover tsan.
(msan has one, so merge msan's one into sanitizer_common).
also, would be nice to have a test in test/asan/TestCases/Linux
OK, let's try more. Moved recvfrom and recv interceptors from TSan and MSan to sanitizer_common. I'm adding Dmitry to reviewers because this change affects TSan. The testcase for ASan may look scary at first glance, but actually it's quite simple:
- Create simple UDP server in thread 1 and wait for a message. The size of allocated destination buffer is less then expected message length.
- Create simple UDP client in thread 0 and send the message.
- Crash in recvfrom function due to buffer overflow.
| lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5352 ↗ | (On Diff #48907) | this is copied from recv, needs to be updated |
| 5354 ↗ | (On Diff #48907) | this var is unused |
| 5357 ↗ | (On Diff #48907) | res > 0 |
| 5359 ↗ | (On Diff #48907) | this is different from what msan did |
| 5361 ↗ | (On Diff #48907) | drop this |
| lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5359 ↗ | (On Diff #48907) | You are right. This is msan specific code, so perhaps we could wrap the whole if to macro (say, COMMON_INTERCEPTOR_UNPOISON_COND) and define it like this: #define COMMON_INTERCEPTOR_UNPOISON_COND(srcaddr, sz, srcaddr_sz) \
do { \
if (srcaddr) { \
SIZE_T sz = *addrlen; \
__msan_unpoison(srcaddr, Min(sz, srcaddr_sz)); \
} \
} while (false)for msan and empty macros for others (just like COMMON_INTERCEPTOR_UNPOISON_PARAM)? |
| lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5359 ↗ | (On Diff #48907) | __msan_unpoison(srcaddr, Min(sz, *addrlen)) looks simpler to me |
Otherwise looks good.
| lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5364 ↗ | (On Diff #48944) | I would just do: if (srcaddr)
__msan_unpoison(srcaddr, Min(srcaddr_sz, *addrlen));The macro makes code more convoluted without adding significant value. Every time I read this function I will need to go and check macro definition. |
| lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5364 ↗ | (On Diff #48944) |
Agree here, but wouldn't this lead to use of undeclared identifier '__msan_unpoison' errors in {a, t}san_interceptors.cc? I used the macro just to avoid such issues. Perhaps I can avoid introducing a new macro and write something like this: if (srcaddr) COMMON_INTERCEPTOR_INITIALIZE_RANGE(srcaddr, Min(srcaddr_sz, (SIZE_T)*addrlen)); |
| lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5364 ↗ | (On Diff #48944) | Right. |
I've also disabled recvfrom.cc testcase (http://reviews.llvm.org/rL261870) for now due to buildbot failure:
FAIL: AddressSanitizer-i386-linux :: TestCases/Linux/recvfrom.cc (524 of 1166) ******************** TEST 'AddressSanitizer-i386-linux :: TestCases/Linux/recvfrom.cc' FAILED ******************** Script: -- /mnt/b/sanitizer-buildbot1/sanitizer-x86_64-linux/build/clang_build/./bin/clang --driver-mode=g++ -fsanitize=address -mno-omit-leaf-frame-pointer -fno-omit-frame-pointer -fno-optimize-sibling-calls -gline-tables-only -m32 /mnt/b/sanitizer-buildbot1/sanitizer-x86_64-linux/build/llvm/projects/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc -o /mnt/b/sanitizer-buildbot1/sanitizer-x86_64-linux/build/clang_build/projects/compiler-rt/test/asan/I386LinuxConfig/TestCases/Linux/Output/recvfrom.cc.tmp && not /mnt/b/sanitizer-buildbot1/sanitizer-x86_64-linux/build/clang_build/projects/compiler-rt/test/asan/I386LinuxConfig/TestCases/Linux/Output/recvfrom.cc.tmp 2>&1 | FileCheck /mnt/b/sanitizer-buildbot1/sanitizer-x86_64-linux/build/llvm/projects/compiler-rt/test/asan/TestCases/Linux/recvfrom.cc -- Exit Code: 2 Command Output (stderr): -- FileCheck error: '-' is empty. --
| compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5343 | I think you can submit such an obvious fix directly. | |
| compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc | ||
|---|---|---|
| 5343 | Thanks, I've already done it (approved by Dmitry): http://reviews.llvm.org/D17608. | |
I've just noticed, that here and below in recvfrom we should pass res as third parameter, not len. Should I create a new revision on Phabricator?