ref: cc066d813083789d76169720edbf7a3104538117
parent: 6f30420136d8f2a87790dbe826bc6800de74770a
author: aiju <devnull@localhost>
date: Tue Dec 11 04:09:08 EST 2018
dtracy: catch page faults
--- a/sys/src/9/pc/l.s
+++ b/sys/src/9/pc/l.s
@@ -511,6 +511,17 @@
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
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -450,6 +450,7 @@
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 @@
ureg->pc += 2;
return;
}
+ } else if(pc == _peekinst){
+ if(vno == VectorGPF){
+ ureg->ax = -1;
+ ureg->pc += 2;
+ return;
+ }
}
}
@@ -712,6 +719,14 @@
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)
--- a/sys/src/9/pc64/l.s
+++ b/sys/src/9/pc64/l.s
@@ -449,6 +449,18 @@
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
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -440,6 +440,7 @@
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 @@
ureg->pc += 2;
return;
}
+ } else if(pc == _peekinst){
+ if(vno == VectorGPF){
+ ureg->ax = -1;
+ ureg->pc += 2;
+ return;
+ }
}
}
@@ -672,6 +679,15 @@
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)
--- a/sys/src/9/port/devdtracy.c
+++ b/sys/src/9/port/devdtracy.c
@@ -518,10 +518,16 @@
}
}
+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);
}