From cc066d813083789d76169720edbf7a3104538117 Mon Sep 17 00:00:00 2001 From: aiju Date: Tue, 11 Dec 2018 09:09:08 +0000 Subject: [PATCH] dtracy: catch page faults --- sys/src/9/pc/l.s | 11 +++++++++++ sys/src/9/pc/trap.c | 15 +++++++++++++++ sys/src/9/pc64/l.s | 12 ++++++++++++ sys/src/9/pc64/trap.c | 16 ++++++++++++++++ sys/src/9/port/devdtracy.c | 12 +++++++++--- 5 files changed, 63 insertions(+), 3 deletions(-) diff --git a/sys/src/9/pc/l.s b/sys/src/9/pc/l.s index 217088ecb..151985f3f 100644 --- a/sys/src/9/pc/l.s +++ b/sys/src/9/pc/l.s @@ -511,6 +511,17 @@ TEXT _wrmsrinst(SB), $0 MOVL BP, AX /* BP set to -1 if traped */ RET +/* fault-proof memcpy */ +TEXT peek(SB), $0 + MOVL $0, AX /* AX set to -1 if traped */ + MOVL src+0(FP), SI + MOVL dst+4(FP), DI + MOVL cnt+8(FP), CX + CLD +TEXT _peekinst(SB), $0 + REP; MOVSB + RET + /* * Try to determine the CPU type which requires fiddling with EFLAGS. * If the Id bit can be toggled then the CPUID instruction can be used diff --git a/sys/src/9/pc/trap.c b/sys/src/9/pc/trap.c index b76afaff2..12d062adf 100644 --- a/sys/src/9/pc/trap.c +++ b/sys/src/9/pc/trap.c @@ -450,6 +450,7 @@ trap(Ureg* ureg) extern void _forkretiret(void); extern void _rdmsrinst(void); extern void _wrmsrinst(void); + extern void _peekinst(void); extern void load_fs(ulong); extern void load_gs(ulong); @@ -478,6 +479,12 @@ trap(Ureg* ureg) ureg->pc += 2; return; } + } else if(pc == _peekinst){ + if(vno == VectorGPF){ + ureg->ax = -1; + ureg->pc += 2; + return; + } } } @@ -712,6 +719,14 @@ fault386(Ureg* ureg, void*) if(!user){ if(vmapsync(addr)) return; + { + extern void _peekinst(void); + if((void(*)(void))ureg->pc == _peekinst){ + ureg->ax = -1; + ureg->pc += 2; + return; + } + } if(addr >= USTKTOP) panic("kernel fault: bad address pc=0x%.8lux addr=0x%.8lux", ureg->pc, addr); if(up == nil) diff --git a/sys/src/9/pc64/l.s b/sys/src/9/pc64/l.s index 7143d3b69..25d5c71e0 100644 --- a/sys/src/9/pc64/l.s +++ b/sys/src/9/pc64/l.s @@ -449,6 +449,18 @@ TEXT _wrmsrinst(SB), $0 MOVQ BP, AX /* BP set to -1 if traped */ RET +/* fault-proof memcpy */ +TEXT peek(SB), 1, $-4 + MOVQ $0, AX + MOVQ RARG, SI + MOVQ dst+8(FP), DI + MOVL cnt+16(FP), CX + CLD +TEXT _peekinst(SB), $0 + REP; MOVSB + RET + + TEXT invlpg(SB), 1, $-4 INVLPG (RARG) RET diff --git a/sys/src/9/pc64/trap.c b/sys/src/9/pc64/trap.c index 1944f43bd..17a356463 100644 --- a/sys/src/9/pc64/trap.c +++ b/sys/src/9/pc64/trap.c @@ -440,6 +440,7 @@ trap(Ureg *ureg) extern void _rdmsrinst(void); extern void _wrmsrinst(void); + extern void _peekinst(void); pc = (void*)ureg->pc; if(pc == _rdmsrinst || pc == _wrmsrinst){ @@ -448,6 +449,12 @@ trap(Ureg *ureg) ureg->pc += 2; return; } + } else if(pc == _peekinst){ + if(vno == VectorGPF){ + ureg->ax = -1; + ureg->pc += 2; + return; + } } } @@ -672,6 +679,15 @@ faultamd64(Ureg* ureg, void*) read = !(ureg->error & 2); user = userureg(ureg); if(!user){ + { + extern void _peekinst(void); + + if((void(*)(void))ureg->pc == _peekinst){ + ureg->ax = -1; + ureg->pc += 2; + return; + } + } if(addr >= USTKTOP) panic("kernel fault: bad address pc=%#p addr=%#p", ureg->pc, addr); if(up == nil) diff --git a/sys/src/9/port/devdtracy.c b/sys/src/9/port/devdtracy.c index 53da2c46b..1d382f9f1 100644 --- a/sys/src/9/port/devdtracy.c +++ b/sys/src/9/port/devdtracy.c @@ -518,10 +518,16 @@ dtgetvar(int v) } } +int peek(char *, char *, int); + int dtpeek(uvlong addr, void *buf, int len) { - if((uintptr)addr != addr || up == nil || !okaddr((uintptr) addr, len, 0)) return -1; - memmove(buf, (void *) addr, len); - return 0; + uintptr a; + + a = addr; + if(len == 0) return 0; + if(a != addr || a > -(uintptr)len || len < 0) return -1; + if(up == nil || up->privatemem || a >= KZERO) return -1; + return peek((void *)a, buf, len); }