Page MenuHomePhabricator

Add NetBSD ASAN shadow mapping for x86-64
ClosedPublic

Authored by krytarowski on Aug 10 2017, 12:33 PM.

Details

Summary

The maximal virtual address on NetBSD/amd64 is 0x7f7ffffff000.
Define shadow offset 0x400000000000 (1ULL << 46).

Sponsored by <The NetBSD Foundation>

Diff Detail

Repository
rL LLVM

Event Timeline

krytarowski created this revision.Aug 10 2017, 12:33 PM

I don't really get why the shadow offset differs between systems, I copied it from FreeBSD.
Please help to optimize it.

Also there is a problem with X86 (32-bit). There are two possible options: 32-bit application on 32-bit kernel or on 64-bit kernel.

For 32-bit kernel the maximal user address:
0xfffff000
For 64-bit kernel the maximal user address of 32-bit application:
0xbfbff000

What would be the proper offset here?

Adding more reviewers to get feedback.

joerg edited edge metadata.Aug 17 2017, 8:38 AM

Just assume that the full 32bit address space is available.

fjricci resigned from this revision.Aug 22 2017, 8:21 AM

I'm not familiar with this part of the codebase.

krytarowski added a comment.EditedAug 28 2017, 2:28 PM

ping x3

This is the last functional patch for asan/NetBSD support in compiler-rt.

kcc accepted this revision.Aug 28 2017, 2:29 PM

LGTM

This revision is now accepted and ready to land.Aug 28 2017, 2:29 PM

I kindly ask for explanation of this shadow offset value. (My questions were on top, I see them hidden by Phabricator now)

But anyway, I will commit it now and keep it optimizing in future.

krytarowski closed this revision.Aug 28 2017, 2:42 PM
eugenis edited edge metadata.Aug 28 2017, 2:53 PM

It's just an address where a shadow-sized hole is most like to be found.
But there are other considerations. For example, 0x7FFF8000 is the highest (or close to highest) address that allows shorter instruction encoding on x86_64. Zero offset is typically not used (even though it is usually the fastest option) because it conflicts with MAP_32BIT.

It's just an address where a shadow-sized hole is most like to be found.
But there are other considerations. For example, 0x7FFF8000 is the highest (or close to highest) address that allows shorter instruction encoding on x86_64. Zero offset is typically not used (even though it is usually the fastest option) because it conflicts with MAP_32BIT.

MAP_32BIT is Linux/FreeBSD specific, it's absent in NetBSD... does it mean that the shadowoffset should be 0?

How about i386?

For 32-bit kernel the maximal user address:
0xfffff000
For 64-bit kernel the maximal user address of 32-bit application:
0xbfbff000

Does NetBSD support non-PIE executables? Will they work with shadow at 0?

Does NetBSD support non-PIE executables? Will they work with shadow at 0?

NetBSD supports PIE and non-PIE executables. The non-PIE ones are the default option on x86_64.

I'm going to execute tests with shadow at 0.

While there waiting for build.. is PIE required for tsan? If so, why?

https://github.com/llvm-mirror/compiler-rt/blob/master/lib/tsan/rtl/tsan_platform_posix.cc#L34
https://github.com/llvm-mirror/compiler-rt/blob/master/lib/tsan/rtl/tsan_platform_posix.cc#L119

I need also enlightening how to translate struct Mapping to NetBSD

https://github.com/llvm-mirror/compiler-rt/blob/master/lib/tsan/rtl/tsan_platform_posix.cc#L119

I'm not sure if that is the real reason, but TSan shadow is 8-to-1. It's hard to find an address that can fit such a big allocation in both PIE and non-PIE layout.

Unless I'm looking wrongly Clang in SanitizerArgs.cpp, does not mandate PIE for TSAN.

What determined the defined Linux/FreeBSD struct Mapping?

I will follow it analogously with NetBSD specific bits like MAP_32BIT not needed.

Looking at the comment,
0000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
5500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels
7e80 0000 0000 - 8000 0000 0000: modules and main thread stack

^ these are the OS constraints, the rest can be moved.

Another constraint is MemToShadowImpl() which, for any address in, I assume, writable memory (so any of the above + heap) needs to provide an distinct address in "shadow". AFAIK, "metainfo" and "traces" are completely arbitrary.

I've checked that ShadowOffset 0 breaks ASAN.

Looking at the comment,
0000 0000 1000 - 0080 0000 0000: main binary and/or MAP_32BIT mappings (512GB)
5500 0000 0000 - 5680 0000 0000: pie binaries without ASLR or on 4.1+ kernels
7e80 0000 0000 - 8000 0000 0000: modules and main thread stack

^ these are the OS constraints, the rest can be moved.

I'm having now trouble to translate these values to NetBSD.

Another constraint is MemToShadowImpl() which, for any address in, I assume, writable memory (so any of the above + heap) needs to provide an distinct address in "shadow". AFAIK, "metainfo" and "traces" are completely arbitrary.

Another thread: If I understand correctly there is an assumption that PIE code is mapped on Linux/FreeBSD into adjacent memory regions. This is not true on NetBSD (@joerg can correct me).

I was trying to reuse Linux/FreeBSD process memory mapping and all tests fail. It breaks at PIE detection (I disabled it locally to check what happens).

After turning off PIE verification (Linux/FreeBSD specific?), I was getting random corruption and SIGSEGV.