git: 9front

Download patch

ref: 56fe39da450d8dbc515da70f342bfa4fb626ff9e
parent: 58a65394e12bfe29efd163847280d9a3e99fc22a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Fri Jun 27 13:01:02 EDT 2025

kernel: fix crash in fpunoted() when called from noted(NRSTR) (thanks yuvia)

We must call fpunoted() only when actually notified.
In case of NRSTR, it can be called from outside of note
handler!

This issue was reproduced by hitting del on ape/psh prompt.

--- a/sys/src/9/arm64/trap.c
+++ b/sys/src/9/arm64/trap.c
@@ -268,16 +268,16 @@
 	uintptr oureg, sp;
 
 	qlock(&up->debug);
-	if(arg0 != NRSTR && !up->notified){
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted(up);
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	splhi();
-	fpunoted(up);
-	spllo();
 
 	nureg = up->ureg;
 	
--- a/sys/src/9/cycv/trap.c
+++ b/sys/src/9/cycv/trap.c
@@ -292,17 +292,17 @@
 	ulong oureg, sp;
 	
 	qlock(&up->debug);
-	if(arg0 != NRSTR && !up->notified){
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted();
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
 
-	splhi();
-	fpunoted();
-	spllo();
-	
 	nureg = up->ureg;
 	oureg = (ulong) nureg;
 	if(!okaddr(oureg - BY2WD, BY2WD + sizeof(Ureg), 0) || (oureg & 3) != 0){
--- a/sys/src/9/mt7688/syscall.c
+++ b/sys/src/9/mt7688/syscall.c
@@ -116,14 +116,14 @@
 	ulong oureg, sp;
 
 	qlock(&up->debug);
-	if(arg0!=NRSTR && !up->notified) {
+	if(up->notified){
+		up->notified = 0;
+		fpunoted();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	fpunoted();
 
 	nur = up->ureg;
 
--- a/sys/src/9/omap/syscall.c
+++ b/sys/src/9/omap/syscall.c
@@ -28,16 +28,16 @@
 	NFrame *nf;
 
 	qlock(&up->debug);
-	if(arg0 != NRSTR && !up->notified){
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted();
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	splhi();
-	fpunoted();
-	spllo();
 
 	nf = up->ureg;
 
--- a/sys/src/9/pc/trap.c
+++ b/sys/src/9/pc/trap.c
@@ -534,16 +534,16 @@
 	ulong oureg, sp;
 
 	qlock(&up->debug);
-	if(arg0!=NRSTR && !up->notified) {
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted(up);
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	splhi();
-	fpunoted(up);
-	spllo();
 
 	nureg = up->ureg;	/* pointer to user returned Ureg struct */
 
--- a/sys/src/9/pc64/trap.c
+++ b/sys/src/9/pc64/trap.c
@@ -516,16 +516,16 @@
 	uintptr oureg, sp;
 
 	qlock(&up->debug);
-	if(arg0!=NRSTR && !up->notified) {
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted(up);
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	splhi();
-	fpunoted(up);
-	spllo();
 
 	nureg = up->ureg;	/* pointer to user returned Ureg struct */
 
--- a/sys/src/9/sgi/trap.c
+++ b/sys/src/9/sgi/trap.c
@@ -528,16 +528,16 @@
 	ulong oureg, sp;
 
 	qlock(&up->debug);
-	if(arg0!=NRSTR && !up->notified) {
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted();
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	splhi();
-	fpunoted();
-	spllo();
 
 	nur = up->ureg;
 	oureg = (ulong)nur;
--- a/sys/src/9/xen/trap.c
+++ b/sys/src/9/xen/trap.c
@@ -440,16 +440,16 @@
 	ulong oureg, sp;
 
 	qlock(&up->debug);
-	if(arg0!=NRSTR && !up->notified) {
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted(up);
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	splhi();
-	fpunoted(up);
-	spllo();
 
 	nureg = up->ureg;	/* pointer to user returned Ureg struct */
 
--- a/sys/src/9/zynq/trap.c
+++ b/sys/src/9/zynq/trap.c
@@ -331,16 +331,16 @@
 	ulong oureg, sp;
 	
 	qlock(&up->debug);
-	if(arg0 != NRSTR && !up->notified){
+	if(up->notified){
+		up->notified = 0;
+		splhi();
+		fpunoted();
+		spllo();
+	} else if(arg0!=NRSTR){
 		qunlock(&up->debug);
 		pprint("call to noted() when not notified\n");
 		pexit("Suicide", 0);
 	}
-	up->notified = 0;
-
-	splhi();
-	fpunoted();
-	spllo();
 
 	nureg = up->ureg;	
 	oureg = (ulong) nureg;
--