modprobe_path가 항상 동작하는 것이 아니다.
컴파일 타임에 modprobe가 동작하는 방식이 바뀔 수 있다.
우선 modprobe 동작 시 호출되는 함수를 볼 필요가 있다.
static int call_modprobe(char *module_name, int wait)
{
struct subprocess_info *info;
static char *envp[] = {
"HOME=/",
"TERM=linux",
"PATH=/sbin:/usr/sbin:/bin:/usr/bin",
NULL
};
char **argv = kmalloc(sizeof(char *[5]), GFP_KERNEL);
if (!argv)
goto out;
module_name = kstrdup(module_name, GFP_KERNEL);
if (!module_name)
goto free_argv;
argv[0] = modprobe_path;
argv[1] = "-q";
argv[2] = "--";
argv[3] = module_name; /* check free_modprobe_argv() */
argv[4] = NULL;
info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL,
NULL, free_modprobe_argv, NULL);
if (!info)
goto free_module_name;
return call_usermodehelper_exec(info, wait | UMH_KILLABLE);
free_module_name:
kfree(module_name);
free_argv:
kfree(argv);
out:
return -ENOMEM;
}
여러 argv, envp의 설정을 마치고 call_usermodehelper_setup()
을 호출한다.
이 때 첫 번째 인자로 modprobe_path
가 전달되고, 이것이 우리가 아는 그 modprobe_path
변수이다.
struct subprocess_info *call_usermodehelper_setup(const char *path, char **argv,
char **envp, gfp_t gfp_mask,
int (*init)(struct subprocess_info *info, struct cred *new),
void (*cleanup)(struct subprocess_info *info),
void *data)
{
struct subprocess_info *sub_info;
sub_info = kzalloc(sizeof(struct subprocess_info), gfp_mask);
if (!sub_info)
goto out;
INIT_WORK(&sub_info->work, call_usermodehelper_exec_work);
#ifdef CONFIG_STATIC_USERMODEHELPER
sub_info->path = CONFIG_STATIC_USERMODEHELPER_PATH;
#else
sub_info->path = path;
#endif
sub_info->argv = argv;
sub_info->envp = envp;
sub_info->cleanup = cleanup;
sub_info->init = init;
sub_info->data = data;
out:
return sub_info;
}
잘 보면 CONFIG_STATIC_USERMODEHELPER
가 정의된 경우에는 CONFIG_STATIC_USERMODEHELPER_PATH
, 그렇지 않은 경우에는 인자로 들어온 path
가 경로로 저장된다.
CONFIG_STATIC_USERMODEHELPER_PATH
는 정해진 경로가 저장된 주소값이다. 즉, 더 이상 modprobe_path를 수정해서 exploit하는 방법은 불가능하다.
하지만 실제 modprobe_path값은 메모리 상으로 존재하긴 한다. 의미는 없지만.
애초에 컴파일 타임에 차이가 발생하는 것이기 때문에 CONFIG_STATIC_USERMODEHELPER
가 define 되었는지 아닌지는 call_usermodehelper_setup()
함수의 어셈블리 코드를 보고 확인해도 된다.