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.
This commit is contained in:
cinap_lenrek 2016-08-27 20:33:03 +02:00
parent 8a73650874
commit 0f97eb3a60
3 changed files with 55 additions and 6 deletions

View file

@ -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)
{

View file

@ -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 */

View file

@ -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);