ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • library interpositioning
    운영체제 2025. 4. 18. 19:52

    목차

    • library interpositioning
      • library interpositioning이란?
      • 사용 예시
      • 컴파일타임에 interpositioning하기
      • 링크타임에 interpositioning하기
      • 로드/런타임에 interpositioning하기
      • 정리

    목표

    컴파일타임, 링크타임, 로드/런타임에 interpositioning을 할 수 있다.


    library interpositioning 이란?

    라이브러리 함수 호출시 호출을 가로채 추가 작업을 하는 방법이다. 특정 함수 호출시 실제 함수 대신 커스텀한 함수를 호출하도록 한다.

    이는 컴파일타임, 링킹타임, 로드타임에 모두 구현 가능하다.

     

    사용예시

    - 보안

    ex) sandboxing -  프로그램을 격리된 환경에서 실행시켜서 문제가 생겨도 시스템 전체에 영향을 못 미치게 하는 보안 기법이다. 즉 "가짜 환경"을 만들어 실행을 통제한다.

     

    - 디버깅, 모니터링

    ex) malloc()의 메모리 누수를 감지하고, 할당 주소를 확인할 수 있다.

     


    interpositioning 해보기

    아래 코드는 동적할당,해제하는 간단한 코드다.

    example.c

    #include <stdio.h>
    #include <malloc.h>
    
    int main() {
        int *p = malloc(32);
        free(p);
        return(0);
    }

     

    이 파일을 수정하지 않고 malloc() 호출시 malloc의 할당 주소를 출력하도록 만들어보자.

    컴파일 타임에 malloc 호출을 가로채 출력하는 방법,

    링크타임에 malloc 호출을 가로채 출력하는 방법,

    로드/런타임에 malloc 호출을 가로채 출력하는 방법,

    3가지 모두 구현해보겠다.


     

    컴파일 타임에 interpositioning 하기

     

    mymalloc.c 생성

    malloc(), free()를 커스텀한 함수다. #ifdef를 활용하여 main에서 malloc 호출시 mymalloc이 호출되도록 한다.

    #ifdef COMPILETIME
    #include <stdio.h>
    #include <malloc.h>
    
    void *mymalloc(size_t size){
        void *ptr = malloc(size);			//실제 malloc함수 호출
        printf("malloc(%d)=%p\n", (int)size, ptr);
        return ptr;
    }
    
    void myfree(void *ptr){
        free(ptr);
        printf("free(%p)\n", ptr);
    }
    
    #endif

     

     

    malloc.h 생성

    기존의 malloc.c 대신 mymalloc.c를 사용하라는 헤더파일이다.

    즉 main코드에서 malloc()을 호출하면 mymalloc()이 호출되도록 한다.

    #define malloc(size) mymalloc(size)
    #define free(ptr) myfree(ptr)
    
    void *mymalloc(size_t size);
    void myfree(void *ptr);

     

    터미널 실행

    # mymalloc.c 컴파일하기 
    gcc -DCOMPILETIME -c mymalloc.c		# -DCOMPILETIME : "#ifdef COMPILETIME"인 코드 활성화하기
    
    # example.c 컴파일하기
    gcc -I. -c example.c -o example.o
    
    # exapmple.o, mymalloc.o 링크하기
    gcc -I. -o example example.c mymalloc.o
    
    # 실행하기
    ./example

     

    실행결과

     


    링크 타임에 interpositioning 하기

    __real_malloc()과 __wrap_malloc()을 사용한 방법이다.

    "--wrap" 터미널 명령어를 사용하여 malloc() 호출시 __wrap_malloc()이 호출되도록 한다.

    __wrap_malloc() 함수 내부에 __reall_malloc()을 호출하여 실제 malloc()을 호출하도록 한다.

    이때 __real_malloc 링커가 자동으로 생성해주는 심볼이다.

     

    mymalloc.c 생성

    #ifdef LINKTIME
    #include <stdio.h>
    
    void *__real_malloc(size_t size);		//실제 malloc()을 호출하는 함수
    void __real_free(void *ptr);
    
    void *__wrap_malloc(size_t size){		//.c의 malloc() 호출시 호출되는 함수
        void *ptr = __real_malloc(size);
        printf("malloc(%d) = %p\n", (int)size, ptr);
        return ptr;
    }
    
    void __wrap_free(void *ptr){
        __real_free(ptr);
        printf("free(%p)\n", ptr);
    }
    
    #endif

     

     

    그림으로 나타낸 호출 과정

     

    터미널 실행

    --wrap, malloc : ".c의 malloc()를  __wrap_malloc()로 대체해라"

    두 .o 파일을 링크할때 interpositioning 됨을 알 수 있다.

    # mymalloc.c 컴파일하기
    gcc -DLINKTIME -c mymalloc.c
    
    # example.c 컴파일하기
    gcc -c example.c
    
    # example.o, mymalloc.o링크하기
    gcc -Wl, --wrap,malloc -Wl, --wrap,free -o example example.o mymalloc.o
    
    # 실행하기
    ./example

     

    실행결과

     


    로드/런타임에 interpositioning 하기

    mymalloc.c

    #ifdef RUNTIME
    #define _GNU_SOURCE
    #include <stdio.h>
    #include <stdlib.h>
    #include <dlfcn.h>
    
    void *malloc(size_t size) {
        void*(*mallocp)(size_t size);
        char *error;
        
        mallocp = dlsym(RTLD_NEXT, "malloc");		// 실제 malloc() 가져오기
        if ((error = dlerror()) != NULL){
        	fputs(error, stderr);
            exit(1);
        }
        char *ptr = mallocp(size);				// 실제 malloc() 호출
        printf("malloc(%d) = %p\n", (int)size, ptr);
        return ptr;
    }
    
    #endif

     

     

    터미널

    실행시에 interpositioning된다는 것을 알 수 있다.

    # mymalloc.c을 .so(동적 라이브러리)로 컴파일하기
    gcc -DRUNTIME -shared -fpic -o mymalloc.so mymalloc.c -ldl
    
    # example.c 컴파일하기
    gcc -o example example.c
    
    # 실행하기
    # 동적 링커에게 다른 라이브러리 보기 전에 mymalloc.so에서 먼저 찾으라고 명시
    LD_PRELOAD="./mymalloc.so" ./example

     

    실행결과

     

     


    정리

    이로써 컴파일시, 링크시, 로드/런타임 시에 interpositioning이 가능하다는것을 알 수 있었다.

     

    컴파일 타임에는 전처리기 지시어 (#define, #ifdef)를 사용하고,

    링크 타임에는 링커옵션인 "--wrap"을 사용하고,

    로드/런타임에는 환경변수(LD_PRELOAD)를 사용하여 구현하였다.

    '운영체제' 카테고리의 다른 글

    file descriptor (fd)  (0) 2025.05.03
    IPC - pipe  (0) 2025.04.26
    [OS] unix I/O와 standard I/O 함수  (0) 2025.04.12
    [OS] 접근 권한, UID/GID  (0) 2025.04.04
    [OS] 프로세스 실행~종료 과정 (fork(), exec(), exit(), wait())  (0) 2025.03.29
Designed by Tistory.