Кто-нибудь знает простой способ мониторинга порождения корневого процесса

Я хочу выполнить скрипт, когда появляется новый корневой процесс. (на Linux) Как я могу просто сделать это?

Спасибо

3 ответа

Решение

Это звучит как идеальная работа для аудита. Запустив Audit, службу по умолчанию в современных системах на базе RedHat, вы можете создать правило, которое будет выполнять именно то, что вы хотите, выполнив

auditctl -a task,always -F uid=0

Нарушая это правило команды, чрезмерно используя страницу руководства, мы находим, что:

   -a list,action
          task       Add  a  rule to the per task list. This rule list is used
                     only at the time a task is created -- when fork() or
                     clone() are called by the parent task. When using this
                     list, you should only use fields that are known at task
                     creation time, such as the uid, gid, etc.
          always     Allocate an audit context, always fill it in at syscall 
                     entry time, and always write out a record at syscall exit
                     time.

Поэтому всегда записывайте запись для этого действия всякий раз, когда завершается системный вызов fork или clone.

Последний вариант может рассматриваться как строка фильтра, в нашем использовании -F uid=0 просто ограничивает нас случаями, когда uid владельца процесса равен 0.

Обратите внимание, что это правило можно выполнить во время выполнения, убедившись, что audit правильно настроен, и добавив правило
-a task,always -F uid=0
в соответствующий файл для вашего дистрибутива, скорее всего /etc/audit/audit.rules

Просто имейте в виду, что это будет чертовски шумно, и кто бы ни делал ваши обзоры журналов, он должен быть готов к этому.

Я не думаю, что есть чистый способ сделать это без перекомпиляции вашего ядра с CONFIG_PROC_EVENTS и / или CONFIG_KPROBES (хотя я хотел бы знать, есть ли способ сделать это, поэтому я поставил ваш вопрос на голосование).

У меня была идея использовать iwatch/inotify для создания каталога внутри /proc, но, похоже, это не сработало, как и audctl. Похоже, что ваш лучший выбор, хотя и грязный, это постоянно анализировать ps на предмет изменений в скрипте. Следующий код на Perl сделает это, хотя будет склонен пропускать некоторые и игнорировать ps (так как иначе это сработало бы):

perl -e 'my %pids; while(1) { my @pids = `ps -U root -u root`; foreach (@pids) { next if /ps$/; ($pid) = /^\s*(\d+)\D/; if (!$pids{$pid}) { $pids{$pid}++; print "Process $pid created (" . `cat /proc/$pid/cmdline` . ")\n"; } } }

Вы можете сделать это с помощью exec-snoop (на основе ebpf), точек трассировки, аудита, коннектора процесса netlink и некоторых других механизмов. Я написал здесь сравнение всех методов.

Лучший способ, которым я могу придумать, это создать библиотеку Snoopy. snoopy - очень маленькая общая библиотека, которая подключается к /etc/ld.so.preload и обвивает execve() системные вызовы. Это настраивается, чтобы войти все exec()или просто от root. В своем текущем воплощении snoopy регистрирует в системном журнале каждый раз, когда происходит соответствующее событие (системный вызов для execve()) бывает. Это небольшая программа (не более пары сотен строк кода), и ее можно изменить без особых трудностей, чтобы выполнить сценарий вместо (или в дополнение к) регистрации действия. Снупи написан на C.

Несколько вещей, на которые стоит обратить внимание:

  • Если вы запускаете скрипт каждый раз, когда запускается корневой процесс, ваш сценарий будет корневым процессом, который должен будет снова запустить сценарий, который будет другим корневым процессом и т. Д. Будьте осторожны, чтобы не попасть в цикл там.
  • В типичном Linux-боксе есть много процессов, которые запускаются от имени root и регулярно создаются. Например, cron может порождать системные cronjobs как root каждую минуту или несколько минут. Если вы просто ожидаете, что это произойдет, когда пользователь войдет в систему как root, это будет больше работы.
Другие вопросы по тегам