ref: ccf13d8bc560f4acd4a2028c952e07f001555ecf
parent: 8c9105b655dc3913c04334e9e750894f03502f72
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Aug 27 16:33:03 EDT 2016
kernel: add secalloc() and secfree() functions for secret memory allocation The kernel needs to keep cryptographic keys and cipher states confidential. secalloc() allocates memory from the secret pool which is protected from debuggers reading the memory thru devproc. secfree() releases the memory, overriding the data with garbage.
--- a/sys/src/9/port/alloc.c
+++ b/sys/src/9/port/alloc.c
@@ -53,8 +53,27 @@
.private= &pimagpriv,
};
+static Private psecrpriv;
+static Pool psecrmem = {+ .name= "Secrets",
+ .maxsize= 16*1024*1024,
+ .minarena= 64*1024,
+ .quantum= 32,
+ .alloc= xalloc,
+ .merge= xmerge,
+ .flags= POOL_ANTAGONISM,
+
+ .lock= plock,
+ .unlock= punlock,
+ .print= poolprint,
+ .panic= ppanic,
+
+ .private= &psecrpriv,
+};
+
Pool* mainmem = &pmainmem;
Pool* imagmem = &pimagmem;
+Pool* secrmem = &psecrmem;
/*
* because we can't print while we're holding the locks,
@@ -129,6 +148,7 @@
{poolsummary(mainmem);
poolsummary(imagmem);
+ poolsummary(secrmem);
}
/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */
@@ -171,12 +191,9 @@
{void *v;
- for(;;) {- v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
- if(v != nil)
- break;
+ while((v = poolalloc(mainmem, size+Npadlong*sizeof(ulong))) == nil){ if(!waserror()){- resrcwait(0);
+ resrcwait(nil);
poperror();
}
}
@@ -276,6 +293,34 @@
if(v = mallocz(n*szelem, 1))
setmalloctag(v, getcallerpc(&n));
return v;
+}
+
+/* secret memory, used to back cryptographic keys and cipher states */
+void*
+secalloc(ulong size)
+{+ void *v;
+
+ while((v = poolalloc(secrmem, size+Npadlong*sizeof(ulong))) == nil){+ if(!waserror()){+ resrcwait(nil);
+ poperror();
+ }
+ }
+ if(Npadlong){+ v = (ulong*)v+Npadlong;
+ setmalloctag(v, getcallerpc(&size));
+ setrealloctag(v, 0);
+ }
+ memset(v, 0, size);
+ return v;
+}
+
+void
+secfree(void *v)
+{+ if(v != nil)
+ poolfree(secrmem, (ulong*)v-Npadlong);
}
void
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -9,6 +9,8 @@
#include "ureg.h"
#include "edf.h"
+#include <pool.h>
+
enum
{Qdir,
@@ -789,7 +791,7 @@
if(addr < KZERO)
return procctlmemio(c, p, addr, va, n, 1);
- if(!iseve())
+ if(!iseve() || poolisoverlap(secrmem, (uchar*)addr, n))
error(Eperm);
/* validate kernel addresses */
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -308,6 +308,8 @@
void scheddump(void);
void schedinit(void);
void (*screenputs)(char*, int);
+void* secalloc(ulong);
+void secfree(void*);
long seconds(void);
uintptr segattach(int, char *, uintptr, uintptr);
void segclock(uintptr);
--
⑨