Захват ВДСО в страсе
Мне было интересно, есть ли способ перехвата (другими словами, наблюдения) вызовов VDSO, как gettimeofday
в strace
,
Кроме того, есть ли способ выполнить двоичный файл без загрузки linux-vdso.so.1
(флаг или переменная env)?
И, наконец, что, если я напишу программу, которая удаляет linux-vdso.so.1
адрес из вспомогательного вектора, а затем execve
моя программа? Кто-нибудь когда-нибудь пробовал это?
1 ответ
Вы можете перехватывать вызовы системных вызовов, которые были реализованы через vDSO, используя ltrace
вместо strace
, Это связано с тем, что вызовы системных вызовов, реализованные через vDSO, работают не так, как "обычные" системные вызовы и метод. strace
используется для отслеживания системных вызовов, не работает с системными вызовами, реализованными в vDSO. Чтобы узнать больше о том, как strace
работает, посмотрите этот пост в блоге, который я написал о strace. И, чтобы узнать больше о том, как ltrace
работает, проверьте этот другой пост в блоге, который я написал о ltrace.
Нет, невозможно выполнить бинарный файл без загрузки linux-vdso.so.1
, По крайней мере, не в моей версии libc на Ubuntu точно. Конечно, возможно, что более новые версии libc / eglibc / etc добавили это как функцию, но это кажется очень маловероятным. Смотрите следующий ответ, почему.
Если вы удалите адрес из вспомогательного вектора, ваш двоичный файл, вероятно, потерпит крах. В libc есть фрагмент кода, который сначала попытается обойти объект ELDS vDSO, а в случае неудачи обратится к жестко закодированному адресу vsyscall. Единственный способ избежать этого - это если вы скомпилировали glibc с отключенным vDSO.
Существует другой обходной путь, хотя, если вы действительно, действительно не хотите использовать vDSO. Вы можете попробовать использовать Glibc syscall
функция и передать номер системного вызова для gettimeofday
, Это заставит glibc позвонить gettimeofday
через ядро вместо vDSO.
Ниже я привел пример программы, иллюстрирующей это. Вы можете узнать больше о том, как работают системные вызовы, прочитав мой пост в системном блоге.
#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;
}
Компилировать с gcc -o test test.c
и связать с strace -ttTf ./test 2>&1 | grep gettimeofday
:
09:57:32.651876 gettimeofday({1467305852, 651888}, {420, 140735905220705}) = 0 <0.000006>