Pretty obvious if you dig into the guts of the program.

fetch.c:        oldintr = signal(SIGINT, aborthttp);
fetch.c:        oldintr = signal(SIGINT, aborthttp);
fetch.c:        (void)signal(SIGINT, (sig_t)intr);

means:

static void
aborthttp(int signo)
{
        const char errmsg[] = "\nfetch aborted.\n";

        alarmtimer(0);
        write(fileno(ttyout), errmsg, sizeof(errmsg) - 1);
        longjmp(httpabort, 1);
}

longjmp, eh.

        if (setjmp(httpabort)) {
                if (oldintr)
                        (void)signal(SIGINT, oldintr);
                if (oldinti)
                        (void)signal(SIGINFO, oldinti);
                goto cleanup_copy;

what is at cleanup_copy?

cleanup_copy:
        free(buf);
        ^^^^^ signal race, re-entering malloc
        if (out >= 0 && out != fileno(stdout))
                close(out);
        close(fd);

        return rval;


setjmp + signal + longjmp is a recipe for disaster.

This ancient style of programming should be extinct, but there are a
handful of programs which still think they can get away with it.  Our malloc
won't allow it.



Klemens Nanni <[email protected]> wrote:

> Putting this here because I haven't come around to fully grok this issue
> and don't won't to leave it rot on my list..
> 
> Aborting -CURRENT ftp(1) during a download with SIGINT
> (and vm.malloc_conf=SU) causes the following segmentation fault:
> 
>       $ ftp -o /dev/null 
> https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz
>       Trying 2a04:4e42:1b::223...
>       Requesting https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz
>         8% |********                                                          
>                                   |  2048 KB    00:10 ETA^C
>       fetch aborted.
>       ftp(1755) in free(): recursive call
>       Abort trap (core dumped)
> 
> 
> [New process 138840]
> Core was generated by `ftp'.
> Program terminated with signal SIGABRT, Aborted.
> #0  thrkill () at -:3
> #0  thrkill () at -:3
> #1  0x00000f72e309a33e in _libc_abort () at 
> /usr/src/lib/libc/stdlib/abort.c:51
> #2  0x00000f72e30c9b76 in wrterror (d=0xf72445a2ca0, msg=0xf72e3023e68 
> "recursive call") at /usr/src/lib/libc/stdlib/malloc.c:300
> #3  0x00000f72e30c9e38 in malloc_recurse (d=<optimized out>) at 
> /usr/src/lib/libc/stdlib/malloc.c:1200
> #4  free (ptr=0xf7217de43b0) at /usr/src/lib/libc/stdlib/malloc.c:1485
> #5  0x00000f6ffedefb46 in url_get (origline=0xf723c5bf2c0 
> "https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz";, proxyenv=0x0, 
> outfile=0x7f7ffffc15d5 "/dev/null", lastfile=1) at /s/usr.bin/ftp/fetch.c:1100
> #6  0x00000f6ffedebccf in auto_fetch (argc=1, argv=0x7f7ffffc1470, 
> outfile=0x7f7ffffc15d5 "/dev/null") at /s/usr.bin/ftp/fetch.c:1271
> #7  0x00000f6ffedfa3a8 in main (argc=1, argv=0x7f7ffffc1470) at 
> /s/usr.bin/ftp/main.c:509
> 
> 
> I can only reproduce this in roughly one out of ten cases.
> Full backtrace:
> 
> 
> [New process 138840]
> Core was generated by `ftp'.
> Program terminated with signal SIGABRT, Aborted.
> #0  thrkill () at -:3
> #0  thrkill () at -:3
> No locals.
> #1  0x00000f72e309a33e in _libc_abort () at 
> /usr/src/lib/libc/stdlib/abort.c:51
>         mask = 4294967263
>         sa = <optimized out>
> #2  0x00000f72e30c9b76 in wrterror (d=0xf72445a2ca0, msg=0xf72e3023e68 
> "recursive call") at /usr/src/lib/libc/stdlib/malloc.c:300
>         ap = {{gp_offset = 16, fp_offset = 48, overflow_arg_area = 
> 0x7f7ffffc0210, reg_save_area = 0x7f7ffffc0110}}
>         saved_errno = 0
> #3  0x00000f72e30c9e38 in malloc_recurse (d=<optimized out>) at 
> /usr/src/lib/libc/stdlib/malloc.c:1200
> No locals.
> #4  free (ptr=0xf7217de43b0) at /usr/src/lib/libc/stdlib/malloc.c:1485
>         saved_errno = 0
>         d = 0xf72445a2ca0
> #5  0x00000f6ffedefb46 in url_get (origline=0xf723c5bf2c0 
> "https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz";, proxyenv=0x0, 
> outfile=0x7f7ffffc15d5 "/dev/null", lastfile=1) at /s/usr.bin/ftp/fetch.c:1100
>         pbuf = 
> "443\000\000\000\000\000P\324I\356r\017\000\000\337\025\374\377\177\177\000\000\325$\214ױ{\265u"
>         hbuf = 
> "2a04:4e42:1b::223\000\000\343r\017\000\000\000\350\216\343r\017\000\000\250\343\000\343r\017\000\000\000\350\216\343r\017\000\000\300\213\253\a\000\000\000\000\247\233\223\034\060\000\000\000\346\254\335\376o\017\000\000\000p*\204r\017\000\000\377\377\377\377\060\000\000\000\320\327\335\376o\017\000\000\346\254\335\376o\017\000\000\004\227\f\343r\017\000\000B\000\000\000\000\000\000\000\000p*\204r\017\000\000Z\272\203\340\211\061˸\330\b\374\377\177\177\000\000\243\026J\356r\017\000\000\070i\340\376o\017\000\000\071\000\000\000\000\000\000\000
>  
> \325\f\343\000\000\000\000P\324I\356r\017\000\000\026\000\000\000\000\000\000\000\250\306\016\343r\017\000\000\071"...
>         cp = 0xf7211869000 <error: Cannot access memory at address 
> 0xf7211869000>
>         portnum = 0x0
>         path = 0xf723821c097 "ftp/python/3.8.3/Python-3.8.3.tgz"
>         ststr = "200"
>         hosttail = 0xf723821c088 "www.python.org"
>         cause = 0xf6ffeddfcf1 "unknown"
>         newline = 0xf723821c080 "https://www.python.org";
>         host = 0xf723821c088 "www.python.org"
>         port = 0x7f7ffffc08f0 "443"
>         buf = 0xf7211849000 
> "\365\355\330P\363a\276\212\071\347\321\371\261(\005\307pGF\213\330\353Y\n\031\333\033\214"
>         epath = 0xf720068c7c0 ""
>         redirurl = 0x0
>         loctail = 0x0
>         h = 0x10000002e4 <error: Cannot access memory at address 0x10000002e4>
>         p = 0x0
>         gerror = '\000' <repeats 16 times>, "\230\002\000\000\022", '\000' 
> <repeats 19 times>, "\261\002\000\000\020", '\000' <repeats 19 times>, 
> "\272\002\000\000\020", '\000' <repeats 19 times>, "\300\002\000\000\020", 
> '\000' <repeats 19 times>, "\307\002\000\000\020", '\000' <repeats 19 times>, 
> "\316\002\000\000\020", '\000' <repeats 19 times>, "\327\002\000\000\020", 
> '\000' <repeats 11 times>, 
> "\360\b\374\377\177\177\000\000&\304\004\343r\017\000\000\000\000\000\000\000\000\000"
>         error = 0
>         isftpurl = 0
>         isredirect = 0
>         rval = -1
>         isunavail = 0
>         retryafter = -1
>         hints = {ai_flags = 0, ai_family = 0, ai_socktype = 1, ai_protocol = 
> 0, ai_addrlen = 0, ai_addr = 0x0, ai_canonname = 0x0, ai_next = 0x0}
>         res0 = 0xf720b0b1580
>         res = 0xf720b0b1580
>         savefile = 0x7f7ffffc15d5 "/dev/null"
>         proxyurl = 0x0
>         credentials = 0x0
>         proxy_credentials = 0x0
>         fd = 3
>         out = 4
>         oldintr = 0xf6ffedfaa00 <intr>
>         oldinti = 0x0
>         fin = 0xf72e30ef2c0 <usual>
>         hashbytes = 1024
>         errstr = 0x0
>         len = 0
>         wlen = 131072
>         proxyhost = 0x0
>         sslpath = 0x0
>         sslhost = 0xf729960eaa0 "www.python.org"
>         ishttpsurl = 1
>         full_host = 0xf7217de43b0 "www.python.org"
>         scheme = 0xf6ffede001a "https://";
>         locbase = 0x0
>         ares = 0x0
>         tls = 0xf721f668400
>         status = 200
>         save_errno = 0
>         buflen = 131072
>         chunked = 0
> #6  0x00000f6ffedebccf in auto_fetch (argc=1, argv=0x7f7ffffc1470, 
> outfile=0x7f7ffffc15d5 "/dev/null") at /s/usr.bin/ftp/fetch.c:1271
>         xargv = {0x2f <error: Cannot access memory at address 0x2f>, 0x2f 
> <error: Cannot access memory at address 0x2f>, 0xf72e3027230 <charmap> "", 
> 0xf6ffeddf7bd "stdio rpath wpath cpath dns tty inet proc exec fattr", 0x0}
>         cp = 0xf72ee49dcc0 <_dl_bind_start> 
> "\234PQRVWAPAQARASH\213|$PH\213t$X\350c9"
>         url = 0xf723c5bf2c0 
> "https://www.python.org/ftp/python/3.8.3/Python-3.8.3.tgz";
>         host = 0x0
>         dir = 0x0
>         file = 0x0
>         portnum = 0x0
>         username = 0x0
>         pass = 0x0
>         pathstart = 0xf72ee49d450 <_dl_dtors> "UH\211\345\350\a\221"
>         ftpproxy = 0x0
>         httpproxy = 0x0
>         rval = 0
>         xargc = 8
>         lastfile = 1
>         argpos = 0
>         dirhasglob = 3954
>         filehasglob = -297134429
>         oautologin = 32639
>         rempath = "\b", '\000' <repeats 15 times>, 
> "\377\377\377\377\377\377\377\a\370\377\377\377\377\377\377\377\020\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\b\251\230dr\017\000\000\000\000\000\000\000\000\000\000\200A\242;r\017\000\000\001\000\000\000\000\000\000\000\002\000\000\000\005\000\000\000\b\000\000\000\000\000\000\000\002\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000ب\230dr\017\000\000\000\000\000\000\000\000\000\000\001\000\000\000\000\000\000\000(\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\b\000\000\000\000\000\000\000\365\324\031\270\256\065#\336\020\f\374\377\177\177\000\000&"...
> #7  0x00000f6ffedfa3a8 in main (argc=1, argv=0x7f7ffffc1470) at 
> /s/usr.bin/ftp/main.c:509
>         ch = -1
>         rval = 306490607
>         top = 0
>         pw = 0xf721b1fb000
>         cp = 0xf72e30f5f30 <logname> "kn"
>         homedir = "/home/kn", '\000' <repeats 16 times>, 
> "\066\325F_\036\231\363\000\200\020\374\377\177\177\000\000\231YJ\356r\017\000\000\220\020\374\377\177\177\000\000\000\000\000\000\000\000\000\000;\227\071\356r\017\000\000\270\222\071\356r\017\000\000\000\270v\"r\017\000\000\300\302\000\343r\017\000\000\000\350\216\343r\017\000\000E\022\\\t\000\000\000\000\274Pv\236
>  
> \000\000\000;\227\071\356r\017\000\000\230\020\374\377\177\177\000\000\000h\002T
>  ", '\000' <repeats 11 times>, 
> "\f\000\000\000\000\000\000\000\000P\003\000\000\000\000\000 
> \260Y\356r\017\000\000\000p*\204r\017\000\000aj\200\340\211\061˸ 
> \023\374\377\177\177\000\000\230"...
>         outfile = 0x7f7ffffc15d5 "/dev/null"
>         errstr = 0x0
>         dumb_terminal = 0
> 

Reply via email to