From 2149600d129944f60cbc858bc669193af0523409 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Tue, 27 Aug 2019 03:47:18 +0200 Subject: kernel: catch execution read fault on SG_NOEXEC segment fault() now has an additional pc argument that is used to detect fault on a non-executable segment. that is, we check on read fault if the segment has the SG_NOEXEC attribute and the program counter is within faulting page. --- sys/src/9/port/fault.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'sys/src/9/port/fault.c') diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c index f7732bbc3..4b6e12f67 100644 --- a/sys/src/9/port/fault.c +++ b/sys/src/9/port/fault.c @@ -142,7 +142,6 @@ done: static int fixfault(Segment *s, uintptr addr, int read) { - int type; Pte **pte, *etp; uintptr soff, mmuphys; Page **pg, *old, *new; @@ -159,8 +158,7 @@ fixfault(Segment *s, uintptr addr, int read) if(pg > etp->last) etp->last = pg; - type = s->type & SG_TYPE; - switch(type) { + switch(s->type & SG_TYPE) { default: panic("fault"); return -1; @@ -221,6 +219,12 @@ fixfault(Segment *s, uintptr addr, int read) (*pg)->modref = PG_MOD|PG_REF; break; } + +#ifdef PTENOEXEC + if((s->type & SG_NOEXEC) != 0) + mmuphys |= PTENOEXEC; +#endif + qunlock(s); putmmu(addr, mmuphys, *pg); @@ -246,12 +250,12 @@ mapphys(Segment *s, uintptr addr, int attr) mmuphys |= PTERONLY; #ifdef PTENOEXEC - if((attr & SG_NOEXEC) == SG_NOEXEC) + if((attr & SG_NOEXEC) != 0) mmuphys |= PTENOEXEC; #endif #ifdef PTEDEVICE - if((attr & SG_DEVICE) == SG_DEVICE) + if((attr & SG_DEVICE) != 0) mmuphys |= PTEDEVICE; else #endif @@ -266,7 +270,7 @@ mapphys(Segment *s, uintptr addr, int attr) } int -fault(uintptr addr, int read) +fault(uintptr addr, uintptr pc, int read) { Segment *s; char *sps; @@ -298,7 +302,9 @@ fault(uintptr addr, int read) if((attr & SG_TYPE) == SG_PHYSICAL) attr |= s->pseg->attr; - if((attr & SG_FAULT) != 0 || !read && (attr & SG_RONLY) != 0) { + if((attr & SG_FAULT) != 0 + || read? (attr & SG_NOEXEC) != 0 && (addr & -BY2PG) == (pc & -BY2PG): + (attr & SG_RONLY) != 0) { qunlock(s); up->psstate = sps; if(up->kp && up->nerrlab) /* for segio */ -- cgit v1.2.3