This is an archive of the discontinued LLVM Phabricator instance.

[libunwind,EHABI,ARM] Fix get/set of RA_AUTH_CODE.
ClosedPublic

Authored by simon_tatham on Jun 24 2022, 6:21 AM.

Details

Summary

According to EHABI32 §8.5.2, the PAC for the return address of a
function described in an exception table is supposed to be addressed
in the _Unwind_VRS_{Get,Set} API by setting regclass=_UVRSC_PSEUDO and
regno=0. (The space of 'regno' values is independent for each
regclass, and for _UVRSC_PSEUDO, there is only one valid regno so far.)

That is indeed what libunwind's _Unwind_VRS_{Get,Set} functions expect
to receive. But at two call sites, the wrong values are passed in:
regno is being set to UNW_ARM_RA_AUTH_CODE (0x8F) instead of 0, and in
one case, regclass is _UVRSC_CORE instead of _UVRSC_PSEUDO.

As a result, those calls to _Unwind_VRS_{Get,Set} return
_UVRSR_FAILED, which their callers ignore. So if you compile in the
AUTG instruction that actually validates the PAC, it will try to
validate what's effectively an uninitialised register as an
authentication code, and trigger a CPU fault even on correct exception
unwinding.

Diff Detail

Event Timeline

simon_tatham created this revision.Jun 24 2022, 6:21 AM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJun 24 2022, 6:21 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript
simon_tatham requested review of this revision.Jun 24 2022, 6:21 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 24 2022, 6:21 AM
This revision was not accepted when it landed; it landed in state Needs Review.Jun 27 2022, 1:36 AM
This revision was automatically updated to reflect the committed changes.

Hmm, Phabricator tells me that some other review should have been done before I landed this. That wasn't obvious, sorry – I saw an email saying someone had accepted the change, and assumed that was enough to push it.

If I violated a procedure, sorry about that! But I hope this change will be considered harmless enough to not revert.