Project: mruby (mruby/mruby), language: c++
Vulnerability instance: mruby.cve-2017-9527
Sanitizer: address

================= Bug Report (1/1) ==================
## Source: GitHub Issue
## URL: https://github.com/mruby/mruby/issues/3486
## Description:
Issue: mruby/mruby#3486
Title: Heap use-after-free in mark_context_stack
State: closed
Created by: clayton-shopify
Created at: 2017-03-07 18:22:46+00:00

Issue Body:
The following input to mruby demonstrates a heap use-after-free bug: [208363.txt](https://github.com/mruby/mruby/files/825358/208363.txt)

To demonstrate, build with clang & ASAN (`CFLAGS="-fsanitize=address" LDFLAGS=-fsanitize=address make`) or use gcc & valgrind.

ASAN report:
```
==63159==ERROR: AddressSanitizer: heap-use-after-free on address 0x62f0000231e0 at pc 0x00010993a374 bp 0x7fff56344c50 sp 0x7fff56344c48
READ of size 4 at 0x62f0000231e0 thread T0
    #0 0x10993a373 in mark_context_stack gc.c:554
    #1 0x1099398e6 in mark_context gc.c:571
    #2 0x109938697 in root_scan_phase gc.c:874
    #3 0x109937870 in incremental_gc gc.c:1081
    #4 0x1099339f6 in incremental_gc_until gc.c:1112
    #5 0x109932d0a in mrb_incremental_gc gc.c:1163
    #6 0x109932698 in mrb_obj_alloc gc.c:507
    #7 0x1099afdee in str_new string.c:59
    #8 0x1099b9eb7 in mrb_str_dup string.c:1069
    #9 0x109a3df9d in mrb_vm_exec vm.c:2329
    #10 0x109a16a69 in mrb_vm_run vm.c:822
    #11 0x109a48519 in mrb_top_run vm.c:2581
    #12 0x109b17005 in mrb_load_exec parse.y:5760
    #13 0x109b17e15 in mrb_load_file_cxt parse.y:5769
    #14 0x1098b3776 in main mruby.c:227
    #15 0x7fffb4357254 in start (libdyld.dylib+0x5254)

0x62f0000231e0 is located 28128 bytes inside of 49200-byte region [0x62f00001c400,0x62f000028430)
freed by thread T0 here:
    #0 0x109c58db9 in wrap_free (libclang_rt.asan_osx_dynamic.dylib+0x4adb9)
    #1 0x1099ac20b in mrb_default_allocf state.c:56
    #2 0x10992f0a9 in mrb_free gc.c:268
    #3 0x1099394ff in incremental_sweep_phase gc.c:1055
    #4 0x109937a2c in incremental_gc gc.c:1096
    #5 0x1099339f6 in incremental_gc_until gc.c:1112
    #6 0x109932d0a in mrb_incremental_gc gc.c:1163
    #7 0x109932698 in mrb_obj_alloc gc.c:507
    #8 0x1099afdee in str_new string.c:59
    #9 0x1099b5c92 in mrb_str_plus string.c:800
    #10 0x109a308a4 in mrb_vm_exec vm.c:1930
    #11 0x109a16a69 in mrb_vm_run vm.c:822
    #12 0x109a48519 in mrb_top_run vm.c:2581
    #13 0x109b17005 in mrb_load_exec parse.y:5760
    #14 0x109b17e15 in mrb_load_file_cxt parse.y:5769
    #15 0x1098b3776 in main mruby.c:227
    #16 0x7fffb4357254 in start (libdyld.dylib+0x5254)

previously allocated by thread T0 here:
    #0 0x109c58f87 in wrap_realloc (libclang_rt.asan_osx_dynamic.dylib+0x4af87)
    #1 0x1099ac225 in mrb_default_allocf state.c:60
    #2 0x10992ddd8 in mrb_realloc_simple gc.c:201
    #3 0x10992e4be in mrb_realloc gc.c:215
    #4 0x10992ef33 in mrb_malloc gc.c:236
    #5 0x10992efcd in mrb_calloc gc.c:254
    #6 0x10992f579 in add_heap gc.c:324
    #7 0x1099326f7 in mrb_obj_alloc gc.c:510
    #8 0x1099afdee in str_new string.c:59
    #9 0x1099afbff in mrb_str_new string.c:192
    #10 0x109ad118e in codegen codegen.c:2324
    #11 0x109ae83e9 in gen_literal_array codegen.c:1106
    #12 0x109ad1a4e in codegen codegen.c:2367
    #13 0x109ae3aa0 in gen_values codegen.c:846
    #14 0x109ae0d00 in gen_call codegen.c:875
    #15 0x109ac6381 in codegen codegen.c:1582
    #16 0x109ac70b9 in codegen codegen.c:1654
    #17 0x109ae3aa0 in gen_values codegen.c:846
    #18 0x109ae0d00 in gen_call codegen.c:875
    #19 0x109ac6381 in codegen codegen.c:1582
    #20 0x109ae3aa0 in gen_values codegen.c:846
    #21 0x109ae0d00 in gen_call codegen.c:875
    #22 0x109ac6381 in codegen codegen.c:1582
    #23 0x109ac256b in codegen codegen.c:1271
    #24 0x109adb596 in scope_body codegen.c:737
    #25 0x109ac6353 in codegen codegen.c:1577
    #26 0x109abfab1 in mrb_generate_code codegen.c:2983
    #27 0x109b16480 in mrb_load_exec parse.y:5737
    #28 0x109b17e15 in mrb_load_file_cxt parse.y:5769
    #29 0x1098b3776 in main mruby.c:227

SUMMARY: AddressSanitizer: heap-use-after-free gc.c:554 in mark_context_stack
Shadow bytes around the buggy address:
  0x1c5e000045e0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e000045f0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e00004600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e00004610: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e00004620: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x1c5e00004630: fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd
  0x1c5e00004640: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e00004650: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e00004660: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e00004670: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c5e00004680: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==63159==ABORTING
Abort trap: 6
```
Valgrind report:
```
==34881== Invalid read of size 1
==34881==    at 0x403228: mark_context_stack (gc.c:554)
==34881==    by 0x4032A3: mark_context (gc.c:571)
==34881==    by 0x403D98: root_scan_phase (gc.c:874)
==34881==    by 0x4044B4: incremental_gc (gc.c:1081)
==34881==    by 0x4045B5: incremental_gc_until (gc.c:1112)
==34881==    by 0x4047A3: mrb_incremental_gc (gc.c:1163)
==34881==    by 0x40302D: mrb_obj_alloc (gc.c:507)
==34881==    by 0x413B5D: str_new (string.c:59)
==34881==    by 0x416940: mrb_str_dup (string.c:1069)
==34881==    by 0x410F57: mrb_vm_exec (vm.c:2329)
==34881==    by 0x409E9F: mrb_vm_run (vm.c:822)
==34881==    by 0x4120F4: mrb_top_run (vm.c:2581)
==34881==  Address 0x5608b30 is 28,128 bytes inside a block of size 49,200 free'd
==34881==    at 0x4C2BDEC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==34881==    by 0x406F2D: mrb_default_allocf (state.c:56)
==34881==    by 0x40281E: mrb_free (gc.c:268)
==34881==    by 0x404393: incremental_sweep_phase (gc.c:1055)
==34881==    by 0x404551: incremental_gc (gc.c:1096)
==34881==    by 0x4045B5: incremental_gc_until (gc.c:1112)
==34881==    by 0x4047A3: mrb_incremental_gc (gc.c:1163)
==34881==    by 0x40302D: mrb_obj_alloc (gc.c:507)
==34881==    by 0x413B5D: str_new (string.c:59)
==34881==    by 0x415C72: mrb_str_plus (string.c:800)
==34881==    by 0x40E993: mrb_vm_exec (vm.c:1930)
==34881==    by 0x409E9F: mrb_vm_run (vm.c:822)
==34881==
```

This issue was reported by https://hackerone.com/minhrau



Comments:
Comment by matz on 2017-03-19 17:45:04+00:00:
Cannot reproduce as of 631de65.
Any additional info?

---

Comment by clayton-shopify on 2017-03-20 13:59:28+00:00:
@matz I did a bisect and found that the crash stopped after https://github.com/mruby/mruby/commit/fa502b498ed421a7bc95fb675ae0f4c6e2f1c16f. I'm not sure whether that was the root cause of the crash or just a coincidence. Reverting that commit from the latest master brings back the crash.

---

Comment by matz on 2017-03-21 02:37:28+00:00:
@clayton-shopify I don't know. The source is too cryptic to guess.

---

Comment by clayton-shopify on 2017-04-03 20:48:45+00:00:
@matz This is crashing for me again on the latest master (https://github.com/mruby/mruby/commit/e2e2edae51f33ef5ff164c60ed57e1466d1edaea) on OS X building with clang & ASAN.

---

Comment by clayton-shopify on 2017-04-10 12:41:36+00:00:
It looks like this was fixed by https://github.com/mruby/mruby/commit/5c114c91d4ff31859fcd84cf8bf349b737b90d99.

Attachments:
https://github.com/mruby/mruby/files/825358/208363.txt

Commit References:
5c114c91d4ff31859fcd84cf8bf349b737b90d99
e2e2edae51f33ef5ff164c60ed57e1466d1edaea
fa502b498ed421a7bc95fb675ae0f4c6e2f1c16f

Build script:
#!/bin/bash -eu
# Minimized build script with only core build commands
set -eu
export LD=clang
export LDFLAGS="$CFLAGS"
./minirake clean && ./minirake -j$(nproc) all

Dockerfile:
FROM hwiwonlee/secb.base:latest
RUN apt-get update && apt-get install -y make autoconf automake libtool ruby bison
RUN git clone https://github.com/mruby/mruby mruby
RUN git -C mruby checkout 491d68bb3004eb8d7deec4a3a682b25de0d4afc2
WORKDIR $SRC/mruby
COPY build.sh $SRC/

Additional files: