diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-08-27 03:47:18 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2019-08-27 03:47:18 +0200 |
commit | 2149600d129944f60cbc858bc669193af0523409 (patch) | |
tree | 89cd2d2b36e204bbb50ed2159ebdbf7f2cd7e01c /sys/src/9/port/fault.c | |
parent | 128ea44a89c7905612ad2fa5a61a9325ddfb5e1e (diff) |
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.
Diffstat (limited to 'sys/src/9/port/fault.c')
-rw-r--r-- | sys/src/9/port/fault.c | 20 |
1 files changed, 13 insertions, 7 deletions
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 */ |