(kernel) addr\_limit - kernel space arg
addr_limit
system call은 원래 user mode에서 호출하도록 되어 있기 때문에, system call의 인자로 넘어오는 데이터는 user space의 데이터여야 한다. 인자로 kernel space의 데이터가 넘어오면 제대로 동작하지 않는다. kernel은 addr\_limit
를 기준으로 인자로 넘어온 데이터가 user space data인지 kernel space data를 구분한다. 따라서 이 경계를 조정해주면 user space data를 넘겨도 정상 동작하도록 만들 수 있다.
/source/arch/x86/include/asm/processor.h#L421
1
2
3
4
5
6
7
8
9
10
11
12
typedef struct {
unsigned long seg;
} mm\_segment\_t;
struct thread\_struct {
...
mm\_segment\_t addr\_limit;
...
};
* 기본값은 addr\_limit==PAGE\_OFFSET
이다.
/source/arch/x86/include/asm/uaccess.h#L27
1
2
3
4
#define get\_ds() (KERNEL\_DS) // == MAKE\_MM\_SEG(-1UL)
#define get\_fs() (current->thread.addr\_limit)
#define set\_fs(x) (current->thread.addr\_limit = (x))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <asm/uaccess.h>
mm\_segment\_t orig\_fs;
orig\_fs = get\_fs();
set\_fs(get\_ds());
/\* do something \*/
set\_fs(orig\_fs);
Note ) 현재 thread에 대해서 addr\_limit
를 수정하는 것이기 때문에, 시스템 전역적으로 적용되는 것이 아니다.
Note ) addr\_limit
를 해제한다고 해도, user mode에서 kernel space에 접근할 수 있는 것이 아니다. 따라서 kernel code에 접근하거나, kernel data에 접근하는 것은 불가능하다. user mode의 test 프로세스가 c95d32bc 에 접근하려 하면 segfault 발생.
1
2
3
4
5
6
7
8
root@kali32:~/lkm/addr\_limit# dmesg | tail -6
[91770.266480] b\_hook LKM is loaded
[91770.266482] sct[\_\_NR\_swapon] c95d32bc : c91b0fe0 : 26748d3e
[91770.266484] sct[\_\_NR\_swapon] c95d32bc : f96c9000 : 26748d3e
[91771.717924] orig\_addr\_limit : c0000000
[91771.717925] new\_addr\_limit : ffffffff
[91771.717929] test[10583]: segfault at c95d32bc ip 00400581 sp bffff630 error 5 in test[400000+1000]
e.g.
[ user space data가 들어가야 할 자리에 kernel space data가 들어가는 경우 : ]
1
2
3
4
5
6
7
8
asmlinkage long hook\_sys\_write(unsigned int fd, char \_\_user \*buf, size\_t count){
if (!strcmp(buf, "bum")){
printk("hook");
return orig\_sys\_write(fd, "BUM", count);
}
return orig\_sys\_write(fd, buf, count);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@kali32:~/lkm/addr\_limit/write\_hook# ../../write\_test
bum
root@kali32:~/lkm/addr\_limit/write\_hook# insmod sys\_hook.ko
root@kali32:~/lkm/addr\_limit/write\_hook# ../../write\_test
root@kali32:~/lkm/addr\_limit/write\_hook# rmmod sys\_hook
root@kali32:~/lkm/addr\_limit/write\_hook# ../../write\_test
bum
root@kali32:~/lkm/addr\_limit/write\_hook# dmesg | tail -5
[112700.607849] b\_hook LKM is loaded
[112700.607851] sct[\_\_NR\_write(4)] c95d3170 : c91dc6e0 : 26748d3e
[112700.607852] sct[\_\_NR\_write(4)] c95d3170 : f970c000 : 26748d3e
[112702.850690] hook
[112706.057887] b\_hook LKM is removed.
dmesg
가 제대로 찍히는 것을 보면 LKM은 제대로 동작했는데, orig\_sys\_write()
에서 제대로 출력되지 않은 것 같다. * 사실 이런 종류의 문자열 수정은 그냥 buf[0]
으로 접근하면 addr_limit 설정이 필요 없기는 하다.
[ addr_limit를 해제한 경우 : ]
1
2
3
4
root@kali32:~/lkm/addr\_limit/write\_hook# insmod sys\_hook.ko
root@kali32:~/lkm/addr\_limit/write\_hook# ../../write\_test
BUM