mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-12 21:28:48 +00:00
Reland '[msan] Intercept dladdr1, and refactor dladdr'
Reland with -Wcast-qual issue fixed Original commit message: This patch adds an msan interceptor for dladdr1 (with support for RTLD_DL_LINKMAP and RTLD_DL_SYMENT) and an accompanying test. It also adds a helper file, msan_dl.cpp, that contains UnpoisonDllAddrInfo (refactored out of the dladdr interceptor) and UnpoisonDllAddr1ExtraInfo. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D154272
This commit is contained in:
parent
9df70e4a4d
commit
015dabd767
@ -5,6 +5,7 @@ set(MSAN_RTL_SOURCES
|
||||
msan.cpp
|
||||
msan_allocator.cpp
|
||||
msan_chained_origin_depot.cpp
|
||||
msan_dl.cpp
|
||||
msan_interceptors.cpp
|
||||
msan_linux.cpp
|
||||
msan_report.cpp
|
||||
@ -20,6 +21,7 @@ set(MSAN_RTL_HEADERS
|
||||
msan.h
|
||||
msan_allocator.h
|
||||
msan_chained_origin_depot.h
|
||||
msan_dl.h
|
||||
msan_flags.h
|
||||
msan_flags.inc
|
||||
msan_interface_internal.h
|
||||
|
63
compiler-rt/lib/msan/msan_dl.cpp
Normal file
63
compiler-rt/lib/msan/msan_dl.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
//===-- msan_dl.cpp -------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of MemorySanitizer.
|
||||
//
|
||||
// Helper functions for unpoisoning results of dladdr and dladdr1.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "msan_dl.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "msan_poisoning.h"
|
||||
|
||||
namespace __msan {
|
||||
|
||||
void UnpoisonDllAddrInfo(void *info) {
|
||||
Dl_info *ptr = (Dl_info *)(info);
|
||||
__msan_unpoison(ptr, sizeof(*ptr));
|
||||
if (ptr->dli_fname)
|
||||
__msan_unpoison(ptr->dli_fname, internal_strlen(ptr->dli_fname) + 1);
|
||||
if (ptr->dli_sname)
|
||||
__msan_unpoison(ptr->dli_sname, internal_strlen(ptr->dli_sname) + 1);
|
||||
}
|
||||
|
||||
void UnpoisonDllAddr1ExtraInfo(void **extra_info, int flags) {
|
||||
if (flags == RTLD_DL_SYMENT) {
|
||||
__msan_unpoison(extra_info, sizeof(void *));
|
||||
|
||||
const ElfW(Sym) *s = (const ElfW(Sym) *)*((const ElfW(Sym) **)(extra_info));
|
||||
__msan_unpoison(s, sizeof(ElfW(Sym)));
|
||||
} else if (flags == RTLD_DL_LINKMAP) {
|
||||
__msan_unpoison(extra_info, sizeof(void *));
|
||||
|
||||
struct link_map *map = *((struct link_map **)(extra_info));
|
||||
|
||||
// Walk forward
|
||||
for (auto *ptr = map; ptr; ptr = ptr->l_next) {
|
||||
__msan_unpoison(ptr, sizeof(struct link_map));
|
||||
if (ptr->l_name)
|
||||
__msan_unpoison(ptr->l_name, internal_strlen(ptr->l_name) + 1);
|
||||
}
|
||||
|
||||
if (!map)
|
||||
return;
|
||||
|
||||
// Walk backward
|
||||
for (auto *ptr = map->l_prev; ptr; ptr = ptr->l_prev) {
|
||||
__msan_unpoison(ptr, sizeof(struct link_map));
|
||||
if (ptr->l_name)
|
||||
__msan_unpoison(ptr->l_name, internal_strlen(ptr->l_name) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace __msan
|
28
compiler-rt/lib/msan/msan_dl.h
Normal file
28
compiler-rt/lib/msan/msan_dl.h
Normal file
@ -0,0 +1,28 @@
|
||||
//===-- msan_dl.h ---------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file is a part of MemorySanitizer.
|
||||
//
|
||||
// Helper functions for unpoisoning results of dladdr and dladdr1.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MSAN_DL_H
|
||||
#define MSAN_DL_H
|
||||
|
||||
#include "msan.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
|
||||
namespace __msan {
|
||||
|
||||
void UnpoisonDllAddrInfo(void *info);
|
||||
// void UnpoisonDllAddrInfo(Dl_info *info);
|
||||
void UnpoisonDllAddr1ExtraInfo(void **extra_info, int flags);
|
||||
|
||||
} // namespace __msan
|
||||
|
||||
#endif // MSAN_DL_H
|
@ -19,6 +19,7 @@
|
||||
#include "interception/interception.h"
|
||||
#include "msan.h"
|
||||
#include "msan_chained_origin_depot.h"
|
||||
#include "msan_dl.h"
|
||||
#include "msan_origin.h"
|
||||
#include "msan_poisoning.h"
|
||||
#include "msan_report.h"
|
||||
@ -1520,23 +1521,23 @@ INTERCEPTOR(const char *, strsignal, int sig) {
|
||||
return res;
|
||||
}
|
||||
|
||||
struct dlinfo {
|
||||
char *dli_fname;
|
||||
void *dli_fbase;
|
||||
char *dli_sname;
|
||||
void *dli_saddr;
|
||||
};
|
||||
|
||||
INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
|
||||
INTERCEPTOR(int, dladdr, void *addr, void *info) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
|
||||
int res = REAL(dladdr)(addr, info);
|
||||
if (res != 0)
|
||||
UnpoisonDllAddrInfo(info);
|
||||
return res;
|
||||
}
|
||||
|
||||
INTERCEPTOR(int, dladdr1, void *addr, void *info, void **extra_info,
|
||||
int flags) {
|
||||
void *ctx;
|
||||
COMMON_INTERCEPTOR_ENTER(ctx, dladdr1, addr, info, extra_info, flags);
|
||||
int res = REAL(dladdr1)(addr, info, extra_info, flags);
|
||||
if (res != 0) {
|
||||
__msan_unpoison(info, sizeof(*info));
|
||||
if (info->dli_fname)
|
||||
__msan_unpoison(info->dli_fname, internal_strlen(info->dli_fname) + 1);
|
||||
if (info->dli_sname)
|
||||
__msan_unpoison(info->dli_sname, internal_strlen(info->dli_sname) + 1);
|
||||
UnpoisonDllAddrInfo(info);
|
||||
UnpoisonDllAddr1ExtraInfo(extra_info, flags);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@ -1788,6 +1789,7 @@ void InitializeInterceptors() {
|
||||
MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
|
||||
INTERCEPT_FUNCTION(strsignal);
|
||||
INTERCEPT_FUNCTION(dladdr);
|
||||
INTERCEPT_FUNCTION(dladdr1);
|
||||
INTERCEPT_FUNCTION(dlerror);
|
||||
INTERCEPT_FUNCTION(dl_iterate_phdr);
|
||||
INTERCEPT_FUNCTION(getrusage);
|
||||
|
95
compiler-rt/test/msan/dladdr1_test.c
Normal file
95
compiler-rt/test/msan/dladdr1_test.c
Normal file
@ -0,0 +1,95 @@
|
||||
/* RUN: %clang_msan -g %s -o %t
|
||||
RUN: %clang_msan -g %s -DBUILD_SO -fPIC -o %t-so.so -shared
|
||||
RUN: %run %t 2>&1 | FileCheck %s
|
||||
|
||||
REQUIRES: glibc{{.*}}
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#ifndef BUILD_SO
|
||||
#include <assert.h>
|
||||
#include <dlfcn.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef volatile long *(* get_t)();
|
||||
get_t GetTls;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char path[4096];
|
||||
snprintf(path, sizeof(path), "%s-so.so", argv[0]);
|
||||
int i;
|
||||
|
||||
void *handle = dlopen(path, RTLD_LAZY);
|
||||
if (!handle) fprintf(stderr, "%s\n", dlerror());
|
||||
assert(handle != 0);
|
||||
GetTls = (get_t)dlsym(handle, "GetTls");
|
||||
assert(dlerror() == 0);
|
||||
|
||||
{
|
||||
printf("Testing RTLD_DL_LINKMAP\n");
|
||||
fflush(stdout);
|
||||
|
||||
Dl_info info;
|
||||
struct link_map *map_ptr;
|
||||
int ret = dladdr1(GetTls, &info, (void**)(&map_ptr), RTLD_DL_LINKMAP);
|
||||
assert(ret != 0);
|
||||
printf("fname: %s\n", info.dli_fname);
|
||||
printf("fbase: %p\n", info.dli_fbase);
|
||||
printf("sname: %s\n", info.dli_sname);
|
||||
// CHECK: sname: GetTls
|
||||
printf("saddr: %p\n", info.dli_saddr);
|
||||
|
||||
assert(map_ptr != NULL);
|
||||
printf("map_ptr: %p\n", map_ptr);
|
||||
fflush(stdout);
|
||||
|
||||
// Find the start of the link map
|
||||
while(map_ptr->l_prev != NULL) {
|
||||
fflush(stdout);
|
||||
map_ptr = map_ptr->l_prev;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
while(map_ptr != NULL) {
|
||||
assert(map_ptr->l_name != NULL);
|
||||
printf("0x%lx: '%s', %p\n", map_ptr->l_addr, map_ptr->l_name, map_ptr->l_ld);
|
||||
fflush(stdout);
|
||||
map_ptr = map_ptr->l_next;
|
||||
}
|
||||
// CHECK: libc.so
|
||||
// CHECK: dladdr1_test
|
||||
}
|
||||
|
||||
// Test RTLD_DL_SYMENT
|
||||
|
||||
{
|
||||
printf("Testing RTLD_DL_SYMENT\n");
|
||||
fflush(stdout);
|
||||
|
||||
Dl_info info;
|
||||
ElfW(Sym) *sym;
|
||||
int ret = dladdr1(GetTls, &info, (void**)(&sym), RTLD_DL_SYMENT);
|
||||
assert(ret != 0);
|
||||
printf("fname: %s\n", info.dli_fname);
|
||||
printf("fbase: %p\n", info.dli_fbase);
|
||||
printf("sname: %s\n", info.dli_sname);
|
||||
// CHECK: sname: GetTls
|
||||
printf("saddr: %p\n", info.dli_saddr);
|
||||
|
||||
printf("sym: %d %d %d %d %lu %lu\n",
|
||||
sym->st_name, sym->st_info, sym->st_other,
|
||||
sym->st_shndx, sym->st_value, sym->st_size);
|
||||
// CHECK: sym:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else // BUILD_SO
|
||||
long var;
|
||||
long *GetTls() {
|
||||
return &var;
|
||||
}
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user