ref: 907de081e187e8630a1710d98b2eae84947fe7c2
dir: /chk.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <bio.h> #include <mach.h> #include "dat.h" #include "fns.h" uvlong okrange[32]; int nokrange; void dumpmap(Segment *seg, u32int off, u32int len, char *fmt, ...) { char buf[16*1024], *p, *e; va_list ap; int i, c; p = buf; e = p + sizeof(buf)-1; va_start(ap, fmt); p = vseprint(p, e, fmt, ap); va_end(ap); if(seg->shadow == nil){ print("not tracing\n"); return; } for(i = off/8; i <= (off+len+7)/8; i++){ if(i >= off/8 && i+40 < off/8) c = '*'; else c = ' '; if(i % 40 == 0) p = seprint(p, e, "\n[%04x]%c", seg->start+i*8, c); p = seprint(p, e, "%02ux", seg->shadow[i]); } *p++ = '\n'; write(1, buf, p - buf); } static u32int arg(int n) { /* no locking necessary, since we're on the stack */ return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4, ARD); } static int okfunc(u32int pc) { uvlong *p; int i; for(i = 0, p = okrange; i < nokrange; i += 2, p += 2) if(p[0] <= pc && pc <= p[1]) return 1; return 0; } void checkaccess(Segment *seg, u32int off, u32int len, int chk) { static int never; u32int end, bits; /* * when we're within a malloc or free operation, we're looking at * memory that we don't want to allow user programs to touch; skip * the check here. */ if(P->hookpc != 0) return; end = off+len; if(end > seg->size){ print("read past end of segment: %#x at %#x\n", seg->start+off, P->R[15] - 4); rendezvous(&never, nil); exits("bad access"); } for(; off != end; off++){ bits = seg->shadow[off>>2] >> (2*(off&3)); if((bits&chk) != chk && !okfunc(P->R[15]-4)){ if((bits&MARKALLOC) == 0) print("%d: access outside alloc: %#x at PC %#x\n", P->pid, seg->start+off, P->R[15] - 4); if((bits&MARKINIT) == 0) print("%d: invalid read: %#x at PC %#x\n", P->pid, seg->start+off, P->R[15] - 4); rendezvous(&never, nil); exits("bad access"); } } } void markvalid(Segment *seg, u32int off, u32int len, int chk) { u32int end; end = off+len; if(end > seg->size) end = seg->size; //print("valid: %#x..%#x\n", seg->start+off, seg->start+end); for(; off != end; off++) seg->shadow[off>>2] |= chk<<(2*(off&3)); } void markinvalid(Segment *seg, u32int off, u32int len, int chk) { u32int end; end = off+len; if(end > seg->size) end = seg->size; //print("invalid: %#x..%#x\n", seg->start+off, seg->start+end); for(; off != end; off++) seg->shadow[off>>2] &= ~(chk<<(2*(off&3))); } void hookmalloc(u32int *av) { Segment *seg; uchar *p; p = vaddr(P->R[0], 0, 0, &seg); markvalid(seg, p - (uchar*)seg->data, av[0], MARKALLOC); segunlock(seg); } void hookrealloc(u32int *av) { uchar *oldp, *newp; u32int oldsz, newsz, sz; u32int oldoff, newoff; Segment *seg0, *seg1; seg0 = nil; seg1 = nil; oldp = nil; newp = nil; oldsz = 0; newsz = 0; oldoff = 0; newoff = 0; if(av[0] != 0){ oldp = vaddr(av[0], 0, 0, &seg0); oldsz = av[1]; oldoff = oldp - (uchar*)seg0->data; } if(P->R[0] != 0){ newp = vaddr(P->R[0], 0, 0, &seg1); newsz = av[2]; newoff = newp - (uchar*)seg1->data; } sz = (oldsz < newsz) ? oldsz : newsz; if(oldp != newp && oldsz > 0){ memcpy(seg1->shadow+oldoff/4, seg0->shadow+newoff/4, (sz+3)/4); markinvalid(seg0, oldoff, oldsz, MARKALLOC|MARKINIT); } if(newsz > oldsz){ markvalid(seg1, newoff+oldsz, newsz-oldsz, MARKALLOC); markinvalid(seg1, newoff+oldsz, newsz-oldsz, MARKINIT); } if(seg0 != nil) segunlock(seg0); if(seg1 != nil) segunlock(seg1); } void hookfree(u32int *av) { Segment *seg; uchar *p; p = vaddr(av[0], 0, 0, &seg); markinvalid(seg, p - (uchar*)seg->data, av[1], MARKALLOC|MARKINIT); segunlock(seg); }