ref: 5a514a681e4c2ab86f76509203a0a96d371d51aa
dir: /chk.c/
#include <u.h> #include <libc.h> #include <thread.h> #include <bio.h> #include <mach.h> #include "dat.h" #include "fns.h" extern int vtrace; void dumpmap(Segment *seg, u32int off, char *fmt, ...) { char buf[16*1024], *p, *e; va_list ap; int i; 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&~0x4095)/8; i <= (seg->size + 7)/8; i++){ if(i % 40 == 0) p = seprint(p, e, "\n[%04x] ", seg->start+i*8); 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); } void validmem(Segment *seg, u32int off, u32int len) { static int never; u32int end; /* * 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; for(end = off+len; off != end; off++){ if((seg->shadow[off>>3] & 1<<(off&7)) == 0){ print("invalid read of %#x at %#x\n", seg->start+off, P->R[15] - 4); dumpmap(seg, off, "broken"); rendezvous(&never, nil); exits("bad access"); } } } void markvalid(Segment *seg, u32int off, u32int len) { u32int end; //print("seg: %#p\n", seg); //print("mark[shadow=%#p] %#x+%x [%#x+%#x]\n", seg->shadow, seg->start + off, len, seg->start, off); for(end = off+len; off != end; off++) seg->shadow[off>>3] |= (1<<(off&7)); } void markinvalid(Segment *s, u32int off, u32int len) { u32int end; for(end = off+len; off != end; off++) s->shadow[off>>3] &= ~(1<<(off&7)); } void hookmalloc(u32int *av) { Segment *seg; uchar *p; p = vaddr(P->R[0], 0, 0, &seg); if(mallocverbose) dumpmap(seg, p-(uchar*)seg->start, "malloced %#x+%d\n", P->R[0], av[0]); markinvalid(seg, p - (uchar*)seg->data, av[0]); if(mallocverbose) dumpmap(seg, p-(uchar*)seg->start, "postmalloc"); segunlock(seg); } void hookrealloc(u32int *av) { uchar *oldp, *newp; u32int oldsz, newsz, sz; u32int oldoff, newoff; Segment *seg0, *seg1; oldp = vaddr(av[0], 0, 0, &seg0); newp = vaddr(P->R[0], 0, 0, &seg1); oldsz = av[1]; newsz = av[2]; oldoff = oldp - (uchar*)seg0->data; newoff = newp - (uchar*)seg1->data; sz = (oldsz < newsz) ? oldsz : newsz; if(mallocverbose) dumpmap(seg0, oldp-(uchar*)seg0->start, "realloc %#x+%d => %#x+%d\n", av[0], av[1], P->R[0], av[2]); if(oldp != newp) memcpy(seg1->shadow+oldoff/8, seg0->shadow+newoff/8, (sz+7)/8); if(newsz > oldsz) markinvalid(seg0, oldoff+oldsz, newsz-oldsz); if(mallocverbose) dumpmap(seg1, newp-(uchar*)seg1->start, "postrealloc"); segunlock(seg0); segunlock(seg1); } void hookfree(u32int *av) { Segment *seg; uchar *p; p = vaddr(av[0], 0, 0, &seg); if(mallocverbose) dumpmap(seg, p-(uchar*)seg->start, "free %#x+%d\n", av[0], av[1]); markinvalid(seg, p - (uchar*)seg->data, av[1]); if(mallocverbose) dumpmap(seg, p-(uchar*)seg->start, "postfree"); segunlock(seg); }