[О блоге]
[наверх]
[пред]
[2023-12-16 13:29:14+03:00]
[24acdbc75c8ffae0b70fc127118df12434767dd1]
Нравится писать privsep/privdrop-oriented программки
Переделывал тут одну программу, которая для случайных данных
использовала getrandom() вызов, не мешающий делать Capsicum и
всякий hardening с privilege drop-ом. А теперь она ещё должна
уметь для случайных данных обращаться по EGD-протоколу к внешнему
демону, что уже не дружит с Capsicum так легко и просто. Он заточен на
то, чтобы заранее открыть все нужные сокеты/файлы, настроить права
доступа на них и перейти в режим ограничений. В FreeBSD можно много чего
делать через файлы и не всё так просто и примитивно, но вот уже создавать
новые EGD соединения не выйдет так легко и просто. Плюс появился
собственный PRNG со своим пулом энтропии и хотелось бы чтобы
fork-ающиеся процессы-клиенты имели централизованный PRNG.
Оказалось не так всё сложно. fork-аемся для создания процесса который
отвечает только за PRNG и общение с EGD, заранее имея с ним socketpair
сокет. Перед fork-ом каждого клиента, тоже делаем пару сокетов, один из
которых будет под контролем процесса-клиента, а другой передаём через
Unix-сокет в PRNG-процесс. В итоге появляется двусторонний канал связи
между PRNG-процессом и клиентским. Клиенту уже не нужно общаться с EGD
или чем-то подобным -- он волен спокойно использовать Capsicum и другие
методы hardening.
Не все люди на работе, которые писали под Unix на Си ещё когда я играл
под Windows, знали про возможность передачи файлов/сокетов через
Unix-сокет. Я это делал впервые на практике, но слышал задолго до этого,
ибо например Tmux это использует в себе и поэтому его сокет просто так
удалённо не пробросить.
Вот только отправку control message с передачей сокета я делал просто
скопировав пример из man-а FreeBSD, где полезная нагрузка явно не
передавалась. Сокет/файл передаются, всё ok. Но вот только если это
засунуть в poll(), то он бесконечно зацикливается: постоянно говорит что
из сокета есть что прочитать, но recvmsg() возвращает ноль. Пришлось
хотя бы один байт полезной нагрузки явно передать, для решения проблемы.
Как себя ведёт kqueue тут не пробовал -- задача достаточно проста чтобы
и просто poll()-ом (ради совместимости с GNU/Linux) обходиться.
[оставить комментарий]