call_usermodehelper() 사용법

Linux 커널은 일반적으로 사용자 공간(user space)에서 동작하는 프로그램을 직접 실행하지 않는다. 그러나 특정 상황에서는 커널 모듈 또는 커널 코드에서 사용자 공간의 프로그램을 실행해야 할 필요가 때가 있다. 예를 들어, 커널에서 특정 시점에 로그를 외부로 전송하거나, 오류 발생 시 자동 복구 스크립트를 호출하는 등이 그 예이다. 이러한 기능을 위해 커널은 **call_usermodehelper()**라는 API를 제공한다. 이 글에서는 call_usermodehelper()의 기본 개념과 사용법에 대해 알아본다.

call_usermodehelper() ?

call_usermodehelper()는 커널 코드에서 사용자 공간의 프로그램을 실행할 수 있게 해주는 함수이다. 이는 커널이 명시적으로 지정한 바이너리와 인자, 환경 변수를 가지고 사용자 공간의 프로그램을 실행한다.

int call_usermodehelper(const char *path, char **argv, char **envp, int wait);

각 매개 변수는 다음과 같다.

매개변수설명
path실행할 사용자 공간 바이너리의 경로 (예: /bin/echo)
argv실행 인자 배열 (argv[0]은 프로그램 이름)
envp환경 변수 배열
wait실행 방식: 비동기/동기 선택 (UMH_NO_WAIT, UMH_WAIT_PROC, 등)

주요 사용 방식

wait 플래그

플래그 이름설명
UMH_NO_WAIT비동기로 실행. 즉시 반환
UMH_WAIT_PROC자식 프로세스 종료 시까지 대기
UMH_WAIT_EXEC자식 프로세스가 execve() 호출 후 반환

일반적으로 가장 많이 사용하는 옵션은 UMH_WAIT_PROC이다.

Example: echo 실행

커널 모듈에서 /bin/echo hello kernel 명령어를 실행

커널 모듈 예제 코드

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kmod.h>

static int __init my_module_init(void)
{
    char *argv[] = { "/bin/echo", "hello kernel", NULL };
    char *envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };

    int ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);

    printk(KERN_INFO "call_usermodehelper returned: %d\n", ret);
    return 0;
}

static void __exit my_module_exit(void)
{
    printk(KERN_INFO "Module exit.\n");
}

module_init(my_module_init);
module_exit(my_module_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("call_usermodehelper Example");
MODULE_AUTHOR("YourName");

Makefile 예제

obj-m += call_helper.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

빌드 및 실행

make
sudo insmod call_helper.ko
dmesg | tail

결과

hello kernel
call_usermodehelper returned: 0

call_usermodehelper_setup / exec 방식

보다 세부적으로 사용자 공간 프로세스를 컨트롤할 수 있도록 call_usermodehelper_setup()call_usermodehelper_exec() 함수를 사용할 수도 있다.

Example: call_usermodehelper_setup 사용

#include <linux/module.h>
#include <linux/kmod.h>

static int __init mod_init(void)
{
    struct subprocess_info *info;
    char *argv[] = { "/usr/bin/logger", "Hello from kernel", NULL };
    char *envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };

    info = call_usermodehelper_setup(argv[0], argv, envp, GFP_ATOMIC, NULL, NULL, NULL);
    if (!info)
        return -ENOMEM;

    return call_usermodehelper_exec(info, UMH_WAIT_PROC);
}

static void __exit mod_exit(void)
{
    printk(KERN_INFO "Exiting module.\n");
}

module_init(mod_init);
module_exit(mod_exit);

MODULE_LICENSE("GPL");

call_usermodehelper 작동 흐름

+----------------------+
| 커널 공간 (Kernel) |
+----------+-----------+
|
| call_usermodehelper()
v
+--------------------------+
| subprocess_info 구조체 |
| exec path, argv, envp 등 |
+--------------------------+
|
| fork() + execve()
v
+----------------------+
| 사용자 공간 프로그램 |
+----------------------+

주의사항

1. 실행 파일의 경로 문제

  • /bin/echo 같은 명령어는 경로를 정확히 지정해야 하며, PATH 환경 변수는 명시적으로 제공해야 한다.

2. 커널 로그 외부로 출력

  • printk() 메시지는 dmesg에 기록된다.
  • 사용자 공간에서 로그를 기록하려면 logger 명령이나 /dev/kmsg에 쓰는 방식이 필요하다.

3. 사용자 공간 의존성

  • 사용자 공간 프로그램이 없어도 커널 모듈은 로드되지만, 실행 시 실패할 수 있다.
  • BusyBox 환경 등에서는 경로가 다를 수 있으므로 반드시 존재 여부 확인 필요.

4. 권한 제한

  • 루트 권한으로 동작하므로 신중히 사용해야 한다.
  • 보안 이슈가 될 수 있으므로 외부 입력값을 통한 command 실행은 항상 주의해야 한다.

Example: 스크립트 실행

/usr/local/bin/myhook.sh 실행

char *argv[] = { "/usr/local/bin/myhook.sh", "arg1", "arg2", NULL };
char *envp[] = { "HOME=/", "PATH=/sbin:/bin:/usr/sbin:/usr/bin", NULL };
int ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);

스크립트 예

#!/bin/bash
echo "call_usermodehelper called with $1 and $2" >> /tmp/kernel.log

반드시 chmod +x로 실행 권한 부여

디버깅 방법

1. dmesg 출력 확인

dmesg | tail -n 50

2. 프로그램 실행 실패 확인

strace -e execve /bin/echo hello

3. 로그 파일로 출력 유도

char *argv[] = { "/usr/bin/logger", "Kernel event happened", NULL };

call_usermodehelper 사용 시의 보안 고려사항

  • 입력 값 검증: 사용자 입력을 통한 경로 지정은 절대 금지.
  • 실행 제한: root 권한을 사용하므로 반드시 신뢰된 프로그램만 실행.
  • SElinux / AppArmor 정책: 사용자 공간 실행 제한을 적용할 수 있음.

참고 사이트

This Post Has One Comment

  1. PrimeBiome

    Your writing is like a breath of fresh air in the often stale world of online content. Your unique perspective and engaging style set you apart from the crowd. Thank you for sharing your talents with us.

답글 남기기