LINUX.ORG.RU

Короче сам разобрался. Ниже описываю минимальный рабочий код.

Библиотека libaudit предоставляет интерфейс добавления/удаления правил:

    int fd = audit_open();
    struct audit_rule_data *rule = new audit_rule_data();
    
    // Говорим за какой директорией будем следить.
    audit_add_watch_dir(AUDIT_DIR,
                        &rule,
                        "/etc");

    // Устанавливаем правило.
    audit_add_rule_data(fd,
                        rule,
                        AUDIT_FILTER_EXIT,
                        AUDIT_ALWAYS);

    // Либо удаляем правило.
    audit_delete_rule_data(fd,
                           rule,
                           AUDIT_FILTER_EXIT,
                           AUDIT_ALWAYS);


    audit_close(fd);

Чтобы повесить какое-то определенное событие и установить дополнительный фильтр нужно сделать что-то вроде этого:

    int fd = audit_open();

    // Например, ставим срабатывание на события open, close.
    audit_rule_syscallbyname_data(rule_new, "open");
    audit_rule_syscallbyname_data(rule_new, "close");
    
    // Задаем доп. фильтр, например, следим за пользователем с id=1000.
    char pair[] = "uid=1000";
    audit_rule_fieldpair_data(&rule_new, pair, AUDIT_FILTER_EXIT);
    
    // Устанавливаем правила.
    audit_add_rule_data(fd, rule_new, AUDIT_FILTER_EXIT, AUDIT_ALWAYS);

    audit_close(fd);

Для того, чтобы сделать исключение из правил нужно:


    // Говорим аудиту, что не будем следить за созданием директорий.
    audit_rule_syscallbyname_data(rule, "mkdir");
    char pair[] = "path=/etc";
    audit_rule_fieldpair_data(&rule,
                              pair,
                              AUDIT_FILTER_EXIT);
    audit_add_rule_data(fd,
                        rule,
                        AUDIT_FILTER_EXIT,
                        AUDIT_NEVER);

Для того, чтобы получать сообщения от аудита, делаем примерно следующее:


void monitoring(struct ev_loop *loop, struct ev_io *io, int revents)
{
    struct audit_reply reply;

    // Вычитываем что за событие пришло.
    audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0);

    if (reply.type != AUDIT_EOE &&
        reply.type != AUDIT_PROCTITLE &&
        reply.type != AUDIT_PATH)
    {
        // Получаем текст события.
        char *buf = new char[MAX_AUDIT_MESSAGE_LENGTH];

        snprintf(buf,
                 MAX_AUDIT_MESSAGE_LENGTH,
                 "Type=%s Message=%.*s",
                 audit_msg_type_to_name(reply.type),
                 reply.len,
                 reply.message);

        printf("EVENT: %s\n", buf);

    }
}

int main()
{
    // На чистом C отслеживание производим через библиотеку libev.
    // Можно также отслеживать, например, средствами Qt через QSocketNotifier.
    struct ev_io monitor;
    fd = audit_open();

    // Сообщаем аудиту id процесса нашего мониторинга.
    audit_set_pid(fd, getpid(), WAIT_YES);

    // Инициализируем аудит.
    loop = ev_default_loop(EVFLAG_NOENV);

    ev_io_init(&monitor, monitoring, fd, EV_READ);
    ev_io_start(loop, &monitor);

    // Зацикливаемся и ждем сообщения в monitoring()
    ev_loop(loop, 0);

    audit_close(fd);
    return 0;
}

toolazy4dat ()