Я хочу запустить скрипт, когда появится новый корневой процесс. (в Linux) Как я могу это сделать?
Спасибо
Похоже, это идеальная работа для auditd. После запуска auditd, службы по умолчанию в современных системах на базе 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.
Обратите внимание, что это правило можно выполнить во время выполнения, убедившись, что auditd правильно настроен, и добавив правило
-a task,always -F uid=0
в соответствующий файл для вашего дистрибутива, скорее всего /etc/audit/audit.rules
Просто имейте в виду, что это будет чертовски шумно, и кто бы ни делал ваши обзоры журналов, должен быть к этому готов.
Я не думаю, что есть чистый способ сделать это без перекомпиляции ядра с помощью CONFIG_PROC_EVENTS и / или CONFIG_KPROBES (хотя мне бы хотелось узнать, есть ли способ сделать это, поэтому я поддержал ваш вопрос).
У меня была идея использовать iwatch / inotify для создания каталогов внутри / proc, но это не сработало, как и auditctl. Похоже, ваш лучший выбор, хотя и грязный, - это постоянно разбирать 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"; } } }
Лучший способ, который я могу придумать, - это построить любопытный библиотека. snoopy - это очень маленькая разделяемая библиотека, которая подключается к /etc/ld.so.preload
и оборачивается вокруг execve()
системные вызовы. Можно настроить регистрацию всех exec()
s, или только от root. В его текущем воплощении snoopy регистрирует в системном журнале каждый раз соответствующее событие (системный вызов для execve()
) бывает. Однако это небольшая программа (максимум несколько сотен строк кода), и ее можно без особых трудностей изменить, чтобы выполнить сценарий вместо (или в дополнение к) регистрации активности. Снупи написан на C.
Несколько замечаний: