From Johannes Stille:

When we get an EN8 response while we're already sending the file using
the i protocol, this can happen:

In send.c, flocal_send_await_reply() is called. This function calls
flocal_send_fail() to process the aborted transfer. After this, we run
into the branch that calls ffileseekend() to force the end of the
actual transfer.

Now flocal_send_fail() frees qtrans, but qtrans is still used later!

I propose to fix this by moving the usfree_send(qtrans) out of
flocal_send_fail(), as in the patch I append to this mail.

...

I have found a race condition in the uucp 1.05 code. The typical result
is that the connections mysteriously fails with "conversation failed",
even while all files were transmitted. This is the problem:

At least for the i protocol, the code to send a packet can receive and
process packets after sending.
In several places in the code, we send a command and then prepare to
receive an answer.
Now the answer might already arrive during the call that sends the
command while we aren't ready to process it.

The general solution is IMHO first to do all preparations and only as a
last step to send out the command.

Reviewed by:	John Dyson
Submitted by:	Johannes Stille
This commit is contained in:
dg 1994-11-06 10:17:13 +00:00
parent 196a487259
commit a8a06384b5
2 changed files with 32 additions and 24 deletions

View File

@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
const char rec_rcsid[] = "$Id: rec.c,v 1.34 1994/04/04 03:25:12 ian Rel $";
const char rec_rcsid[] = "$Id: rec.c,v 1.2 1994/05/07 18:13:55 ache Exp $";
#endif
#include <errno.h>
@ -793,15 +793,6 @@ fremote_send_reply (qtrans, qdaemon)
else
sprintf (ab + 2, " 0x%lx", (unsigned long) qtrans->ipos);
if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, qtrans->ilocal,
qtrans->iremote))
{
(void) ffileclose (qtrans->e);
(void) remove (qinfo->ztemp);
urrec_free (qtrans);
return FALSE;
}
qinfo->freplied = TRUE;
if (qdaemon->qproto->pffile != NULL)
@ -818,6 +809,15 @@ fremote_send_reply (qtrans, qdaemon)
}
}
if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, qtrans->ilocal,
qtrans->iremote))
{
(void) ffileclose (qtrans->e);
(void) remove (qinfo->ztemp);
urrec_free (qtrans);
return FALSE;
}
return TRUE;
}
@ -862,6 +862,8 @@ fremote_send_fail_send (qtrans, qdaemon)
struct srecfailinfo *qinfo = (struct srecfailinfo *) qtrans->pinfo;
char ab[4];
boolean fret;
int ilocal = qtrans->ilocal;
int iremote = qtrans->iremote;
/* Wait for the end of file marker if we haven't gotten it yet. */
if (! qinfo->freceived)
@ -898,9 +900,6 @@ fremote_send_fail_send (qtrans, qdaemon)
ab[3] = '\0';
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, qtrans->ilocal,
qtrans->iremote);
qinfo->fsent = TRUE;
if (qinfo->freceived)
@ -909,6 +908,8 @@ fremote_send_fail_send (qtrans, qdaemon)
utransfree (qtrans);
}
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, ab, ilocal, iremote);
return fret;
}
@ -1235,6 +1236,8 @@ frec_file_send_confirm (qtrans, qdaemon)
struct srecinfo *qinfo = (struct srecinfo *) qtrans->pinfo;
const char *zsend;
boolean fret;
int ilocal = qtrans->ilocal;
int iremote = qtrans->iremote;
if (! qinfo->fmoved)
zsend = "CN5";
@ -1252,9 +1255,6 @@ frec_file_send_confirm (qtrans, qdaemon)
zsend = "CYM";
}
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend,
qtrans->ilocal, qtrans->iremote);
/* Now, if that was a remote command, then when the confirmation
message is acked we no longer have to remember that we received
that file. */
@ -1262,6 +1262,9 @@ frec_file_send_confirm (qtrans, qdaemon)
usent_receive_ack (qdaemon, qtrans);
urrec_free (qtrans);
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, ilocal, iremote);
return fret;
}

View File

@ -26,7 +26,7 @@
#include "uucp.h"
#if USE_RCS_ID
const char send_rcsid[] = "$Id: send.c,v 1.46 1994/04/10 23:13:29 ian Rel $";
const char send_rcsid[] = "$Id: send.c,v 1.2 1994/05/07 18:13:57 ache Exp $";
#endif
#include <errno.h>
@ -346,9 +346,6 @@ flocal_send_fail (qtrans, qcmd, qdaemon, zwhy)
(void) fsysdep_did_work (qcmd->pseq);
if (qtrans != NULL)
usfree_send (qtrans);
return TRUE;
}
@ -371,8 +368,12 @@ flocal_send_request (qtrans, qdaemon)
/* Make sure the file meets any remote size restrictions. */
if (qdaemon->cmax_receive != -1
&& qdaemon->cmax_receive < qinfo->cbytes)
return flocal_send_fail (qtrans, &qtrans->s, qdaemon,
{
fret = flocal_send_fail (qtrans, &qtrans->s, qdaemon,
"too large for receiver");
usfree_send (qtrans);
return fret;
}
/* Make sure the file still exists--it may have been removed between
the conversation startup and now. After we have sent over the S
@ -595,7 +596,10 @@ flocal_send_await_reply (qtrans, qdaemon, zdata, cdata)
{
if (! flocal_send_fail ((struct stransfer *) NULL, &qtrans->s,
qdaemon, zerr))
return FALSE;
{
usfree_send (qtrans);
return FALSE;
}
}
/* If the protocol does not support multiple channels, we can
@ -1036,6 +1040,8 @@ fremote_rec_fail_send (qtrans, qdaemon)
enum tfailure *ptinfo = (enum tfailure *) qtrans->pinfo;
const char *z;
boolean fret;
int ilocal = qtrans->ilocal;
int iremote = qtrans->iremote;
switch (*ptinfo)
{
@ -1051,10 +1057,9 @@ fremote_rec_fail_send (qtrans, qdaemon)
break;
}
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, z, qtrans->ilocal,
qtrans->iremote);
xfree (qtrans->pinfo);
utransfree (qtrans);
fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, z, ilocal, iremote);
return fret;
}