이번에는 리눅스 커널을 수정하여, 커널 변수를 만들어고, 그 변수를 활용하여 로깅 시스템 콜을 만들어 볼 것이다.

1. 커널 버전 확인

먼저 커널의 버전을 확인해보자

$ uname -r

그러면 앞에 써있는 숫자가 커널의 버전을 나타낸다.

4.19.110-이름

2. 소스 폴더로 이동

이제 커널의 버전을 확인했으니 커널 소스 폴더로 가보자

$ cd /커널/소스폴더/위치

3. 시스템콜 소스코드 작성

여기서 이제 example 이라는 폴더를 하나 만들것이다. 이 폴더가 시스템 콜의 소스 폴더가 될 것이다.

$ mkdir example

이제 폴더에 들어가서 본격적으로 소스를 작성해 보자.

$ cd example
$ nano example.c
#include<linux/kernel.h>
#include<linux/syscalls.h>
#include<linux/sched.h>

// 현재 로그 레벨을 저장하는 변수다. 시스템이 시작될때 선언되며, 시스템이 종료될때까지 살아있다.
// EXPORT_SYMBOL을 통해 전역 변수로 만들어 준다.
int log_level=0; // 현재 로그레벨 0 부터 2까지만 쓸 예정이다.
EXPORT_SYMBOL(log_level);

// SYSCALL_DEFINE0(get_level) 은 매크로로 get_level이라는 인수 0개를 취하는 함수를 만든다.
// DEFINE 뒤에있는 숫자가 인수의 갯수를 나타낸다.
SYSCALL_DEFINE0(get_level)
{
    return log_level;
}

// SYSCALL_DEFINE1(set_level, int, new_level) 은 매크로로 set_level이라는
// int 인수 1개를 취하는 함수를 만든다. 
SYSCALL_DEFINE1(set_level, int, new_level)
{
    // 만약 Superuser 권한이 없으면 -1 (실패)를 리턴한다.
    if(!capable(CAP_SYS_ADMIN))
        return -1;
    // 만약 새로 설정할 레벨이 범위를 벗어나면 -1 (실패)를 리턴한다.
    if(new_level < 0 || new_level > 2)
        return -1;
    // 로그레벨을 새로 설정한다.
    log_level = new_level;
}

// 매크로를 이용해 add_log라는 1개의 인수 char __user *message를 받는 함수를 만든다.
// char __user * 타입을 쓰는 이유는 시스템콜을 커널 외부에서도 사용하기 때문에, 유저스페이스에서의 변수라는것을 명시해야 하기 때문이다.
SYSCALL_DEFINE1(add_log, char __user *, message)
{
    // 메세지 컨테이너 선언
    char * msg_container;
    // 로그 레벨에 맞게 메세지 레벨 설정
    if (log_level == 0)
        msg_container = KERN_EMERG "message from %s(%d): %s";
    else if (log_level == 1)
        msg_container = KERN_ALERT "message from %s(%d): %s";
    else
        msg_container = KERN_CRIT "message from %s(%d): %s";
    // 커널 메세지 출력 message from 프로세스이름(pid): 메세지
    printk(msg_container, current->comm, (int) task_pid_nr(current), message);
}
이로서 시스템콜 소스파일은 끝났다. ### 4. Makefile 추가 이제 같은 디렉토리에 Makefile을 만들어주자 Makefile
obj-y := example.o
그리고 이제 시스템콜 소스폴더를 커널루트 디렉토리의 Makefile에 추가해주자
$ cd ..
$ nano Makefile
커널 Makefile에서 Ctrl+W를 누르고 core-y를 검색한다 아래처럼 보인다면 뒤에 example/ 을 추가해주자.
core-y          += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ example/
### 5. 마무리 example폴더를 Makefile에 추가해줬으니 다음시간에는 시스템콜 테이블에 시스템콜을 추가해보도록 하자. 이어지는 글: [리눅스 시스템콜 만들기 2](https://holeeman.github.io/linux/%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%8B%9C%EC%8A%A4%ED%85%9C%EC%BD%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0-2/)

Comments