[Bug 763591] New: Bash Crash (double free or corruption) Expanding Number Sequence
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c0 Summary: Bash Crash (double free or corruption) Expanding Number Sequence Classification: openSUSE Product: openSUSE 12.1 Version: Final Platform: x86-64 OS/Version: openSUSE 12.1 Status: NEW Severity: Normal Priority: P5 - None Component: Basesystem AssignedTo: bnc-team-screening@forge.provo.novell.com ReportedBy: scotty.mcmillan+novell@gmail.com QAContact: qa-bugs@suse.de Found By: --- Blocker: --- User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1128.0 Safari/536.11 SUSE/20.0.1128.0 Entering the following into the bash prompt crashes bash on my openSUSE 12.1 systems: echo {9223372036854775805..9223372036854775807} What actually matters for reproducing the crash is that the second number of the two has the value (2^63)-1. If either value is higher than this no expansion is performed (presumably because it's using signed 64 bit integers in the implementation). I notice that in older versions (e.g., on an openSUSE 11.1 system, and a CentOS 5.4 system) the output of the above is -3, -2, -1, which is also incorrect. The following is example output: ^C*** glibc detected *** /bin/bash: double free or corruption (!prev): 0x000000000070b310 *** ======= Backtrace: ========= /lib64/libc.so.6(+0x766d6)[0x7ff1105546d6] /bin/bash(reset_parser+0x47)[0x41e2c7] /bin/bash(throw_to_top_level+0x84)[0x44fd24] /bin/bash(brace_expand+0x807)[0x455b17] /bin/bash[0x44a6ca] /bin/bash(execute_command_internal+0x42f)[0x42d2bf] /bin/bash(execute_command+0x49)[0x430cb9] /bin/bash(reader_loop+0xcd)[0x41d22d] /bin/bash(main+0xbc3)[0x41bae3] /lib64/libc.so.6(__libc_start_main+0xed)[0x7ff1104ff23d] /bin/bash[0x41c731] ======= Memory map: ======== 00400000-0049a000 r-xp 00000000 08:02 2509616 /bin/bash 00699000-0069a000 r--p 00099000 08:02 2509616 /bin/bash 0069a000-0069e000 rw-p 0009a000 08:02 2509616 /bin/bash 0069e000-108faa000 rw-p 00000000 00:00 0 [heap] 7ff1102c8000-7ff1102dd000 r-xp 00000000 08:02 655563 /lib64/libgcc_s.so.1 7ff1102dd000-7ff1104dc000 ---p 00015000 08:02 655563 /lib64/libgcc_s.so.1 7ff1104dc000-7ff1104dd000 r--p 00014000 08:02 655563 /lib64/libgcc_s.so.1 7ff1104dd000-7ff1104de000 rw-p 00015000 08:02 655563 /lib64/libgcc_s.so.1 7ff1104de000-7ff110665000 r-xp 00000000 08:02 655670 /lib64/libc-2.14.1.so 7ff110665000-7ff110864000 ---p 00187000 08:02 655670 /lib64/libc-2.14.1.so 7ff110864000-7ff110868000 r--p 00186000 08:02 655670 /lib64/libc-2.14.1.so 7ff110868000-7ff110869000 rw-p 0018a000 08:02 655670 /lib64/libc-2.14.1.so 7ff110869000-7ff11086e000 rw-p 00000000 00:00 0 7ff11086e000-7ff110870000 r-xp 00000000 08:02 655666 /lib64/libdl-2.14.1.so 7ff110870000-7ff110a70000 ---p 00002000 08:02 655666 /lib64/libdl-2.14.1.so 7ff110a70000-7ff110a71000 r--p 00002000 08:02 655666 /lib64/libdl-2.14.1.so 7ff110a71000-7ff110a72000 rw-p 00003000 08:02 655666 /lib64/libdl-2.14.1.so 7ff110a72000-7ff110abd000 r-xp 00000000 08:02 655387 /lib64/libncurses.so.5.8 7ff110abd000-7ff110cbc000 ---p 0004b000 08:02 655387 /lib64/libncurses.so.5.8 7ff110cbc000-7ff110cc0000 r--p 0004a000 08:02 655387 /lib64/libncurses.so.5.8 7ff110cc0000-7ff110cc6000 rw-p 0004e000 08:02 655387 /lib64/libncurses.so.5.8 7ff110cc6000-7ff110d04000 r-xp 00000000 08:02 655589 /lib64/libreadline.so.6.2 7ff110d04000-7ff110f03000 ---p 0003e000 08:02 655589 /lib64/libreadline.so.6.2 7ff110f03000-7ff110f05000 r--p 0003d000 08:02 655589 /lib64/libreadline.so.6.2 7ff110f05000-7ff110f0b000 rw-p 0003f000 08:02 655589 /lib64/libreadline.so.6.2 7ff110f0b000-7ff110f0d000 rw-p 00000000 00:00 0 7ff110f0d000-7ff110f2d000 r-xp 00000000 08:02 690812 /lib64/ld-2.14.1.so 7ff110f7e000-7ff110f81000 rw-p 00000000 00:00 0 7ff110f81000-7ff110fc0000 r--p 00000000 08:02 2496095 /usr/lib/locale/en_US.utf8/LC_CTYPE 7ff110fc0000-7ff1110f0000 r--p 00000000 08:02 2496096 /usr/lib/locale/en_US.utf8/LC_COLLATE 7ff1110f0000-7ff1110f4000 rw-p 00000000 00:00 0 7ff11111b000-7ff11111c000 r--p 00000000 08:02 2496073 /usr/lib/locale/en_US.utf8/LC_NUMERIC 7ff11111c000-7ff11111d000 r--p 00000000 08:02 2624016 /usr/lib/locale/en_US.utf8/LC_TIME 7ff11111d000-7ff11111e000 r--p 00000000 08:02 2624015 /usr/lib/locale/en_US.utf8/LC_MONETARY 7ff11111e000-7ff11111f000 r--p 00000000 08:02 2636444 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES 7ff11111f000-7ff111120000 r--p 00000000 08:02 2636451 /usr/lib/locale/en_US.utf8/LC_PAPER 7ff111120000-7ff111121000 r--p 00000000 08:02 2622011 /usr/lib/locale/en_US.utf8/LC_NAME 7ff111121000-7ff111122000 r--p 00000000 08:02 2623784 /usr/lib/locale/en_US.utf8/LC_ADDRESS 7ff111122000-7ff111123000 r--p 00000000 08:02 2622047 /usr/lib/locale/en_US.utf8/LC_TELEPHONE 7ff111123000-7ff111124000 r--p 00000000 08:02 2636452 /usr/lib/locale/en_US.utf8/LC_MEASUREMENT 7ff111124000-7ff11112b000 r--s 00000000 08:02 568092 /usr/lib64/gconv/gconv-modules.cache 7ff11112b000-7ff11112c000 r--p 00000000 08:02 2624014 /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION 7ff11112c000-7ff11112d000 rw-p 00000000 00:00 0 7ff11112d000-7ff11112e000 r--p 00020000 08:02 690812 /lib64/ld-2.14.1.so 7ff11112e000-7ff11112f000 rw-p 00021000 08:02 690812 /lib64/ld-2.14.1.so 7ff11112f000-7ff111130000 rw-p 00000000 00:00 0 7fff780ea000-7fff7810b000 rw-p 00000000 00:00 0 [stack] 7fff78181000-7fff78182000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Warning: Program '/bin/bash' crashed. Reproducible: Always Steps to Reproduce: 1.Enter the following command into a bash prompt: echo {9223372036854775805..9223372036854775807} 2.Wait for it to crash. Maybe you will have to enter control-c. The result won't be good, in any case. 3.Profit. Actual Results: Crashing, usually with a stack trace printed as given in the description. Sometimes it just hangs. Expected Results: Output: 9223372036854775805 9223372036854775806 9223372036854775807 -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c kk zhang <kkzhang@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |kkzhang@suse.com AssignedTo|bnc-team-screening@forge.pr |nld10-bugs-qa@forge.provo.n |ovo.novell.com |ovell.com -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c1 --- Comment #1 from S M <scotty.mcmillan+novell@gmail.com> 2012-05-29 10:33:59 UTC --- I investigated the cause of this bug and found several issues in bash. I submitted a bug report using the bashbug program. This program doesn't give me any bug number to link to, so I'll just paste the details I sent to bug-bash in case it's useful. From: scotty.mcmillan@gmail.com <Scott McMillan> To: bug-bash@gnu.org Subject: Brace expansion infinite loop, memory corruption, and other bugs. Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: gcc -I/home/abuild/rpmbuild/BUILD/bash-4.2 -L/home/abuild/rpmbuild/BUILD/bash-4.2/../readline-6.2 Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu' -DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I. -I./include -I./lib -fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -D_GNU_SOURCE -DRECYCLES_PIDS -Wall -g -std=gnu89 -Wuninitialized -Wextra -Wno-unprototyped-calls -Wno-switch-enum -Wno-unused-variable -Wno-unused-parameter -ftree-loop-linear -pipe -fprofile-use uname output: Linux wks-smcmillan 3.1.10-1.9-desktop #1 SMP PREEMPT Thu Apr 5 18:48:38 UTC 2012 (4a97ec8) x86_64 x86_64 x86_64 GNU/Linux Machine Type: x86_64-suse-linux-gnu Bash Version: 4.2 Patch Level: 10 Release Status: release Description: The errors are all to do with brace expansion in braces.c. 1) echo {9223372036854775806..9223372036854775807} was getting an infinite loop (or crash with memory corruption or seg fault). The error was in the mkseq function, because the increment of n done before checking the loop termination condition was susceptible to incidences of undefined signed integer overflow. This is fixed in the patch below. 2) The rhs value and any user-specified increment value were always clamped to the valid range while the sequence would refuse to expand if lhs was out of range. This is because strtoimax clamps on under/overflow and sets errno, but errno was only getting checked for lhs (inside the legal_number function). expand_seqterm has been changed in the patch below so that errno is checked after using strtoimax to read the rhs and incr values. This gives more correct and consistent behaviour. 3) The incr value was an int but was getting read using strtoimax, so values beyond the range of an int were getting truncated. incr has been changed to intmax_t in the patch below to fix this problem. 4) -incr in mkseq must be valid since the sign is switched depending on the order of start and end. There was potential undefined behaviour where it was equal to INTMAX_MIN. expand_seqterm now guarantees -incr will be valid in the patch below. 5) echo {0..9223372036854775807} was getting a segmentation fault due to overflow calculating the result size in mkseq. This is because the result size calculated in mkseq is an int (necessarily, since strvec_create takes an int as an argument), and because the wrong absolute value function was getting used (abs instead of imaxabs). After applying the patch below, expand_seqterm makes extra guarantees on the end and start values passed to mkseq such that no overflow will occur during the calculation and the result will not overflow int. This means that the example input given would fail to expand. Input such as {0..2147483645} will likely give an out of memory error, which is preferable to segmentation faults or corrupted memory. Repeat-By: 1) echo {9223372036854775806..9223372036854775807} 2) echo {9223372036854775806..9223372036854775808} (note second value is more than INTMAX_MAX, but the output before applying the patch is as if it were equal to INTMAX_MAX). 3) echo {0..10..9223372036854775807}. 4) Self-evident from code, -INTMAX_MIN is not valid. 5) echo {0..9223372036854775807} Fix: A patch to apply to braces.c to fix the issues mentioned above has been pasted in below. The fixes are: 1) Check for overflow before incrementing in the loop in mkseq. 2) Check errno after strtoimax when reading the rhs and incr values in expand_seqterm. 3) incr in expand_seqterm and mkseq is now intmax_t. 4) expand_seqterm verifies that -incr is not undefined. 5) code uses imaxabs for intmax_t values and expand_seqterm verifies the start and end values won't result in a range that overflows INT_MAX. *************** *** 31,36 **** --- 31,37 ---- # include <unistd.h> #endif + #include <errno.h> #include "bashansi.h" #if defined (SHELL) *************** *** 63,69 **** static int brace_gobbler __P((char *, size_t, int *, int)); static char **expand_amble __P((char *, size_t, int)); static char **expand_seqterm __P((char *, size_t)); ! static char **mkseq __P((intmax_t, intmax_t, int, int, int)); static char **array_concat __P((char **, char **)); #else static int brace_gobbler (); --- 64,70 ---- static int brace_gobbler __P((char *, size_t, int *, int)); static char **expand_amble __P((char *, size_t, int)); static char **expand_seqterm __P((char *, size_t)); ! static char **mkseq __P((intmax_t, intmax_t, intmax_t, int, int)); static char **array_concat __P((char **, char **)); #else static int brace_gobbler (); *************** *** 305,325 **** #define ST_CHAR 2 #define ST_ZINT 3 static char ** mkseq (start, end, incr, type, width) ! intmax_t start, end; ! int incr, type, width; { intmax_t n; int i; char **result, *t; ! ! i = abs (end - start) + 1; ! result = strvec_create (i + 1); ! if (incr == 0) incr = 1; if (start > end && incr > 0) incr = -incr; else if (start < end && incr < 0) --- 306,361 ---- #define ST_CHAR 2 #define ST_ZINT 3 + /* Returns true if lhs + rhs would under/overflow outside of [minval, maxval].*/ + static int + addwilloverflow(lhs, rhs, minval, maxval) + intmax_t lhs, rhs, minval, maxval; + { + return + (((lhs > 0) && (rhs > (maxval - lhs))) + || + ((lhs < 0) && (rhs < (minval - lhs)))); + } + + /* Returns true if lhs - rhs would under/overflow outside of [minval, maxval].*/ + static int + subtractwilloverflow(lhs, rhs, minval, maxval) + intmax_t lhs, rhs, minval, maxval; + { + return + (((rhs > 0) && (lhs < (minval + rhs))) + || + ((rhs < 0) && (lhs > (maxval + rhs)))); + } + + /* Caller must guarantee that incr > INTMAX_MIN, because -incr must be + valid. + Caller must also guarantee that the expression: imaxabs(end - start) + 2 + results in no under/overflow, will not result in passing INTMAX_MIN to + imaxabs, and has a value not greater than INT_MAX. */ static char ** mkseq (start, end, incr, type, width) ! intmax_t start, end, incr; ! int type, width; { intmax_t n; int i; char **result, *t; ! ! /* strvec_create argument is an int, so must make sure that the number of ! elements in the sequence (abs(end - start) + 1), + 1 for a NULL terminator, ! does not overflow int. This is covered by the function preconditions. */ ! i = imaxabs(end - start) + 1 + 1; ! ! /* Note: potentially allocating a lot more memory than required if ! incr > 1. */ ! result = strvec_create (i); ! if (incr == 0) incr = 1; + /* caller guarantees incr is > INTMAX_MIN, so we know + -incr is valid. */ if (start > end && incr > 0) incr = -incr; else if (start < end && incr < 0) *************** *** 349,354 **** --- 385,398 ---- t[1] = '\0'; result[i++] = t; } + + /* Can't increment n with incr before loop termination check, due to the + possibility of undefined signed integer overflow. */ + if (addwilloverflow(n, incr, INTMAX_MIN, INTMAX_MAX)) + { + break; + } + n += incr; if ((incr < 0 && n < end) || (incr > 0 && n > end)) break; *************** *** 365,372 **** size_t tlen; { char *t, *lhs, *rhs; ! int i, lhs_t, rhs_t, incr, lhs_l, rhs_l, width; ! intmax_t lhs_v, rhs_v; intmax_t tl, tr; char **result, *ep, *oep; --- 409,416 ---- size_t tlen; { char *t, *lhs, *rhs; ! int i, lhs_t, rhs_t, lhs_l, rhs_l, width; ! intmax_t lhs_v, rhs_v, incr; intmax_t tl, tr; char **result, *ep, *oep; *************** *** 397,404 **** { rhs_t = ST_INT; tr = strtoimax (rhs, &ep, 10); ! if (ep && *ep != 0 && *ep != '.') ! rhs_t = ST_BAD; /* invalid */ } else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.')) { --- 441,448 ---- { rhs_t = ST_INT; tr = strtoimax (rhs, &ep, 10); ! if (errno || ep && *ep != 0 && *ep != '.') ! rhs_t = ST_BAD; /* invalid or overflow/underflow */ } else if (ISALPHA (rhs[0]) && (rhs[1] == 0 || rhs[1] == '.')) { *************** *** 417,424 **** oep = ep; if (ep && *ep == '.' && ep[1] == '.' && ep[2]) incr = strtoimax (ep + 2, &ep, 10); ! if (*ep != 0) ! rhs_t = ST_BAD; /* invalid incr */ tlen -= ep - oep; } --- 461,472 ---- oep = ep; if (ep && *ep == '.' && ep[1] == '.' && ep[2]) incr = strtoimax (ep + 2, &ep, 10); ! if (errno || *ep != 0 || incr == INTMAX_MIN) ! /* invalid incr or overflow/underflow. Also, don't allow incr ! to be INTMAX_MIN, since the mkseq function requires that -incr ! is valid. */ ! rhs_t = ST_BAD; ! tlen -= ep - oep; } *************** *** 461,466 **** --- 509,524 ---- if (width < rhs_l && lhs_t == ST_ZINT) width = rhs_l; } + + /* Check the range of the sequence satisfies the preconditions for + mkseq, to avoid overflow. */ + if (subtractwilloverflow(rhs_v, lhs_v, INTMAX_MIN + 1 + 2, INTMAX_MAX - 2) || + ((imaxabs(rhs_v - lhs_v) + 2) > INT_MAX)) + { + free (lhs); + free (rhs); + return ((char **)NULL); + } result = mkseq (lhs_v, rhs_v, incr, lhs_t, width); -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c Andreas Jaeger <aj@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- AssignedTo|nld10-bugs-qa@forge.provo.n |werner@suse.com |ovell.com | -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c2 Dr. Werner Fink <werner@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |NEEDINFO CC| |chet.ramey@case.edu InfoProvider| |scotty.mcmillan+novell@gmai | |l.com --- Comment #2 from Dr. Werner Fink <werner@suse.com> 2012-06-22 11:07:22 UTC --- Please attach the patch as copy&past will/has destroyed the line layout. Was this patch accepted by upstream? AFAICS from mailing list is that Chet will take a look at your patch. -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c3 --- Comment #3 from S M <scotty.mcmillan+novell@gmail.com> 2012-06-22 11:58:31 UTC --- Created an attachment (id=495998) --> (http://bugzilla.novell.com/attachment.cgi?id=495998) Patch containing potential fixes for issues encountered in brace expansion. No, the potential fixes in the patch haven't been accepted upstream (yet?). I think it's still waiting to be looked at by Chet. -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c4 Dr. Werner Fink <werner@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Severity|Normal |Minor --- Comment #4 from Dr. Werner Fink <werner@suse.com> 2012-06-22 14:10:21 UTC --- I'd like to wait on the decision of Chet -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c5 Dr. Werner Fink <werner@suse.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEEDINFO |RESOLVED InfoProvider|scotty.mcmillan+novell@gmai | |l.com | Resolution| |FIXED --- Comment #5 from Dr. Werner Fink <werner@suse.com> 2012-07-09 11:04:30 UTC --- Chet has accepted this one with message-ID <120622142714.AA33456.SM@caleb.ins.cwru.edu> -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
https://bugzilla.novell.com/show_bug.cgi?id=763591 https://bugzilla.novell.com/show_bug.cgi?id=763591#c6 --- Comment #6 from Swamp Workflow Management <swamp@suse.de> 2013-07-29 13:05:49 UTC --- openSUSE-RU-2013:1271-1: An update that has 7 recommended fixes can now be installed. Category: recommended (low) Bug References: 382214,763591,793536,804551,806628,820149,828877 CVE References: Sources used: openSUSE 12.2 (src): bash-4.2-51.13.1 -- Configure bugmail: https://bugzilla.novell.com/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.
participants (1)
-
bugzilla_noreply@novell.com