Nie jest to możliwe, ponieważ tablica wywołań systemowych (wywoływana sys_call_table
) jest tablicą rozmiarów statycznych. A jego rozmiar jest określany w czasie kompilacji na podstawie liczby zarejestrowanych wywołań systemowych. Oznacza to, że nie ma miejsca na kolejne.
Możesz sprawdzić implementację na przykład architektury x86 w arch/x86/kernel/syscall_64.c
pliku, w którym sys_call_table
jest zdefiniowany. Jego rozmiar jest dokładnie __NR_syscall_max+1
. __NR_syscall_max
jest zdefiniowane arch/x86/kernel/asm-offsets_64.c
jako sizeof(syscalls) - 1
(jest to liczba ostatniego wywołania syscall
systemowego ), gdzie jest tabela ze wszystkimi wywołaniami systemowymi.
Jednym z możliwych rozwiązań jest ponowne użycie części istniejącego (lub przestarzałego, jeśli twoja architektura go posiada, patrz sys_setaltroot
na przykład) numer systemowy z twoim, ponieważ nie będzie to wymagało więcej miejsca w pamięci. Niektóre architektury mogą mieć również dziury w tabeli syscall (np. 64-bitowa wersja x86), więc możesz również z tego korzystać.
Możesz użyć tej techniki, jeśli tworzysz nowe połączenie systemowe i chcesz uniknąć ponownego uruchamiania podczas eksperymentów. Będziesz musiał zdefiniować nowe wywołanie systemowe, znaleźć istniejący wpis w tabeli syscall, a następnie zastąpić go z modułu.
Wykonanie tego z modułu jądra nie jest trywialne, ponieważ jądro nie eksportuje sys_call_table
do modułów od wersji 2.6 (ostatnia wersja jądra, z której ten symbol został wyeksportowany, to była 2.5.41
).
Jednym ze sposobów obejścia tego jest zmiana jądra w celu wyeksportowania sys_call_table
symbolu do modułów. Aby to zrobić, musisz dodać następujące dwa wiersze kernel/kallsyms.c
( nie rób tego na maszynach produkcyjnych ):
extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);
Inną techniką jest dynamiczne znajdowanie tabeli syscall. Iterujesz po pamięci jądra, porównując każde słowo ze wskaźnikiem ze znaną funkcją wywołania systemowego. Ponieważ znasz przesunięcie tego znanego połączenia systemowego w tabeli, możesz obliczyć początkowy adres tabeli.