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, .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* mainmem = &pmainmem;
Pool* imagmem = &pimagmem; Pool* imagmem = &pimagmem;
Pool* secrmem = &psecrmem;
/* /*
* because we can't print while we're holding the locks, * because we can't print while we're holding the locks,
@ -129,6 +148,7 @@ mallocsummary(void)
{ {
poolsummary(mainmem); poolsummary(mainmem);
poolsummary(imagmem); poolsummary(imagmem);
poolsummary(secrmem);
} }
/* everything from here down should be the same in libc, libdebugmalloc, and the kernel */ /* everything from here down should be the same in libc, libdebugmalloc, and the kernel */
@ -171,12 +191,9 @@ smalloc(ulong size)
{ {
void *v; void *v;
for(;;) { while((v = poolalloc(mainmem, size+Npadlong*sizeof(ulong))) == nil){
v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
if(v != nil)
break;
if(!waserror()){ if(!waserror()){
resrcwait(0); resrcwait(nil);
poperror(); poperror();
} }
} }
@ -278,6 +295,34 @@ calloc(ulong n, ulong szelem)
return v; 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 void
setmalloctag(void *v, uintptr pc) setmalloctag(void *v, uintptr pc)
{ {

View file

@ -9,6 +9,8 @@
#include "ureg.h" #include "ureg.h"
#include "edf.h" #include "edf.h"
#include <pool.h>
enum enum
{ {
Qdir, Qdir,
@ -789,7 +791,7 @@ procread(Chan *c, void *va, long n, vlong off)
if(addr < KZERO) if(addr < KZERO)
return procctlmemio(c, p, addr, va, n, 1); return procctlmemio(c, p, addr, va, n, 1);
if(!iseve()) if(!iseve() || poolisoverlap(secrmem, (uchar*)addr, n))
error(Eperm); error(Eperm);
/* validate kernel addresses */ /* validate kernel addresses */

View file

@ -308,6 +308,8 @@ void sched(void);
void scheddump(void); void scheddump(void);
void schedinit(void); void schedinit(void);
void (*screenputs)(char*, int); void (*screenputs)(char*, int);
void* secalloc(ulong);
void secfree(void*);
long seconds(void); long seconds(void);
uintptr segattach(int, char *, uintptr, uintptr); uintptr segattach(int, char *, uintptr, uintptr);
void segclock(uintptr); void segclock(uintptr);