Add dlopen/dlclose interceptors to update CFI shadow for loaded/unloaded libraries.
Diff Detail
- Repository
- rL LLVM
Event Timeline
lib/cfi/cfi.cc | ||
---|---|---|
331 | As you mentioned offline, this won't correctly handle dependencies. Perhaps the code should be building the shadow from scratch using dl_iterate_phdr every time a rebuild is needed? That way, you save needing to worry about dependencies. This may require a redesign of D16098 to avoid the copy. |
A new approach.
dlclose may unmap (and dlopen may map) multiple libraries, so we actually need to do the entire dl_iterate_phdr run and update all libraries. For dlclose, we also need to detect libraries that have disappeared from the address space, so we do dl_iterate_phdr before and after dlclose and compare the results.
lib/cfi/cfi.cc | ||
---|---|---|
40 | Looks like we already have a kMaxNumberOfModules constant defined. | |
172 | I changed this interface in r257858. | |
235–261 | Can you avoid needing to take the set difference by rebuilding from scratch? | |
lib/sanitizer_common/sanitizer_common.cc | ||
344 | Should there be a single init() function that combines set and set_phdr? | |
lib/sanitizer_common/sanitizer_common.h | ||
635 | Is this function needed? Looks like you're passing a comparator to your sort function above. |
The previous approach contained a data race on the shadow pointer, which can not be updated without a lock in __cfi_slowpath. That would not be acceptable performance-wise. Probably.
This new version is linux-only as it requires mremap().
lib/cfi/cfi.cc | ||
---|---|---|
34 | Maybe assert somewhere that this is equal to GetPageSize()? | |
38 | This name is unclear. It should reflect that the shadow pointer is stored here, not the shadow itself. | |
48 | Please inline into ShadowBuilder::Install, as the pre-conditions of this function aren't clear without context. | |
101 | Do you need to set the memory protection for shadow_ first? | |
327 | You can use it now I guess. | |
lib/sanitizer_common/sanitizer_posix.cc | ||
178 ↗ | (On Diff #45288) | This function is unused. |
lib/cfi/cfi.cc | ||
---|---|---|
101 | Of course. |
lib/cfi/cfi.cc | ||
---|---|---|
17 | This is done now, right? | |
101 | Thanks. Is it possible to construct a test case that makes sure we get the memory protection right? I was thinking that the test case would try to write to the shadow at various points (e.g. start of main, after dlopen, after dlclose), and use %expect_crash to test that the write fails. |
lib/cfi/cfi.cc | ||
---|---|---|
101 | But we don't really want there to be an easy way to find the cfi shadow. |
This is done now, right?