Pracuję nad biblioteką śledzenia pamięci, w której używamy mprotect
aby usunąć dostęp do większości pamięci programu i obsługi SIGSEGV, aby przywrócić dostęp do poszczególnych stron, gdy program ich dotyka. To działa świetnie przez większość czasu.
Moim problemem jest to, że gdy program wywołuje wywołanie systemowe (powiedzmy read
) W przypadku pamięci, w której moja biblioteka zaznaczyła brak dostępu, wywołanie systemowe po prostu zwraca -1 i ustawia errno
do EFAULT
. Zmienia to zachowanie programów testowanych w dziwny sposób. Chciałbym móc przywrócić dostęp do każdej strony pamięci przekazanej do wywołania systemowego, zanim rzeczywiście trafi do jądra.
Moje obecne podejście polega na stworzeniu opakowania dlakażde wywołanie systemowe, które dotyka pamięci. Każde opakowanie dotknęłoby całej podanej pamięci przed przekazaniem go do rzeczywistego wywołania systemowego. Wygląda na to, że będzie działać dla połączeń wykonywanych bezpośrednio z programu, ale nie dla połączeń wykonywanych przez libc (na przykład, fread
zadzwonię read
bezpośrednio bez używania mojego opakowania). Czy jest jakieś lepsze podejście? Jak można uzyskać takie zachowanie?
Odpowiedzi:
5 dla odpowiedzi № 1Możesz użyć ptrace(2)
osiągnąć to. Umożliwia monitorowanie procesu i otrzymywanie informacji o wystąpieniu określonych zdarzeń. Dla swoich celów spójrz na PTRACE_SYSCALL
co pozwala zatrzymać proces po wejściu i wyjściu z systemu.
Musisz jednak zmienić część swojej infrastruktury śledzenia pamięci ptrace
działa tak, że proces nadrzędny monitoruje aproces potomny, a jeśli chodzi o dziecko, nie ma widoczności, kiedy występuje zdarzenie monitorowane. Powiedziawszy to, powinieneś być w stanie zrobić coś na wzór:
- Instalator śledzi rodzica i dziecko, monitoruje (przynajmniej)
PTRACE_SYSCALL
. - Proces potomny wykonuje wywołanie systemowe; a rodzic zostanie powiadomiony.
- Parent zapisuje żądaną informację o wywołaniu systemu; i używa
PTRACE_GETREGS
iPTRACE_SETREGS
aby zmienić stan dziecka, zamiast wywoływać wywołanie systemowe; proces potomny wywołuje procedurę „zabezpieczyć pamięć”. - Dziecko chroni pamięć „s”; potem podnosi
SIGUSR1
lub podobny, aby powiedzieć kontrolującemu rodzicowi, że praca pamięci jest zakończona. - Połowy rodziców
SIGUSR
, używaPTRACE_SETREGS
przywrócić poprzednio zapisane informacje o wywołaniu i wznowić dziecko. - Dziecko wznawia i wykonuje wywołanie systemowe.