Подтвердить что ты не робот

Как я могу перехватить вызовы linux sys?

Помимо трюка LD_PRELOAD и модулей ядра Linux, которые заменяют определенный syscall одним предоставленным вами, есть ли возможность перехвата syscall (например, открыта), чтобы он сначала проходил вашу функцию, прежде чем он достигнет фактический открытый?

4b9b3361

Ответ 2

Почему вы/не хотите использовать трюк LD_PRELOAD?

Пример кода здесь:

/*
 * File: soft_atimes.c
 * Author: D.J. Capelis
 *
 * Compile:
 * gcc -fPIC -c -o soft_atimes.o soft_atimes.c
 * gcc -shared -o soft_atimes.so soft_atimes.o -ldl
 *
 * Use:
 * LD_PRELOAD="./soft_atimes.so" command
 *
 * Copyright 2007 Regents of the University of California
 */

#define _GNU_SOURCE
#include <dlfcn.h>
#define _FCNTL_H
#include <bits/fcntl.h>

extern int errorno;

int (*_open)(const char * pathname, int flags, ...);
int (*_open64)(const char * pathname, int flags, ...);

int open(const char * pathname, int flags, mode_t mode)
{
    _open = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open");
    if(flags & O_CREAT)
        return _open(pathname, flags | O_NOATIME, mode);
    else
        return _open(pathname, flags | O_NOATIME, 0);
}

int open64(const char * pathname, int flags, mode_t mode)
{
    _open64 = (int (*)(const char * pathname, int flags, ...)) dlsym(RTLD_NEXT, "open64");
    if(flags & O_CREAT)
        return _open64(pathname, flags | O_NOATIME, mode);
    else
        return _open64(pathname, flags | O_NOATIME, 0);
}

Из того, что я понимаю... это в значительной степени трюк LD_PRELOAD или модуль ядра. Там не так много среднего уровня, если вы не хотите запускать его под эмулятором, который может ухватиться за вашу функцию или перезаписать код в реальном двоичном файле, чтобы захватить вашу функцию.

Предполагая, что вы не можете изменять программу и не можете (или не хотите) модифицировать ядро, подход LD_PRELOAD является лучшим, если ваше приложение является довольно стандартным и на самом деле не является тем, что злонамеренно пытается чтобы пройти мимо вашего перехвата. (В этом случае вам понадобится один из других методов.)

Ответ 3

Valgrind можно использовать для перехвата любого вызова функции. Если вам нужно перехватить системный вызов в готовом продукте, это будет бесполезно. Однако, если вы пытаетесь перехватить во время разработки, это может быть очень полезно. Я часто использовал этот метод для перехвата функций хэширования, чтобы я мог контролировать возвращенный хэш для целей тестирования.

Если вы не знаете, Valgrind в основном используется для обнаружения утечек памяти и других ошибок, связанных с памятью. Но основная технология - это в основном эмулятор x86. Он эмулирует вашу программу и перехватывает вызовы в malloc/free и т.д. Хорошо, вам не нужно перекомпилировать, чтобы использовать его.

У Valgrind есть функция, которую они называют Function Wrapping, которая используется для управления перехватом функций. Подробнее см. Раздел 3.2 Руководство Valgrind. Вы можете настроить перенос функций для любой функции. После того как вызов перехвачен, вызывается альтернативная функция, которую вы предоставляете.

Ответ 4

Некоторые приложения могут обмануть strace/ptrace, чтобы не запускаться, поэтому единственный реальный вариант, который у меня был, - использование systemtap

Systemtap может перехватывать кучу системных вызовов, если это необходимо из-за его сопоставления с дикими картами. Systemtap - это не C, а отдельный язык. В базовом режиме системная карта должна помешать вам делать глупые вещи, но она также может работать в "экспертном режиме", которая возвращается, чтобы позволить разработчику использовать C, если это необходимо.

Это не требует, чтобы вы исправляли свое ядро ​​(или, по крайней мере, не должны), и как только модуль был скомпилирован, вы можете скопировать его из окна тестирования/разработки и вставить его (через insmod) в производственную систему.

Мне еще предстоит найти приложение linux, которое нашло способ обойти/избежать попадания в systemtap.

Ответ 5

Если вы просто хотите посмотреть, что было открыто, вы хотите посмотреть функцию ptrace() или исходный код утилиты командной строки. Если вы действительно хотите перехватить вызов, возможно, чтобы он сделал что-то еще, я думаю, что перечисленные вами опции - LD_PRELOAD или модуль ядра - являются вашими единственными параметрами.

Ответ 6

У меня нет синтаксиса, чтобы сделать это изящно с помощью LKM, но эта статья дает хороший обзор того, что вам нужно сделать: http://www.linuxjournal.com/article/4378

Вы также можете просто исправить функцию sys_open. Он начинается в строке 1084 файла /open.c с Linux-2.6.26.

Вы также можете увидеть, не можете ли вы использовать inotify, systemtap или SELinux, чтобы сделать все это для вас, без необходимости создавать новую систему.

Ответ 7

Если вы просто хотите сделать это для целей отладки, посмотрите на strace, который построен в верхней части системного вызова ptrace (2), который позволяет вам подключать код при выполнении системного вызова. См. Раздел PTRACE_SYSCALL на странице руководства.

Ответ 8

Похоже, вам нужен аудит.

Auditd позволяет осуществлять глобальное отслеживание всех системных вызовов или доступа к файлам с протоколированием. Вы можете установить ключи для определенных событий, которые вас интересуют.