Plan 9 from Bell Labs’s /usr/web/sources/contrib/yk/dist/9legacy/applied/9-sysproc-close-on-exec.diff

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


Plan 9 sysexec clears pending notes (unlike posix which leaves pending
signals active across exec).  So if fork+exec is followed immediately
by postnote("kill"), there is a window in sysexec between the last sleep
and the clearing of up->nnote where the note from the parent can be lost.
This also triggers another bug: exec clears up->nnote but does not clear
up->notepending, and therefore the first system call in the child
process which calls sleep() will be wrongly terminated with Eintr.

The parent process can detect when the child's exec has succeeded,
by opening a close-on-exec file before the fork, and waiting for
it to be closed before sending a note.  (The Go language runtime,
for example, does this.)  To eliminate the exec-postnote race in
this case, this patch moves the close-on-exec code to a later point
in the sysexec function, after pending notes have been cleared.

The race could be eliminated more simply by not clearing up->nnote
on exec, but that would change the semantics of exec and possibly
disturb some existing programs.

Reference: /n/sources/patch/exec-postnote-race
Date: Thu Apr  5 13:36:20 GMT 2018
Signed-off-by: [email protected]

--- /sys/src/9/port/sysproc.c	Thu Apr  5 13:19:42 2018
+++ /sys/src/9/port/sysproc.c	Thu Apr  5 13:19:38 2018
@@ -421,13 +421,6 @@
 		}
 	}
 
-	/*
-	 * Close on exec
-	 */
-	f = up->fgrp;
-	for(i=0; i<=f->maxfd; i++)
-		fdclose(i, CCEXEC);
-
 	/* Text.  Shared. Attaches to cache image if possible */
 	/* attachimage returns a locked cache image */
 	img = attachimage(SG_TEXT|SG_RONLY, tc, UTZERO, (t-UTZERO)>>PGSHIFT);
@@ -480,6 +473,7 @@
 	flushmmu();
 	qlock(&up->debug);
 	up->nnote = 0;
+	up->notepending = 0;
 	up->notify = 0;
 	up->notified = 0;
 	up->privatemem = 0;
@@ -487,6 +481,13 @@
 	qunlock(&up->debug);
 	if(up->hang)
 		up->procctl = Proc_stopme;
+
+	/*
+	 * Close on exec
+	 */
+	f = up->fgrp;
+	for(i=0; i<=f->maxfd; i++)
+		fdclose(i, CCEXEC);
 
 	return execregs(entry, ssize, nargs);
 }

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].