itlibthread: fix use after free of first thread in each proc - plan9port - [fork] Plan 9 from user space Err mx1.adamsgaard.dk 70 hgit clone git://src.adamsgaard.dk/plan9port URL:git://src.adamsgaard.dk/plan9port mx1.adamsgaard.dk 70 1Log /src/plan9port/log.gph mx1.adamsgaard.dk 70 1Files /src/plan9port/files.gph mx1.adamsgaard.dk 70 1Refs /src/plan9port/refs.gph mx1.adamsgaard.dk 70 1README /src/plan9port/file/README.md.gph mx1.adamsgaard.dk 70 1LICENSE /src/plan9port/file/LICENSE.gph mx1.adamsgaard.dk 70 i--- Err mx1.adamsgaard.dk 70 1commit 2991442aef1cf020ffde43673433ee97ef322a53 /src/plan9port/commit/2991442aef1cf020ffde43673433ee97ef322a53.gph mx1.adamsgaard.dk 70 1parent a012d174336358f997ddcb0099c0b01499b053e4 /src/plan9port/commit/a012d174336358f997ddcb0099c0b01499b053e4.gph mx1.adamsgaard.dk 70 hAuthor: Russ Cox URL:mailto:rsc@swtch.com mx1.adamsgaard.dk 70 iDate: Tue, 15 Dec 2020 00:05:17 -0500 Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 ilibthread: fix use after free of first thread in each proc Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 iThis was causing sporadic but frequent crashes at startup Err mx1.adamsgaard.dk 70 iin 9pserve on the new M1 Macs, correctly diagnosing a Err mx1.adamsgaard.dk 70 iuse-after-free. Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 iDiffstat: Err mx1.adamsgaard.dk 70 i M src/libthread/thread.c | 10 +++++++++- Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i1 file changed, 9 insertions(+), 1 deletion(-) Err mx1.adamsgaard.dk 70 i--- Err mx1.adamsgaard.dk 70 1diff --git a/src/libthread/thread.c b/src/libthread/thread.c /src/plan9port/file/src/libthread/thread.c.gph mx1.adamsgaard.dk 70 it@@ -411,7 +411,14 @@ Top: Err mx1.adamsgaard.dk 70 i p->nthread--; Err mx1.adamsgaard.dk 70 i /*print("nthread %d\n", p->nthread); */ Err mx1.adamsgaard.dk 70 i _threadstkfree(t->stk, t->stksize); Err mx1.adamsgaard.dk 70 i- free(t); Err mx1.adamsgaard.dk 70 i+ /* Err mx1.adamsgaard.dk 70 i+ * Cannot free p->thread0 yet: it is used for the Err mx1.adamsgaard.dk 70 i+ * context switches back to the scheduler. Err mx1.adamsgaard.dk 70 i+ * Instead, we will free it at the end of this function. Err mx1.adamsgaard.dk 70 i+ * But all the other threads can be freed now. Err mx1.adamsgaard.dk 70 i+ */ Err mx1.adamsgaard.dk 70 i+ if(t != p->thread0) Err mx1.adamsgaard.dk 70 i+ free(t); Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 i Err mx1.adamsgaard.dk 70 i for(;;){ Err mx1.adamsgaard.dk 70 it@@ -490,6 +497,7 @@ Out: Err mx1.adamsgaard.dk 70 i unlock(&threadnproclock); Err mx1.adamsgaard.dk 70 i unlock(&p->lock); Err mx1.adamsgaard.dk 70 i _threadsetproc(nil); Err mx1.adamsgaard.dk 70 i+ free(p->thread0); Err mx1.adamsgaard.dk 70 i free(p); Err mx1.adamsgaard.dk 70 i _threadpexit(); Err mx1.adamsgaard.dk 70 i } Err mx1.adamsgaard.dk 70 .