Control: reopen 921959 Control: reassign 921959 tftpd 0.17-22
Hello Everyone, I hope it is ok to reopen and reassign this report to package tftpd, which I assume Alison Chaiken has installed, based on the addresses in the supplied backtrace. I assume this is the result of some implicit "Object Size Checking" used by the compiler in "__strcpy_chk", while in tftpd.c:624 is just a "strcpy" [1]. In the backtrace the parameter destlen has just a value of 0. And [2] shows in that case we divert into the error path. Unfortunately I cannot find the last amd64 build logs from the developer information page, but the i386 log shows following warning [3] since 0.17-22. The log contains one more such warning. So it looks like the compiler could not determine the available memory in the pointer tp->th_msg. This may be related to the -D_FORTIFY_SOURCE=2 that was not showing up in the build log for 0.17-21. Attached file contains some more details. Kind regards, Bernhard [1] (gdb) list tftpd.c:607,631 607 static void 608 nak(int error) 609 { 610 register struct tftphdr *tp; 611 int length; 612 register struct errmsg *pe; 613 614 tp = (struct tftphdr *)buf; 615 tp->th_opcode = htons((u_short)ERROR); 616 tp->th_code = htons((u_short)error); 617 for (pe = errmsgs; pe->e_code >= 0; pe++) 618 if (pe->e_code == error) 619 break; 620 if (pe->e_code < 0) { 621 pe->e_msg = strerror(error - 100); 622 tp->th_code = EUNDEF; /* set 'undef' errorcode */ 623 } 624 strcpy(tp->th_msg, pe->e_msg); <<<<<<<<< 625 length = strlen(pe->e_msg); 626 tp->th_msg[length] = '\0'; 627 length += 5; 628 if (sendto(peer, buf, length, 0, (struct sockaddr *)&from, fromlen) != length) 629 syslog(LOG_ERR, "nak: %m\n"); 630 } [2] (gdb) list strcpy_chk.c:30 25 char * 26 __strcpy_chk (char *dest, const char *src, size_t destlen) 27 { 28 size_t len = strlen (src); 29 if (len >= destlen) 30 __chk_fail (); <<<<<<<< 31 32 return memcpy (dest, src, len + 1); 33 } [3] https://buildd.debian.org/status/fetch.php?pkg=netkit-tftp&arch=i386&ver=0.17-22&stamp=1544734969&raw=0 ... cd /<<PKGBUILDDIR>>/obj-i686-linux-gnu/tftp && /usr/bin/cc -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -o CMakeFiles/tftp.dir/tftpsubs.c.o -c /<<PKGBUILDDIR>>/tftp/tftpsubs.c ... In file included from /usr/include/string.h:494, from /<<PKGBUILDDIR>>/tftpd/tftpd.c:66: In function 'strcpy', inlined from 'nak' at /<<PKGBUILDDIR>>/tftpd/tftpd.c:624:2: /usr/include/i386-linux-gnu/bits/string_fortified.h:90:10: warning: '__builtin___strcpy_chk' writing 1 or more bytes into a region of size 0 overflows the destination [-Wstringop-overflow=] return __builtin___strcpy_chk (__dest, __src, __bos (__dest)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ...
# Buster amd64 qemu VM 2019-02-25 apt update apt dist-upgrade apt install gdb ############# apt install atftpd atftpd-dbgsym gdb -q -ex 'set width 0' -ex 'set pagination off' -ex 'b main' -ex run -ex 'disassemble main' --args /usr/sbin/in.tftpd Reading symbols from /usr/sbin/in.tftpd...Reading symbols from /usr/lib/debug/.build-id/4a/f9379ec9fd666c9dd97dad57bf0c652b5664fe.debug...done. ... Dump of assembler code for function main: ... -> no line with offset 7a2 apt remove --purge atftpd atftpd-dbgsym apt install tftp-hpa tftp-hpa-dbg gdb -q -ex 'set width 0' -ex 'set pagination off' -ex 'b main' -ex run -ex 'disassemble main' --args /usr/sbin/in.tftpd Reading symbols from /usr/sbin/in.tftpd...Reading symbols from /usr/lib/debug/.build-id/d1/27b4ec61c7068d74fcc0a7c63d79180efc8416.debug...done. ... Dump of assembler code for function main: ... -> no line with offset 7a2 apt remove --purge tftp-hpa tftp-hpa-dbg apt install tftpd tftpd-dbgsym gdb -q -ex 'set width 0' -ex 'set pagination off' -ex 'b main' -ex run -ex 'disassemble main' --args /usr/sbin/in.tftpd Reading symbols from /usr/sbin/in.tftpd...Reading symbols from /usr/lib/debug/.build-id/71/ec94654597b3b11d2d01a17ce776065786a694.debug...done. ... Dump of assembler code for function main: ... 0x000055555555679d <+1149>: callq 0x5555555568d0 <nak> 0x00005555555567a2 <+1154>: mov $0x1,%edi ... apt remove --purge tftpd tftpd-dbgsym --> So assuming Alison Chaiken used package "tftpd" --> src:netkit-tftp ############# apt install dpkg-dev devscripts mkdir /tmp/source/netkit-tftp/orig -p cd /tmp/source/netkit-tftp/orig apt source netkit-tftp cd mkdir /tmp/source/libc6/orig -p cd /tmp/source/libc6/orig apt source libc6 cd ############# Backtrace from Message #5: Program terminated with signal SIGABRT, Aborted. #0 __GI_raise (sig=sig@entry=0x6) at ../sysdeps/unix/sysv/linux/raise.c:50 50 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory. (gdb) bt #0 __GI_raise (sig=sig@entry=0x6) at ../sysdeps/unix/sysv/linux/raise.c:50 #1 0x00007f2cefaf1535 in __GI_abort () at abort.c:79 #2 0x00007f2cefb48778 in __libc_message (action=<optimized out>, fmt=fmt@entry=0x7f2cefc5307b "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:181 #3 0x00007f2cefbd9b3d in __GI___fortify_fail_abort (need_backtrace=need_backtrace@entry=0x1, msg=msg@entry=0x7f2cefc52ff8 "buffer overflow detected") at fortify_fail.c:28 #4 0x00007f2cefbd9b71 in __GI___fortify_fail (msg=msg@entry=0x7f2cefc52ff8 "buffer overflow detected") at fortify_fail.c:44 #5 0x00007f2cefbd7c70 in __GI___chk_fail () at chk_fail.c:28 #6 0x00007f2cefbd7082 in __strcpy_chk (dest=0x564f2a4b4724 "ftpboot/nitrogen.dtb", src=0x564f2a4b20f8 "Access violation", destlen=0x0) at strcpy_chk.c:30 #7 0x0000564f2a4b094f in ?? () #8 0x0000564f2a4b07a2 in ?? () #9 0x00007f2cefaf309b in __libc_start_main (main=0x564f2a4b0320, argc=0x2, argv=0x7ffc2216ec78, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffc2216ec68) at ../csu/libc-start.c:308 #10 0x0000564f2a4b07fa in ?? () apt install tftpd tftpd-dbgsym root@debian:~# gdb -q -ex 'set width 0' -ex 'set pagination off' -ex 'directory /tmp/source/netkit-tftp/orig/netkit-tftp-0.17' -ex 'directory /tmp/source/libc6/orig/glibc-2.28/debug' -ex 'b main' -ex run --args /usr/sbin/in.tftpd Reading symbols from /usr/sbin/in.tftpd...Reading symbols from /usr/lib/debug/.build-id/71/ec94654597b3b11d2d01a17ce776065786a694.debug...done. done. Source directories searched: /tmp/source/netkit-tftp/orig/netkit-tftp-0.17:$cdir:$cwd Source directories searched: /tmp/source/libc6/orig/glibc-2.28/debug:/tmp/source/netkit-tftp/orig/netkit-tftp-0.17:$cdir:$cwd Breakpoint 1 at 0x2320: file ./tftpd/tftpd.c, line 103. Starting program: /usr/sbin/in.tftpd Breakpoint 1, main (ac=1, av=0x7fffffffed08) at ./tftpd/tftpd.c:103 warning: Source file is more recent than executable. 103 { (gdb) disassemble /m main,main+1202 Dump of assembler code from 0x555555556320 to 0x5555555567d2: 103 { => 0x0000555555556320 <main+0>: push %r12 ... 315 if (suppress_naks && *filename != '/' && ecode == ENOTFOUND) 0x0000555555556780 <main+1120>: cmpl $0x0,0x3cdd(%rip) # 0x55555555a464 <suppress_naks> 0x0000555555556787 <main+1127>: je 0x55555555679b <main+1147> 0x0000555555556789 <main+1129>: cmpb $0x2f,0x3f92(%rip) # 0x55555555a722 <buf+2> 0x0000555555556790 <main+1136>: je 0x55555555679b <main+1147> 0x0000555555556792 <main+1138>: cmp $0x1,%eax 0x0000555555556795 <main+1141>: je 0x5555555564c4 <main+420> 316 exit(0); 317 nak(ecode); 0x000055555555679b <main+1147>: mov %eax,%edi 0x000055555555679d <main+1149>: callq 0x5555555568d0 <nak> <<<<<<<<<<< ...7a2, the return address 318 exit(1); 0x00005555555567a2 <main+1154>: mov $0x1,%edi 0x00005555555567a7 <main+1159>: callq 0x555555556250 <exit@plt> 319 } ... End of assembler dump. (gdb) disassemble nak,nak+280 Dump of assembler code from 0x5555555568d0 to 0x5555555569e8: 0x00005555555568d0 <nak+0>: push %rbp ... 0x0000555555556929 <nak+89>: callq 0x555555556270 <strerror@plt> 0x000055555555692e <nak+94>: mov %rax,%rbp 0x0000555555556931 <nak+97>: mov %rax,0x8(%rbx) 0x0000555555556935 <nak+101>: xor %eax,%eax 0x0000555555556937 <nak+103>: mov %ax,0x3de4(%rip) # 0x55555555a722 <buf+2> 0x000055555555693e <nak+110>: xor %edx,%edx 0x0000555555556940 <nak+112>: mov %rbp,%rsi 0x0000555555556943 <nak+115>: lea 0x3dda(%rip),%rdi # 0x55555555a724 <buf+4> 0x000055555555694a <nak+122>: callq 0x5555555561a0 <__strcpy_chk@plt> <<<<<<<<<<<< ...94f, the return address 0x000055555555694f <nak+127>: mov %rbp,%rdi ... 0x00005555555569dc <nak+268>: jmpq 0x55555555693e <nak+110> 0x00005555555569e1: data16 nopw %cs:0x0(%rax,%rax,1) End of assembler dump. (gdb) list tftpd.c:607,631 607 static void 608 nak(int error) 609 { 610 register struct tftphdr *tp; 611 int length; 612 register struct errmsg *pe; 613 614 tp = (struct tftphdr *)buf; 615 tp->th_opcode = htons((u_short)ERROR); 616 tp->th_code = htons((u_short)error); 617 for (pe = errmsgs; pe->e_code >= 0; pe++) 618 if (pe->e_code == error) 619 break; 620 if (pe->e_code < 0) { 621 pe->e_msg = strerror(error - 100); 622 tp->th_code = EUNDEF; /* set 'undef' errorcode */ 623 } 624 strcpy(tp->th_msg, pe->e_msg); 625 length = strlen(pe->e_msg); 626 tp->th_msg[length] = '\0'; 627 length += 5; 628 if (sendto(peer, buf, length, 0, (struct sockaddr *)&from, fromlen) != length) 629 syslog(LOG_ERR, "nak: %m\n"); 630 } (gdb) disassemble __strcpy_chk Dump of assembler code for function __strcpy_chk: 0x00007ffff7f0e050 <+0>: push %r12 0x00007ffff7f0e052 <+2>: mov %rdi,%r12 0x00007ffff7f0e055 <+5>: mov %rsi,%rdi 0x00007ffff7f0e058 <+8>: push %rbp 0x00007ffff7f0e059 <+9>: mov %rdx,%rbp 0x00007ffff7f0e05c <+12>: push %rbx 0x00007ffff7f0e05d <+13>: mov %rsi,%rbx 0x00007ffff7f0e060 <+16>: callq 0x7ffff7e28130 <*ABS*+0x882b0@plt> 0x00007ffff7f0e065 <+21>: cmp %rbp,%rax 0x00007ffff7f0e068 <+24>: jae 0x7ffff7f0e07d <__strcpy_chk+45> 0x00007ffff7f0e06a <+26>: mov %rbx,%rsi 0x00007ffff7f0e06d <+29>: mov %r12,%rdi 0x00007ffff7f0e070 <+32>: lea 0x1(%rax),%rdx 0x00007ffff7f0e074 <+36>: pop %rbx 0x00007ffff7f0e075 <+37>: pop %rbp 0x00007ffff7f0e076 <+38>: pop %r12 0x00007ffff7f0e078 <+40>: jmpq 0x7ffff7e28190 <*ABS*+0x89620@plt> 0x00007ffff7f0e07d <+45>: callq 0x7ffff7f0ec60 <__GI___chk_fail> End of assembler dump. (gdb) list strcpy_chk.c:30 25 char * 26 __strcpy_chk (char *dest, const char *src, size_t destlen) 27 { 28 size_t len = strlen (src); 29 if (len >= destlen) 30 __chk_fail (); 31 32 return memcpy (dest, src, len + 1); 33 } ############ # Unfortunately no build log for amd64 ... i386 at least shows this: https://buildd.debian.org/status/fetch.php?pkg=netkit-tftp&arch=i386&ver=0.17-22&stamp=1544734969&raw=0 ... cd /<<PKGBUILDDIR>>/obj-i686-linux-gnu/tftp && /usr/bin/cc -g -O2 -fdebug-prefix-map=/<<PKGBUILDDIR>>=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -o CMakeFiles/tftp.dir/tftpsubs.c.o -c /<<PKGBUILDDIR>>/tftp/tftpsubs.c ... In file included from /usr/include/string.h:494, from /<<PKGBUILDDIR>>/tftpd/tftpd.c:66: In function 'strcpy', inlined from 'nak' at /<<PKGBUILDDIR>>/tftpd/tftpd.c:624:2: /usr/include/i386-linux-gnu/bits/string_fortified.h:90:10: warning: '__builtin___strcpy_chk' writing 1 or more bytes into a region of size 0 overflows the destination [-Wstringop-overflow=] return __builtin___strcpy_chk (__dest, __src, __bos (__dest)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ... First appeared in 0.17-22. ############ http://www.informit.com/articles/article.aspx?p=2036582&seqNum=6 "Object Size Checking"