Skip to content
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

Out-of-bounds read in multiple functions and NULL pointer dereference #1050

Open
269261 opened this issue Nov 19, 2023 · 0 comments · May be fixed by #1080
Open

Out-of-bounds read in multiple functions and NULL pointer dereference #1050

269261 opened this issue Nov 19, 2023 · 0 comments · May be fixed by #1080
Labels

Comments

@269261
Copy link
Contributor

269261 commented Nov 19, 2023

Sample files were attached to this issue in a ZIP file (s2.zip).

Issue 1 - OOB read past the end of itype array

Crash is reproducible only if mupen64plus-core lib was compiled with AddressSanitizer.

Loading and executing attached bug1.z64 file results in the following crash:

$ ./BinAsan/Release/RMG /tmp/bug1.z64
=================================================================
==185744==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7fb32e8d0b60 at pc 0x7fb32ad7ce36 bp 0x7fb300a9cab0 sp 0x7fb300a9caa0
READ of size 1 at 0x7fb32e8d0b60 thread T13 (Thread::Emulati)
    #0 0x7fb32ad7ce35 in address_generation /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:4379
    #1 0x7fb32add0dc2 in new_recompile_block /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:11539
    #2 0x7fb32ad6d338 in get_addr /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:2677
    #3 0x7fb32ad6d5ea in get_addr_ht /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:2693
    #4 0x7fb32add7f12  (/tmp/RMG/BinAsan/Release/Core/libmupen64plus.so+0x1d7f12) (BuildId: b6a0b16a4fee2ce372193dff1a7b713543d87145)

0x7fb32e8d0b60 is located 32 bytes before global variable 'opcode' defined in '/tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:247:15' (0x7fb32e8d0b80) of size 4096
0x7fb32e8d0b60 is located 0 bytes after global variable 'itype' defined in '/tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:246:15' (0x7fb32e8cfb60) of size 4096
SUMMARY: AddressSanitizer: global-buffer-overflow /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:4379 in address_generation
...

Crash happens in:

if(itype[i+1]==LOAD||itype[i+1]==LOADLR||itype[i+1]==STORE||itype[i+1]==STORELR||itype[i+1]==C1LS) {

In presented case itype array index is 4096 (i+1=4096), but array size is only 4096 (so highest valid index is 4095). This leads to out-of-bounds read past the end of the itype array.

Issue 2 - OOB read past the end of LUT_r and LUT_w arrays

Loading and executing attached bug2a.z64 and bug2b.z64 files results in the following crashes:

$ gdb -ex run --args Bin/Release/RMG /tmp/bug2a.z64
GNU gdb (Ubuntu 13.1-2ubuntu2) 13.1
...

Thread 14 "Thread::Emulati" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffa63fd6c0 (LWP 186033)]
0x00007fffcc08ed4a in invalidate_block (block=3466518528) at /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:2816
2816	  if(page>262143&&g_dev.r4300.cp0.tlb.LUT_r[block]) page=(g_dev.r4300.cp0.tlb.LUT_r[block]^0x80000000)>>12;
(gdb) print block
$1 = 3466518528
...

$ gdb -ex run --args Bin/Release/RMG /tmp/bug2b.z64
GNU gdb (Ubuntu 13.1-2ubuntu2) 13.1
...

Thread 14 "Thread::Emulati" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffd23fd6c0 (LWP 186077)]
0x00007fffc808efac in invalidate_block (block=2433696) at /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:2874
2874	  if(g_dev.r4300.cp0.tlb.LUT_w[block]) {
(gdb) print block
$1 = 2433696

Crash happens in one of these places:

if(page>262143&&g_dev.r4300.cp0.tlb.LUT_r[block]) page=(g_dev.r4300.cp0.tlb.LUT_r[block]^0x80000000)>>12;
if(g_dev.r4300.cp0.tlb.LUT_w[block]) {

In presented cases LUT_r and LUT_w arrays index (block) equals 3,466,518,528 or 2,433,696, but array size is only 1,048,576. This leads to out-of-bounds read past the end of the arrays and crash due to memory access violation.

Note: not sure, but it looks like g_dev.r4300.cached_interp.invalid_code access also leads to OOB read, though app doesn't crash there:

g_dev.r4300.cached_interp.invalid_code[block]=1;

Issue 3 - OOB read of bytes placed before invalidate_block_reg array

Crash is reproducible only if mupen64plus-core lib was compiled with AddressSanitizer.

Loading and executing attached bug3.z64 file results in the following crash:

$ ./BinAsan/Release/RMG /tmp/bug3.z64
=================================================================
==186182==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7f03fe614cb8 at pc 0x7f03fe560f6c bp 0x7f03d438eb60 sp 0x7f03d438eb50
READ of size 8 at 0x7f03fe614cb8 thread T13 (Thread::Emulati)
    #0 0x7f03fe560f6b in do_invstub /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/x64/assem_x64.c:3032
    #1 0x7f03fe5d36c6 in new_recompile_block /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:11693
    #2 0x7f03fe5d7f72  (/tmp/RMG/BinAsan/Release/Core/libmupen64plus.so+0x1d7f72) (BuildId: b6a0b16a4fee2ce372193dff1a7b713543d87145)

...
0x7f03fe614cb8 is located 8 bytes before global variable 'invalidate_block_reg' defined in '/tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/x64/assem_x64.c:58:24' (0x7f03fe614cc0) of size 64
SUMMARY: AddressSanitizer: global-buffer-overflow /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/x64/assem_x64.c:3032 in do_invstub
Shadow bytes around the buggy address:
  0x7f03fe614a00: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f03fe614a80: 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 00 00 00 00
  0x7f03fe614b00: 00 00 00 00 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9
  0x7f03fe614b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f9
  0x7f03fe614c00: f9 f9 f9 f9 00 00 00 00 f9 f9 f9 f9 00 00 00 00
=>0x7f03fe614c80: 00 00 00 00 f9 f9 f9[f9]00 00 00 00 00 00 00 00
  0x7f03fe614d00: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f03fe614d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f03fe614e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f03fe614e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x7f03fe614f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
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
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
...

Crash happens in:

emit_call((intptr_t)invalidate_block_reg[stubs[n][4]]);

In presented case invalidate_block_reg array index is -1. This leads to out-of-bounds read of bytes placed before invalidate_block_reg array.

Please note that the similar issue may exist in related files too (e.g. assem_x86.c).

Issue 4 - NULL pointer dereference in set_jump_taget function

Loading and executing attached bug4.z64 file results in the following crash:

$ gdb -ex run --args Bin/Release/RMG /tmp/bug4.z64
GNU gdb (Ubuntu 13.1-2ubuntu2) 13.1
...

Thread 14 "Thread::Emulati" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fffd23fd6c0 (LWP 186544)]
0x00007fffc8080a13 in set_jump_target (addr=0, target=140736559244610) at /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/x64/assem_x64.c:73
73	  if(*ptr==0x0f)
(gdb) print ptr
$1 = (u_char *) 0x0
(gdb) bt
#0  0x00007fffc8080a13 in set_jump_target (addr=0, target=140736559244610) at /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/x64/assem_x64.c:73
#1  0x00007fffc80a3f14 in sjump_assemble (i=743, i_regs=0x7fffcbc2cbf8 <regs+101048>) at /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:7939
#2  0x00007fffc80bd03d in new_recompile_block (addr=-1543503808) at /tmp/RMG/Source/3rdParty/mupen64plus-core/src/device/r4300/new_dynarec/new_dynarec.c:11612
#3  0x00007fffc80bf7f3 in new_dyna_start () at /tmp/RMG/Bin/Release/Core/libmupen64plus.so
#4  0x0000000000000000 in  ()

Crash happens in:

In presented case ptr value is NULL, leading to NULL pointer dereference and crash. This issue does not seem to lead to any security issues.

Please note that the similar issue may exist in related files too (e.g. assem_x86.c).

Test platform

  • Ubuntu 23.04 (x86-64)
  • RMG emulator (https://github.com/Rosalie241/RMG)
    • built from master branch
    • Release build, x86-64
    • custom flags added to mupen64plus-core Makefile:
      • CFLAGS += -O0 -g -fsanitize=address
      • -O0 and -g for better crash backtraces in Release build
      • -fsanitize=address to compile with AddressSanitizer
  • gdb 13.1 for debugging
@richard42 richard42 added the bug label Jan 13, 2024
@Rosalie241 Rosalie241 linked a pull request May 8, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants