▷ 작성자 : minams (minams@a3sc.co.kr)
▷ 편집자 : minams (minams@a3sc.co.kr)
Sys_call_table Wrapping
목차
1. Introduce
2. Find_sys_call_table for kernel 2.6
3. Test kernel 2.6.22
4. Reference
5. Source code
1. Introduce
kernel 개발 등 여러 가지 작업을 하다 보면 부득이하게 Sys_call_table을 수정해야만 하는 상황이 생긴다.
지금 소개하는 방법은 module을 통해 sys_call_table을 wrapping하는 방법으로 kernel 2.6 이상에서도 가능하며 현재, 2.6.22까지 테스트를 마쳤다.
- Module을 사용하는 이유는 kernel을 컴파일 하지 않고도 wrapping 할 수 있어서이다.
2. Find_sys_call_table for kernel 2.6
잘 알려진 방법으로 sys_call_table 보다 주소가 낮은 공개심볼인 loops_per_jiffy와 높은 주소인 boot_cpu_data 를 이용하여 다음과 같은 코드로 sys_call_table 주소를 찾아낼 수 있다.
for ( ptr = ( unsigned long )&loops_per_jiffy;
ptr < ( unsigned long )&init_mm ; ptr += sizeof( void* ) )
{
p = ( unsigned long * )ptr;
if ( p[ 6 ] == ( unsigned long ) sys_close )
{
return (void**)p;
}
}
그러나 이 소스는 kernel 2.6.22 전까지만 유요한 코드이다. 이유는 심볼 주소가 바뀌었기 때문이다. 확인해보자
Sys_call_table < Loops_per_jiffy < Boot_cpu_data로 변경 된 것을 알 수 있다.
그리하여 a < sys_call_table < b 를 만족하는 공개심볼을 찾아냈다. 바로 _read_lock와 init_mm이다.
# 주소 확인은 직접 해보자!! /boot/System.map 파일을 열어보면 커널 심볼주소(커널 컴파일시)가 들어있다.
이로 만들어지는 코드는 다음과 같다.
for ( ptr = ( unsigned long )_read_lock; ptr < ( unsigned long )&init_mm ; ptr += sizeof( void* ) ) { p = ( unsigned long * )ptr; if ( p[ 6 ] == ( unsigned long ) sys_close ) { return (void**)p; } } |
여기서 해결되면 쉽겠지만 문제가 또 하나 발생한다. 이유는 sys_call_table 이 읽기전용으로 바뀐 것이다.
해당 page의 속성을 바꾸기 위해서 다음을 추가하자 해더는 asm/cacheflush.h 이다
// 쓰기로 변경
change_page_attr(virt_to_page(sys_call_table), 1, PAGE_KERNEL);
// 다음으로 캐시라인 전체를 업데이트
global_flush_tlb();
3. Test kernel 2.6.22
Sys_open을 다음과 같이 간략히 Wrapping
다음과 같은 실수를 하지 않도록 ㅡㅡㅋ
다음은 컴파일 하는 화면이다.
다은은 Test 하는 화면입니다.
4. 참고 사이트 및 문헌
IT EXPORT 리눅스 커널 프로그래밍
http://monac.egloos.com/1308090
5. Source code
--------minux.c------------------------------------------------------- #include <linux/kernel.h> #include <linux/init.h> #include <linux/syscalls.h> #include <linux/module.h> #include <asm/unistd.h> #include <linux/sched.h> //extern int change_page_attr; asmlinkage int (*org_sys_open)(const char*, int, int); asmlinkage int minux_sys_open(char *fname, int flags, int mode) static void **find_system_call_table(void) for( ptr = (unsigned long)_read_lock; ptr < (unsigned long)&init_mm; ptr return NULL; int __init minux_init(void) if( sys_call_table != NULL ) org_sys_getuid = sys_call_table[__NR_getuid]; void __exit minux_exit(void) module_init(minux_init); MODULE_LICENSE( "GPL" ); -----------Makefile--------------------------------- obj-m = minux.o KDIR := /lib/modules/$(shell uname -r)/build default: clean: |