https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91205
Bug ID: 91205 Summary: -fstack-protector-strong -D_FORTIFY_SOURCE=2 breaks tftpd Product: gcc Version: 9.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: ricardo at ribalda dot com Target Milestone: --- Current GNU inetutils tftpd breaks at runtime with current gcc (also tested with 8.3). The code throws a: *** buffer overflow detected ***: Aborted on its error path. The error seems to be due to the way the arpa/tftp.h headers are handled. The simplest testcase that I have managed to craft is: //compile with: CFLAGS=-fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -O2 #include <string.h> #include <stdio.h> struct tftphdr { short th_opcode; /* packet type */ union { char tu_padding[3]; /* sizeof() compat */ struct { char tu_data[0]; /* data or error string */ } __attribute__ ((__packed__)) th_u2; } __attribute__ ((__packed__)) th_u1; } __attribute__ ((__packed__)); static char buf[512]; int main(int argc, char* argv[]) { struct tftphdr *tp; tp = (struct tftphdr *) buf; strcpy(tp->th_u1.th_u2.tu_data, "Hello world"); fprintf(stdout, "Code works!\n"); return 0; } Although this other testcase is closer to the original source: #include <string.h> #include <stdio.h> #include <arpa/inet.h> #include <arpa/tftp.h> /* Some systems define PKTSIZE in <arpa/tftp.h>. */ #ifndef PKTSIZE #define PKTSIZE SEGSIZE+4 #endif static char buf[PKTSIZE]; struct errmsg { int e_code; const char *e_msg; } errmsgs[] = { {EUNDEF, "Undefined error code"}, {ENOTFOUND, "File not found"}, {EACCESS, "Access violation"}, {ENOSPACE, "Disk full or allocation exceeded"}, {EBADOP, "Illegal TFTP operation"}, {EBADID, "Unknown transfer ID"}, {EEXISTS, "File already exists"}, {ENOUSER, "No such user"}, {-1, 0} }; static void nak (int error) { register struct tftphdr *tp; int length; register struct errmsg *pe = &errmsgs[error]; tp = (struct tftphdr *) buf; tp->th_opcode = htons ((unsigned short) ERROR); tp->th_code = htons (pe->e_code); strcpy(tp->th_msg, pe->e_msg); length = strlen (pe->e_msg); length += 5; } int main(int argc, char* argv[]) { int i; for (i=0;i<8;i++) nak(i); fprintf(stdout, "Code works!\n"); return 0; } Replacing strcpy with memcpy solves the issue. A patch has been sent to inetutils. https://www.mail-archive.com/bug-inetutils@gnu.org/msg03036.html