UNIX ptrace () блокирует системные вызовы ребенка - PullRequest
3 голосов
/ 16 января 2011

Разрабатываю грейдер для соревнований по программированию.По сути, грейдер должен запустить программу решения в «изолированном» процессе.Итак, я хотел бы, чтобы решение не вызывало какие-либо вредные системные вызовы (такие как system (), fork () и т. Д.).Могу ли я использовать ptrace () для этого?

Ответы [ 2 ]

1 голос
/ 16 января 2011

Я думаю, что есть 2 возможных решения:

  1. Использование механизма LD_PRELOAD для создания 'shim' для замены системных вызовов, которые вы хотите остановить.
  2. Используйте setrlimit () для ограничения возможностей вызывающего процесса. К сожалению, эти ограничения, похоже, основаны на пользователях, а не на процессах, что делает вычисление правильного значения для установки очень трудным.

РЕДАКТИРОВАТЬ: у меня работает первый вариант, и включил необходимый код ниже. Создайте двоичные файлы, используя make all, а затем протестируйте с помощью make runtests:

$ make all
gcc -fPIC -shared -Wl,-soname,libmy.so.1 -o libmy.so.1.0 lib.c
ln -sf libmy.so.1.0 libmy.so.1
ln -sf libmy.so.1 libmy.so
gcc -o test test.c

$ make runtests
Without LD_PRELOAD:
./test
in child: retval=9273
in parent: retval=0
With LD_PRELOAD:
LD_PRELOAD=./libmy.so ./test
libmy.so fork!
fork error: error=Operation not permitted (1)

Makefile:

all: libs test

runtests:
    @echo Without LD_PRELOAD:
    ./test
    @echo With LD_PRELOAD:
    LD_PRELOAD=./libmy.so ./test


libs: lib.c
    gcc -fPIC -shared -Wl,-soname,libmy.so.1 -o libmy.so.1.0 lib.c
    ln -sf libmy.so.1.0 libmy.so.1
    ln -sf libmy.so.1 libmy.so

test: test.c
    gcc -o test test.c

clean:
    rm -f test libmy.so.1.0 libmy.so.1 libmy.so lib.o

lib.c:

#include <stdio.h>
#include <unistd.h>
#include <errno.h>

pid_t fork()
{
    printf("libmy.so fork!\n");
    errno = EPERM;
    return (pid_t)-1;
}

test.c:

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main(int argc, char **argv)
{
    int retval = fork();
    if (retval == 0)
        printf("in parent: retval=%d\n", retval);
    else if (retval > 0)
        printf("in child: retval=%d\n", retval);
    else
        printf("fork error: error=%s (%d)\n", strerror(errno), errno);
    return 0;
}
0 голосов
/ 02 июня 2016

Да, вы можете использовать ptrace () для блокировки определенных системных вызовов, используя опцию PTRACE_SYSCALL.Вот проект, использующий эту функцию:

https://github.com/t00sh/p-sandbox/blob/master/p-sandbox.c

Если вы ориентируетесь только на Linux, я бы предложил вместо этого использовать seccomp, который является более быстрым методом, для внесения в белый / черный список определенных системных вызовов или ограниченияих аргументы.

Альтернативой может быть собственный клиент Google .В этих проектах реализована межплатформенная реализация изолированной программной среды приложения.

Вы также можете запускать приложения как непривилегированный пользователь в контейнере, таком как Docker или LXC, чтобы ограничить ущерб.

Использование *Один только 1014 * небезопасен, так как исполняемый файл может поставляться со своей собственной реализацией системного вызова и обходить базовый libc.

...