2016-06-29 2 views
3

Мне было интересно, есть ли способ захвата (другими словами, наблюдать) vDSO-звонки, такие как gettimeofday в strace.Захват vDSO в strace

Также существует способ выполнить двоичный код без загрузки linux-vdso.so.1 (флаг или переменная env)?

И, наконец, что делать, если я пишу программу, которая удаляет адрес linux-vdso.so.1 из вспомогательного вектора, а затем execve моей программой? Кто-нибудь когда-нибудь пробовал это?

ответ

4

Вы можете записывать вызовы на системные вызовы, которые были реализованы через vDSO, используя ltrace вместо strace. Это связано с тем, что вызовы системных вызовов, реализованные через vDSO, работают иначе, чем «обычные» системные вызовы, а метод strace использует для отслеживания системных вызовов, не работает с системными вызовами, реализованными в VDSO. Чтобы узнать больше о том, как работает strace, ознакомьтесь с this blog post I wrote about strace. И, чтобы узнать больше о том, как работает ltrace, ознакомьтесь с this other blog post I wrote about ltrace.

Нет, невозможно выполнить двоичный код без загрузки linux-vdso.so.1. По крайней мере, не в моей версии libc на Ubuntu точной. Конечно, возможно, что более новые версии libc/eglibc/etc добавили это как функцию, но это кажется очень маловероятным. См. Следующий ответ, почему.

Если вы удалите адрес из вспомогательного вектора, ваш двоичный файл, скорее всего, сработает. У libc есть piece of code, который сначала попытается пройти объект ELF vDSO, и если это не удастся, он вернется к жестко закодированному адресу vsyscall. Единственный способ избежать этого - собрать компиляцию glibc с отключенным vDSO.

Существует еще одно обходное решение, если вы действительно не хотите использовать vDSO. Вы можете попробовать использовать glibc's syscall function и передать номер в системном номере gettimeofday. Это заставит glibc вызвать gettimeofday через ядро ​​вместо vDSO.

Я включил образец программы, иллюстрирующий это. Вы можете узнать больше о том, как работают системные вызовы, читая мои syscall blog post.

#include <sys/time.h> 
#include <stdio.h> 

#define _GNU_SOURCE 
#include <unistd.h> 
#include <sys/syscall.h> 

int 
main(int argc, char *argv[]) { 
    struct timeval tv; 
    syscall(SYS_gettimeofday, &tv); 

    return 0; 
} 

Compile с gcc -o test test.c и Трассирование с strace -ttTf ./test 2>&1 | grep gettimeofday:

09:57:32.651876 gettimeofday({1467305852, 651888}, {420, 140735905220705}) = 0 <0.000006>