Основная проблема заключается в том, что многие аргументы системного вызова, такие как имена файлов, передаются ядру в качестве указателей пользовательского пространства.Любая задача, которой разрешено запускаться одновременно и которая имеет доступ на запись в память, на которую указывает указатель, может эффективно изменить эти аргументы после того, как они проверены вашим супервизором и до того, как ядро воздействует на них.К тому времени, когда ядро следует за указателем, указанное содержимое может быть преднамеренно изменено другой запланированной задачей (процессом или потоком) с доступом к этой памяти.Например:
Thread 1 Supervisor Thread 2
-----------------------------------------------------------------------------------------------------
strcpy(filename, "/dev/null");
open(filename, O_RDONLY);
Check filename - OK
strcpy(filename, "/home/user/.ssh/id_rsa");
(in kernel) opens "/home/user/.ssh/id_rsa"
Один из способов остановить это - запретить вызов clone()
с флагом CLONE_VM
и, кроме того, предотвратить любое создание доступных для записи отображений памяти MAP_SHARED
(или, по крайней мере, отслеживатьиз них такие, что вы отрицаете любой системный вызов, который пытается напрямую ссылаться на данные из такого сопоставления).Вы также можете скопировать любой такой аргумент в неиспользуемый bounce-буфер перед тем, как продолжить системный вызов.Это эффективно предотвратит запуск любого многопоточного приложения в «песочнице».
Альтернативой является SIGSTOP
любой другой процесс в отслеживаемой группе вокруг каждого потенциально опасного системного вызова, подождите, пока они действительно остановятся, затем разрешите системный вызов.продолжать.После того, как он возвращается, вы затем SIGCONT
их (если они не были уже остановлены).Излишне говорить, что это может оказать существенное влияние на производительность.
(Есть также аналогичные проблемы с аргументами системного вызова, которые передаются в стек, и с таблицами общих открытых файлов).