ref: 0f97eb3a609cd892a0de1d61ef61e5b48be082d8
parent: 8a73650874a68575fb7b93a44f3bba352c50288a
author: cinap_lenrek <[email protected]>
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);