ref: d6a35f12c5156009d35534fb9bb3d59a541d2e2c
parent: c0fef42e25d7b90e3982d6be1d571d631b895ef6
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Sep 9 16:51:41 EDT 2023
5e: add alloc bit
--- a/arm.c
+++ b/arm.c
@@ -21,6 +21,13 @@
int vtrace;
+u32int mallocaddr;
+u32int freeaddr;
+u32int reallocaddr;
+u32int setmalloctagaddr;
+u32int setrealloctagaddr;
+u32int vtraceaddr;
+
static u32int
arg(int n)
{
@@ -337,6 +344,10 @@
P->hookarg[1] = asize(1);
P->hookfn = hookfree;
P->hookpc = P->R[15];
+ }else if(npc == setmalloctagaddr){
+ P->hookpc = P->R[15];
+ }else if(npc == setrealloctagaddr){
+ P->hookpc = P->R[15];
}else if(npc == vtraceaddr){
vtrace = arg(0);
}
@@ -575,7 +586,8 @@
);
}
if(P->R[15] == P->hookpc){
- P->hookfn(P->hookarg);
+ if(P->hookfn)
+ P->hookfn(P->hookarg);
P->hookpc = 0;
P->hookfn = nil;
}
--- a/chk.c
+++ b/chk.c
@@ -7,7 +7,7 @@
#include "fns.h"
void
-dumpmap(Segment *seg, u32int off, char *fmt, ...)
+dumpmap(Segment *seg, u32int off, u32int len, char *fmt, ...)
{
char buf[16*1024], *p, *e;
va_list ap;
@@ -22,7 +22,8 @@
print("not tracing\n");
return;
}
- for(i = 0; i <= (seg->size + 7)/8; i++){
+print("off: %d, len: %d\n", off, len);
+ for(i = off/8; i <= (off+len+7)/8; i++){
if(i >= off/8 && i+40 < off/8)
c = '*';
else
@@ -43,10 +44,10 @@
}
void
-validmem(Segment *seg, u32int off, u32int len)
+checkaccess(Segment *seg, u32int off, u32int len, int chk)
{
static int never;
- u32int end;
+ u32int end, bits;
/*
* when we're within a malloc or free operation, we're looking at
@@ -55,30 +56,44 @@
*/
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);
+ 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 = chk << (2*(off&3));;
+ if((seg->shadow[off>>2] & bits) != bits){
+ print("invalid read: %#x at %#x (%x != %x)\n", seg->start+off, P->R[15] - 4, bits, (seg->shadow[off>>2] & bits));
rendezvous(&never, nil);
exits("bad access");
}
}
}
+
void
-markvalid(Segment *seg, u32int off, u32int len)
+markvalid(Segment *seg, u32int off, u32int len, int chk)
{
u32int end;
- for(end = off+len; off != end; off++)
- seg->shadow[off>>3] |= (1<<(off&7));
+ end = off+len;
+ if(end > seg->size)
+ end = seg->size;
+ for(; off != end; off++)
+ seg->shadow[off>>2] |= chk<<(2*(off&3));
}
void
-markinvalid(Segment *s, u32int off, u32int len)
+markinvalid(Segment *seg, u32int off, u32int len, int chk)
{
u32int end;
- for(end = off+len; off != end; off++)
- s->shadow[off>>3] &= ~(1<<(off&7));
+ end = off+len;
+ if(end > seg->size)
+ end = seg->size;
+ for(; off != end; off++)
+ seg->shadow[off>>2] &= ~(chk<<(2*(off&3)));
}
void
@@ -88,11 +103,7 @@
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");
+ markvalid(seg, p - (uchar*)seg->data, av[0], MARKALLOC);
segunlock(seg);
}
@@ -105,6 +116,8 @@
u32int oldoff, newoff;
Segment *seg0, *seg1;
+ seg0 = nil;
+ seg1 = nil;
oldp = nil;
newp = nil;
oldsz = 0;
@@ -122,18 +135,19 @@
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);
- markinvalid(seg0, oldoff, oldsz);
+ 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)
- markinvalid(seg1, newoff+oldsz, newsz-oldsz);
- if(mallocverbose)
- dumpmap(seg1, newp-(uchar*)seg1->start, "postrealloc");
- segunlock(seg0);
- segunlock(seg1);
+ 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
@@ -143,10 +157,6 @@
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");
+ markinvalid(seg, p - (uchar*)seg->data, av[1], MARKALLOC|MARKINIT);
segunlock(seg);
}
--- a/dat.h
+++ b/dat.h
@@ -29,6 +29,11 @@
AWR = 1<<1,
};
+enum {
+ MARKALLOC = 1<<0,
+ MARKINIT = 1<<1,
+};
+
struct Process {
Process *prev, *next; /* linked list (for fs) */
int pid;
@@ -70,10 +75,12 @@
extern Process plist;
extern Lock plistlock;
extern int check;
-u32int mallocaddr;
-u32int freeaddr;
-u32int reallocaddr;
-u32int vtraceaddr;
+extern u32int mallocaddr;
+extern u32int freeaddr;
+extern u32int reallocaddr;
+extern u32int setmalloctagaddr;
+extern u32int setrealloctagaddr;
+extern u32int vtraceaddr;
enum {
SEGFLLOCK = 1,
@@ -98,5 +105,4 @@
#define fulltrace 0
#define ultraverbose 0
-#define mallocverbose 0
#define systrace 0
--- a/fns.h
+++ b/fns.h
@@ -31,7 +31,7 @@
void donote(char *, ulong);
void addnote(char *);
void dump(void);
-void dumpmap(Segment *, u32int, char *, ...);
+void dumpmap(Segment *, u32int, u32int, char *, ...);
void resetfpa(void);
void invalid(u32int);
u32int evenaddr(u32int,u32int);
@@ -44,9 +44,9 @@
void vfpoperation(u32int);
void inittos(void);
void initmem(void);
-void validmem(Segment*, u32int, u32int);
-void markvalid(Segment*, u32int, u32int);
-void markinvalid(Segment*, u32int, u32int);
+void checkaccess(Segment*, u32int, u32int, int);
+void markvalid(Segment*, u32int, u32int, int);
+void markinvalid(Segment*, u32int, u32int, int);
void hookmalloc(u32int*);
void hookrealloc(u32int*);
void hookfree(u32int*);
--- a/proc.c
+++ b/proc.c
@@ -195,35 +195,33 @@
return -1;
}
-static void
-inithooks(void)
+u32int
+hookaddr(char *name)
{
Symbol s;
- if(lookup("poolalloc", nil, &s) == -1)
- mallocaddr = -1;
- else
- mallocaddr = s.value;
- if(lookup("poolrealloc", nil, &s) == -1)
- reallocaddr = -1;
- else
- reallocaddr = s.value;
- if(lookup("poolfree", nil, &s) == -1)
- freeaddr = -1;
- else
- freeaddr = s.value;
- if(lookup("vtrace", nil, &s) == -1)
- vtraceaddr = -1;
- else
- vtraceaddr = s.value;
+ if(lookup(name, nil, &s) == -1)
+ return -1;
+ return s.value;
}
+static void
+inithooks(void)
+{
+ mallocaddr = hookaddr("poolalloc");
+ reallocaddr = hookaddr("poolrealloc");
+ freeaddr = hookaddr("poolfree");
+ setmalloctagaddr = hookaddr("setmalloctag");
+ setrealloctagaddr = hookaddr("setrealloctag");
+ vtraceaddr = hookaddr("vtrace");
+}
+
int
loadtext(char *file, int argc, char **argv)
{
int fd;
Fhdr fp;
- Segment *text, *data, *bss;
+ Segment *text, *data, *bss, *stk;
char buf[2];
fd = open(file, OREAD);
@@ -243,12 +241,13 @@
text = newseg(fp.txtaddr - fp.hdrsz, fp.txtsz + fp.hdrsz, SEGTEXT);
data = newseg(fp.dataddr, fp.datsz, SEGDATA);
bss = newseg(fp.dataddr + fp.datsz, fp.bsssz, SEGBSS);
+ stk = newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);
if(check){
- markvalid(text, 0, fp.txtsz+fp.hdrsz);
- markvalid(data, 0, fp.datsz);
- markvalid(bss, 0, fp.bsssz);
+ markvalid(text, 0, fp.txtsz+fp.hdrsz, MARKALLOC|MARKINIT);
+ markvalid(data, 0, fp.datsz, MARKALLOC|MARKINIT);
+ markvalid(bss, 0, fp.bsssz, MARKALLOC|MARKINIT);
+ markvalid(stk, 0, stk->size, MARKALLOC|MARKINIT);
}
- newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);
seek(fd, fp.txtoff - fp.hdrsz, 0);
if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
sysfatal("%r");
--- a/seg.c
+++ b/seg.c
@@ -18,7 +18,7 @@
incref(s->dref);
s->data = s->dref + 1;
if(check)
- s->shadow = emallocz((size+7)/8);
+ s->shadow = emallocz((size+3)/4);
if(idx == SEGBSS)
s->flags = SEGFLLOCK;
P->S[idx] = s;
@@ -46,6 +46,7 @@
{
Segment **ss, *s;
u32int off;
+ int bits;
for(ss = P->S; ss < P->S + SEGNUM; ss++) {
if(*ss == nil)
@@ -58,9 +59,11 @@
rlock(&s->rw);
*seg = s;
off = (addr - s->start);
- if(check){
- if(op&ARD) validmem(s, off, len);
- if(op&AWR) markvalid(s, off, len);
+ if(check && op != 0){
+ bits = MARKALLOC;
+ if(op & ARD) bits |= MARKINIT;
+ checkaccess(s, off, len, bits);
+ if(op & AWR) markvalid(s, off, len, MARKINIT);
}
return (char *)s->data + off;
}
--- a/sys.c
+++ b/sys.c
@@ -101,7 +101,8 @@
copyback(buf, P->R[0], targ);
if(check && (s32int)P->R[0] > 0){
vaddr(buf, 0, 0, &seg);
- markvalid(seg, buf-seg->start, P->R[0]);
+ checkaccess(seg, buf-seg->start, P->R[0], MARKALLOC);
+ markvalid(seg, buf-seg->start, P->R[0], MARKINIT);
segunlock(seg);
}
}
@@ -185,7 +186,8 @@
copyback(edir, P->R[0], edirt);
if(check && (s32int)P->R[0] > 0){
vaddr(edir, 0, 0, &seg);
- markvalid(seg, edir-seg->start, P->R[0]);
+ checkaccess(seg, edir-seg->start, P->R[0], MARKALLOC);
+ markvalid(seg, edir-seg->start, P->R[0], MARKINIT);
segunlock(seg);
}
}
@@ -209,7 +211,8 @@
copyback(edir, P->R[0], edirt);
if(check && (s32int)P->R[0] > 0){
vaddr(edir, 0, 0, &seg);
- markvalid(seg, edir-seg->start, P->R[0]);
+ checkaccess(seg, edir-seg->start, P->R[0], MARKALLOC);
+ markvalid(seg, edir-seg->start, P->R[0], MARKINIT);
segunlock(seg);
}
}
@@ -289,11 +292,11 @@
if(o < n)
memset((char*)s->data + o, 0, n - o);
if(s->shadow != nil){
- s->shadow = realloc(s->shadow, n);
+ s->shadow = realloc(s->shadow, (n+3)/4);
if(s->shadow == nil)
sysfatal("error reallocating");
if(n - o > 0)
- memset(s->shadow + o, 0, n - o);
+ memset(s->shadow + (o+3)/4, 0, (n - o + 3)/4);
}
s->size = v - s->start;
P->R[0] = 0;
--- a/test.c
+++ b/test.c
@@ -10,6 +10,7 @@
x = malloc(123);
x[1] = 123;
+ x[124] = 7;
y = x[1];
argv[0][0] = y;
free(x);