LINUX.ORG.RU

Очистить состояние процесса без execve()

 


0

1

Допустим, у нас есть привилегированный процесс, и он хочет сделать что-то в контексте каких-то непривилегированных прав (и там и остаться). Для этого он переключает себе uid/gid или лезет в контейнер, не важно.

Тут нас подстерегает опасность: у привилегированного процесса в памяти могут находиться привилегированные данные (те, которые не положено знать обычным процессам), в том числе оставшиеся от когда-то давно free()-d блоков памяти (про explicit_bzero() и подобное тут не будем, это другая тема). Проблема в том, что как только процесс поставит себе права обычного юзера, этот самый обычный юзер может поймать его отладчиком и сдампить память.

Если у нас скрипт и переключаемся на юзера с помощью su, то такой проблемы не возникает: сначала скрипт (форкаясь) делает execve() в su, тот уже с чистой от важных данных памятью делает setuid() и прочее, и потом запускает полезную нагрузку непривилегированного юзера. Но неужели без execve() это никак не сделать? У него есть проблема: ему нужен бинарник в доступном на данный момент файловом пространстве, а если мы например в chroot-е, то там нашего бинарника уже может не быть, либо мы не можем полагаться на его подлинность. Как быть?

Лучше всего подошло бы что-то типа execve-сам-себя, но без указания на файл бинарника (через /proc/self/exe тоже нельзя, потому что в chroot-е его тоже может не быть). Если при этом ещё и можно было передать не только набор текстовых строк, а указать диапазон адресов памяти которые не надо чистить, и точку входа, отличную от main() - вообще прекрасно.

★★★★★

Последнее исправление: firkax (всего исправлений: 1)

Подписался на ответы, хотя сдаётся мне, что «мсье большой оригинал» (c). :)

указать диапазон адресов памяти которые не надо чистить

Ну уж это ты совсем загнул, поскольку (1) PIC; (2) вдруг тебе приспичит несколько раз сделать malloc(1GB), и указать диапазон адресов внутри последнего выделенного блока.

pr849
()
Ответ на: комментарий от pr849

Не вижу проблемы ни в PIC ни в диапазоне из последнего malloc'а (если он выровнен по границам страниц). Да и пусть даже будет ограничение что он должен быть выделен через mmap() (чтобы не думать над тем как он будет взаимодействовать с sbrk в будущем процессе).

firkax ★★★★★
() автор топика

провел тест, через gdb dump binary memory [heap] для родителя и потомка, то что они разные по размеру и приватных для себя данных не увидел, ядро старое 4.14

anonymous2 ★★★★★
()
Последнее исправление: anonymous2 (всего исправлений: 1)
Ответ на: комментарий от anonymous2

sudo тут ни при чём. В скриптах проблемы нет, я ж написал уже почему. Вопрос про её решение без запуска доп. прог в рамках одного запущеного бинарника.

firkax ★★★★★
() автор топика
Ответ на: комментарий от anonymous2

Мешает то что ввиду сложности работы как компиляторов так и различных библиотек, а так же кода собственно программы, ты не можешь гарантированно знать в каких байтах памяти могло что-то от них записаться и остаться. А секретны по-хорошему все данные о работе рутовых процессов, кроме тех, которые эти процессы сами кому-то сообщают через свои апи, и тех, которые статически прописаны в общедоступных бинарниках.

Но тема не об этом, прочти наконец её первое сообщение (ну или можешь не читать) и хватит флудить всякими глупостями.

firkax ★★★★★
() автор топика
Ответ на: комментарий от firkax

проблема надумана, нехотите чистить мусор - запускайте под системным пользователем у которого есть права делать что вам нужно в контексте не доверенного пользователя

anonymous2 ★★★★★
()
Последнее исправление: anonymous2 (всего исправлений: 3)

Коротко - никак. Форк был спроектирован для другого. Но можно посоветовать форкаться заранее, до того как в памяти появятся чувствительные данные. Заслипать свою молодую копию, и потом размножать уже её, по необходимости.

raspopov
()
Ответ на: комментарий от raspopov

Ух ты, как хитро, я б не догадался. Хотя это и выглядит костыльно, и есть очевидный минус что эту копию надо постоянно держать параллельно себе (и при «нырянии» в сомнительные контексты там опять делать ещё одну копию если придётся повторить процедуру), но зато вроде бы решает все остальные проблемы. И данные этой копии передать можно любым способом на выбор, включая бесплатное shared memory. Только надо ей на старте ещё почистить аргументы и env. Ну а с дескрипторами (а ещё терминалом и cwd) уже штатная процедура по избавлению от ненужных в момент выполнения задачи.

Ну, с другой стороны, это можно считать закешированным бинарником для запуска.

firkax ★★★★★
() автор топика