Skip to content
Permalink
master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time

Garmin Forerunner 235: Unchecked read outside of TVM stack in DUP

Vendors

  • Garmin

Affected Products

Forerunner 235 firmware version 7.90

Summary

The ConnectIQ program interpreter trusts the offset provided for the stack value duplication instruction, DUP. The offset is unchecked and memory prior to the start of the execution stack can be read and treated as a TVM object. A succesful exploit could use the vulnerability to leak runtime information such as the heap handle or pointer for a number of TVM context variables. This could help create a reliable exploit when paired with some other vulnerability classes.

Mitigation

This issue was fixed by Forerunner 235 software version 8.20.

Credit

This issue was found by Dion Blazakis of Atredis Partners.

References

Report Timeline

  • 2020-04-17: Atredis Partners sent an initial notification to Garmin, including a draft advisory.
  • 2020-08-17: Atredis Partners shared a copy of the draft advisory with CERT/CC.
  • 2020-10-05: Atredis Partners published this advisory.

Technical Details

The TVM interpreter is responsible for running the application (or .PRG) downloaded from the Garmin ConnectIQ app store. The .PRG file packages both resources (e.g., images and text) and TVM bytecode needed to run the program. Applications are programmed in the proprietary MonkeyC language and are built into .PRG programs via the free Garmin ConnectIQ SDK. Once on the device, the virtual machine ensures the applications are strictly constrained to prevent excess use of memory or computation time. Additionally, the runtime API exposed to each program is constrained based on the type of application installed (e.g., a watchface, a widget, a full application).

The TVM is a stack based virtual machine and maintains a runtime stack of TVM values. The DUP instruction allows the running program to duplicate a value from any slot on the stack and push the copy on the top of the stack.

int __fastcall tvm_op_dup(struct tvm *ctx)
{
  char *pc; // r1
  struct stack_value *sp; // r2
  int stack_offset; // t1
  struct tvm *ctx:v4; // r3
  int v5; // r0
  struct stack_value v7; // [sp+0h] [bp-10h]

  pc = ctx->pc_ptr;
  sp = ctx->stack_ptr;
  stack_offset = (unsigned __int8)*pc;
  ctx->pc_ptr = pc + 1;
  ctx:v4 = ctx;
  v7 = sp[-stack_offset];
  v5 = *(_DWORD *)&v7.type;
  ctx:v4->stack_ptr = sp + 1;
  *(_DWORD *)&sp[1].type = v5;
  HIBYTE(sp[1].value) = HIBYTE(v7.value);
  tvm_value_incref(ctx:v4, (struct tvm_value *)&v7);
  return 0;
}

The implementation is not complex. It reads the next byte from the instruction stream, uses this byte as the negative offset to read from the top of the stack, and then copies that value to the next stack entry. Finally, the function increases the reference count in the tvm value.

Triggering this requires direct bytecode manipulation of a PRG file (or construction of one from scratch). The vulnerability is likely only useful when used in conjunction with another vulnerability to provide a reliable read/write primitive.