New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use-after-free in mrb_obj_extend #3419

Closed
clayton-shopify opened this Issue Jan 31, 2017 · 0 comments

Comments

Projects
None yet
1 participant
@clayton-shopify
Contributor

clayton-shopify commented Jan 31, 2017

The following input demonstrates a use-after-free bug in mrb_obj_extend:

def recurse(n)
  return if n == 0
  extend(Kernel)
  recurse(n-1)
end

recurse(100)

To see that there is a use-after-free, build MRuby with clang and ASAN (CFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address make).

The use-after-free occurs here:

mruby/src/kernel.c

Lines 412 to 413 in 6420951

mrb_funcall(mrb, argv[argc], "extend_object", 1, obj);
mrb_funcall(mrb, argv[argc], "extended", 1, obj);

The mrb_funcall on the first line can trigger a stack extension (stack_extend and stack_extend_alloc) which then leaves argv[argc] referring to the old (freed) stack on the second line.

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

ASAN report:

==81058==ERROR: AddressSanitizer: heap-use-after-free on address 0x6210000178b0 at pc 0x000105b0d911 bp 0x7fff5a19f650 sp 0x7fff5a19f648
READ of size 8 at 0x6210000178b0 thread T0
    #0 0x105b0d910 in mrb_obj_extend (mruby+0x1000b6910)
    #1 0x105b03943 in mrb_obj_extend_m (mruby+0x1000ac943)
    #2 0x105bc41fa in mrb_vm_exec (mruby+0x10016d1fa)
    #3 0x105bb9ea9 in mrb_vm_run (mruby+0x100162ea9)
    #4 0x105bea8d9 in mrb_top_run (mruby+0x1001938d9)
    #5 0x105cb7a55 in mrb_load_exec (mruby+0x100260a55)
    #6 0x105cb8865 in mrb_load_file_cxt (mruby+0x100261865)
    #7 0x105a590ba in main mruby.c:232
    #8 0x7fffb4357254 in start (libdyld.dylib+0x5254)

0x6210000178b0 is located 4016 bytes inside of 4096-byte region [0x621000016900,0x621000017900)
freed by thread T0 here:
    #0 0x105df7f87 in wrap_realloc (libclang_rt.asan_osx_dynamic.dylib+0x4af87)
    #1 0x105b505c5 in mrb_default_allocf (mruby+0x1000f95c5)
    #2 0x105ad4328 in mrb_realloc_simple gc.c:201
    #3 0x105ad4a0e in mrb_realloc gc.c:215
    #4 0x105beb1a1 in stack_extend_alloc (mruby+0x1001941a1)
    #5 0x105bb2c55 in stack_extend (mruby+0x10015bc55)
    #6 0x105baf9b0 in mrb_funcall_with_block (mruby+0x1001589b0)
    #7 0x105badbc7 in mrb_funcall_argv (mruby+0x100156bc7)
    #8 0x105bad64e in mrb_funcall (mruby+0x10015664e)
    #9 0x105b0d815 in mrb_obj_extend (mruby+0x1000b6815)
    #10 0x105b03943 in mrb_obj_extend_m (mruby+0x1000ac943)
    #11 0x105bc41fa in mrb_vm_exec (mruby+0x10016d1fa)
    #12 0x105bb9ea9 in mrb_vm_run (mruby+0x100162ea9)
    #13 0x105bea8d9 in mrb_top_run (mruby+0x1001938d9)
    #14 0x105cb7a55 in mrb_load_exec (mruby+0x100260a55)
    #15 0x105cb8865 in mrb_load_file_cxt (mruby+0x100261865)
    #16 0x105a590ba in main mruby.c:232
    #17 0x7fffb4357254 in start (libdyld.dylib+0x5254)

previously allocated by thread T0 here:
    #0 0x105df7f87 in wrap_realloc (libclang_rt.asan_osx_dynamic.dylib+0x4af87)
    #1 0x105b505c5 in mrb_default_allocf (mruby+0x1000f95c5)
    #2 0x105ad4328 in mrb_realloc_simple gc.c:201
    #3 0x105ad4a0e in mrb_realloc gc.c:215
    #4 0x105beb1a1 in stack_extend_alloc (mruby+0x1001941a1)
    #5 0x105bb2c55 in stack_extend (mruby+0x10015bc55)
    #6 0x105bc503d in mrb_vm_exec (mruby+0x10016e03d)
    #7 0x105bb9ea9 in mrb_vm_run (mruby+0x100162ea9)
    #8 0x105bea8d9 in mrb_top_run (mruby+0x1001938d9)
    #9 0x105cb7a55 in mrb_load_exec (mruby+0x100260a55)
    #10 0x105cb8865 in mrb_load_file_cxt (mruby+0x100261865)
    #11 0x105a590ba in main mruby.c:232
    #12 0x7fffb4357254 in start (libdyld.dylib+0x5254)

SUMMARY: AddressSanitizer: heap-use-after-free (mruby+0x1000b6910) in mrb_obj_extend
Shadow bytes around the buggy address:
  0x1c4200002ec0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200002ed0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200002ee0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200002ef0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x1c4200002f00: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
=>0x1c4200002f10: fd fd fd fd fd fd[fd]fd fd fd fd fd fd fd fd fd
  0x1c4200002f20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c4200002f30: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c4200002f40: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c4200002f50: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x1c4200002f60: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
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
==81058==ABORTING
Abort trap: 6

@matz matz closed this in bf4e79c Feb 4, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment