Skip to content

ARM64 asm uses reserved registers #46

@StephenButtolph

Description

@StephenButtolph

Background

In golang for arm64, the following registers are marked as reserved

  • R18
  • R27
  • R28
  • R29
  • R30

The registers of note here are R27 and R29 as they are used by the mul macro (expanded in gfpMul).

Explanation

I'm not sure what the impact is of overwriting R27, but R29 (the frame pointer) gets written to the stack when calling another function after executing the mul code. The go runtime assumes that it is able to traverse the stack by repeatedly dereferencing the frame pointer. Some examples of functions that traverse the stack by following the frame pointer are:

Because the frame pointer has been clobbered, these stack traversals can segfault.

Test

When run on arm64, the following test (added here) may produce a SIGSEGV: segmentation violation. The crash does not happen every time, as it requires lock contention inside the call to fmt.Print("").

t.Run("mul_fp_corruption", func(t *testing.T) {
	// By enabling mutex profiling, the go runtime will traverse the stack
	// to measure mutex operations when a mutex is unlocked when a goroutine
	// is blocking on it.
	runtime.SetMutexProfileFraction(1)

	var wg sync.WaitGroup
	wg.Add(testTimes)
	for i := 0; i < testTimes; i++ {
		// If multiple goroutines interact with a global sync pool, the
		// goroutines may block on acquiring a lock. When that happens, the
		// mutex profiler will traverse the stack.
		go func() {
			defer wg.Done()

			a := togfP(randomGF(rand.Reader))
			b := togfP(randomGF(rand.Reader))
			c := &gfP{}

			// Corrupt the Frame Pointer.
			gfpMul(c, a, b)

			// Calling another function stores the FP on the stack.
			//
			// Additionally, Print ends up interacting with a global sync
			// pool which can cause this stack to be traversed.
			fmt.Print("")
		}()
	}
	wg.Wait()
})

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions