Pracuję nad projektem, w którym muszę podłączyć 80% -90% funkcji wywołania systemowego na OSX (10.10.5). Robię to z rozszerzenia jądra. Ponieważ muszę (nie) przechwytywać wiele funkcji, chcę zapisać oryginalną funkcję jądra w tablicy wskaźników funkcji, tak, żebym mógł szybko przejrzeć tablicę, aby przywrócić pierwotną funkcję po odhaczeniu.Przechowywanie funkcji SYSCALL w tablicy wskaźników funkcji
int (*kern_open)(struct proc *, struct open_args *, int *);
int mon_open(struct proc *p, struct open_args *uap, int *retval) {
kern_open = sysent[SYS_open].sy_call;
sysent[SYS_open].sy_call = mon_open;
działa ta funkcja kern_open służy do przechowywania pierwotnej funkcji jądra, który nazywa po wywołania systemowego. mon_open jest moją funkcją zahaczania.
Co chcę osiągnąć, to co następuje; tak, że po odhaczeniu mogę po prostu wykonać iterację w tablicy KernSysCall i przywrócić funkcje.
// global array of function pointers that all have the same func def.
static int (*KernSysCall[SYS_MAXSYSCALL])(struct proc *, struct args *, int *);
KernSysCall[SYS_open] = sysent[SYS_open].sy_call;
sysent[SYS_open].sy_call = mon_open;
przywracanie: sysent[SYS_open].sy_call = KernSysCall[SYS_open];
Jednak przechowywanie pierwotną funkcję jądra wewnątrz tablicy wskaźników funkcji powoduje paniki jądra. Nie udało mi się jeszcze dołączyć lldb z powodu błędu error: KDP_REATTACH failed
. Mam nadzieję, że ktoś wie, co powoduje panikę jądra.
Poniżej znajduje się dziennik stanu paniki jądra.
Anonymous UUID: 052D64D2-A43C-99F8-D221-B591991E54AF
Wed Nov 11 12:55:06 2015
*** Panic Report ***
panic(cpu 0 caller 0xffffff80093f0024): Kernel trap at 0x0000000000000000, type 14=page fault, registers:
CR0: 0x0000000080010033, CR2: 0x0000000000000000, CR3: 0x00000000769bb018, CR4: 0x00000000001606e0
RAX: 0x0000000000000000, RBX: 0xffffff80115e3fc0, RCX: 0x0000000000000001, RDX: 0xffffff80115e3fc0
RSP: 0xffffff8068dabaf8, RBP: 0xffffff8068dabf50, RSI: 0xffffff80115e3f80, RDI: 0xffffff8010059cf0
R8: 0xffffff7f8afaccdf, R9: 0xffffff8009ae2a18, R10: 0xffffff8009939740, R11: 0x0000000000000000
R12: 0xffffff8010059cf0, R13: 0x0000000000000005, R14: 0xffffff80115e3f80, R15: 0xffffff801188b480
RFL: 0x0000000000010282, RIP: 0x0000000000000000, CS: 0x0000000000000008, SS: 0x0000000000000010
Fault CR2: 0x0000000000000000, Error code: 0x0000000000000010, Fault CPU: 0x0 VMM
Backtrace (CPU 0), Frame : Return Address
0xffffff8068dab790 : 0xffffff80092e4ed1 mach_kernel : _panic + 0xd1
0xffffff8068dab810 : 0xffffff80093f0024 mach_kernel : _kernel_trap + 0x664
0xffffff8068dab9e0 : 0xffffff800940de53 mach_kernel : trap_from_kernel + 0x26
0xffffff8068daba00 : 0x0
0xffffff8068dabf50 : 0xffffff800982c0c1 mach_kernel : _unix_syscall64 + 0x2f1
0xffffff8068dabfb0 : 0xffffff800940e656 mach_kernel : _hndl_unix_scall64 + 0x16
BSD process name corresponding to current thread: xpcproxy
Boot args: debug=0x14e kext-dev-mode=1 -v keepsyms=1 kmem=1
Mac OS version:
14F27
Kernel version:
Darwin Kernel Version 14.5.0: Wed Jul 29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/DEVELOPMENT_X86_64
Kernel UUID: C75BDFDD-9F27-3694-BB80-73CF991C13D8
Kernel slide: 0x0000000009000000
Kernel text base: 0xffffff8009200000
__HIB text base: 0xffffff8009100000
System model name: VMware7,1 (Mac-66F35F19FE2A0D05)
System uptime in nanoseconds: 251264993940
last loaded kext at 249789197520: my.kext 1 (addr 0xffffff7f8afa9000, size 57344)
last unloaded kext at 116769666233: com.apple.driver.AppleFileSystemDriver 3.0.1 (addr 0xffffff7f8aed3000, size 16384)
loaded kexts:
my.kext 1
[more kexts here]
Na żądanie kodu dla mon_open():
int
mon_open(struct proc *p, struct open_args *uap, int *r) {
int error;
char processname[MAXCOMLEN+1];
char intercepted_path[MAXPATHLEN];
pid_t pid = proc_pid(p);
proc_name(pid, processname, sizeof(processname));
size_t dummy = 0;
error = copyinstr((void *)uap->path, (void *)intercepted_path, MAXPATHLEN, &dummy);
if (!error) {
printf("[MYKEXT] open called with path: %s, PID: %d, processname: %s\n", intercepted_path, pid, processname);
}
return kern_open(p, uap, r);
}
Dziękuję bardzo z góry!
Dość dobrze napisane pytanie! Jesteś pewien, że to linia 'KernSysCall [SYS_open] = sysent [SYS_open] .sy_call;' która powoduje panikę? (Zakładam, że '[SYS_open]' w pytaniu miało być 'sysent [SYS_open]') – immibis
Dziękuję. To jest poprawne. Jestem prawie w 100% pewien. Deklaracja tablicy statycznej nie powoduje paniki. Wykonywanie tej samej operacji macierzowej z prymitywami (np. Int) nie wywołuje paniki. Dopiero gdy przypiszę 'KernSysCall [SYS_open] = sysent [SYS_open] .sy_call;' Reszta jest prawie taka sama jak brzydkie rozwiązanie "bez tablicy". – Joseph
Zauważ, że DTrace zmienia także sy_call różnych wpisów sysent, więc jeśli cokolwiek w twoim systemie używa DTrace, to i twój hak może nadepnąć na palce u nóg. Czy to się rozbija * rozładowując * twój kext, czy odpinasz bez rozładowywania? Czy symbolizowałeś panikę w kernelu, aby dokładnie sprawdzić, co się dzieje? (z argumentem jądra 'keepsyms = 1' jądro wskaże ci awarię) Aby pomóc Ci zdiagnozować awarię LLDB, będziesz musiał podać nam trochę więcej informacji na temat twojej instalacji. – pmdj