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

[AArch64][PAC] Emit a fatal error when ptrauth target feature is missing #62

Open
wants to merge 8 commits into
base: elf-pauth
Choose a base branch
from

Conversation

kovdan01
Copy link
Contributor

@kovdan01 kovdan01 commented Dec 4, 2023

Previously, in expandPtrAuthPseudo we expanded MOVaddrPAC, LOADgotPAC and LOADauthptrgot pseudo-instructions without taking presense of PAuth subtarget feature into account. In case of LOADauthptrgot, it resulted in undesired so-called $auth_ptr$ stub and a corresponding AUTH relocation. In case MOVaddrPAC and LOADgotPAC, it resulted in pac-specific instructions (e.g. paciza) emitted which was only caught via assertion during machine instructions verification (and not caught at all when assertions are disabled).

This patch makes us emit a fatal error and fail fast in such cases.

Previously, in `expandPtrAuthPseudo` we expanded `MOVaddrPAC`,
`LOADgotPAC` and `LOADauthptrgot` pseudo-instructions without taking
presense of PAuth subtarget feature into account. In case of
`LOADauthptrgot`, it resulted in undesired so-called `$auth_ptr$` stub and a
corresponding AUTH relocation. In case `MOVaddrPAC` and `LOADgotPAC`, it
resulted in pac-specific instructions (e.g. `paciza`) emitted which was
only caught via assertion during machine instructions verification (and
not caught at all when assertions are disabled).

This patch makes us emit a fatal error and fail fast in such cases.
@kovdan01 kovdan01 added the pauth label Dec 4, 2023
@kovdan01 kovdan01 requested review from asl and atrosinenko December 4, 2023 08:05
@asl
Copy link
Contributor

asl commented Dec 5, 2023

@atrosinenko please review

The option is not present on assertion-disabled builds.
A test without the option (and without verifying debug output ensuring
which particular pseudo-instructions are expanded) is also added - it
looks reasonable since the PR itself is intended to add proper error
handling for assertion-disabled builds.
Copy link
Contributor

@atrosinenko atrosinenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if other code paths have to be guarded as well.


;--- MOVaddrPAC.ll

; RUN: not --crash llc -debug -mtriple aarch64-elf MOVaddrPAC.ll 2>&1 | \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-debug may be replaced with -debug-only=aarch64-expand-hardened-pseudos for less verbose debug output (not sure which is more canonical in tests, though).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, fixed in 52afe42

@kovdan01
Copy link
Contributor Author

kovdan01 commented Dec 7, 2023

@atrosinenko Thanks for review. Several points:

  1. See 81cb742 and 3821445 for additional tests on other code paths

    I wonder if other code paths have to be guarded as well.

  2. Switched to CHECK-NEXT where suitable 9ed8fc6

@kovdan01 kovdan01 requested a review from atrosinenko December 7, 2023 03:13
Copy link
Contributor

@atrosinenko atrosinenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is AArch64ExpandHardenedPseudos::expandAuthLoad method expected to contain a similar check?

Comment on lines 53 to 59
define i8* @foo() #0 {
%tmp = bitcast { i8*, i32, i64, i64 }* @g_weak.ptrauth to i8*
ret i8* %tmp
}

@g_weak = extern_weak global i32
@g_weak.ptrauth = private constant { i8*, i32, i64, i64 } { i8* bitcast (i32* @g_weak to i8*), i32 0, i64 0, i64 0 }, section "llvm.ptrauth"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typed pointers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8e30a83

Comment on lines 46 to 52
define i8* @foo() #0 {
%tmp = bitcast { i8*, i32, i64, i64 }* @g_weak.ptrauth to i8*
ret i8* %tmp
}

@g_weak = extern_weak global i32
@g_weak.ptrauth = private constant { i8*, i32, i64, i64 } { i8* bitcast (i32* @g_weak to i8*), i32 0, i64 0, i64 0 }, section "llvm.ptrauth"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typed pointers.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8e30a83

@kovdan01
Copy link
Contributor Author

kovdan01 commented Dec 8, 2023

Is AArch64ExpandHardenedPseudos::expandAuthLoad method expected to contain a similar check?

@atrosinenko In bffc609 I've added checks in AArch64DAGToDAGISel::tryAuthLoad and before AArch64InstructionSelector::selectAuthLoad - those are the places where LDRA* pseudos are emitted. So, we should only go to AArch64ExpandHardenedPseudos::expandAuthLoad after these checks - inserted a corresponding assertion there.

@kovdan01 kovdan01 requested a review from atrosinenko December 8, 2023 21:29
Copy link
Contributor

@atrosinenko atrosinenko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for too many iterations, I just spotted the tests are in the llvm/lib/Target/AArch64/GISel/ directory. Maybe these could be moved to llvm/lib/Target/AArch64 and updated to test both DAGISel and GlobalISel like it is done in ptrauth-intrinsic-blend.ll. This should make TODO unneeded, I guess.

@kovdan01
Copy link
Contributor Author

@atrosinenko Thanks, testing both with -global-isel=0 and -global-isel=1 is definitely needed. It revealed several new cases with failures.

I don't feel the approach initially taken suites best now - trying to guard every place where we potentially emit auth-specific instructions makes things harder to maintain, understand, and there are way too many points responsible for checking such a simple things.

I suppose the following approach could be better.

  • For each function, if PAuth subtarget feature is not enabled, see if there are "ptrauth-*" attributes ("ptrauth-calls", "ptrauth-returns", etc). We can implement a separate pass for such a check.
  • If PAuth subtarget feature is not enabled, check if there are any objects in "llvm.ptrauth" section.
  • Check llvm ptrauth intrinsics separately.

Please let me know your thoughts on this. Thanks!

@kovdan01
Copy link
Contributor Author

As discussed with @asl, we should move the checks to frontend. See #65.

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

Successfully merging this pull request may close these issues.

3 participants