Что я хочу сделать, это сделать системный вызов и заставить ядро действовать так, как если бы это был другой процесс, делающий вызов. Вы могли бы подумать об этом, как о выдаче другого процесса. Я знаю, что могу использовать код программы, используя ptrace, но это не очень элегантно и, вероятно, требует настройки для работы с любым процессом, который я делаю. Плюс то, что я прошу, должно быть возможным для ядра без необходимости касаться памяти или процесса процесса другого процесса, если, конечно, эффект от системного вызова, который я выполняю, не вызвал бы этого.Есть ли системный вызов Linux, который позволяет мне делать системные вызовы в контексте другого процесса?
Способ, которым я собираюсь работать, будет иметь (привилегированный) системный вызов (назовем его setepid
, для «set effective PID»), который принимает PID в качестве аргумента. После setepid
любые будущие системные вызовы, выполненные этим процессом (или, возможно, только этот поток), будут вести себя так, как если бы это был указанный процесс, вызывающий системный вызов. Исключением является сам вызов setepid
, который может быть использован для восстановления исходного контекста или иным образом нацелен на другой процесс.
Например, следующий код может быть использован для перенаправления стандартного вывода уже запущенного процесс (PID 1234 в данном примере) в файл output.txt
, расположенный в процессе 1234 в текущем рабочем каталоге:
setepid(1234); /* perform following system calls on process 1234 */
int fd = open("output.txt", O_WRONLY|O_CREAT|O_TRUNC);
if (fd > 0) {
dup2(fd, 1);
close(fd);
}
setepid(0); /* done acting as 1234, restore original context */
Возможна одна из возможных проблем: строка константы "output.txt"
, которая передается как указатель. В зависимости от того, как реализован setepid
, возможно, по необходимости он может обрабатывать этот указатель как адрес в памяти процесса 1234. Как правило, она даже не имеет смысла статически выделить память (в том числе и для постоянной) в другом процессе во время компиляции, обходящий, что потребовало бы что-то уродливое, как это вместо:
setepid(1234);
char *buf = mmap(NULL, 12, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
setepid(0);
const char *str = "output.txt\0"; /* extra byte to make it a multiple of 4 */
/* Disclaimer: I'm not sure if I'm using ptrace correctly, but you get the idea. */
ptrace(PTRACE_ATTACH, 1234, NULL, NULL);
ptrace(PTRACE_POKEDATA, 1234, buf, *(void**)str);
ptrace(PTRACE_POKEDATA, 1234, buf+4, *(void**)(str+4));
ptrace(PTRACE_POKEDATA, 1234, buf+8, *(void**)(str+8));
ptrace(PTRACE_DETACH, 1234, NULL, NULL);
setepid(1234);
int fd = open(buf, O_WRONLY|O_CREAT|O_TRUNC);
if (fd > 0) {
dup2(fd, 1);
close(fd);
}
setepid(0);
Я предполагаю, что такая механизма не существует, хотя я надеюсь, что ошибаюсь. Если мое предположение верно, есть ли какие-либо проблемы, которые помешали бы этому добавить в будущую версию Linux? Было бы просто (или даже возможно) реализовать это в модуле ядра? Похоже, это был бы опасный, но мощный и потенциально полезный инструмент.
Имеет смысл. Я надеялся поэкспериментировать с этим, но спасибо. – flarn2006