Можно ли привязать выполнение скрипта к созданию каждого процесса?
По сути, эквивалент inotifywait для мониторинга активности диска, но применяемый к таблице процессов.
Это позволило бы выполнять действие при порождении процессов, например, регистрировать его, cgset его и т. д. Я вижу проблему в том, что это будет рекурсивно применяться к новым процессам. Но вместо того, чтобы опрашивать таблицу процессов как можно быстрее, чтобы поймать изменения, которые будут уязвимы для условий гонки, есть ли лучший способ.
Спасибо
решение1
Во-первых, создание процесса редко бывает полезным событием для регистрации, и это не имеет значения для безопасности (за исключением ограничения ресурсов). Я думаю, вы имеете в виду перехват выполнения программ, что делаетсяexecve
, нетfork
.
Во-вторых, приведенные вами варианты использования обычно лучше всего реализуются с помощью уже существующего механизма, созданного для этой цели, а не путем разработки собственного.
- Для регистрации,Учет процесса BSDпредоставляет небольшой объем информации и доступен в большинстве вариантов Unix; в Linux установитеУтилиты бухгалтерского учета GNU(установите пакет из вашего дистрибутива). Для более сложного ведения журнала в Linux вы можете использоватьподсистема аудита(тот
auditctl
на странице руководства есть примеры; как я объяснил выше, системный вызов, который вам нужно будет регистрировать, — этоexecve
). - Если вы хотите применить ограничения безопасности к определенным программам, используйте фреймворк безопасности, напримерSELinuxилиAppArmor.
- Если вы хотите запустить определенную программу в контейнере или с определенными настройками, переместите исполняемый файл и поместите на его место скрипт-оболочку, который устанавливает нужные вам настройки и вызывает исходный исполняемый файл.
Если вы хотите изменить способ вызова других программ одной конкретной программой, не влияя на поведение других программ, возможны два случая: либо программа потенциально враждебна, либо нет.
- Если программа потенциально вредоносна, запустите ее на отдельной виртуальной машине.
- Если программа кооперативная, наиболее очевидным углом атаки является запуск ее с другим
PATH
. Если программа использует абсолютные пути, которые нелегко настроить, на не-старинной системе Linux, вы можете запустить ее в отдельноммонтировать пространство имен(смотрите такжеядро: поддержка пространств имен). Если вам действительно нужен точный контроль, вы можете загрузить библиотеку, которая переопределяет некоторые библиотечные вызовы, вызвав программу с помощьюLD_PRELOAD=my_override_library.so theprogram
. СмотритеПеренаправить дескриптор файла перед выполнениемдля примера. Обратите внимание, что в дополнение кexecve
вам нужно будет переопределить все функции библиотеки C, которые вызываютсяexecve
внутри, посколькуLD_PRELOAD
не влияет на внутренние вызовы библиотеки C. Вы можете получить более точный контроль, запустив программу подptrace
; это позволяет вам переопределить системный вызов, даже если он сделан функцией библиотеки C, но это сложнее настроить (я не знаю простого способа сделать это).
решение2
//fakeExec.c
#include <unistd.h>
#include <stdio.h>
#include <sys/syscall.h>
int execve(const char *path, char *const argv[], char *const envp[]) {
printf("Execing \"%s\"\n", path);
return syscall(SYS_execve, path, argv, envp);
}
В терминале:
$ gcc -fPIC -shared fakeExec.c -o fakeExec.so
$ export LD_PRELOAD=$PWD/fakeExec.so
И теперь каждый новый исполняемый файл должен регистрироваться в stdout
.
Судя по всему, для изготовления правильной обертки для вилки потребуется немного больше работы.
(Тривиальная fork
оболочка (подобная приведенной выше, но вместо fork
) execve
вроде бы работает, но приводит к некоторым setgpid
ошибкам в процессах, порожденных ею.
Видимо, в libc fork
есть какие-то дополнительные функции, которые я не совсем понимаю.)