diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-08-27 20:33:03 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-08-27 20:33:03 +0200 |
commit | 0f97eb3a609cd892a0de1d61ef61e5b48be082d8 (patch) | |
tree | 5685c0bfe39b4fa9c29645cddf2152114660e86b /sys/src/9/port | |
parent | 8a73650874a68575fb7b93a44f3bba352c50288a (diff) |
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.
Diffstat (limited to 'sys/src/9/port')
-rw-r--r-- | sys/src/9/port/alloc.c | 55 | ||||
-rw-r--r-- | sys/src/9/port/devproc.c | 4 | ||||
-rw-r--r-- | sys/src/9/port/portfns.h | 2 |
3 files changed, 55 insertions, 6 deletions
diff --git a/sys/src/9/port/alloc.c b/sys/src/9/port/alloc.c index fc562bc55..963d60fd2 100644 --- a/sys/src/9/port/alloc.c +++ b/sys/src/9/port/alloc.c @@ -53,8 +53,27 @@ static Pool pimagmem = { .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 @@ mallocsummary(void) { poolsummary(mainmem); poolsummary(imagmem); + poolsummary(secrmem); } /* everything from here down should be the same in libc, libdebugmalloc, and the kernel */ @@ -171,12 +191,9 @@ smalloc(ulong size) { 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(); } } @@ -278,6 +295,34 @@ calloc(ulong n, ulong szelem) 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 setmalloctag(void *v, uintptr pc) { diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c index 49340adbb..9f9b9380b 100644 --- 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 @@ procread(Chan *c, void *va, long n, vlong off) 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 */ diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h index 4b639c3a1..bd0c6f16c 100644 --- a/sys/src/9/port/portfns.h +++ b/sys/src/9/port/portfns.h @@ -308,6 +308,8 @@ void sched(void); 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); |