https://sourceware.org/bugzilla/show_bug.cgi?id=34498

            Bug ID: 34498
           Summary: eu-stacktrace: aarch64 SP register number is used as
                    packed perf-array index, causing out-of-frame read
           Product: elfutils
           Version: unspecified
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: tools
          Assignee: unassigned at sourceware dot org
          Reporter: karankurani3k at gmail dot com
                CC: elfutils-devel at sourceware dot org
  Target Milestone: ---

Created attachment 16916
  --> https://sourceware.org/bugzilla/attachment.cgi?id=16916&action=edit
Detailed analysis and aarch64 runtime reproduction of a register-number versus
packed perf-array index mismatch causing an out-of-frame read in eu-stacktrace.

On aarch64, eu-stacktrace uses the architectural stack-pointer register
number (31) directly as an index into the packed PERF_SAMPLE_REGS_USER
register array.

The perf register array contains only the registers selected by the sample
mask, packed in ascending mask-bit order. Therefore an architectural register
number is not necessarily the physical array index.

In src/stacktrace.c, sp_reg_index() returns 31 for 64-bit aarch64 and the
result is used directly as:

    regs->regs[31]

The existing expected_frame_nregs() check accepts 14 registers for
EM_AARCH64, so it does not protect the later index-31 access.

For the aarch64 register masks, SP is at packed index 12 or 25 depending on
the mask being used; index 31 is outside the array in either case.

The issue is reachable through the normal:

    eu-stacktrace -i <capture>

path on aarch64.

Testing against origin/main
fb5473ac7368bbbbc2ea9d86241bd6c882e3fcb5 using a cross-built aarch64
eu-stacktrace under qemu-aarch64-static confirmed:

- n_regs=14 while index 31 is still read
- the access is 17 elements / 136 bytes beyond the declared register array
- with a tightly sized STACK_USER frame, the value read comes from the next
  capture frame
- reproduced 3/3
- ABI32 control uses index 13 and remains in bounds

This demonstrates an out-of-bounds read of the declared register array that
crosses the enclosing STACK_USER frame.

I have not demonstrated escape beyond the larger Sysprof reader allocation,
information disclosure of secret process memory, a crash, code execution, or
RCE.

Separately, because register number 31 is not the physical packed index of SP
under the aarch64 masks, the last_sp value is incorrect even for normal valid
aarch64 samples.

The correct fix needs to translate the architectural SP register number
through the perf register mapping/mask before indexing the packed array and
then validate the resulting physical index against the number of registers
present.

A detailed root-cause analysis and runtime validation are included in the
attached report.

Reporter:

Karan Kurani <[email protected]>

-- 
You are receiving this mail because:
You are on the CC list for the bug.

Reply via email to