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
>