Skip to content

Commit

Permalink
refactor library building
Browse files Browse the repository at this point in the history
Mark all symbols (except those in the public interface) as hidden
during compilation.
This allows symbols to be resolved while linking
libsyscall_intercept_static -- otherwise the code would refer to
PLT entries, which would not be found due to hiding symbols using objcopy.

Objcopy is not used anymore on the shared library.

The library init routine is moved to intercept.c from entry.c .
  • Loading branch information
GBuella committed Aug 28, 2017
1 parent 4fab456 commit 68ad9c8
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 51 deletions.
24 changes: 7 additions & 17 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ include(GNUInstallDirs)
include(cmake/toolchain_features.cmake)
include(cmake/find_capstone.cmake)

# main source files - intentionally excluding src/entry.c
# main source files - intentionally excluding src/cmdline_filter.c
set(SOURCES_C
src/disasm_wrapper.c
src/intercept.c
Expand All @@ -85,7 +85,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# the library trying to hotpatch libc every time.
add_library(syscall_intercept_base_c OBJECT ${SOURCES_C})
add_library(syscall_intercept_base_asm OBJECT ${SOURCES_ASM})
add_library(syscall_intercept_base_entry OBJECT src/entry.c)
add_library(syscall_intercept_base_clf OBJECT src/cmdline_filter.c)

if(HAS_NOUNUSEDARG)
target_compile_options(syscall_intercept_base_asm BEFORE
Expand All @@ -99,11 +99,14 @@ set_property(TARGET syscall_intercept_base_c
add_library(syscall_intercept_shared SHARED
$<TARGET_OBJECTS:syscall_intercept_base_c>
$<TARGET_OBJECTS:syscall_intercept_base_asm>
$<TARGET_OBJECTS:syscall_intercept_base_entry>)
$<TARGET_OBJECTS:syscall_intercept_base_clf>)
add_library(syscall_intercept_static STATIC
$<TARGET_OBJECTS:syscall_intercept_base_c>
$<TARGET_OBJECTS:syscall_intercept_base_asm>
$<TARGET_OBJECTS:syscall_intercept_base_entry>)
$<TARGET_OBJECTS:syscall_intercept_base_clf>)

set_target_properties(syscall_intercept_base_c
PROPERTIES C_VISIBILITY_PRESET hidden)

target_link_libraries(syscall_intercept_shared
PRIVATE ${CMAKE_DL_LIBS} ${capstone_LIBRARIES})
Expand All @@ -117,19 +120,6 @@ set_target_properties(syscall_intercept_shared

add_executable(cpp_test src/cpp_compile_test.cc src/cpp_compile_mock.c)

if(CMAKE_OBJCOPY)
foreach(target syscall_intercept_shared syscall_intercept_static)
add_custom_command(TARGET ${target}
POST_BUILD COMMAND ${CMAKE_OBJCOPY}
--localize-hidden
-G intercept_hook_point
-G intercept_hook_point_clone_child
-G syscall_no_intercept
-G syscall_hook_in_process_allowed
$<TARGET_FILE:${target}>)
endforeach()
endif()

set_target_properties(syscall_intercept_shared syscall_intercept_static
PROPERTIES
PUBLIC_HEADER "include/libsyscall_intercept_hook_point.h"
Expand Down
30 changes: 3 additions & 27 deletions src/entry.c → src/cmdline_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
* entry.c -- the entry point for libsyscall_intercept
* expected to be executed by the loader while using LD_PRELOAD
*/

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
Expand All @@ -45,28 +40,6 @@
#include "libsyscall_intercept_hook_point.h"
#include "intercept.h"

static const char *cmdline;

/*
* entry_point - the main entry point for syscall_intercept
*
* The loader calls this routine once the library is loaded, except in certain
* cases when testing -- see asm_wrapper.c for more details.
* The actual work of hotpatching libraries is done the routine
* called intercept.
*/
static __attribute__((constructor)) void
entry_point(int argc, char **argv)
{
if (argc < 1)
return;

cmdline = argv[0];

if (syscall_hook_in_process_allowed())
intercept();
}

/*
* cmdline_match - match the last component of the path in cmdline
*/
Expand Down Expand Up @@ -112,6 +85,9 @@ syscall_hook_in_process_allowed(void)
if (is_decided)
return result;

if (cmdline == NULL)
return 0;

result = cmdline_match(getenv("INTERCEPT_HOOK_CMDLINE_FILTER"));
is_decided = true;

Expand Down
35 changes: 29 additions & 6 deletions src/intercept.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,11 @@ int (*intercept_hook_point)(long syscall_number,
long arg0, long arg1,
long arg2, long arg3,
long arg4, long arg5,
long *result);
long *result)
__attribute__((visibility("default")));

void (*intercept_hook_point_clone_child)(void);
void (*intercept_hook_point_clone_child)(void)
__attribute__((visibility("default")));

bool debug_dumps_on;

Expand Down Expand Up @@ -306,7 +308,15 @@ is_vdso(uintptr_t addr, const char *path)
static bool
should_patch_object(uintptr_t addr, const char *path)
{
static const char self[] = "libsyscall_intercept";
static uintptr_t self_addr;
if (self_addr == 0) {
extern unsigned char intercept_asm_wrapper_tmpl[];
Dl_info self;
if (!dladdr((void *)&intercept_asm_wrapper_tmpl, &self))
xabort("self dladdr failure");
self_addr = (uintptr_t)self.dli_fbase;
}

static const char libc[] = "libc";
static const char pthr[] = "libpthread";
static const char caps[] = "libcapstone";
Expand All @@ -322,7 +332,7 @@ should_patch_object(uintptr_t addr, const char *path)
if (len == 0)
return false;

if (str_match(name, len, self)) {
if (addr == self_addr) {
debug_dump(" - skipping: matches self\n");
return false;
}
Expand Down Expand Up @@ -403,15 +413,28 @@ analyze_object(struct dl_phdr_info *info, size_t size, void *data)
return 0;
}

const char *cmdline;

/*
* intercept - This is where the highest level logic of hotpatching
* is described. Upon startup, this routine looks for libc, and libpthread.
* If these libraries are found in the process's address space, they are
* patched.
*
* This is init routine of syscall_intercept. This library constructor
* must be in a TU which also contains public symbols, otherwise linkers
* might just get rid of the whole object file containing it, when linking
* statically with libsyscall_intercept.
*/
void
intercept(void)
static __attribute__((constructor)) void
intercept(int argc, char **argv)
{
(void) argc;
cmdline = argv[0];

if (!syscall_hook_in_process_allowed())
return;

vdso_addr = (void *)(uintptr_t)getauxval(AT_SYSINFO_EHDR);
debug_dumps_on = getenv("INTERCEPT_DEBUG_DUMP") != NULL;
patch_all_objs = (getenv("INTERCEPT_ALL_OBJS") != NULL);
Expand Down
2 changes: 1 addition & 1 deletion src/intercept.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,6 @@ bool is_overwritable_nop(const struct intercept_disasm_result *ins);

void create_jump(unsigned char opcode, unsigned char *from, void *to);

void intercept(void);
const char *cmdline;

#endif
26 changes: 26 additions & 0 deletions src/intercept_template.s
Original file line number Diff line number Diff line change
Expand Up @@ -214,35 +214,61 @@
*/

.global backtrace_placeholder;
.hidden backtrace_placeholder;
.type backtrace_placeholder, @function

.global backtrace_placeholder_2;
.hidden backtrace_placeholder_2;
.type backtrace_placeholder_2, @function

.global intercept_asm_wrapper_tmpl;
.hidden intercept_asm_wrapper_tmpl;
.global intercept_asm_wrapper_simd_save;
.hidden intercept_asm_wrapper_simd_save;
.global intercept_asm_wrapper_prefix;
.hidden intercept_asm_wrapper_prefix;
.global intercept_asm_wrapper_push_origin_addr;
.hidden intercept_asm_wrapper_push_origin_addr;
.global intercept_asm_wrapper_mov_return_addr_r11_no_syscall;
.hidden intercept_asm_wrapper_mov_return_addr_r11_no_syscall;
.global intercept_asm_wrapper_mov_return_addr_r11_syscall;
.hidden intercept_asm_wrapper_mov_return_addr_r11_syscall;
.global intercept_asm_wrapper_mov_libpath_r11;
.hidden intercept_asm_wrapper_mov_libpath_r11;
.global intercept_asm_wrapper_mov_phaddr_r11;
.hidden intercept_asm_wrapper_mov_phaddr_r11;
.global intercept_asm_wrapper_mov_ph2addr_r11;
.hidden intercept_asm_wrapper_mov_ph2addr_r11;
.global intercept_asm_wrapper_call;
.hidden intercept_asm_wrapper_call;
.global intercept_asm_wrapper_simd_restore;
.hidden intercept_asm_wrapper_simd_restore;
.global intercept_asm_wrapper_postfix;
.hidden intercept_asm_wrapper_postfix;
.global intercept_asm_wrapper_return_jump;
.hidden intercept_asm_wrapper_return_jump;
.global intercept_asm_wrapper_end;
.hidden intercept_asm_wrapper_end;
.global intercept_asm_wrapper_simd_save_YMM;
.hidden intercept_asm_wrapper_simd_save_YMM;
.global intercept_asm_wrapper_simd_save_YMM_end;
.hidden intercept_asm_wrapper_simd_save_YMM_end;
.global intercept_asm_wrapper_simd_restore_YMM;
.hidden intercept_asm_wrapper_simd_restore_YMM;
.global intercept_asm_wrapper_simd_restore_YMM_end;
.hidden intercept_asm_wrapper_simd_restore_YMM_end;
.global intercept_asm_wrapper_return_and_no_syscall;
.hidden intercept_asm_wrapper_return_and_no_syscall;
.global intercept_asm_wrapper_return_and_syscall;
.hidden intercept_asm_wrapper_return_and_syscall;
.global intercept_asm_wrapper_push_stack_first_return_addr;
.hidden intercept_asm_wrapper_push_stack_first_return_addr;
.global intercept_asm_wrapper_mov_r11_stack_first_return_addr;
.hidden intercept_asm_wrapper_mov_r11_stack_first_return_addr;
.global intercept_asm_wrapper_clone_wrapper;
.hidden intercept_asm_wrapper_clone_wrapper;
.global intercept_asm_wrapper_call_clone_child_intercept;
.hidden intercept_asm_wrapper_call_clone_child_intercept;

.text

Expand Down
2 changes: 2 additions & 0 deletions src/util.s
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@
*/

.global xlongjmp;
.hidden xlongjmp;
.type xlongjmp, @function

.global has_ymm_registers;
.hidden has_ymm_registers;
.type has_ymm_registers, @function

.global syscall_no_intercept;
Expand Down
15 changes: 15 additions & 0 deletions test/asm_pattern.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,18 @@ main(int argc, char **argv)

return EXIT_SUCCESS;
}

/*
* syscall_hook_in_process_allowed - this symbol must be provided to
* be able to link with syscall_intercept's objects (other then the one
* created from cmdline_filter.c).
* This symbol is referenced from intercept.c,
* defined once in cmdline_filter.c, and defined here as well.
*
* Note: this function is actually never called in this test.
*/
int
syscall_hook_in_process_allowed(void)
{
return 0;
}

0 comments on commit 68ad9c8

Please sign in to comment.