UNIX ptrace()阻止子系统调用

时间:2011-01-16 11:34:37

标签: linux unix ptrace

我正在为编程竞赛开发一名评分员。基本上,评分者必须在“孤立”过程中运行解决方案程序。所以,我希望解决方案不要调用任何危害系统调用(例如system(),fork()等)。我可以使用ptrace()来实现吗?

2 个答案:

答案 0 :(得分:1)

我认为有两种可能的解决方案:

  1. 使用LD_PRELOAD机制创建“shim”以替换您要停止的系统调用。
  2. 使用setrlimit()来限制调用进程可以执行的操作。不幸的是,这些限制似乎是每个用户,而不是每个进程的基础,这使得计算正确的值设置非常困难。
  3. 编辑:我有第一个选项,并在下面包含了必要的代码。使用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)
    

    生成文件:

    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;
    }
    

答案 1 :(得分:0)

是的,你可以使用ptrace()来阻止使用PTRACE_SYSCALL选项的某些系统调用。 这是一个使用此功能的项目:

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

如果您只针对Linux,我会建议使用seccomp,这是一种更快的技术,可以将某些系统调用白名单/黑名单或限制其参数。

另一种选择是Google的Native Client。 此项目提供应用程序沙箱的跨平台实现。

您还可以在容器(如docker或LXC)中以非特权用户身份运行应用程序,以限制损坏。

单独使用LD_PRELOAD是不安全的,因为可执行文件可能带有自己的系统调用实现并绕过底层的libc。