Your message dated Sun, 27 Sep 2026 15:00:07 +0200 with message-id <[email protected]> and subject line Re: Bug#979209: handle interrupted and partial uploads has caused the Debian Bug report #979209, regarding handle interrupted and partial uploads to be marked as done.
This means that you claim that the problem has been dealt with. If this is not the case it is now your responsibility to reopen the Bug report if necessary, and/or fix the problem forthwith. (NB: If you are a system administrator and have no idea what this message is talking about, this may indicate a serious mail system misconfiguration somewhere. Please contact [email protected] immediately.) -- 979209: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=979209 Debian Bug Tracking System Contact [email protected] with problems
--- Begin Message ---Package: tftpd-hpa Version: 5.2+20150808-1.2 We have discovered that tftpd-hpa does not detect a partial upload nor does it remove the file in case of an interrupted upload. The attached patch fixes both of these issues. Specifically, it does the following: 1. If the client sent the upload tsize, then verify that it matches the final file size on disk. 2. And, if the sizes do not match or any other error was encountered during upload, log a warning and remove the file. We have tested the patch both manually with curl to confirm the above error cases are indeed handled as expected, and on our CI system (where tftpd-hpa is used to communicate result from the VM to the host) for any regressions. I am also happy to answer any questions about the issues or the patch.--- tftp-hpa-5.2+20150808.orig/tftpd/tftpd.c 2015-08-08 06:24:45.000000000 +0200 +++ tftp-hpa-5.2+20150808/tftpd/tftpd.c 2020-09-30 16:00:50.512458328 +0200 @@ -151,13 +151,13 @@ exit_signal = sig; } -/* Handle timeout signal or timeout event */ +/* Handle timeout event */ void timer(int sig) { (void)sig; /* Suppress unused warning */ timeout <<= 1; if (timeout >= maxtimeout || timeout_quit) - exit(0); + return; siglongjmp(timeoutbuf, 1); } @@ -264,7 +264,8 @@ } while (rv == -1 && err == EINTR); if (rv == 0) { - timer(0); /* Should not return */ + timer(0); /* If returns, fail. */ + errno = ETIMEDOUT; return -1; } @@ -1245,8 +1246,20 @@ if (!tsize_ok) return 0; + if (tsize_ok == 1) { /* RRQ */ if (sz == 0) sz = tsize; + } + else { /* WRQ */ + /* Note that a client may send 0 tsize both when the size is unknown + and when uploading 0 bytes (at least this is what curl does). But + this ambiguity doesn't matter in our case since 0 bytes cannot be + truncated to anything less. So we treat both cases as unknown. */ + if (sz != 0) { + tsize = sz; + tsize_ok = 1; /* ok to get */ + } + } *vp = sz; return 1; @@ -1418,6 +1431,7 @@ #endif static FILE *file; +static const char *filename; /* * Validate file access. Since we * have no uid or gid, for now require @@ -1429,18 +1443,19 @@ * Note also, full path name must be * given as we have no login directory. */ -static int validate_access(char *filename, int mode, +static int validate_access(char *fname, int mode, const struct formats *pf, const char **errmsg) { struct stat stbuf; int i, len; int fd, wmode, rmode; - char *cp; + const char *cp; const char **dirp; char stdio_mode[3]; tsize_ok = 0; *errmsg = NULL; + filename = fname; if (!secure) { if (*filename != '/') { @@ -1510,7 +1525,7 @@ } tsize = stbuf.st_size; /* We don't know the tsize if conversion is needed */ - tsize_ok = !pf->f_convert; + tsize_ok = pf->f_convert ? 0 : 1 /* ok to get */; } else { if (!unixperms) { if ((stbuf.st_mode & (S_IWRITE >> 6)) == 0) { @@ -1527,7 +1542,7 @@ } #endif tsize = 0; - tsize_ok = 1; + tsize_ok = 2; /* ok to set */ } stdio_mode[0] = (mode == RRQ) ? 'r' : 'w'; @@ -1652,6 +1667,7 @@ static int acksize; u_short dp_opcode, dp_block; unsigned long r_timeout; + struct stat stbuf; dp = w_init(); do { @@ -1711,6 +1727,17 @@ } } while (size == segsize); write_behind(file, pf->f_convert); + + /* Verify the file size if it was sent by the client. */ + if (tsize_ok == 1) { + (void)fflush(file); + if (fstat(fileno(file), &stbuf) < 0) + exit(EX_OSERR); /* This shouldn't happen */ + if (stbuf.st_size != tsize) { + goto abort; + } + } + (void)fclose(file); /* close data file */ ap->th_opcode = htons((u_short) ACK); /* send the "final" ack */ @@ -1726,7 +1753,11 @@ block == dp_block) { /* then my last ack was lost */ (void)send(peer, ackbuf, 4, 0); /* resend final ack */ } + return; abort: + /* Remove the file in case of a partial upload. */ + syslog(LOG_WARNING, "Partial/interrupted upload, removing %s", filename); + (void)unlink(filename); return; }
--- End Message ---
--- Begin Message ---Source: tftp-hpa Source-Version: 7.1-1 On Mon, Jan 04, 2021 at 10:15:46AM +0200, Boris Kolpackov wrote: > Package: tftpd-hpa > Version: 5.2+20150808-1.2 > > We have discovered that tftpd-hpa does not detect a partial upload nor > does it remove the file in case of an interrupted upload. Upstream's 7.1 changelog says: If --create is specified, the server will now delete a failed upload file. I hope this is what you mean. Best, Chris
--- End Message ---

