tftpd: support full 512-byte requests
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 3 Sep 2014 16:35:38 +0000 (18:35 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 3 Sep 2014 16:35:38 +0000 (18:35 +0200)
Some HP PA-RISC firmware always sends fixed 512-byte requests,
with trailing garbage.

function                                             old     new   delta
tftpd_main                                           578     572      -6

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
networking/tftp.c

index 630fdaf9a8b66b1da5b38465ef91064cbacf9f59..8e3b0a2dcede43a10a455d499e27b6ba47bd01c7 100644 (file)
@@ -119,6 +119,7 @@ struct globals {
        struct passwd *pw;
        /* used in tftpd_main(), a bit big for stack: */
        char block_buf[TFTP_BLKSIZE_DEFAULT];
+       char block_buf_tail[1];
 #if ENABLE_FEATURE_TFTP_PROGRESS_BAR
        off_t pos;
        off_t size;
@@ -793,14 +794,16 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
                xchroot(argv[0]);
        }
 
-       result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf),
+       result = recv_from_to(STDIN_FILENO,
+                       G.block_buf, sizeof(G.block_buf) + 1,
+                       /* ^^^ sizeof+1 to reliably detect oversized input */
                        0 /* flags */,
                        &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len);
 
        error_msg = "malformed packet";
        opcode = ntohs(*(uint16_t*)G.block_buf);
-       if (result < 4 || result >= sizeof(G.block_buf)
-        || G.block_buf[result-1] != '\0'
+       if (result < 4 || result > sizeof(G.block_buf)
+       /*|| G.block_buf[result-1] != '\0' - bug compatibility, see below */
         || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */
             IF_GETPUT(&&)
             IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */
@@ -808,6 +811,13 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
        ) {
                goto err;
        }
+       /* Some HP PA-RISC firmware always sends fixed 512-byte requests,
+        * with trailing garbage.
+        * Support that by not requiring NUL to be the last byte (see above).
+        * To make strXYZ() ops safe, force NUL termination:
+        */
+       G.block_buf_tail[0] = '\0';
+
        local_file = G.block_buf + 2;
        if (local_file[0] == '.' || strstr(local_file, "/.")) {
                error_msg = "dot in file name";