Linux syscalls: PTRACE_O_TRACECLONE вызывает неопределенное зависание - PullRequest
1 голос
/ 28 мая 2020

У меня есть двоичный файл, из которого мне нужно перехватить определенный системный вызов - в данном случае unlinkat - и заставить его ничего не делать. У меня есть следующий код, который отлично работает для одного процесса; однако с добавлением PTRACE_O_TRACECLONE к параметрам ptrace после того, как трассируемый вызовет clone, вызов waitpid зависнет навсегда. Я выдергивал свои волосы в течение нескольких дней на разных частях inte rnet, до точки, где я проходил через источник strace, и фактически натянул strace, чтобы увидеть, что strace, который я натянул, отслеживает.

Вот источник - я удалил кое-что, чтобы сделать его как можно меньше для удобочитаемости. В основном я пишу Python, поэтому многое из этого было просто скопировано и вставлено из разных руководств, которые я нашел, и я в основном добавлял / удалял случайное дерьмо, пока g cc не давал мне столько предупреждений.

Основываясь на том, что я читал, я подозреваю, что проблема в том, чтобы подавать сигналы задействованным процессам и ждать SIGTRAP, у меня просто нет реальной интуиции, что делать на этом уровне.

1 Ответ

0 голосов
/ 01 июня 2020

Вместо этого в решении использовалось libseccomp.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <seccomp.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>

int do_child(int argc, char **argv)
{
    char *args[argc + 1];
    memcpy(args, argv, argc * sizeof(char *));
    args[argc] = NULL;

    return execvp(args[0], args);
}

int main(int argc, char **argv)
{
    if (argc < 2)
    {
        fprintf(stderr, "Usage: %s prog args\n", argv[0]);
        exit(1);
    }

    // Init the filter
    scmp_filter_ctx ctx;
    ctx = seccomp_init(SCMP_ACT_ALLOW); // default allow

    // setup basic whitelist
    seccomp_rule_add(ctx, SCMP_ACT_ERRNO(0), SCMP_SYS(unlinkat), 0);

    // build and load the filter
    seccomp_load(ctx);

    pid_t child = fork();
    if (child == 0)
    {
        return do_child(argc - 1, argv + 1);
    }

    return 0;
}
...