jprobe do_execve не работает с ядром 4.1
Я хочу установить хук jprobe на do_execve, чтобы перехватывать каждую исполняемую программу.
Мой код работает на <= 3.2 ядре Linux (Debian). Это мой вывод о ядре Linux 3.2:
[ 628.534037] registered: do_execve, ret: 0
[ 723.995797] execve: /usr/bin/vi
[ 726.807025] execve: /bin/dmesg
на ядре 4.1 у меня тот же результат (все прописано) но нет "execve":
[ 8621.430568] registered: do_execve, ret: 0
И это мой код:
static struct jprobe jprobe_hooks[] = {
{
.entry = jdo_execve,
.kp = { .symbol_name = "do_execve" }
}};
static long jdo_execve(const char *filename, const char __user *const __user *argv, const char __user *const __user *envp, struct pt_regs *regs)
{
printk(KERN_INFO "execve: %s", filename );
}
//
// registration
//
int ret, x, reg_error;
reg_error = 0;
for (x = 0; x < sizeof(jprobe_hooks) / sizeof(jprobe_hooks[0]); x++)
{
ret = register_jprobe(&jprobe_hooks[x]);
if (ret < 0)
{
printk(KERN_INFO "register_jprobe failed, returned %d, item: %s\n", ret, jprobe_hooks[x].kp.symbol_name);
reg_error++;
}
else
{
printk(KERN_INFO "registered: %s, ret: %u\n", jprobe_hooks[x].kp.symbol_name, ret);
}
}
Когда я делаю grep на kallsyms, я получаю 3.2:
grep do_execv /proc/kallsyms
ffffffff81100650 T do_execve
и на 4.2:
grep do_execv /proc/kallsyms
ffffffff811d2950 T do_execve
ffffffff811d2980 T do_execveat
Я даже пытался изменить функцию (потому что прототип do_execve изменился) на это:
static int jdo_execve(struct filename *fname, const char __user *const __user *__argv, const char __user *const __user *__envp)
{
int i = 0;
printk(KERN_INFO "execve: %s ", fname->name );
}
и даже это не помогло.
Я могу установить хуки на другие функции, такие как do_fork или sys_open, но не на do_execve. Зачем? У кого-нибудь есть идеи? Почему это больше не работает?
Редактировать:
Я также подключаю do_execveat:
static int jdo_execveat(int fd, struct filename *fname, const char __user *const __user *__argv, const char __user *const __user *__envp, int flags)
1 ответ
Есть несколько проблем, которые могут помешать вам сообщения jprobe:
- Вы не заканчиваете печатные сообщения
printk(KERN_INFO "execve: %s", filename );
с новой строкой, таким образом, ваш буфер журнала не очищается. - API изменился. Сейчас
do_execve
имеет параметр имени файла какstruct filename
, - Ваш код jprobe глуп: у вас нет входа в модуль, процедура jprobe должна заканчиваться на
jprobe_return()
звони и тд. Посмотрите примеры в дереве исходного кода ядра в "samples/kprobes"
Попробуйте это исправить - возможно, это поможет.
Во всяком случае, я попробовал это сам - вот код - и все, действительно, выглядит странно. Когда я загружаю модуль, он регистрирует 2 jprobes - один для do_execve, другой для do_execveat. Но я не вижу сообщений при выполнении программ. НО я вижу периодические сообщения, подобные этому:
jprobe: execve: /usr/lib/systemd/systemd-cgroups-agent
Это означает, что сам jprobe работает, но не для каждого execve
вызов.
Поэтому я написал простую C-программу для вызова execve
просто чтобы быть уверенным, что он действительно называется, а у меня все еще ничего не происходит, за исключением systemd-cgroups-agent.