-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang] Implement function pointer signing and authenticated function calls #93906
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
Changes from all commits
016baec
4cebec2
6d578df
0598b29
cbb9bb0
99b2bf2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,10 +14,144 @@ | |
#ifndef LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H | ||
#define LLVM_CLANG_BASIC_POINTERAUTHOPTIONS_H | ||
|
||
#include "clang/Basic/LLVM.h" | ||
#include "clang/Basic/LangOptions.h" | ||
#include "llvm/ADT/STLForwardCompat.h" | ||
#include "llvm/Support/ErrorHandling.h" | ||
#include "llvm/Target/TargetOptions.h" | ||
#include <optional> | ||
|
||
namespace clang { | ||
|
||
constexpr unsigned PointerAuthKeyNone = -1; | ||
|
||
class PointerAuthSchema { | ||
public: | ||
enum class Kind : unsigned { | ||
None, | ||
ARM8_3, | ||
}; | ||
|
||
/// Hardware pointer-signing keys in ARM8.3. | ||
/// | ||
/// These values are the same used in ptrauth.h. | ||
enum class ARM8_3Key : unsigned { | ||
ASIA = 0, | ||
ASIB = 1, | ||
ASDA = 2, | ||
ASDB = 3 | ||
}; | ||
|
||
/// Forms of extra discrimination. | ||
enum class Discrimination : unsigned { | ||
/// No additional discrimination. | ||
None, | ||
|
||
/// Discriminate using a constant value. | ||
Constant, | ||
}; | ||
|
||
private: | ||
Kind TheKind : 2; | ||
unsigned IsAddressDiscriminated : 1; | ||
unsigned IsIsaPointer : 1; | ||
unsigned AuthenticatesNullValues : 1; | ||
PointerAuthenticationMode SelectedAuthenticationMode : 2; | ||
Discrimination DiscriminationKind : 2; | ||
unsigned Key : 2; | ||
unsigned ConstantDiscriminator : 16; | ||
|
||
public: | ||
PointerAuthSchema() : TheKind(Kind::None) {} | ||
|
||
PointerAuthSchema( | ||
ARM8_3Key Key, bool IsAddressDiscriminated, | ||
PointerAuthenticationMode AuthenticationMode, | ||
Discrimination OtherDiscrimination, | ||
std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt, | ||
bool IsIsaPointer = false, bool AuthenticatesNullValues = false) | ||
: TheKind(Kind::ARM8_3), IsAddressDiscriminated(IsAddressDiscriminated), | ||
IsIsaPointer(IsIsaPointer), | ||
AuthenticatesNullValues(AuthenticatesNullValues), | ||
SelectedAuthenticationMode(AuthenticationMode), | ||
DiscriminationKind(OtherDiscrimination), Key(llvm::to_underlying(Key)) { | ||
assert((getOtherDiscrimination() != Discrimination::Constant || | ||
ConstantDiscriminatorOrNone) && | ||
"constant discrimination requires a constant!"); | ||
if (ConstantDiscriminatorOrNone) | ||
ConstantDiscriminator = *ConstantDiscriminatorOrNone; | ||
Comment on lines
+81
to
+82
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @ahmedbougacha @ahatanak The static verifier is reporting that 'ConstantDiscriminator' is not initialized when taking the false branch of that if. Is that possible? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mikerice1969 The logic is a bit convoluted here. But essentially this field is only initialized when |
||
} | ||
|
||
PointerAuthSchema( | ||
ARM8_3Key Key, bool IsAddressDiscriminated, | ||
Discrimination OtherDiscrimination, | ||
std::optional<uint16_t> ConstantDiscriminatorOrNone = std::nullopt, | ||
bool IsIsaPointer = false, bool AuthenticatesNullValues = false) | ||
: PointerAuthSchema(Key, IsAddressDiscriminated, | ||
PointerAuthenticationMode::SignAndAuth, | ||
OtherDiscrimination, ConstantDiscriminatorOrNone, | ||
IsIsaPointer, AuthenticatesNullValues) {} | ||
|
||
Kind getKind() const { return TheKind; } | ||
|
||
explicit operator bool() const { return isEnabled(); } | ||
|
||
bool isEnabled() const { return getKind() != Kind::None; } | ||
|
||
bool isAddressDiscriminated() const { | ||
assert(getKind() != Kind::None); | ||
return IsAddressDiscriminated; | ||
} | ||
|
||
bool isIsaPointer() const { | ||
assert(getKind() != Kind::None); | ||
return IsIsaPointer; | ||
} | ||
|
||
bool authenticatesNullValues() const { | ||
assert(getKind() != Kind::None); | ||
return AuthenticatesNullValues; | ||
} | ||
|
||
bool hasOtherDiscrimination() const { | ||
return getOtherDiscrimination() != Discrimination::None; | ||
} | ||
|
||
Discrimination getOtherDiscrimination() const { | ||
assert(getKind() != Kind::None); | ||
return DiscriminationKind; | ||
} | ||
|
||
uint16_t getConstantDiscrimination() const { | ||
assert(getOtherDiscrimination() == Discrimination::Constant); | ||
return ConstantDiscriminator; | ||
} | ||
|
||
unsigned getKey() const { | ||
switch (getKind()) { | ||
case Kind::None: | ||
llvm_unreachable("calling getKey() on disabled schema"); | ||
case Kind::ARM8_3: | ||
return llvm::to_underlying(getARM8_3Key()); | ||
} | ||
llvm_unreachable("bad key kind"); | ||
} | ||
|
||
PointerAuthenticationMode getAuthenticationMode() const { | ||
return SelectedAuthenticationMode; | ||
} | ||
|
||
ARM8_3Key getARM8_3Key() const { | ||
assert(getKind() == Kind::ARM8_3); | ||
return ARM8_3Key(Key); | ||
} | ||
}; | ||
|
||
struct PointerAuthOptions { | ||
/// The ABI for C function pointers. | ||
PointerAuthSchema FunctionPointers; | ||
}; | ||
|
||
} // end namespace clang | ||
|
||
#endif |
Uh oh!
There was an error while loading. Please reload this page.