summaryrefslogtreecommitdiff
path: root/sys/src/9/port
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2016-08-27 20:33:03 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2016-08-27 20:33:03 +0200
commit0f97eb3a609cd892a0de1d61ef61e5b48be082d8 (patch)
tree5685c0bfe39b4fa9c29645cddf2152114660e86b /sys/src/9/port
parent8a73650874a68575fb7b93a44f3bba352c50288a (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.c55
-rw-r--r--sys/src/9/port/devproc.c4
-rw-r--r--sys/src/9/port/portfns.h2
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);