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

DebugWire flash read causes heap corruption on LP64 hosts #107

Open
tlyu opened this issue Dec 28, 2023 · 3 comments · May be fixed by #90
Open

DebugWire flash read causes heap corruption on LP64 hosts #107

tlyu opened this issue Dec 28, 2023 · 3 comments · May be fixed by #90

Comments

@tlyu
Copy link

tlyu commented Dec 28, 2023

Target is an ATmega328P (Arduino Uno) connected to Atmel-ICE (also observed with AVR Dragon). Host is a MacBook Air M2 running macOS Ventura (also observed with an Intel MacBook Pro on an older OS).

Reading from flash via DebugWire can cause heap corruption on LP64 hosts, due to a confluence of errors. If the address would be a negative host int (typically 0x80000000 or greater), chunksize can get inappropriately reduced, leading to a very extended loop due to underflow/wraparound of numBytes. This eventually causes host heap corruption as the loop attempts to write beyond the end of the flash cache.

This demo required a patched avarice instrumented to show the intermediate values involved in the erroneous calculations. I used netcat to talk to avarice, because my previous reproducer was an older GDB plus an older version of avarice that didn't send memory maps (and thus allowed GDB to read from "negative" addresses).

It's possible that a future GDB bug or newer target memory maps might allow this to happen.

GDB: <mffffffe0,10>

GDB: Read 16 bytes from 0xFFFFFFE0
jtagRead large addr FFFFFFFFFF68FFE0
reducing chunksize from 10 to 20
command "read memory" [0x12, 0x21]
0E 00 09 00 12 21 00 B0 80 FF 68 FF 80 00 00 00
Received 0x81 0x11 0x00 0x87 0x0e 0x09
read:  0e 09 00 12 84 00 0a d0 8f e0 7a cf 81 35 11 f4 88 e0 18 d0 1d d0 80 e1 01 d0 65 cf 98 2f 80 91 c0 00 85 ff fc cf 90 93 c6 00 08 95 80 91 c0 00 87 ff fc cf 80 91 c0 00 84 fd 01 c0 a8 95 80 91 c6 00 08 95 e0 e6 f0 e0 98 e1 90 83 80 83 08 95 ed df 80 32 19 f0 88 e0 f5 df ff cf 84 e1 de cf 1f 93 18 2f e3 df 11 50 e9 f7 f2 df 1f 91 08 95 80 e0 e8 df ee 27 ff 27 09 94 ff ff ff ff ff ff ff ff ff ff 04 04 00

Got message seqno 9 (command_sequence == 9)
response: 12 84 00 0A D0 8F E0 7A CF 81 35 11 F4 88 E0 18 D0 1D D0 80 E1 01 D0 65 CF 98 2F 80 91 C0 00 85 FF FC CF 90 93 C6 00 08 95 80 91 C0 00 87 FF FC CF 80 91 C0 00 84 FD 01 C0 A8 95 80 91 C6 00 08 95 E0 E6 F0 E0 98 E1 90 83 80 83 08 95 ED DF 80 32 19 F0 88 E0 F5 DF FF CF 84 E1 DE CF 1F 93 18 2F E3 DF 11 50 E9 F7 F2 DF 1F 91 08 95 80 E0 E8 DF EE 27 FF 27 09 94 FF FF FF FF FF FF FF FF FF FF 04 04 00

It looped, continuing for over a hundred iterations. Eventually, this ended with:

command "read memory" [0x12, 0x21]
0E 00 8B 00 12 21 00 B0 80 40 69 FF 80 00 00 00
libc++abi: terminating due to uncaught exception of type jtag_exception: Querying for response: hid_write() failed

remote.cc calls hexToInt with a signed int addr as the destination. It then calls jtagRead, which takes an unsigned long as the address. This causes sign extension while converting a negative number to unsigned long. The chunksize adjustment calculations in jtag3rw.cc then increase chunksize beyond numBytes, leading to the integer underflow/wraparound and buffer overflow.

I have a patch in #90 that needs to be cleaned up and duplicated in jtag3rw.cc. (I created it when I first ran across this bug with AVR Dragon.)

Full log:

overflow.txt

@tlyu tlyu linked a pull request Dec 28, 2023 that will close this issue
@tlyu
Copy link
Author

tlyu commented Dec 28, 2023

Updated #90.

@tlyu
Copy link
Author

tlyu commented Dec 28, 2023

Crash reporter excerpt:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Termination Reason:    Namespace SIGNAL, Code 6 Abort trap: 6
Terminating Process:   avarice [92774]

Application Specific Information:
abort() called


Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	       0x19af78744 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x19afafc28 pthread_kill + 288
2   libsystem_c.dylib             	       0x19aebdae8 abort + 180
3   libsystem_malloc.dylib        	       0x19addee28 malloc_vreport + 908
4   libsystem_malloc.dylib        	       0x19adf55d4 malloc_zone_error + 104
5   libsystem_malloc.dylib        	       0x19aded148 nanov2_guard_corruption_detected + 44
6   libsystem_malloc.dylib        	       0x19adec344 nanov2_allocate_outlined + 404
7   libc++abi.dylib               	       0x19af6a924 operator new(unsigned long) + 32
8   avarice                       	       0x10009282c jtag3::sendFrame(unsigned char*, int) + 72
9   avarice                       	       0x100093064 jtag3::sendJtagCommand(unsigned char*, int, char const*, unsigned char*&, int&) + 116
10  avarice                       	       0x1000931d0 jtag3::doJtagCommand(unsigned char*, int, char const*, unsigned char*&, int&) + 64
11  avarice                       	       0x1000964ac jtag3::jtagRead(unsigned long, unsigned int) + 892
12  avarice                       	       0x1000a08c8 talkToGdb() + 1268
13  avarice                       	       0x10009e5c8 main + 4088
14  dyld                          	       0x19ac57f28 start + 2236

@tlyu
Copy link
Author

tlyu commented Dec 28, 2023

Diagnostics printed to terminal, which I wasn't able to capture by redirection:

avarice(92815,0x1f66fa100) malloc: Heap corruption detected, free list is damaged at 0x600000f78010
*** Incorrect guard value: 18446744071898212351
avarice(92815,0x1f66fa100) malloc: *** set a breakpoint in malloc_error_break to debug
[1]    92815 abort      ~/src/avarice/src/avarice -d -w -C -4 localhost:6000

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant