Seccomp
seccomp (сокращение от англ. secure computing mode) — средство обеспечения безопасности ядра Linux, предназначенное для ограничения доступных процессу системных вызовов. В сочетании с механизмом BPF (Berkeley Packet Filter) позволяет реализовывать гибкую фильтрацию вызовов и их аргументов на основе заданных правил.
Общие сведения
| seccomp | |
|---|---|
| Тип | механизм безопасности ядра |
| Разработчик | Андреа Арканджели |
| Написана на | Си |
| Операционная система | Linux |
| Первый выпуск | март 2005 |
| Лицензия | GPL |
| Сайт | code.google.com/p/seccom… |
История
Механизм seccomp разработал Андреа Арканджели (итал. Andrea Arcangeli) в рамках коммерческого проекта CPUShare. В основе его идеи было предоставление вычислительных ресурсов компьютеров, в частности с ОС Linux, для исполнения стороннего кода. Впервые появился в ядре Linux в марте 2005 года (версия 2.6.12). В первой версии, чтобы включить seccomp, процесс должен был записать «1» в файл /proc/PID/seccomp. После этого гостевому коду были доступны только четыре системных вызова: read(), write(), exit() и sigreturn()[3]. В 2007 году в версии 2.6.23 была добавлена возможность включения seccomp через системный вызов prctl() с помощью операции PR_SET_SECCOMP, а интерфейс через /proc был исключён[4].
Несмотря на то, что проект CPUShare не получил развития, seccomp остался в ядре Linux[3]. В феврале 2009 года в реализации seccomp была обнаружена уязвимость, обусловленная несовпадением номеров системных вызовов в 32-битной и 64-битной архитектурах ядра Linux. Например, разрешённому вызову read() из 64-битной версии соответствовал запрещённый вызов restart_syscall() из 32-битной версии. После этого возникло обсуждение об исключении seccomp из Linux, а Линус Торвальдс предположил, что seccomp никем не используется[5].
Поскольку seccomp был достаточно прост для использования, у разработчиков Google Chrome возникла идея реализовать на его основе средство для запуска сторонних плагинов. Однако для реализации этой задачи простого блокирования всех системных вызовов за исключением четырёх разрешённых было недостаточно. В итоге в 2012 году с seccomp был интегрирован механизм BPF (Berkeley Packet Filter) (в версии 3.5 добавлен второй режим работы — SECCOMP_MODE_FILTER), что значительно расширило возможности механизма: после нововведения гостевой процесс мог более гибко выбирать набор разрешённых и запрещённых системных вызовов, присоединяя соответствующую BPF-программу. В 2012 году появилась также библиотека libseccomp, предоставляющая простой API для фильтрации системных вызовов[4].
Для упрощения использования seccomp, в 2013 году в версии 3.8 было добавлено поле «Seccomp» в /proc/PID/status, позволяющее выяснить состояние seccomp. В 2014 году в версии 3.17 был добавлен специальный системный вызов — seccomp(), который частично повторяет функциональность prctl()[4].
В ноябре 2017 года, с выходом glibc версии 2.26, появилась новая проблема: поскольку в программах на языке C системные вызовы делаются не напрямую, а через обёртки стандартной библиотеки, названия которых могут не совпадать с названиями системных вызовов, запрет какого-либо вызова может неожиданно повлиять на программу. Например, функция open() из glibc версии 2.26 реализована через системный вызов openat(), который не совпадает с вызовом open() и может быть ошибочно заблокирован автором фильтра[6].
Описание
Для работы с недоверенными или потенциально опасными программами желательно использовать специально выделенные среды — песочницы или контейнеры, — из которых нельзя нанести вред работоспособности системы в целом. В таких средах для запускаемых программ лимитированы многие системные возможности, такие как доступ к сети, устройствам ввода-вывода, взаимодействие с операционной системой. Механизм seccomp определяет для процесса набор разрешённых системных вызовов и блокирует те, которые не были заранее объявлены. В настоящее время используется в ряде браузеров, Linux-подобных ОС и некоторых системах виртуализации.
Для включения seccomp в программе используется системный вызов seccomp() или prctl(). Существует два режима работы: SECCOMP_MODE_STRICT и SECCOMP_MODE_FILTER. Узнать, включён ли seccomp и в каком режиме, можно по полю «Seccomp» в файле /proc/[pid]/status. Поле принимает значения: 0 — seccomp не включён, 1 — режим SECCOMP_MODE_STRICT, 2 — режим SECCOMP_MODE_FILTER[4] Включить seccomp для других процессов невозможно[7].
Режим SECCOMP_MODE_STRICT
Это единственный режим работы до Linux 3.5. Для его использования ядро должно быть сконфигурировано с ключом CONFIG_SECCOMP=y[2].
Чтобы войти в этот режим, выполняется вызов prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT) или seccomp(SECCOMP_SET_MODE_STRICT, 0, NULL). После этого процесс может использовать лишь четыре системных вызова: read(), write(), _exit() и sigreturn()[3]. Попытка использования других системных вызовов приведёт к прерыванию процесса сигналом SIGKILL. Так как open() запрещён, проверку включения seccomp происходит желательно до входа в ограниченный режим[4].
Режим SECCOMP_MODE_FILTER
Режим появился в ядре Linux версии 3.5.[8]. Он доступен, если ядро собрано с флагом CONFIG_SECCOMP_FILTER=y.
Перед переходом в этот режим необходимо выполнить вызов prctl(PR_SET_NO_NEW_PRIVS, 1), чтобы установить бит no_new_privs. Это обязательное требование связано с тем, чтобы предотвратить возможность повышения привилегий через execve(). Без этого перейти в режим SECCOMP_MODE_FILTER не удастся[4].
Далее, чтобы присоединить к процессу фильтр, выполняется вызов prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, args) или seccomp(SECCOMP_SET_MODE_FILTER, 0, args), где args — указатель на структуру sock_fprog, содержащую массив BPF-инструкций и его длину. Фильтр запускается каждый раз при системном вызове, получая на вход структуру с данными: номер вызова, архитектуру, состояние счётчика команд и аргументы[8]. Фильтр должен возвращать 32-битное значение: верхние 16 бит — действие, нижние 16 — данные. Фильтры, в которых не предусмотрён возврат значения, не будут установлены[9].
Если установлено несколько фильтров, они объединяются в односвязный список и запускаются в порядке, обратном их добавлению, даже если один фильтр должен завершить процесс.
Приоритет действий определяется следующим образом[10]:
| Действие | Результат |
|---|---|
| SECCOMP_RET_KILL | Системный вызов не выполняется, процесс завершён сигналом SIGSYS[4] |
| SECCOMP_RET_TRAP | Системный вызов не выполняется, процесс получает сигнал SIGSYS, обработчику сигнала доступна информация о вызове |
| SECCOMP_RET_ERRNO | Системный вызов не выполняется, в переменной errno содержится возвращённое фильтром значение
|
| SECCOMP_RET_TRACE | Если для процесса указан трассировщик через ptrace(), он будет уведомлён о вызове. Если не указан — вызов блокируется
|
| SECCOMP_RET_ALLOW | Системный вызов выполняется |
Примеры использования
Включение режима SECCOMP_MODE_STRICT[4]
# include <stdio.h>
# include <unistd.h>
# include <linux/seccomp.h>
# include <sys/prctl.h>
# include <fcntl.h>
int main () {
int fd;
prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
fprintf(stderr, "try open\n");
fd = open("test_file", O_CREAT);
fprintf(stderr, "fd = %d", fd);
return 0;
}
Результат работы:
$ gcc test_seccomp.c -o test_seccomp
$ ./test_seccomp
try open
Killed
В приведённом примере после вызова prctl() процесс работает ровно до момента, когда попытается сделать вызов open().
Примеры использования в ПО
Примечания
- ↑ 1 2 3 Imamjafar Borate, Chavan R. K. (2016). “Sandboxing in Linux: From Smartphone to Cloud” (PDF). International Journal of Computer Applications [англ.]. 148 (8). Дата обращения 2024-06-15.
- ↑ 1 2 Greg Kroah-Hartman. Linux Kernel in a Nutshell. — O'Reilly Media, 2007. — P. 208. — ISBN 978-0596100797.
- ↑ 1 2 3 Kurt Dietrich, Johannes Winter (2011). “Towards a Trustworthy, Lightweight Cloud Computing Framework for Embedded Systems”. Trust and Trustworthy Computing: 4th International Conference [англ.]. Pittsburgh, PA, USA: Springer. Дата обращения 2024-06-15.
- ↑ 1 2 3 4 5 6 7 8 Jake Edge, Michael Kerrisk (2015). “A seccomp overview”. LWN.net [англ.]. Дата обращения 2024-06-15.
- ↑ Seccomp and sandboxing. LWN.net. Eklektix, Inc. (13 мая 2009). Дата обращения: 15 июня 2024. Архивировано 12 ноября 2017 года.
- ↑ The inherent fragility of seccomp(). LWN.net (10 ноября 2017). Дата обращения: 15 июня 2024. Архивировано 9 декабря 2017 года.
- ↑ Lingguang Lei, Jianhua Sun, Kun Sun, Chris Shenefiel, Rui Ma, Yuewu Wang, Qi Li (2017). “SPEAKER: Split-Phase Execution of Application Containers”. Detection of Intrusions and Malware, and Vulnerability Assessment: 14th International Conference, DIMVA 2017 [англ.]. Bonn, Germany: Springer. Дата обращения 2024-06-15.
- ↑ 1 2 Taesoo Kim, Nickolai Zeldovich (2013). “Practical and effective sandboxing for non-root users” (PDF). 2013 USENIX Annual Technical Conference [англ.]. Дата обращения 2024-06-15.
- ↑ Steven McCanne, Van Jacobson (1993). “The BSD Packet Filter: A New Architecture for User-level Packet Capture” (PDF). 1993 Winter USENIX. Дата обращения 2024-06-15.
- ↑ SECure COMPuting with filters. The Linux Kernel Archives. Linux Kernel Organization. Дата обращения: 15 июня 2024. Архивировано 13 октября 2017 года.
- ↑ Anto.Y. Chrome OS and Secret of Google. — Lambert Academic Publishing, 2012. — P. 41. — ISBN 978-3-659-17127-7.
- ↑ Adrian Mouat. Using Docker: Developing and Deploying Software with Containers. — O'Reilly Media, 2015. — P. 320. — ISBN 978-1-4842-3024-4.
- ↑ Senthil Kumaran S. Practical LXC and LXD: Linux Containers for Virtualization and Orchestration. — Apress, 2017. — P. 147. — ISBN 978-1-4842-3024-4.
Литература
- Steven McCanne, Van Jacobson (1993). “The BSD Packet Filter: A New Architecture for User-level Packet Capture” (PDF). 1993 Winter USENIX. Дата обращения 2024-06-15.
- Greg Kroah-Hartman. Linux Kernel in a Nutshell. — O'Reilly Media, 2007. — P. 208. — ISBN 978-0596100797.
- Michael Kerrisk. The Linux Programming Interface. — No Starch Press, 2010. — P. 1556. — ISBN 978-1-59327-220-3.
- Jake Edge, Michael Kerrisk (2015). “A seccomp overview”. LWN.net. Дата обращения 2024-06-15.
- Taesoo Kim, Nickolai Zeldovich (2013). “Practical and effective sandboxing for non-root users” (PDF). 2013 USENIX Annual Technical Conference. Дата обращения 2024-06-15.
- Ma Bo, Mu Dejun, Fan Wei, Hu Wei (July 2013). “Improvements the Seccomp sandbox based on PBE theory”. IEEE [англ.]. DOI:10.1109/WAINA.2013.81. Дата обращения 2024-06-15. Используется устаревший параметр
|month=(справка) - Imamjafar Borate, Chavan R. K. (2016). “Sandboxing in Linux: From Smartphone to Cloud” (PDF). International Journal of Computer Applications [англ.]. 148 (8). Дата обращения 2024-06-15.
- Senthil Kumaran S. Practical LXC and LXD: Linux Containers for Virtualization and Orchestration. — Apress, 2017. — P. 147. — ISBN 978-1-4842-3024-4.
- Adrian Mouat. Using Docker: Developing and Deploying Software with Containers. — O'Reilly Media, 2015. — P. 320. — ISBN 978-1-4842-3024-4.
- Kurt Dietrich, Johannes Winter (2011). “Towards a Trustworthy, Lightweight Cloud Computing Framework for Embedded Systems”. Trust and Trustworthy Computing: 4th International Conference [англ.]. Pittsburgh, PA, USA: Springer. Дата обращения 2024-06-15.
- Anto.Y. Chrome OS and Secret of Google. — Lambert Academic Publishing, 2012. — P. 41. — ISBN 978-3-659-17127-7.
- Lingguang Lei, Jianhua Sun, Kun Sun, Chris Shenefiel, Rui Ma, Yuewu Wang, Qi Li (2017). “SPEAKER: Split-Phase Execution of Application Containers”. Detection of Intrusions and Malware, and Vulnerability Assessment: 14th International Conference, DIMVA 2017 [англ.]. Bonn, Germany: Springer. Дата обращения 2024-06-15.
Ссылки
- Michael Kerrisk. seccomp/seccomp_perf.c. Michael Kerrisk. Дата обращения: 15 июня 2024. — пример использования seccomp из The Linux Programming Interface.
- SECure COMPuting with filters. The Linux Kernel Archives. Linux Kernel Organization. Дата обращения: 15 июня 2024. — часть документации ядра Linux kernel
- Julien Tinnes, Chris Evans (October 2009). “Security In-Depth for Linux Software Preventing and Mitigating Security Bugs” (PDF). HITB Malaysia [англ.]. Дата обращения 2024-06-15. Используется устаревший параметр
|month=(справка) - Jake Edge. A seccomp overview (англ.). Eklektix, Inc. (2 сентября 2015). Дата обращения: 15 июня 2024.
- Jonathan Corbet. Seccomp and sandboxing (англ.). Eklektix, Inc. (13 мая 2009). Дата обращения: 15 июня 2024.