shithub: riscv

Download patch

ref: 15fc6c1cc05249f342ff4279688f1f9c4e162dec
parent: b672403c6d9ad0029782a71c2b9e4bbb8fe7fbf1
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun May 25 20:27:06 EDT 2014

devproc: handle 64bit address writes to /proc/n/mem files

procwrite() did truncate the offset to 32bit ulong.
introduce off2addr() function that does the sign
extension hack and use it conststently for Qmem
reads and writes.

--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -691,6 +691,19 @@
 	return p->pid != PID(c->qid) || p->waitq != 0;
 }
 
+/*
+ * userspace can't pass negative file offset for a
+ * 64 bit kernel address, so we use 63 bit and sign
+ * extend to 64 bit.
+ */
+static uintptr
+off2addr(vlong off)
+{
+	off <<= 1;
+	off >>= 1;
+	return off;
+}
+
 static long
 procread(Chan *c, void *va, long n, vlong off)
 {
@@ -699,7 +712,8 @@
 	int i, j, m, navail, ne, rsize;
 	long l;
 	uchar *rptr;
-	uintptr offset;
+	uintptr addr;
+	ulong offset;
 	Confmem *cm;
 	Mntwalk *mw;
 	Proc *p;
@@ -708,12 +722,7 @@
 	Waitq *wq;
 	
 	a = va;
-
-	/* sign extend 63 bit to 64 bit */
-	off <<= 1;
-	off >>= 1;
 	offset = off;
-
 	if(c->qid.type & QTDIR)
 		return devdirread(c, a, n, 0, 0, procgen);
 
@@ -763,26 +772,27 @@
 		return n;
 
 	case Qmem:
-		if(offset < KZERO)
-			return procctlmemio(p, offset, n, va, 1);
+		addr = off2addr(off);
+		if(addr < KZERO)
+			return procctlmemio(p, addr, n, va, 1);
 
 		if(!iseve())
 			error(Eperm);
 
 		/* validate kernel addresses */
-		if(offset < (uintptr)end) {
-			if(offset+n > (uintptr)end)
-				n = (uintptr)end - offset;
-			memmove(a, (char*)offset, n);
+		if(addr < (uintptr)end) {
+			if(addr+n > (uintptr)end)
+				n = (uintptr)end - addr;
+			memmove(a, (char*)addr, n);
 			return n;
 		}
 		for(i=0; i<nelem(conf.mem); i++){
 			cm = &conf.mem[i];
 			/* klimit-1 because klimit might be zero! */
-			if(cm->kbase <= offset && offset <= cm->klimit-1){
-				if(offset+n >= cm->klimit-1)
-					n = cm->klimit - offset;
-				memmove(a, (char*)offset, n);
+			if(cm->kbase <= addr && addr <= cm->klimit-1){
+				if(addr+n >= cm->klimit-1)
+					n = cm->klimit - addr;
+				memmove(a, (char*)addr, n);
 				return n;
 			}
 		}
@@ -1057,9 +1067,10 @@
 	int id, m;
 	Proc *p, *t, *et;
 	char *a, *arg, buf[ERRMAX];
-	ulong offset = off;
+	ulong offset;
 
 	a = va;
+	offset = off;
 	if(c->qid.type & QTDIR)
 		error(Eisdir);
 
@@ -1103,8 +1114,7 @@
 	case Qmem:
 		if(p->state != Stopped)
 			error(Ebadctl);
-
-		n = procctlmemio(p, offset, n, va, 0);
+		n = procctlmemio(p, off2addr(off), n, va, 0);
 		break;
 
 	case Qregs:
--