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"

Reply via email to