set_task_stack_end_magic()

set_task_stack_end_magic()

  • start_kernel()이 커널 초기화 과정을 수행하는 동안 사용할 최초 커널 스택의 마지막에 magic value를 기록한다. 이후에 만들어지는 커널 스택은 메모리를 할당 받아 생성되어 사용되며 태스크가 종료되는 경우 메모리를 회수한다.
  • 기록된 magic value(STACK_END_MAGIC: 0x57AC6E9D)를 통해 kernel stack overflow를 감지하는데 사용된다.
void set_task_stack_end_magic(struct task_struct *tsk)
{
        unsigned long *stackend;

        stackend = end_of_stack(tsk);
        *stackend = STACK_END_MAGIC;    /* for overflow detection */
}
  • STACK_END_MAGIC=0x57AC_6E9D

 

end_of_stack()

/*
 * Return the address of the last usable long on the stack.
 *
 * When the stack grows down, this is just above the thread
 * info struct. Going any lower will corrupt the threadinfo.
 *
 * When the stack grows up, this is the highest address.
 * Beyond that position, we corrupt data on the next page.
 */
static inline unsigned long *end_of_stack(struct task_struct *p)
{
#ifdef CONFIG_STACK_GROWSUP
        return (unsigned long *)((unsigned long)task_thread_info(p) + THREAD_SIZE) - 1; 
#else
        return (unsigned long *)(task_thread_info(p) + 1);
#endif
}
  • CONFIG_STACK_GROWSUP
    • 스택이 상향으로 push되는 경우에 사용
    • rpi2: 하향으로 스택이 push된다.
  • task가 가지고 있는 kernel stack의 마지막 주소를 리턴한다.
    • task는 kernel stack과 user stack를 각각 하나씩 가진다.
    • kernel stack은 kernel이 자신의 코드를 수행할 때 사용하는 코드이다.
    • 예를 들어, user application이 요청한 시스템 콜을 수행할 때 kernel stack이 사용될 수 있다.
    • 참고: kernel stack

 

kernel stack 구조

  • 아키텍처마다 커널 스택 크기가 다르다. (라즈베리파이2: 8KB)
  • 커널 버전마다 커졌다 작아졌다 하지만 최근엔 커널 스택 다이어트로 줄여나가는 중(8K → 4K)

stack

thread_union

union thread_union {
    struct thread_info thread_info;
    unsigned long stack[THREAD_SIZE/sizeof(long)];
};

thread_info

struct thread_info {
    unsigned long       flags;      		/* low level flags */
    int         preempt_count;  		/* 0 => preemptable, <0 => bug */
    mm_segment_t        addr_limit; 	/* address limit */
    struct task_struct  *task;      		/* main task structure */
    struct exec_domain  *exec_domain;   	/* execution domain */
    __u32           cpu;        		/* cpu */
    __u32           cpu_domain; 		/* cpu domain */
    struct cpu_context_save cpu_context;    	/* cpu context */
    __u32           syscall;    		/* syscall number */
    __u8            used_cp[16];    		/* thread used copro */
    unsigned long       tp_value[2];    	/* TLS registers */
    union fp_state      fpstate __attribute__((aligned(8)));
    union vfp_state     vfpstate;
};

task_thread_info()

#define task_thread_info(task)  ((struct thread_info *)(task)->stack)

참고

답글 남기기

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