[net.sources.bugs] Another race condition fixed in RFS

toddb@tekcrl.UUCP (Todd Brunhoff) (08/22/86)

Bill Sommerfeld <wesommer@athena.mit.edu> has done another marvelous job
of finding another crash condition and providing the fix.  These are
his paraphrased comments followed by the diffs.

	When sleeping in rmt_getmsg, waiting to grab the
	connection, you didn't check to see if rp->close is true every time
	you wake up..  

	Imagine the following scenario:

	(watching this with debug set to 0xc00 helps)

	A: goes into the sleep waiting for the connection (on &rp->r_recver)
	B: does random remote i/o and sees the connection break in getmsg
	B: calls rmt_shutdown, sets rp->r_close to true, wakes up
		&rp->r_recver, 
	B: returns error code from remoteio
	A: wakes up, grabs the connection
	A: drops right into rmt_uio where it attempts to access the socket
	A: falls down dead in sorecieve with a protection fault (scribbled
		socket).

	This fix also means that when there are multiple processes using a
	connection, and the connection dies, *ALL* of them wake up with error
	messages (not just the one which happened to be active at the time).
	This is a feature!

RCS file: RCS/rmt_io.c,v
retrieving revision 2.6
diff -c -r2.6 rmt_io.c
*** /tmp/,RCSt1014402	Fri Aug 22 10:49:55 1986
--- rmt_io.c	Fri Aug 22 10:41:54 1986
***************
*** 11,17
   * may be copied, modified or used in any way, without fee, provided this
   * notice remains an unaltered part of the software.
   *
!  * $Header: rmt_io.c,v 2.6 86/08/08 14:39:13 toddb Exp $
   *
   * $Log:	rmt_io.c,v $
   * Revision 2.6  86/08/08  14:39:13  toddb

--- 11,17 -----
   * may be copied, modified or used in any way, without fee, provided this
   * notice remains an unaltered part of the software.
   *
!  * $Header: rmt_io.c,v 2.7 86/08/22 10:37:11 toddb Exp $
   *
   * $Log:	rmt_io.c,v $
   * Revision 2.7  86/08/22  10:37:11  toddb
***************
*** 14,19
   * $Header: rmt_io.c,v 2.6 86/08/08 14:39:13 toddb Exp $
   *
   * $Log:	rmt_io.c,v $
   * Revision 2.6  86/08/08  14:39:13  toddb
   * Removed unnecessary printf from rmt_closehost().
   * 

--- 14,26 -----
   * $Header: rmt_io.c,v 2.7 86/08/22 10:37:11 toddb Exp $
   *
   * $Log:	rmt_io.c,v $
+  * Revision 2.7  86/08/22  10:37:11  toddb
+  * While waiting for the use of the socket, the code in rmt_getmsg()
+  * neglected to check whether the connection was closed or closing.
+  * This meant that if it did close while a process was waiting, the
+  * process would begin to use an invalid socket.  Fix by
+  * wesommer@athena.mit.edu.
+  * 
   * Revision 2.6  86/08/08  14:39:13  toddb
   * Removed unnecessary printf from rmt_closehost().
   * 
***************
*** 435,441
  		 * that we are the recipient of this message.  In fact,
  		 * the message may have already arrived.
  		 */
! 		while (rp->r_recver != u.u_procp->p_pid && rp->r_recver != -1)
  			sleep((caddr_t)&rp->r_recver, PZERO+1);
  		if (rp->r_recver == u.u_procp->p_pid && rp->r_received) {
  			auio.uio_resid = 0;

--- 442,450 -----
  		 * that we are the recipient of this message.  In fact,
  		 * the message may have already arrived.
  		 */
! 		while (rp->r_recver != u.u_procp->p_pid
! 		    && rp->r_recver != -1
! 		    && ! rp->r_close)
  			sleep((caddr_t)&rp->r_recver, PZERO+1);
  		if (rp->r_close)
  			break;
***************
*** 437,442
  		 */
  		while (rp->r_recver != u.u_procp->p_pid && rp->r_recver != -1)
  			sleep((caddr_t)&rp->r_recver, PZERO+1);
  		if (rp->r_recver == u.u_procp->p_pid && rp->r_received) {
  			auio.uio_resid = 0;
  			break;

--- 446,453 -----
  		    && rp->r_recver != -1
  		    && ! rp->r_close)
  			sleep((caddr_t)&rp->r_recver, PZERO+1);
+ 		if (rp->r_close)
+ 			break;
  		if (rp->r_recver == u.u_procp->p_pid && rp->r_received) {
  			auio.uio_resid = 0;
  			break;