LINUX.ORG.RU

Ограничение прав дочернего процесса

 , ,


0

4

Здравствуйте. Ситуация: есть программа-сервер на C, которая запускает программы-клиенты (не только бинарники, но и java апплеты и python скрипты) и общается с ними с помощью каналов (перенаправив stdin/stdout). Работает он по такой схеме: запускает все клиенты, приостанавливает их; по очереди восстанавливает, обменивается сообщениями и приостанавливает опять. Клиенты уже ограничены в памяти и времени отклика. У меня есть непосредственный доступ к исходному коду клиентов (я их обрабатываю/компилирую перед запуском сервера).

Проблема: не дать клиенту выполнить потенциально опасный код (fork, exec, write, работа с файловой системой, сетью, потоками и т.д., тоесть [практически] все системные вызовы). Если остановить клиента перед системным вызовом, сервер сам его завершит, поскольку клиент не сможет вовремя ответить. Я пересмотрел исходный код ejudge, там используется ptrace(0x4281, 0, 0, 0), но нужно устанавливать патч ядра. Как можно организовать подобную защиту?

первое, что приходит на ум - нужно ioperm_set (в glibc нет, вызывается через syscall) и поиграться с capabilities (man libcap)

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

Sandbox через ptrace.
Создать список разрешённых вызовов, иное запретить.
Думаю, есть готовые варианты.

mittorn ★★★★★
()

lxc, docker.

anonymous
()

Самое извращенное здесь, имхо, это вырезать/заменить все «опасные» вызовы на свои в своих же компиляторах/интерпретаторах. Да, потребуется мастерские скил, зато не придется мириться с тем, что надо использовать страшное и сложное в настройке ядро (читай, юзай виртуалки + selinux/docker-шмокер и не **** людям мозг, никто не поможет тебе сделать лучше ideone за бесплатно).

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

к ideone система вообще никакого отношения не имеет, т.к. я пишу RPG с управлением героем с помощью кода. если программа пользователя будет использовать запрещенные вызовы, я должен не сказать аяяй и продолжить выполнение, а просто завершить ее.

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

упс, пардон муа, напутал вчера - не ioperm_set, а ioprio_set:

#include <sys/syscall.h>

//  кучка дефайнов, спертая, например, из "linux-4.2.7/include/linux/ioprio.h"
enum {
    IOPRIO_CLASS_NONE,
    IOPRIO_CLASS_RT,
    IOPRIO_CLASS_BE,
    IOPRIO_CLASS_IDLE,
};   
enum {
    IOPRIO_WHO_PROCESS = 1, 
    IOPRIO_WHO_PGRP,
    IOPRIO_WHO_USER,
};   
#define IOPRIO_CLASS_SHIFT (13)
#define IOPRIO_PRIO_MASK    ((1UL << IOPRIO_CLASS_SHIFT) - 1)
#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT)
#define IOPRIO_PRIO_DATA(mask)  ((mask) & IOPRIO_PRIO_MASK)
#define IOPRIO_PRIO_VALUE(class, data)  (((class) << IOPRIO_CLASS_SHIFT) | data)

// и сам вызов (тут выдается текущему процессу максимальный IO приоритет)
err = syscall(SYS_ioprio_set, IOPRIO_WHO_PROCESS, 0, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_RT,7));

но Вам лучше смотреть в сторону capabilities, там не все, но хотя бы часть желаемого Вами ограничить можно, да и то, это будет меньше, чем возможности функции от beastie

_или_ воспользоваться вариантом от mittorn

metawishmaster ★★★★★
()
Последнее исправление: metawishmaster (всего исправлений: 2)
Ответ на: комментарий от val-amart

Если из systrace (ныне покойный) сделали selinux, то есть ненулевой шанс, что когда-нибудь и это подтянется.

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

Нашел вполне читаемый вариант песочницы на ptrace. Но тут начинается самое веселье. Для систем типа ejudge или ideone подобный подход более чем применим: перенаправялем потоки ввода/вывода, при старте даем нужные данные, по завершению забираем результат, в процессе выполнения просто вызываем wait и смотрим сигнал. Я же общаюсь с дочерними процессами хоть и по очереди, но многократно, так что просто сидеть и ждать waitpid - далеко не лучший способ (сейчас на один цикл 10 раз вызывается peekPipe с интервалом в 10мс). Есть идеи как алгоритмически реализовать песочницу для этого случая?

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

тоесть можно сделать два потока, один для общения, второй для песочницы. Я так понимаю, что мои сигналы об остановке и возобновлении процесса тоже будут отображаться в ptrace?

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

выяснился один не очень приятный момент. Если делать песочицу в одном потоке - все работает нормально. Но если fork и exec выполнить в основном потоке, а ptrace в дополнительном - ptrace генерирует ошибку ESRCH. Есть предположения, из-за чего такое могло случиться и как с ним бороться?

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

нет. В потоке не работает, даже если сделать один шаг трассировки в основном потоке

sungmaster
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.