summaryrefslogtreecommitdiff
path: root/sys/src/9
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2023-04-08 20:30:47 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2023-04-08 20:30:47 +0000
commit60b1a2f82dc96b254d6dec1bfd1c14ca056c21dd (patch)
tree1de5c2c26d7f7d0a0def0bbe4c11971a12735730 /sys/src/9
parentbd43bd6f1ae1b1ec7ee6873d9fd6766b049802e9 (diff)
kernel: Clear secrets on reboot
The idea is that when we reboot, we zero out memory written by processes that have the private flag set (such as factotum and keyfs), and also clear the secrmem pool, which contains TLS keys and the state of the random number generator. This is so the newly booted kernel or firmware will not find these secret keys in memory.
Diffstat (limited to 'sys/src/9')
-rw-r--r--sys/src/9/bcm/main.c15
-rw-r--r--sys/src/9/bcm64/main.c18
-rw-r--r--sys/src/9/cycv/main.c6
-rw-r--r--sys/src/9/imx8/main.c11
-rw-r--r--sys/src/9/kw/main.c11
-rw-r--r--sys/src/9/mt7688/main.c8
-rw-r--r--sys/src/9/omap/main.c9
-rw-r--r--sys/src/9/pc/main.c14
-rw-r--r--sys/src/9/pc64/main.c15
-rw-r--r--sys/src/9/port/alloc.c23
-rw-r--r--sys/src/9/port/devproc.c8
-rw-r--r--sys/src/9/port/devsegment.c9
-rw-r--r--sys/src/9/port/devswap.c2
-rw-r--r--sys/src/9/port/edf.c2
-rw-r--r--sys/src/9/port/fault.c4
-rw-r--r--sys/src/9/port/page.c44
-rw-r--r--sys/src/9/port/portclock.c2
-rw-r--r--sys/src/9/port/portdat.h2
-rw-r--r--sys/src/9/port/portfns.h2
-rw-r--r--sys/src/9/port/rebootcmd.c12
-rw-r--r--sys/src/9/port/taslock.c1
-rw-r--r--sys/src/9/sgi/main.c5
-rw-r--r--sys/src/9/teg2/main.c17
-rw-r--r--sys/src/9/xen/main.c10
-rw-r--r--sys/src/9/zynq/main.c6
25 files changed, 206 insertions, 50 deletions
diff --git a/sys/src/9/bcm/main.c b/sys/src/9/bcm/main.c
index a5b32d28f..03eeb51de 100644
--- a/sys/src/9/bcm/main.c
+++ b/sys/src/9/bcm/main.c
@@ -281,9 +281,14 @@ exit(int)
{
cpushutdown();
splfhi();
- if(m->machno == 0)
- archreboot();
- rebootjump(0, 0, 0);
+ if(m->machno)
+ rebootjump(0, 0, 0);
+
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
+ archreboot();
}
/*
@@ -323,6 +328,10 @@ reboot(void *entry, void *code, ulong size)
clockshutdown();
wdogoff();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* off we go - never to return */
rebootjump(entry, code, size);
}
diff --git a/sys/src/9/bcm64/main.c b/sys/src/9/bcm64/main.c
index 38c9770b3..dc5a58af4 100644
--- a/sys/src/9/bcm64/main.c
+++ b/sys/src/9/bcm64/main.c
@@ -230,20 +230,26 @@ exit(int)
{
cpushutdown();
splfhi();
- if(m->machno == 0)
- archreboot();
- rebootjump(0, 0, 0);
+
+ if(m->machno)
+ rebootjump(0, 0, 0);
+
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
+ archreboot();
}
void
reboot(void *entry, void *code, ulong size)
{
writeconf();
+
while(m->machno != 0){
procwired(up, 0);
sched();
}
-
cpushutdown();
delay(2000);
@@ -260,6 +266,10 @@ reboot(void *entry, void *code, ulong size)
wdogoff();
intrsoff();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* off we go - never to return */
rebootjump(entry, code, size);
}
diff --git a/sys/src/9/cycv/main.c b/sys/src/9/cycv/main.c
index 569f6cb8e..e5f40ab8d 100644
--- a/sys/src/9/cycv/main.c
+++ b/sys/src/9/cycv/main.c
@@ -20,6 +20,12 @@ void
exit(int)
{
cpushutdown();
+ splhi();
+ if(m->machno == 0){
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+ }
for(;;) idlehands();
}
diff --git a/sys/src/9/imx8/main.c b/sys/src/9/imx8/main.c
index 8c90c63ac..dc64115bf 100644
--- a/sys/src/9/imx8/main.c
+++ b/sys/src/9/imx8/main.c
@@ -357,8 +357,13 @@ exit(int)
cpushutdown();
splfhi();
- if(m->machno == 0)
+ if(m->machno == 0){
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
u.r0 = 0x84000009; /* SYSTEM RESET */
+ }
smccall(&u);
}
@@ -408,6 +413,10 @@ reboot(void*, void *code, ulong size)
clockshutdown();
intrsoff();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* off we go - never to return */
rebootjump((void*)(KTZERO-KZERO), code, size);
}
diff --git a/sys/src/9/kw/main.c b/sys/src/9/kw/main.c
index 5c935b926..d0baa1e4b 100644
--- a/sys/src/9/kw/main.c
+++ b/sys/src/9/kw/main.c
@@ -308,6 +308,13 @@ exit(int)
{
cpushutdown();
splhi();
+
+ if(m->machno == 0){
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+ }
+
archreboot();
}
@@ -334,6 +341,10 @@ reboot(void *entry, void *code, ulong size)
splhi();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* setup reboot trampoline function */
f = (void*)REBOOTADDR;
memmove(f, rebootcode, sizeof(rebootcode));
diff --git a/sys/src/9/mt7688/main.c b/sys/src/9/mt7688/main.c
index 8a825cb6b..4984b0861 100644
--- a/sys/src/9/mt7688/main.c
+++ b/sys/src/9/mt7688/main.c
@@ -247,10 +247,14 @@ init0(void)
void
exit(int)
{
- iprint("main exit called\n");
- delay(50);
cpushutdown();
splhi();
+ if(m->machno == 0){
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+ }
+ for(;;);
}
void
diff --git a/sys/src/9/omap/main.c b/sys/src/9/omap/main.c
index 913a03b58..3826ca40b 100644
--- a/sys/src/9/omap/main.c
+++ b/sys/src/9/omap/main.c
@@ -253,6 +253,11 @@ exit(int)
{
cpushutdown();
splhi();
+ if(m->machno == 0){
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+ }
archreboot();
}
@@ -319,6 +324,10 @@ reboot(void *entry, void *code, ulong size)
splhi();
intrsoff();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* setup reboot trampoline function */
f = (void*)REBOOTADDR;
memmove(f, rebootcode, sizeof(rebootcode));
diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c
index b662323ef..38ac64313 100644
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -316,7 +316,6 @@ rebootjump(uintptr entry, uintptr code, ulong size)
void (*f)(uintptr, uintptr, ulong);
ulong *pdb;
- splhi();
arch->introff();
/*
@@ -342,8 +341,15 @@ void
exit(int)
{
cpushutdown();
+ splhi();
+
if(m->machno)
rebootjump(0, 0, 0);
+
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
arch->reset();
}
@@ -359,7 +365,7 @@ reboot(void *entry, void *code, ulong size)
* because the hardware has a notion of which processor was the
* boot processor and we look at it at start up.
*/
- if (m->machno != 0) {
+ if(m->machno){
procwired(up, 0);
sched();
}
@@ -373,6 +379,10 @@ reboot(void *entry, void *code, ulong size)
/* shutdown devices */
chandevshutdown();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* disable pci devices */
pcireset();
diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c
index 02b551165..3caeece36 100644
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -225,7 +225,6 @@ rebootjump(uintptr entry, uintptr code, ulong size)
void (*f)(uintptr, uintptr, ulong);
uintptr *pte;
- splhi();
arch->introff();
/*
@@ -252,13 +251,19 @@ rebootjump(uintptr entry, uintptr code, ulong size)
for(;;);
}
-
void
exit(int)
{
cpushutdown();
+ splhi();
+
if(m->machno)
rebootjump(0, 0, 0);
+
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
arch->reset();
}
@@ -274,7 +279,7 @@ reboot(void *entry, void *code, ulong size)
* because the hardware has a notion of which processor was the
* boot processor and we look at it at start up.
*/
- if (m->machno != 0) {
+ while(m->machno != 0){
procwired(up, 0);
sched();
}
@@ -288,6 +293,10 @@ reboot(void *entry, void *code, ulong size)
/* shutdown devices */
chandevshutdown();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* disable pci devices */
pcireset();
diff --git a/sys/src/9/port/alloc.c b/sys/src/9/port/alloc.c
index 6c3519fdf..70ea42a15 100644
--- a/sys/src/9/port/alloc.c
+++ b/sys/src/9/port/alloc.c
@@ -171,7 +171,7 @@ mallocsummary(void)
/* non tracing
*
enum {
- Npadlong = 0,
+ Npadlong = 0,
MallocOffset = 0,
ReallocOffset = 0,
};
@@ -180,7 +180,7 @@ enum {
/* tracing */
enum {
- Npadlong = 2,
+ Npadlong = 2,
MallocOffset = 0,
ReallocOffset = 1
};
@@ -228,12 +228,14 @@ mallocz(ulong size, int clr)
void *v;
v = poolalloc(mainmem, size+Npadlong*sizeof(ulong));
- if(Npadlong && v != nil){
+ if(v == nil)
+ return nil;
+ if(Npadlong){
v = (ulong*)v+Npadlong;
setmalloctag(v, getcallerpc(&size));
setrealloctag(v, 0);
}
- if(clr && v != nil)
+ if(clr)
memset(v, 0, size);
return v;
}
@@ -244,13 +246,14 @@ mallocalign(ulong size, ulong align, long offset, ulong span)
void *v;
v = poolallocalign(mainmem, size+Npadlong*sizeof(ulong), align, offset-Npadlong*sizeof(ulong), span);
- if(Npadlong && v != nil){
+ if(v == nil)
+ return nil;
+ if(Npadlong){
v = (ulong*)v+Npadlong;
setmalloctag(v, getcallerpc(&size));
setrealloctag(v, 0);
}
- if(v)
- memset(v, 0, size);
+ memset(v, 0, size);
return v;
}
@@ -268,10 +271,10 @@ realloc(void *v, ulong size)
if(v != nil)
v = (ulong*)v-Npadlong;
- if(Npadlong !=0 && size != 0)
+ if(Npadlong && size != 0)
size += Npadlong*sizeof(ulong);
-
- if(nv = poolrealloc(mainmem, v, size)){
+ nv = poolrealloc(mainmem, v, size);
+ if(nv != nil){
nv = (ulong*)nv+Npadlong;
setrealloctag(nv, getcallerpc(&v));
if(v == nil)
diff --git a/sys/src/9/port/devproc.c b/sys/src/9/port/devproc.c
index b56b69e59..ffabca2d5 100644
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -1474,6 +1474,14 @@ procctlreq(Proc *p, char *va, int n)
break;
case CMprivate:
p->privatemem = 1;
+ /*
+ * pages will now get marked private
+ * when faulted in for writing
+ * so force a tlb flush.
+ */
+ p->newtlb = 1;
+ if(p == up)
+ flushmmu();
break;
case CMprofile:
s = p->seg[TSEG];
diff --git a/sys/src/9/port/devsegment.c b/sys/src/9/port/devsegment.c
index d24e0b72e..8c3a503ea 100644
--- a/sys/src/9/port/devsegment.c
+++ b/sys/src/9/port/devsegment.c
@@ -467,7 +467,6 @@ Found:
static Segment*
fixedseg(uintptr va, ulong len)
{
- KMap *k;
Segment *s;
Page **f, *p, *l, *h, *t;
ulong n, i;
@@ -522,15 +521,11 @@ fixedseg(uintptr va, ulong len)
p++;
p->ref = 1;
p->va = va;
+ va += BY2PG;
p->modref = 0;
settxtflush(p, 1);
-
- k = kmap(p);
- memset((void*)VA(k), 0, BY2PG);
- kunmap(k);
-
+ zeropage(p);
segpage(s, p);
- va += BY2PG;
} while(p != l);
poperror();
return s;
diff --git a/sys/src/9/port/devswap.c b/sys/src/9/port/devswap.c
index a30560c90..e1a2d5e4b 100644
--- a/sys/src/9/port/devswap.c
+++ b/sys/src/9/port/devswap.c
@@ -245,7 +245,7 @@ pageout(Proc *p, Segment *s)
continue;
for(pg = l->first; pg <= l->last; pg++) {
entry = *pg;
- if(pagedout(entry))
+ if(pagedout(entry) || entry->modref & PG_PRIV)
continue;
if(entry->modref & PG_REF) {
entry->modref &= ~PG_REF;
diff --git a/sys/src/9/port/edf.c b/sys/src/9/port/edf.c
index 213567023..c8c5410c2 100644
--- a/sys/src/9/port/edf.c
+++ b/sys/src/9/port/edf.c
@@ -134,7 +134,6 @@ static void
deadlineintr(Ureg*, Timer *t)
{
/* Proc reached deadline */
- extern int panicking;
Proc *p;
void (*pt)(Proc*, int, vlong);
@@ -210,7 +209,6 @@ static void
releaseintr(Ureg *u, Timer *t)
{
Proc *p;
- extern int panicking;
Schedq *rq;
if(panicking || active.exiting)
diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c
index 719b64f46..f6751cea9 100644
--- a/sys/src/9/port/fault.c
+++ b/sys/src/9/port/fault.c
@@ -209,12 +209,12 @@ fixfault(Segment *s, uintptr addr, int read)
/* wet floor */
case SG_STICKY: /* Never paged out */
mmuphys = PPN((*pg)->pa) | PTEWRITE | PTECACHED | PTEVALID;
- (*pg)->modref = PG_MOD|PG_REF;
+ (*pg)->modref |= up->privatemem? PG_PRIV|PG_MOD|PG_REF: PG_MOD|PG_REF;
break;
case SG_FIXED: /* Never paged out */
mmuphys = PPN((*pg)->pa) | PTEWRITE | PTEUNCACHED | PTEVALID;
- (*pg)->modref = PG_MOD|PG_REF;
+ (*pg)->modref |= up->privatemem? PG_PRIV|PG_MOD|PG_REF: PG_MOD|PG_REF;
break;
}
diff --git a/sys/src/9/port/page.c b/sys/src/9/port/page.c
index 869a8733e..089b8dcd3 100644
--- a/sys/src/9/port/page.c
+++ b/sys/src/9/port/page.c
@@ -169,7 +169,6 @@ Page*
newpage(int clear, Segment **s, uintptr va)
{
Page *p, **l;
- KMap *k;
int color;
lock(&palloc);
@@ -229,11 +228,8 @@ newpage(int clear, Segment **s, uintptr va)
p->modref = 0;
inittxtflush(p);
- if(clear) {
- k = kmap(p);
- memset((void*)VA(k), 0, BY2PG);
- kunmap(k);
- }
+ if(clear)
+ zeropage(p);
return p;
}
@@ -266,6 +262,16 @@ copypage(Page *f, Page *t)
}
void
+zeropage(Page *p)
+{
+ KMap *k;
+
+ k = kmap(p);
+ memset((void*)VA(k), 0, BY2PG);
+ kunmap(k);
+}
+
+void
cachepage(Page *p, Image *i)
{
Page **h;
@@ -392,3 +398,29 @@ freepte(Segment*, Pte *p)
}
free(p);
}
+
+void
+zeroprivatepages(void)
+{
+ Page *p, *pe;
+
+ /*
+ * in case of a panic, we might not have a process
+ * context to do the clearing of the private pages.
+ */
+ if(up == nil){
+ assert(panicking);
+ return;
+ }
+
+ lock(&palloc);
+ pe = palloc.pages + palloc.user;
+ for(p = palloc.pages; p != pe; p++) {
+ if(p->modref & PG_PRIV){
+ incref(p);
+ zeropage(p);
+ decref(p);
+ }
+ }
+ unlock(&palloc);
+}
diff --git a/sys/src/9/port/portclock.c b/sys/src/9/port/portclock.c
index e12938bc3..a1bef59a4 100644
--- a/sys/src/9/port/portclock.c
+++ b/sys/src/9/port/portclock.c
@@ -164,7 +164,7 @@ hzclock(Ureg *ur)
return;
if(active.exiting)
- exit(0);
+ exit(panicking);
if(m->machno == 0)
checkalarms();
diff --git a/sys/src/9/port/portdat.h b/sys/src/9/port/portdat.h
index f78f5f35d..7a4c88746 100644
--- a/sys/src/9/port/portdat.h
+++ b/sys/src/9/port/portdat.h
@@ -322,6 +322,7 @@ enum
{
PG_MOD = 0x01, /* software modified bit */
PG_REF = 0x02, /* software referenced bit */
+ PG_PRIV = 0x04, /* private page */
};
struct Page
@@ -808,6 +809,7 @@ extern uchar initcode[];
extern Queue* kprintoq;
extern int nsyscall;
extern Palloc palloc;
+extern int panicking;
extern Queue* serialoq;
extern char* statename[];
extern Image swapimage;
diff --git a/sys/src/9/port/portfns.h b/sys/src/9/port/portfns.h
index c6877690d..53de3210a 100644
--- a/sys/src/9/port/portfns.h
+++ b/sys/src/9/port/portfns.h
@@ -407,6 +407,8 @@ int xmerge(void*, void*);
void* xspanalloc(ulong, int, ulong);
void xsummary(void);
void yield(void);
+void zeropage(Page*);
+void zeroprivatepages(void);
Segment* data2txt(Segment*);
Segment* dupseg(Segment**, int, int);
Segment* newseg(int, uintptr, ulong);
diff --git a/sys/src/9/port/rebootcmd.c b/sys/src/9/port/rebootcmd.c
index 4f3b8fb03..7aef57d19 100644
--- a/sys/src/9/port/rebootcmd.c
+++ b/sys/src/9/port/rebootcmd.c
@@ -33,8 +33,18 @@ rebootcmd(int argc, char *argv[])
ulong magic, text, rtext, entry, data, size, align;
uchar *p;
- if(argc == 0)
+ if(argc == 0){
+ /*
+ * call exit() from cpu0, so zeroprivatepages()
+ * has our user process for kmap().
+ */
+ while(m->machno != 0){
+ procwired(up, 0);
+ sched();
+ }
exit(0);
+ return;
+ }
c = namec(argv[0], Aopen, OEXEC, 0);
if(waserror()){
diff --git a/sys/src/9/port/taslock.c b/sys/src/9/port/taslock.c
index 54aabf758..cc424c9b3 100644
--- a/sys/src/9/port/taslock.c
+++ b/sys/src/9/port/taslock.c
@@ -36,7 +36,6 @@ dumplockmem(char *tag, Lock *l)
void
lockloop(Lock *l, uintptr pc)
{
- extern int panicking;
Proc *p;
if(panicking)
diff --git a/sys/src/9/sgi/main.c b/sys/src/9/sgi/main.c
index 4e0aa75ba..d1bafbd29 100644
--- a/sys/src/9/sgi/main.c
+++ b/sys/src/9/sgi/main.c
@@ -266,6 +266,11 @@ exit(int)
{
cpushutdown();
splhi();
+
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
arcs(0x18); /* reboot */
}
diff --git a/sys/src/9/teg2/main.c b/sys/src/9/teg2/main.c
index abef6d200..6625a021a 100644
--- a/sys/src/9/teg2/main.c
+++ b/sys/src/9/teg2/main.c
@@ -427,14 +427,19 @@ exit(int)
{
cpushutdown();
splhi();
- if (m->machno == 0)
- archreboot();
- else {
+
+ if(m->machno){
intrcpushutdown();
stopcpu(m->machno);
for (;;)
idlehands();
}
+
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
+ archreboot();
}
int
@@ -489,7 +494,7 @@ reboot(void *entry, void *code, ulong size)
* the boot processor is cpu0. execute this function on it
* so that the new kernel has the same cpu0.
*/
- if (m->machno != 0) {
+ while(m->machno != 0){
procwired(up, 0);
sched();
}
@@ -514,6 +519,10 @@ reboot(void *entry, void *code, ulong size)
splhi();
intrshutdown();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* setup reboot trampoline function */
f = (void*)REBOOTADDR;
memmove(f, rebootcode, sizeof(rebootcode));
diff --git a/sys/src/9/xen/main.c b/sys/src/9/xen/main.c
index 5590f763b..2e667df63 100644
--- a/sys/src/9/xen/main.c
+++ b/sys/src/9/xen/main.c
@@ -380,6 +380,10 @@ reboot(void *entry, void *code, ulong size)
/* shutdown devices */
chandevshutdown();
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
/* reboot(0, ...) on Xen causes domU shutdown */
if(entry == 0)
HYPERVISOR_shutdown(0);
@@ -398,5 +402,11 @@ void
exit(int)
{
cpushutdown();
+ splhi();
+
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+
arch->reset();
}
diff --git a/sys/src/9/zynq/main.c b/sys/src/9/zynq/main.c
index dd40547be..06686e81a 100644
--- a/sys/src/9/zynq/main.c
+++ b/sys/src/9/zynq/main.c
@@ -20,6 +20,12 @@ void
exit(int)
{
cpushutdown();
+ splhi();
+ if(m->machno == 0){
+ /* clear secrets */
+ zeroprivatepages();
+ poolreset(secrmem);
+ }
for(;;) idlehands();
}