• 리눅스 커널 개론
- 컴퓨터의 가장 기본적인 자원들을 관리하고 통제하기 위한, 운영체제의 핵심이 되는 소프트웨어
- 커널 내부는 태스크 관리자, 메모리 관리자, 파일 시스템, 네트워크 관리자, 디바이스 드라이버 관리자 등으로 구분됨
- 가상 메모리 구조상 스택의 윗 영역에 존재
- 가상 메모리의 3~4GB 구간에 존재하는 커널 영역은 모든 태스크들의 공통 영역으로 사용됨
- 가상 메모리 주소와 물리 메모리 주소를 변환하기 위해 커널 내부에는 페이징 기법이 구현되어 있음
1. 유저 모드 / 커널 모드란?
- 하나의 프로세스가 실수로 다른 프로세스에 입출력 작업을 하는 등의 보안적 이슈르 방지하기 위해, 유저가 컴퓨터의 자원에 함부로 접근할 수 없도록 모드를 나누어 둔 것
- 유저 모드 : 접근할 수 있는 영역이 제한적이며, 유저 애플리케이션이 실행되는 모드
- 커널 모드 : 컴퓨터의 모든 자원에 접근할 수 있으며 커널이 실행되는 모드
2. 시스템 호출이란?
- 유저 공간에 유저 애플리케이션의 요청에 따라 커널에 접근하기 위한 인터페이스
- input/ output 작업을 하기 위해선 커널에게 요청해야 함
- 시스템 호출을 했을 경우 현재 모드를 커널 모드로 바꾼 뒤, 특정 작업 후 system call function을 호출
3. 태스크란?
- 리눅스 커널에서는 프로세스와 스레드를 별도로 구분하지 않고, 모두 태스크로 동등하게 관리함(단지 쓰레드 그룹에 속해 있는 가 등의 여부에 따라 차이)
- 모든 태스크들은 task_struct 구조체로 관리
- 프로세스와 쓰레드를 생성하는 모든 함수는 do_fork() 함수를 거치며, 이 함수는 taks_struct를 생성하는 역할을 함
- 하나의 태스크가 생성될 때, 커널 스택과 taks_struct가 할당됨 -> 각 태스크마다 커널 스택이 할당 됨
task_struct | |
pid_t pid | 프로세스마다 부여하는 식별 값 |
pid_t tgid | 쓰레드 그룹 아이디 |
chat comm[] | 프로세스의 이름 |
sturct task_strcut*real_parent | 자신을 생성한 부모 태스크를 가리킴 |
struct task_struct*parent | 현재 부모 태스크를 가림킴 |
struct mm_struct*mm | mm_struct는 유저 공간의 텍스터, 데이터, 스택 힙 등의 영역의 위치와 메타데이터를 가지고 있음 |
* mm_struct
-> start_code, end_cdoe : 각각 Text 영역의 시작과 끝의 주소
-> start_data, end_data : 각각 Data 영역의 시작과 끝의 주소
-> start_brk, brk : 각각 Heap 영역의 시작과 끝의 주소, brk는 증가가 가능
-> stack_start : Stack 영역의 시작 주소
4. 슬랩 할당자란?
- 커널에서 사용하는 동적 메모리 할당자이며 메모리 풀 구조를 가지고 있음, 미리 고정된 크기의 메모리 블록들을 할당해 놓는다는 것
- 슬랩 캐시 : 커널에서 자주 요청하는 크기에 대한 동적 메모리를 확보하고 관리하는 주체
- 슬랩 객체 : 슬랩 캐시가 할당해 놓은 메모리 블록, malloc()의 chunk와 비슷한 개념 -> 커널에서는 kmalloc() 함수 사용
- 슬랩 페이지 : 슬랩 객체로 구성된 페이지
* 주요 자료 구조
- 슬랩 할당자는 kmalloc_caches []라는 전역 배열을 이용해 각 크기별 슬랩 캐시들을 관리함
- 각 슬랩 캐시는 keme_cache라는 구조체로 표현됨
- 슬랩 캐시는 슬랩 객체의 할당 속도를 높이기 위해 CPU 개수만큼 kmem_cache_cpu라는 구조체를 추가적으로 이용함
kmalloc() 함수 실행 과정: kmalloc() -> kmem_cache_alloc_trace() -> slab_alloc() -> slab_alloc_node()
* slab_alloc_node()
- kmem_cache_cpu 구조체로 관리되는 per-cpu 슬럽 캐시를 불러옴
- 각종 작업 후 kmem_cache_cpu의 freelist에 해제된 슬랩 객체가 있을 경우 해당 슬랩 객체를 최종적으로 반환
- kmem_cache_cpu의 freelist에 NULL이 있을 경우 슬랩 페이지를 새로 할당받은 뒤 슬랩 객체를 반환
5. 디바이스 드라이버란?
종류 | 설명 |
Character Device | 버퍼 캐시를 사용하지 않으며 Device를 파일처럼 직접 접근 (마우스, 키보드 등의 드라이브) |
Block Device | Hard Disk와 같은 file system을 기반으로 block단위로 접근 |
Network Device | 네트워크 스택과 네트워크 하드웨어 사이에 위치하여 데이터의 송수신 담당 |
- 유저 애플리케이션이 정형화된 인터페이스를 통해 장치에 접근할 수 있도록 해주는 소프트웨어
- 커널이 컴파일될 때부터 포함된 디바이스 드라이버도 있고 별도로 컴파일되어 커널 부팅 후에 로드되는 디바이스 드라이버도 있음
- 디바이스 드라이버는 모듈의 일종, 모듈 프로그래밍을 통해 프로그래밍할 수 있음
* file_operations
- 디바이스 드라이버와 유저 애플리케이션 간의 커뮤니케이션을 위한 인터페이스
- 각종 함수 포인터 멤버들이 선언되어 있음
* 주로 사용되는 함수
- copy_from_user(a, b, c) : 유저 공간에서 커널 공간으로 데이터를 안전하게 복사하는 함수. 유저 공간 주소 b에서 c바이트만큼 커널 공간 주소 a로 복사
- copy_to_user(a, b, c) : 커널 공간에서 유저 공간으로 데이터를 안전하게 복사하는 함수. 커널 공간 주소 b에서 c바이트만큼 유저 공간 주소 a로 복사
- mutex / spinlock : 커널에서의 race condition을 방지하기 위한 커널 동기화 함수
6. 모듈 프로그래밍
- 모듈이란 동적으로 커널에 등록하거나 제거할 수 있는 프로그램을 뜻함. 이로 인해 커널 이미지를 재컴파일 하지 않고도 기능을 추가할 수 있음
- 모듈 프로그래밍을 통해 디바이스 드라이버를 작성할 수 있음
- 모듈은 kbuild라는 규칙이 있는 Makefile을 통해 컴파일할 수 있음
- 컴파일된 모듈은 insmod, rmmod 등의 명령어로 등록 및 제거가 가능
'모의해킹 > 시스템 해킹' 카테고리의 다른 글
shell_basic (0) | 2023.12.09 |
---|---|
Welcome (0) | 2023.12.09 |
qemu & gdb 세팅 (0) | 2023.05.30 |
리눅스 커널 & 파일 시스템 빌드 (0) | 2023.05.29 |
시스템 해킹 기본 지식 (0) | 2023.05.11 |