Bug 34412 - [patch] tftp(1) will still try and receive traffic even after receiver's disk has filled
Summary: [patch] tftp(1) will still try and receive traffic even after receiver's disk...
Status: Closed Overcome By Events
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: Unspecified
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-01-29 15:40 UTC by Todd Hayton
Modified: 2018-08-22 16:36 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Todd Hayton 2002-01-29 15:40:01 UTC
When copying a large file using tftp, if during the course of the
transfer the disk of the receiver fills up, tftp will still try
and receive more data from the sender ignoring the fact that the
write()'s are failing because there is no more space left.

Glancing over the tftp code (/usr/src/usr.bin/tftp) I noticed that
the function recvfile() in tftp.c is responsible for the reception 
of a file. Within this function another function called write_behind() 
is responsible for writing the received data to disk. Although the
write_behind() function returns the return value of the write() system 
call, this return value is never checked in the calling function recvfile().

The result is that tftp will continue recv'ing and subsequently
trying to write() the data despite the fact that each call to write()
fails.

How-To-Repeat: Try tftp'ing a large file onto a filesystem that doesn't have enough
room to hold it.
Comment 1 Maxim Konovalov 2002-01-29 17:00:02 UTC
Here is untested patch for -current (applied for RELENG_2_2_0_RELEASE
too):

Index: tftpd.c
===================================================================
RCS file: /home/ncvs/src/libexec/tftpd/tftpd.c,v
retrieving revision 1.21
diff -u -r1.21 tftpd.c
--- tftpd.c	2001/11/22 05:08:35	1.21
+++ tftpd.c	2002/01/29 16:51:15
@@ -652,7 +652,12 @@
 			syslog(LOG_ERR, "write: %m");
 			goto abort;
 		}
+		errno = 0;
 		write_behind(file, pf->f_convert);
+		if (errno == ENOSPC) {
+			nak(ENOSPACE);
+			goto abort;
+		}
 		for ( ; ; ) {
 			alarm(rexmtval);
 			n = recv(peer, dp, PKTSIZE, 0);
@@ -683,7 +688,12 @@
 			goto abort;
 		}
 	} while (size == SEGSIZE);
+	errno = 0;
 	write_behind(file, pf->f_convert);
+	if (errno == ENOSPC) {
+		nak(ENOSPACE);
+		goto abort;
+	}
 	(void) fclose(file);            /* close data file */

 	ap->th_opcode = htons((u_short)ACK);    /* send the "final" ack */

-- 
Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer
phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru
Comment 2 Maxim Konovalov 2002-01-29 18:16:16 UTC
... and for tftp:

Index: tftp.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/tftp/tftp.c,v
retrieving revision 1.7
diff -u -r1.7 tftp.c
--- tftp.c	2001/12/11 23:43:15	1.7
+++ tftp.c	2002/01/29 18:13:09
@@ -242,6 +242,10 @@
 			goto abort;
 		}
 		write_behind(file, convert);
+		if (errno == ENOSPC ) {
+			nak(errno + 100);
+			break;
+		}
 		for ( ; ; ) {
 			alarm(rexmtval);
 			do  {

-- 
Maxim Konovalov, MAcomnet, Internet-Intranet Dept., system engineer
phone: +7 (095) 796-9079, mailto: maxim@macomnet.ru
Comment 3 Crist J. Clark freebsd_committer freebsd_triage 2002-01-29 22:50:17 UTC
On Tue, Jan 29, 2002 at 10:20:02AM -0800, Maxim Konovalov wrote:
[snip]

>  ... and for tftp:
>  
>  Index: tftp.c
>  ===================================================================
>  RCS file: /home/ncvs/src/usr.bin/tftp/tftp.c,v
>  retrieving revision 1.7
>  diff -u -r1.7 tftp.c
>  --- tftp.c	2001/12/11 23:43:15	1.7
>  +++ tftp.c	2002/01/29 18:13:09
>  @@ -242,6 +242,10 @@
>   			goto abort;
>   		}
>   		write_behind(file, convert);
>  +		if (errno == ENOSPC ) {
>  +			nak(errno + 100);
>  +			break;
>  +		}
>   		for ( ; ; ) {
>   			alarm(rexmtval);
>   			do  {

Actually, this should read,

Index: tftp.c
===================================================================
RCS file: /home/ncvs/src/usr.bin/tftp/tftp.c,v
retrieving revision 1.7
diff -u -r1.7 tftp.c
--- tftp.c	2001/12/11 23:43:15	1.7
+++ tftp.c	2002/01/29 18:13:09
@@ -242,6 +242,10 @@
 			goto abort;
 		}
 		write_behind(file, convert);
+		if (errno == ENOSPC ) {
+			nak(ENOSPACE);
+			break;
+		}
 		for ( ; ; ) {
 			alarm(rexmtval);
 			do  {

That is, there is a specific error code for this condition specified
within the TFTP protocol (RFC 1350).
-- 
Crist J. Clark                     |     cjclark@alum.mit.edu
                                   |     cjclark@jhu.edu
http://people.freebsd.org/~cjc/    |     cjc@freebsd.org
Comment 4 Sheldon Hearn freebsd_committer freebsd_triage 2002-01-30 12:32:46 UTC
State Changed
From-To: open->feedback

Waiting for the originator to try Maxim's tftpd patch and Crist's 
tftp patch. 

Please copy your feedback to <bug-followup@freebsd.org>, using the 
subject line of this message.
Comment 5 Ceri Davies freebsd_committer freebsd_triage 2003-06-08 19:02:38 UTC
State Changed
From-To: feedback->closed

Feedback timeout (6 months or more). 
I will handle any feedback that this closure generates. 


Comment 6 Ceri Davies freebsd_committer freebsd_triage 2003-06-08 19:02:38 UTC
Responsible Changed
From-To: freebsd-bugs->ceri

Feedback timeout (6 months or more). 
I will handle any feedback that this closure generates.
Comment 7 Maxim Konovalov freebsd_committer freebsd_triage 2003-06-08 19:38:37 UTC
State Changed
From-To: closed->open

It is still an issue. 


Comment 8 Maxim Konovalov freebsd_committer freebsd_triage 2003-06-08 19:38:37 UTC
Responsible Changed
From-To: ceri->maxim

Hope I will commit a fix soon.
Comment 9 jyoung 2003-09-03 07:56:12 UTC
I modified Crist's and Maxim's patches slightly to improve error
reporting, and to compile for CURRENT. Light testing of out-of-space
conditions on both the client and server side succeeded.

*** tftp.c.orig Tue Sep  2 20:02:18 2003
--- tftp.c      Tue Sep  2 20:08:53 2003
***************
*** 261,270 ****
--- 261,275 ----
                        alarm(0);
                        warn("sendto");
                        goto abort;
                }
                write_behind(file, convert);
+               if (errno == ENOSPC ) {
+                       nak(ENOSPACE, (struct sockaddr *)&peer);
+                       printf("Transfer aborted (out of space)\n");
+                       break;
+               }
                for ( ; ; ) {
                        alarm(rexmtval);
                        do  {
                                fromlen = sizeof(from);
                                n = recvfrom(f, dp, PKTSIZE, 0,

*** tftpd.c.orig        Tue Sep  2 20:11:48 2003
--- tftpd.c     Tue Sep  2 20:38:20 2003
***************
*** 680,690 ****
--- 680,696 ----
  send_ack:
                if (send(peer, ackbuf, 4, 0) != 4) {
                        syslog(LOG_ERR, "write: %m");
                        goto abort;
                }
+               errno = 0;
                write_behind(file, pf->f_convert);
+               if (errno == ENOSPC) {
+                       nak(ENOSPACE);
+                       syslog(LOG_ERR, "write_behind: %m");
+                       goto abort;
+               }
                for ( ; ; ) {
                        alarm(rexmtval);
                        n = recv(peer, dp, PKTSIZE, 0);
                        alarm(0);
                        if (n < 0) {            /* really? */


-- 
Jason Young, CCIE #8607, MCSE
Sr. Network Technician, WAN Technologies
(314)817-0131
http://www.wantec.com
Comment 10 Maxim Konovalov 2003-09-03 08:46:22 UTC
Hi Jason,

On Wed, 3 Sep 2003, 00:00-0700, Jason A. Young wrote:

> The following reply was made to PR misc/34412; it has been noted by GNATS.
>
> From: "Jason A. Young" <jyoung@power.doogles.com>
> To: freebsd-gnats-submit@freebsd.org, <thayton@torrentnet.com>
> Cc:
> Subject: Re: misc/34412: tftp will still try and receive traffic even after
>  receiver disk has filled
> Date: Wed, 3 Sep 2003 01:56:12 -0500 (CDT)
>
>  I modified Crist's and Maxim's patches slightly to improve error
>  reporting, and to compile for CURRENT. Light testing of out-of-space
>  conditions on both the client and server side succeeded.

I do not think it is a correct solution for the problem.  It is a
workaround but a more correct solution is adding an error check to
write_behind() and writeit().  See a comment at the top of
tftp/tftpsubs.c.  Thanks for the effort anyway.

-- 
Maxim Konovalov, maxim@macomnet.ru, maxim@FreeBSD.org
Comment 11 Maxim Konovalov freebsd_committer freebsd_triage 2004-04-09 18:48:02 UTC
Responsible Changed
From-To: maxim->freebsd-bugs

Be honest - I do not have a free time to work on this.
Comment 12 Edwin Groothuis freebsd_committer freebsd_triage 2007-10-08 09:23:12 UTC
Responsible Changed
From-To: freebsd-bugs->edwin

I'm interested in this patch.
Comment 13 Edwin Groothuis freebsd_committer freebsd_triage 2008-02-14 10:27:36 UTC
Responsible Changed
From-To: edwin->freebsd-bugs

Give back into the pool until later.
Comment 14 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 07:59:32 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped
Comment 15 Alan Somers freebsd_committer freebsd_triage 2018-08-22 16:36:51 UTC
This is no longer an issue.  Edwin's tftpd rewrite from 2010 (r207608 and r207614) switched tftpd to buffer the entire file before writing it, rather than write it packet-at-a-time.