[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xdm race condition



I found another xdm bug.  This time it's a race condition in 

xc/programs/xdm/policy.c:Willing

around line numbers 140--145, which reads

	    if ((fd = popen(willing, "r")))
	    {
		char *s = NULL;
		while(!(s = fgets(statusBuf, 256, fd)) && errno == EINTR)
			;

Here's the problem.  The "popen" call creates a child process and a
pipe to communicate with it.  If the child process exits during the
"fgets" call without generating any output, the parent process
receives SIGCHLD and the read system call gets interrupted.  Therefore
errno == EINTR, and since the child has exited the pipe never returns
any data.  xdm goes into an infinite loop.  I think the problem is
that fgets doesn't reset errno to zero; we have to do that manually.
The fix is the trivial patch attached to this email.

(The child process is the "Xwilling" script; in the case of the default
Debian configuration it is

"su nobody -c /usr/X11R6/lib/X11/xdm/Xwilling")

Chip

-- 
Charles M. "Chip" Coldwell
System Administrator
Harvard Physics Department
617-495-3388
--- xc/programs/xdm/policy.c~	2002-12-07 15:31:04.000000000 -0500
+++ xc/programs/xdm/policy.c	2004-06-24 09:56:19.000000000 -0400
@@ -140,8 +140,9 @@
 	    if ((fd = popen(willing, "r")))
 	    {
 		char *s = NULL;
+		errno = 0;
 		while(!(s = fgets(statusBuf, 256, fd)) && errno == EINTR)
-			;
+			errno = 0;
 		if (s && strlen(statusBuf) > 0)
 			statusBuf[strlen(statusBuf)-1] = 0; /* chop newline */
 		else

Reply to: