9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] 5e: add support for memory constraint checking
@ 2023-09-10  1:46 ori
  0 siblings, 0 replies; only message in thread
From: ori @ 2023-09-10  1:46 UTC (permalink / raw)
  To: 9front

similar to valgrind, '5e -c' is growing support for finding
use-after-free, out of bounds reads, and other similar bugs.

It works by maintaing a bitmap with 2 bits for each byte
in the program segments: one for whether the bit has been
written to (initialized), and one for whether the bit has
been allocated with malloc, realloc, or a raw sbrk.

So far, it seems to be working, though there are still
a few unresolved issues:

	- It doesn't know about the APE allocator, which
	  means that it will report uninitialized memory
	  for nearly all APE programs.

	- It doesn't know about how much stack a function
	  uses, so it will flag it as initialized even
	  after a function returns

	- It has not been tested heavily, especially not
	  on concurrent code.

And almost certainly a few others. But so far, it's been
quite useful, and I'd be happy to expand it to make it
more useful.

To use it, simply do something like:

	cd /sys/src/cmd && objtype=arm mk 5.ls
	5e -c 5.ls

And the emulated program will either work as normal (but
slower), or will die.

diff 41a932f370cee1423827e0c0175ba457d3cacd82 uncommitted
--- a/sys/src/cmd/5e/5e.c
+++ b/sys/src/cmd/5e/5e.c
@@ -6,6 +6,12 @@
 
 int vfp = 1;
 int nflag, pflag, bflag;
+int check;
+u32int mallocaddr;
+u32int freeaddr;
+u32int reallocaddr;
+u32int setmalloctagaddr;
+u32int setrealloctagaddr;
 Ref nproc;
 
 void
@@ -85,17 +91,22 @@
 static void
 dotext(int argc, char **argv)
 {
-	char *file;
-	
+	char *file, **p, *path[] = {"/bin", ".", nil};
+
 	if(**argv == '/' || **argv == '.' || **argv == '#') {
 		if(loadtext(*argv, argc, argv) < 0)
 			sysfatal("loadtext: %r");
 		return;
 	}
-	file = smprint("/bin/%s", *argv);
-	if(loadtext(file, argc, argv) < 0)
-		sysfatal("loadtext: %r");
-	free(file);
+	for(p = path; *p; p++){
+		file = smprint("%s/%s", *p, *argv);
+		if(loadtext(file, argc, argv) >= 0){
+			free(file);
+			return;
+		}
+		free(file);
+	}
+	sysfatal("loadtext: %r");
 }
 
 void
@@ -107,6 +118,7 @@
 	case 'b': bflag++; break;
 	case 'f': vfp = 1; break;
 	case 'F': vfp = 0; break;
+	case 'c': check++; break;
 	default: usage();
 	} ARGEND;
 	if(argc < 1)
@@ -118,7 +130,7 @@
 	atexit(cleanup);
 	if(!nflag)
 		adjustns();
-	if(pflag)
+	if(pflag || check)
 		initfs("armproc", "/proc");
 	initproc();
 	dotext(argc, argv);
--- a/sys/src/cmd/5e/arm.c
+++ b/sys/src/cmd/5e/arm.c
@@ -19,6 +19,35 @@
 	fH = 1<<5,
 };
 
+u32int mallocaddr;
+u32int freeaddr;
+u32int reallocaddr;
+u32int sbrkaddr;
+u32int setmalloctagaddr;
+u32int setrealloctagaddr;
+
+static u32int
+arg(int n)
+{
+	/* no locking necessary, since we're on the stack */
+	if(n == 0)
+		return P->R[0];
+	else
+		return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4, ARD);
+}
+
+static u32int
+asize(int n)
+{
+	/* keep in sync with Bhdr in pool.c */
+	u32int a;
+
+	a = *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4, ARD);
+	if(a == 0)
+		return ~0;
+	return *(ulong*) vaddrnol(a-4, 4, 0);
+}
+
 void
 invalid(u32int instr)
 {
@@ -117,27 +146,32 @@
 		if(instr & fW)
 			invalid(instr);
 		addr = P->R[15] + 4;
-	}
-	else
+	}else
 		addr = *Rn;
 	if(instr & fP)
 		addr += offset;
 	if((instr & fB) == 0)
 		addr = evenaddr(addr, 3);
-	targ = vaddr(addr, (instr & fB) == 0 ? 4 : 1, &seg);
 	switch(instr & (fB | fL)) {
 	case 0:
+		targ = vaddr(addr, 4, AWR, &seg);
 		*(u32int*) targ = *Rd;
 		break;
 	case fB:
+		targ = vaddr(addr, 1, AWR, &seg);
 		*(u8int*) targ = *Rd;
 		break;
 	case fL:
+		targ = vaddr(addr, 4, ARD, &seg);
 		*Rd = *(u32int*) targ;
 		break;
 	case fB | fL:
+		targ = vaddr(addr, 1, ARD, &seg);
 		*Rd = *(u8int*) targ;
 		break;
+	default:
+		targ = nil;
+		abort();
 	}
 	if(Rd == P->R + 15 && !(instr & fL)) {
 		if(instr & fB)
@@ -169,7 +203,7 @@
 	addr = *Rn;
 	if((instr & fB) == 0)
 		addr = evenaddr(addr, 3);
-	targ = (u32int *) vaddr(addr & ~3, 4, &seg);
+	targ = (u32int *) vaddr(addr & ~3, 4, ARD|AWR, &seg);
 	do {
 		old = *targ;
 		new = *Rm;
@@ -196,16 +230,23 @@
 	if(type) {
 		res2 = (u64int)a - b + *carry - 1;
 		res1 = res2;
-		if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31))) *overflow = 1;
-		else *overflow = 0;
-		if(res2 & 0x100000000LL) *carry = 0;
-		else *carry = 1;	
+		if(((a ^ b) & (1<<31)) && !((b ^ res1) & (1<<31)))
+			*overflow = 1;
+		else
+			*overflow = 0;
+		if(res2 & 0x100000000LL)
+			*carry = 0;
+		else
+			*carry = 1;	
 	} else {
 		res2 = (u64int)a + b + *carry;
 		res1 = res2;
-		if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31))) *overflow = 1;
-		else *overflow = 0;
-		if(res2 & 0x100000000LL) *carry = 1;
+		if(!((a ^ b) & (1<<31)) && ((b ^ res1) & (1<<31)))
+			*overflow = 1;
+		else
+			*overflow = 0;
+		if(res2 & 0x100000000LL)
+			*carry = 1;
 		else *carry = 0;
 	}
 	return res1;
@@ -276,14 +317,44 @@
 branch(u32int instr)
 {
 	long offset;
+	u32int npc;
 	
 	offset = instr & ((1<<24) - 1);
 	if(offset & (1<<23))
 		offset |= ~((1 << 24) - 1);
 	offset *= 4;
-	if(instr & fLi)
+	npc = P->R[15] + offset + 4;
+	if(instr & fLi){
 		P->R[14] = P->R[15];
-	P->R[15] += offset + 4;
+		if(check && P->hookpc == 0){
+			if(npc == mallocaddr){
+				P->hookarg[0] = arg(1);	/* size */
+				P->hookfn = hookmalloc;
+				P->hookpc = P->R[15];
+			}else if(npc == reallocaddr){
+				P->hookarg[0] = arg(1);		/* old */
+				P->hookarg[1] = asize(1);	/* oldsz */
+				P->hookarg[2] = arg(2);		/* newsz */
+				P->hookfn = hookrealloc;
+				P->hookpc = P->R[15];
+			}else if(npc == freeaddr){
+				P->hookarg[0] = arg(1);
+				P->hookarg[1] = asize(1);
+				P->hookfn = hookfree;
+				P->hookpc = P->R[15];
+			}else if(npc == sbrkaddr){
+				P->hookarg[0] = arg(0);
+				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];
+			}
+		}
+	}
+	P->R[15] = npc;
 }
 
 static void
@@ -313,11 +384,21 @@
 	if(instr & fH)
 		target = evenaddr(target, 1);
 	switch(instr & (fSg | fH | fL)) {
-	case fSg: *(u8int*) vaddr(target, 1, &seg) = *Rd; break;
-	case fSg | fL: *Rd = (long) *(char*) vaddr(target, 1, &seg); break;
-	case fH: case fSg | fH: *(u16int*) vaddr(target, 2, &seg) = *Rd; break;
-	case fH | fL: *Rd = *(u16int*) vaddr(target, 2, &seg); break;
-	case fH | fL | fSg: *Rd = (long) *(short*) vaddr(target, 2, &seg); break;
+	case fSg:
+		*(u8int*) vaddr(target, 1, AWR, &seg) = *Rd;
+		break;
+	case fSg | fL:
+		*Rd = (long) *(char*) vaddr(target, 1, ARD, &seg);
+		break;
+	case fH: case fSg | fH:
+		*(u16int*) vaddr(target, 2, AWR, &seg) = *Rd;
+		break;
+	case fH | fL:
+		*Rd = *(u16int*) vaddr(target, 2, ARD, &seg);
+		break;
+	case fH | fL | fSg:
+		*Rd = (long) *(short*) vaddr(target, 2, ARD, &seg);
+		break;
 	}
 	segunlock(seg);
 	if(!(instr & fP))
@@ -346,9 +427,9 @@
 			if(instr & fP)
 				targ += 4;
 			if(instr & fL)
-				P->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+				P->R[i] = *(u32int*) vaddr(targ, 4, ARD, &seg);
 			else
-				*(u32int*) vaddr(targ, 4, &seg) = P->R[i];
+				*(u32int*) vaddr(targ, 4, AWR, &seg) = P->R[i];
 			segunlock(seg);
 			if(!(instr & fP))
 				targ += 4;
@@ -360,9 +441,9 @@
 			if(instr & fP)
 				targ -= 4;
 			if(instr & fL)
-				P->R[i] = *(u32int*) vaddr(targ, 4, &seg);
+				P->R[i] = *(u32int*) vaddr(targ, 4, ARD, &seg);
 			else
-				*(u32int*) vaddr(targ, 4, &seg) = P->R[i];
+				*(u32int*) vaddr(targ, 4, AWR, &seg) = P->R[i];
 			segunlock(seg);
 			if(!(instr & fP))
 				targ -= 4;
@@ -406,7 +487,8 @@
 	Rs = P->R + ((instr >> 8) & 15);
 	RdL = P->R + ((instr >> 12) & 15);
 	RdH = P->R + ((instr >> 16) & 15);
-	if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == P->R + 15 || Rs == P->R + 15 || RdL == P->R + 15 || RdH == P->R + 15)
+	if(RdL == RdH || RdH == Rm || RdL == Rm || Rm == P->R + 15
+	|| Rs == P->R + 15 || RdL == P->R + 15 || RdH == P->R + 15)
 		invalid(instr);
 	if(instr & (1<<22))
 		res = ((vlong)*(int*)Rs) * *(int*)Rm;
@@ -441,7 +523,7 @@
 		invalid(instr);
 	addr = evenaddr(*Rn, 3);
 	if(instr & fS) {
-		targ = vaddr(addr, 4, &seg);
+		targ = vaddr(addr, 4, ARD, &seg);
 		*Rd = *targ;
 		P->lladdr = addr;
 		P->llval = *Rd;
@@ -450,7 +532,7 @@
 		Rm = P->R + (instr & 15);
 		if(Rm == P->R + 15)
 			invalid(instr);
-		targ = vaddr(addr, 4, &seg);
+		targ = vaddr(addr, 4, ARD|AWR, &seg);
 
 		/*
 		 * this is not quite correct as we will succeed even
@@ -486,19 +568,17 @@
 	u32int instr;
 	Segment *seg;
 
-	instr = *(u32int*) vaddr(P->R[15], 4, &seg);
+	instr = *(u32int*) vaddr(P->R[15], 4, 0, &seg);
 	segunlock(seg);
 	if(fulltrace) {
 		print("%d ", P->pid);
-		if(havesymbols) {
-			Symbol s;
-			char buf[512];
-			
-			if(findsym(P->R[15], CTEXT, &s) >= 0)
-				print("%s ", s.name);
-			if(fileline(buf, 512, P->R[15]) >= 0)
-				print("%s ", buf);
-		}
+		Symbol s;
+		char buf[512];
+		
+		if(findsym(P->R[15], CTEXT, &s) >= 0)
+			print("%s ", s.name);
+		if(fileline(buf, 512, P->R[15]) >= 0)
+			print("%s ", buf);
 		print("%.8ux %.8ux %c%c%c%c\n", P->R[15], instr,
 			(P->CPSR & flZ) ? 'Z' : ' ',
 			(P->CPSR & flC) ? 'C' : ' ',
@@ -505,6 +585,12 @@
 			(P->CPSR & flN) ? 'N' : ' ',
 			(P->CPSR & flV) ? 'V' : ' '
 			);
+	}
+	if(P->R[15] == P->hookpc){
+		if(P->hookfn)
+			P->hookfn(P->hookarg);
+		P->hookpc = 0;
+		P->hookfn = nil;
 	}
 	P->R[15] += 4;
 	switch(instr >> 28) {
--- a/sys/src/cmd/5e/dat.h
+++ b/sys/src/cmd/5e/dat.h
@@ -24,6 +24,16 @@
 	SEGSTACK,
 };
 
+enum {
+	ARD	= 1<<0,
+	AWR	= 1<<1,
+};
+
+enum {
+	MARKALLOC	= 1<<0,
+	MARKINIT	= 1<<1,
+};
+
 struct Process {
 	Process *prev, *next;	/* linked list (for fs) */
 	int pid;
@@ -50,6 +60,10 @@
 	jmp_buf notejmp;
 	char notes[ERRMAX][NNOTE];
 	long notein, noteout;
+
+	u32int	hookpc;
+	u32int	hookarg[3];
+	void	(*hookfn)(u32int*);
 };
 
 int vfp;
@@ -60,6 +74,15 @@
 extern Ref nproc;
 extern Process plist;
 extern Lock plistlock;
+extern int check;
+extern u32int mallocaddr;
+extern u32int freeaddr;
+extern u32int reallocaddr;
+extern u32int sbrkaddr;
+extern u32int setmalloctagaddr;
+extern u32int setrealloctagaddr;
+extern uvlong okrange[];
+extern int nokrange;
 
 enum {
 	SEGFLLOCK = 1,
@@ -71,6 +94,7 @@
 	RWLock rw; /* lock for SEGFLLOCK segments */
 	u32int start, size;
 	void *data;
+	uchar *shadow;
 	Ref *dref;
 };
 
@@ -82,6 +106,5 @@
 };
 
 #define fulltrace 0
-#define havesymbols 0
 #define ultraverbose 0
 #define systrace 0
--- a/sys/src/cmd/5e/fns.h
+++ b/sys/src/cmd/5e/fns.h
@@ -4,8 +4,8 @@
 void initproc(void);
 int loadtext(char *, int, char **);
 Segment *newseg(u32int, u32int, int);
-void *vaddr(u32int, u32int, Segment **);
-void *vaddrnol(u32int, u32int);
+void *vaddr(u32int, u32int, int, Segment **);
+void *vaddrnol(u32int, u32int, int);
 void step(void);
 void syscall(void);
 void cherrstr(char *, ...);
@@ -31,6 +31,7 @@
 void donote(char *, ulong);
 void addnote(char *);
 void dump(void);
+void dumpmap(Segment *, u32int, u32int, char *, ...);
 void resetfpa(void);
 void invalid(u32int);
 u32int evenaddr(u32int,u32int);
@@ -42,3 +43,10 @@
 void vfprmtransfer(u32int);
 void vfpoperation(u32int);
 void inittos(void);
+void initmem(void);
+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/sys/src/cmd/5e/fpa.c
+++ b/sys/src/cmd/5e/fpa.c
@@ -44,13 +44,13 @@
 	addr = *Rn;
 	if(instr & fP)
 		addr += off;
-	targ = vaddr(addr, 8, &seg);
+	targ = vaddr(addr, 8, 0, &seg);
 	switch(instr & (fT0 | fT1 | fL)) {
-	case 0: *(float *) targ = *Fd; break;
-	case fL: *Fd = *(float *) targ; break;
-	case fT0: *(double *) targ = *Fd; break;
-	case fT0 | fL: *Fd = *(double *) targ; break;
-	default: invalid(instr);
+	case 0:		*(float *) targ = *Fd; break;
+	case fL:	*Fd = *(float *) targ; break;
+	case fT0:	*(double *) targ = *Fd; break;
+	case fT0 | fL:	*Fd = *(double *) targ; break;
+	default:	invalid(instr);
 	}
 	segunlock(seg);
 	if(!(instr & fP))
--- a/sys/src/cmd/5e/mkfile
+++ b/sys/src/cmd/5e/mkfile
@@ -1,7 +1,7 @@
 </$objtype/mkfile
 
 TARG=5e
-OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O fpa.$O vfp.$O
+OFILES=5e.$O seg.$O proc.$O util.$O arm.$O sys.$O fs.$O fpa.$O vfp.$O chk.$O
 HFILES=dat.h fns.h
 BIN=/$objtype/bin
 
--- a/sys/src/cmd/5e/proc.c
+++ b/sys/src/cmd/5e/proc.c
@@ -120,17 +120,17 @@
 	P->R[1] = mach->utop - 4;
 	P->R[13] = sp;
 	
-	*(ulong *) vaddrnol(sp, 4) = argc;
+	*(ulong *) vaddrnol(sp, 4, AWR) = argc;
 	sp += 4;
 	ap = sp + (argc + 1) * 4;
 	for(i = 0; i < argc; i++) {
-		*(ulong *) vaddrnol(sp, 4) = ap;
+		*(ulong *) vaddrnol(sp, 4, AWR) = ap;
 		sp += 4;
 		len = strlen(argv[i]) + 1;
-		memcpy(vaddrnol(ap, len), argv[i], len);
+		memcpy(vaddrnol(ap, len, AWR), argv[i], len);
 		ap += len;
 	}
-	*(ulong *) vaddrnol(sp, 4) = 0;
+	*(ulong *) vaddrnol(sp, 4, AWR) = 0;
 	inittos();
 }
 
@@ -140,7 +140,7 @@
 	ulong tos;
 
 	tos = (mach->utop & ~7) - sizeof(Tos) * 2;
-	((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = P->pid;
+	((Tos *) vaddrnol(tos, sizeof(Tos), AWR))->pid = P->pid;
 }
 
 static int
@@ -195,12 +195,50 @@
 	return -1;
 }
 
+u32int
+hookaddr(char *name)
+{
+	Symbol s;
+
+	if(lookup(name, nil, &s) == -1)
+		return -1;
+	return s.value;
+}
+
 int
+getokrange(char *name, uvlong *bounds)
+{
+	uvlong addr;
+
+	if((addr = hookaddr(name)) == -1)
+		return 0;
+	if(fnbound(addr, bounds) == 0)
+		return 0;
+	return 2;
+}
+
+static void
+inithooks(void)
+{
+	mallocaddr = hookaddr("poolalloc");
+	reallocaddr = hookaddr("poolrealloc");
+	freeaddr = hookaddr("poolfree");
+	setmalloctagaddr = hookaddr("setmalloctag");
+	setrealloctagaddr = hookaddr("setrealloctag");
+	nokrange += getokrange("memmove", &okrange[nokrange]);
+	nokrange += getokrange("memcpy", &okrange[nokrange]);
+	nokrange += getokrange("memset", &okrange[nokrange]);
+	nokrange += getokrange("strchr", &okrange[nokrange]);
+	nokrange += getokrange("strcmp", &okrange[nokrange]);
+	nokrange += getokrange("strcpy", &okrange[nokrange]);
+}
+
+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);
@@ -220,7 +258,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);
-	newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);
+	stk = newseg((mach->utop & ~7) - STACKSIZE, STACKSIZE, SEGSTACK);
+	if(check){
+		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);
+	}
 	seek(fd, fp.txtoff - fp.hdrsz, 0);
 	if(readn(fd, text->data, fp.txtsz + fp.hdrsz) < fp.txtsz + fp.hdrsz)
 		sysfatal("%r");
@@ -229,8 +273,10 @@
 		sysfatal("%r");
 	memset(bss->data, 0, bss->size);
 	P->R[15] = fp.entry;
-	if(havesymbols && syminit(fd, &fp) < 0)
+	if(syminit(fd, &fp) < 0)
 		fprint(2, "initializing symbol table: %r\n");
+	if(check)
+		inithooks();
 	close(fd);
 	fdclear(P->fd);
 	initstack(argc, argv);
@@ -380,7 +426,7 @@
 
 	clrex();
 	uregp = P->R[13] - 18 * 4;
-	ureg = vaddrnol(uregp, 18 * 4);
+	ureg = vaddrnol(uregp, 18 * 4, 0);
 	memcpy(ureg, P->R, 15 * 4);
 	ureg[15] = type;
 	ureg[16] = P->CPSR;
@@ -387,10 +433,10 @@
 	ureg[17] = P->R[15];
 	P->R[13] = uregp;
 	msgp = P->R[13] -= ERRMAX;
-	msgb = vaddrnol(msgp, ERRMAX);
+	msgb = vaddrnol(msgp, ERRMAX, 0);
 	strncpy(msgb, msg, ERRMAX);
 	P->R[13] -= 3 * 4;
-	sp = vaddrnol(P->R[13], 3 * 4);
+	sp = vaddrnol(P->R[13], 3 * 4, 0);
 	sp[0] = 0;
 	sp[2] = msgp;
 	P->R[0] = uregp;
@@ -411,7 +457,7 @@
 		sysfatal("unhandled noted argument %d", rc);
 	}
 	P->innote = 0;
-	ureg = vaddrnol(uregp, 18 * 4); /* just to be sure */
+	ureg = vaddrnol(uregp, 18 * 4, 0); /* just to be sure */
 	memcpy(P->R, ureg, 15 * 4);
 	P->CPSR = ureg[16];
 	P->R[15] = ureg[17];
--- a/sys/src/cmd/5e/seg.c
+++ b/sys/src/cmd/5e/seg.c
@@ -17,6 +17,8 @@
 	memset(s->dref, 0, sizeof(Ref));
 	incref(s->dref);
 	s->data = s->dref + 1;
+	if(check)
+		s->shadow = emallocz((size+3)/4);
 	if(idx == SEGBSS)
 		s->flags = SEGFLLOCK;
 	P->S[idx] = s;
@@ -40,9 +42,11 @@
 }
 
 void *
-vaddr(u32int addr, u32int len, Segment **seg)
+vaddr(u32int addr, u32int len, int op, Segment **seg)
 {
 	Segment **ss, *s;
+	u32int off;
+	int bits;
 
 	for(ss = P->S; ss < P->S + SEGNUM; ss++) {
 		if(*ss == nil)
@@ -54,20 +58,28 @@
 			if(s->flags & SEGFLLOCK)
 				rlock(&s->rw);
 			*seg = s;
-			return (char *)s->data + (addr - s->start);
+			off = (addr - s->start);
+			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;
 		}
 	}
+	abort();
 	suicide("fault %.8ux (%d) @ %.8ux", addr, len, P->R[15]);
 	return nil;
 }
 
 void *
-vaddrnol(u32int addr, u32int len)
+vaddrnol(u32int addr, u32int len, int op)
 {
 	Segment *seg;
 	void *ret;
 	
-	ret = vaddr(addr, len, &seg);
+	ret = vaddr(addr, len, op, &seg);
 	segunlock(seg);
 	return ret;
 }
@@ -86,7 +98,7 @@
 	void *targ, *ret;
 	Segment *seg;
 	
-	targ = vaddr(addr, len > 0 ? len : 0, &seg);
+	targ = vaddr(addr, len > 0 ? len : 0, 0, &seg);
 	if((seg->flags & SEGFLLOCK) == 0) {
 		*copied = 0;
 		return targ;
@@ -107,7 +119,7 @@
 	void *targ, *v;
 	Segment *seg;
 	
-	targ = vaddr(addr, len, &seg);
+	targ = vaddr(addr, len, 0, &seg);
 	if((seg->flags & SEGFLLOCK) == 0) {
 		*buffered = 0;
 		return targ;
@@ -129,7 +141,7 @@
 		free(data);
 		return;
 	}
-	targ = vaddr(addr, len, &seg);
+	targ = vaddr(addr, len, 0, &seg);
 	memmove(targ, data, len);
 	segunlock(seg);
 	free(data);
--- a/sys/src/cmd/5e/sys.c
+++ b/sys/src/cmd/5e/sys.c
@@ -9,7 +9,7 @@
 arg(int n)
 {
 	/* no locking necessary, since we're on the stack */
-	return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4);
+	return *(u32int*) vaddrnol(P->R[13] + 4 + 4 * n, 4, ARD);
 }
 
 static u64int
@@ -87,6 +87,7 @@
 	u32int fd, size, buf;
 	u64int off;
 	void *targ;
+	Segment *seg;
 	
 	fd = arg(0);
 	buf = arg(1);
@@ -98,6 +99,12 @@
 	P->R[0] = noteerr(pread(fd, targ, size, off), size);
 	if(buffered)
 		copyback(buf, P->R[0], targ);
+	if(check && (s32int)P->R[0] > 0){
+		vaddr(buf, 0, 0, &seg);
+		checkaccess(seg, buf-seg->start, P->R[0], MARKALLOC);
+		markvalid(seg, buf-seg->start, P->R[0], MARKINIT);
+		segunlock(seg);
+	}
 }
 
 static void
@@ -127,7 +134,7 @@
 	vlong n, *ret;
 	Segment *seg;
 	
-	ret = vaddr(arg(0), 8, &seg);
+	ret = vaddr(arg(0), 8, 0, &seg);
 	fd = arg(1);
 	n = argv(2);
 	type = arg(4);
@@ -163,6 +170,7 @@
 	char *namet;
 	void *edirt;
 	int copied, buffered;
+	Segment *seg;
 	
 	name = arg(0);
 	namet = copyifnec(name, -1, &copied);
@@ -176,6 +184,12 @@
 		free(namet);
 	if(buffered)
 		copyback(edir, P->R[0], edirt);
+	if(check && (s32int)P->R[0] > 0){
+		vaddr(edir, 0, 0, &seg);
+		checkaccess(seg, edir-seg->start, P->R[0], MARKALLOC);
+		markvalid(seg, edir-seg->start, P->R[0], MARKINIT);
+		segunlock(seg);
+	}
 }
 
 static void
@@ -184,6 +198,7 @@
 	u32int fd, edir, nedir;
 	void *edirt;
 	int buffered;
+	Segment *seg;
 	
 	fd = arg(0);
 	edir = arg(1);
@@ -194,6 +209,12 @@
 	P->R[0] = noteerr(fstat(fd, edirt, nedir), nedir);
 	if(buffered)
 		copyback(edir, P->R[0], edirt);
+	if(check && (s32int)P->R[0] > 0){
+		vaddr(edir, 0, 0, &seg);
+		checkaccess(seg, edir-seg->start, P->R[0], MARKALLOC);
+		markvalid(seg, edir-seg->start, P->R[0], MARKINIT);
+		segunlock(seg);
+	}
 }
 
 static void
@@ -242,7 +263,7 @@
 	if(arg(0) == 0)
 		exits(nil);
 	else
-		exits(vaddrnol(arg(0), 0));
+		exits(vaddrnol(arg(0), 0, ARD));
 }
 
 static void
@@ -249,6 +270,7 @@
 sysbrk(void)
 {
 	ulong v;
+	vlong o, n;
 	Segment *s;
 	
 	v = arg(0);
@@ -260,13 +282,22 @@
 	if(v < P->S[SEGBSS]->start)
 		sysfatal("bss length < 0, wtf?");
 	s = P->S[SEGBSS];
+	n = v - s->start;
+	o = s->size;
 	wlock(&s->rw);
-	s->dref = realloc(s->dref, v - s->start + sizeof(Ref));
+	s->dref = realloc(s->dref, n + sizeof(Ref));
 	if(s->dref == nil)
 		sysfatal("error reallocating");
 	s->data = s->dref + 1;
-	if(s->size < v - s->start)
-		memset((char*)s->data + s->size, 0, v - s->start - s->size);
+	if(o < n)
+		memset((char*)s->data + o, 0, n - o);
+	if(s->shadow != nil){
+		s->shadow = realloc(s->shadow, (n+3)/4);
+		if(s->shadow == nil)
+			sysfatal("error reallocating");
+		if(n - o > 0)
+			memset(s->shadow + (o+3)/4, 0, (n - o + 3)/4);
+	}
 	s->size = v - s->start;
 	P->R[0] = 0;
 	wunlock(&s->rw);
@@ -382,6 +413,10 @@
 			incref(t->dref);
 			t->data = t->dref + 1;
 			memcpy(t->data, s->data, s->size);
+			if(t->shadow != nil){
+				t->shadow = emalloc((s->size+7)/8);
+				memcpy(t->shadow, s->shadow, (s->size+7)/8);
+			}
 			p->S[i] = t;
 		} else {
 			incref(s->dref);
@@ -420,9 +455,9 @@
 	
 	name = arg(0);
 	argv = arg(1);
-	namet = strdup(vaddr(name, 0, &seg1));
+	namet = strdup(vaddr(name, 0, ARD, &seg1));
 	segunlock(seg1);
-	argvt = vaddr(argv, 0, &seg1);
+	argvt = vaddr(argv, 0, ARD, &seg1);
 	if(systrace)
 		fprint(2, "exec(%#ux=\"%s\", %#ux)\n", name, namet, argv);
 	for(argc = 0; argvt[argc]; argc++)
@@ -429,7 +464,7 @@
 		;
 	argvv = emalloc(sizeof(char *) * argc);
 	for(i = 0; i < argc; i++) {
-		argvv[i] = strdup(vaddr(argvt[i], 0, &seg2));
+		argvv[i] = strdup(vaddr(argvt[i], 0, ARD, &seg2));
 		segunlock(seg2);
 	}
 	segunlock(seg1);
@@ -627,7 +662,7 @@
 	block = arg(1);
 	if(systrace)
 		fprint(2, "semacquire(%#ux, %ud)\n", addr, block);
-	addrt = vaddrnol(addr, 4);
+	addrt = vaddrnol(addr, 4, ARD|AWR);
 	P->R[0] = noteerr(semacquire(addrt, block), 0);
 }
 
@@ -642,7 +677,7 @@
 	count = arg(1);
 	if(systrace)
 		fprint(2, "semrelease(%#ux, %ud)\n", addr, count);
-	addrt = vaddr(addr, 4, &seg);
+	addrt = vaddr(addr, 4, ARD|AWR, &seg);
 	P->R[0] = noteerr(semrelease(addrt, count), 0);
 	segunlock(seg);
 }
--- a/sys/src/cmd/5e/vfp.c
+++ b/sys/src/cmd/5e/vfp.c
@@ -45,7 +45,7 @@
 void
 vfprmtransfer(u32int instr)
 {
-	int n, d, off, sz;
+	int m, n, d, off, sz;
 	void* ea;
 	Segment *seg;
 
@@ -55,8 +55,9 @@
 	sz = instr & (1<<8);
 	if((instr & (1<<23)) == 0)
 		off = -off;
-	ea = vaddr(evenaddr(P->R[n] + off, 3), sz ? 8 : 4, &seg);
-	switch((instr>>20)&0x3){
+	m = (instr>>20)&0x3;
+	ea = vaddr(evenaddr(P->R[n] + off, 3), sz ? 8 : 4, m?ARD:AWR, &seg);
+	switch(m){
 	case 0:
 		if(sz)
 			*(double*)ea = P->F[d];


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-09-10  1:48 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-10  1:46 [9front] 5e: add support for memory constraint checking ori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).