boot_init_stack_canary()

gcc가 지원하는 스택 프로텍터 기능에서 사용할 canary 값을 초기화한다.

  • 함수의 진입시 stack에 canary 값을 기록하고 함수를 빠져나올 때 기록해 두었던 stack canary 값을 확인하여 stack 영역이 침범되었는지 확인할 수 있는 기능을 사용할 때 사용된다.
  • gcc에서 -fstack-protector-all 옵션을 사용할 때 각 함수에서 canary 값을 기록하고 비교하는 루틴이 추가된다.
  • buffer를 overflow 시키는 공격 등을 통해 stack overflow를 시도 시 stack-smashing-detected 가 출력된 후 태스크가 중단된다.
    • 보안 공격을 받아 변조된채 프로그램이 계속 진행되지 않도록 막을 수 있다.

 

boot_init_stack_canary-1

 

boot_init_stack_canary()

  • stack overflow 검출을  위한 canary 값을 알아온다.

arch/arm/include/asm/stackprotector.h

/*
 * Initialize the stackprotector canary value.
 *
 * NOTE: this must only be called from functions that never return,
 * and it must always be inlined.
 */

static __always_inline void boot_init_stack_canary(void)
{
        unsigned long canary;

        /* Try to get a semi random initial value. */
        get_random_bytes(&canary, sizeof(canary));
        canary ^= LINUX_VERSION_CODE;

        current->stack_canary = canary;
        __stack_chk_guard = current->stack_canary;
}

gcc가 지원하는 스택 프로텍터 기능에서 사용할 canary 값을 초기화한다.

  •  __always_inline:
    • 100% inline화 할 수 있도록 컴파일러에 요청.
  • current:
    • 커널 스택의 마지막에 thread_info가 담기고 thread_info->task는 task_struct를 가리킨다. 즉 current->는 현재 task의 task_struct 구조체 정보를 가리킨다.

 

get_random_bytes()

drivers/char/random.c

/*
 * This function is the exported kernel interface.  It returns some
 * number of good random numbers, suitable for key generation, seeding
 * TCP sequence numbers, etc.  It does not rely on the hardware random
 * number generator.  For random bytes direct from the hardware RNG
 * (when available), use get_random_bytes_arch().
 */
void get_random_bytes(void *buf, int nbytes)
{
#if DEBUG_RANDOM_BOOT > 0
        if (unlikely(nonblocking_pool.initialized == 0))
                printk(KERN_NOTICE "random: %pF get_random_bytes called "
                       "with %d bits of entropy available\n",
                       (void *) _RET_IP_,
                       nonblocking_pool.entropy_total);

#endif
        trace_get_random_bytes(nbytes, _RET_IP_);
        extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
}
EXPORT_SYMBOL(get_random_bytes);
  • unlikely()
    • false가 될 확률이 높은 경우를 위한 optimization
  • trace_get_random_bytes(nbytes, _RET_IP_);
    • DEFINE_EVENT(random__get_random_bytes, … 로 만들어지는 트레이스 이벤트용 함수를 호출한다.
DEFINE_EVENT(random__get_random_bytes, get_random_bytes,
        TP_PROTO(int nbytes, unsigned long IP), 
        TP_ARGS(nbytes, IP)
);
  • extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
    • buf에 nBytes만큼 random 값을 만들어 온다.
    • 이 함수는 아키텍처마다 구현이 다르지만 기본적으로 drivers/char/random.c를 사용한다.

 

참고

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.