[clang] [llvm] [PAC][Driver] Implement `-mbranch-protection=pauthabi` option (PR #97237)
Peter Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 9 15:43:43 PDT 2024
smithp35 wrote:
Apologies for the length of the post, it could probably do with more revisions and research but I thought it better to send what I have and refine later after comments. Most of this is a summation of a discussion had in the PAuthABI call, followed by my attempts at analysing the options we discussed. My apologies if I've misrepresented or missed out anything in the call. Please feel free to correct me where I'm wrong or have missed something out. I'll be at a conference this week so I may be slow to respond.
#### Known use cases and background.
We have three known use cases for PAuthABI, with two in active development:
* A platform either ELF or MachO based deploys PAuthABI in all or, most likely, a subset of programs.
* A bare-metal system that can statically compile everything the same way for the device. This not in active development.
* Enabling PAuthABI for testing in upstream LLVM.
On each of the platforms, there is expected to be more than onesigning schema, for example kernel vs user-space. With the possible exception of return address signing, each signing schema is its own ABI. While low-level options may exist to control the signing schema, we do not expect end users to use them as they risk breaking the platform ABI.
This infers that we need an option to choose between high-level signing schemas, that map to some combination of the low-level options. This mapping will need to be per-platform as Linux may choose differently to BSD.
The signing schema will also need to be used as the multilib key so that a compatible set of libraries can be linked for the signing schema.
On ELF the (platform, signing-schema) choice can be recorded in the ELF properties.
Users of the low-level command line options cannot be easily recorded in the ELF properties. There are various platform specific choices that could be made if the low-level options are used. For example:
* Record the high-level signing schema and trust the user has written the code such that it is compatible.
* Reject the low-level option.
* Ignore the low-level option.
* Record a custom signing schema.
I think that this has to be under control of the platform. My intuition is that we trust the user, perhaps with a warning, and
record the high-level signing schema.
On a bare-metal embedded system each toolchain can make up their own signing schema, however no toolchain is likely to provide pre-compiled libraries for every possible choice so we expect there to be a sensible default signing schema.
#### Thoughts on `-mbranch-protection=pauthabi`
While pauthabi is a form of CFI like the other mbranch-protection
options there are a number of differences that cause problems:
* All existing `-mbranch-protection` options have a hint space implementation so are compatible with any architecture. PAuthABI requires an extension.
* All existing `-mbranch-protection` options are compatible, pauthabi conflicts with standard and pac-ret.
* All existing `-mbranch-protection` options are ABI neutral, pauthabi is not and any use of it on a standard linux platform would not work.
* Not got an easy way to extend with the signing schema.
### Alternatives discussed
#### A single option using -mabi:
Use the existing `-mabi` option to indicate the signing schema (or absence of
signing schema) if pauthabi is not used. The `-mabi` option for AArch64 is
currently permits `aapcs` (default hard-float) `aapcs-soft` and `darwinpcs`.
`-mabi=pauth` // default signing schema for the platform (OS in triple).
`-mabi=pauth<signing-schema>` // named signing schema, interpreted per platform.
The <signing-schema> expands to a number of low-level options. This is
determined per platform. With this information we can derive a
<Platform, signing-schema> for the ELF marking.
For example:
* `--target=aarch64-none-elf -mabi=pauth`
* `--target=aarch64-linux-gnu -mabi=pauthkernel`
There is an open question over what we should do with the theoretical combination of soft-floating point and pauth as these both use the `-mabi=<abi>` option. While each combination is its own ABI, the choice of float-abi is orthogonal to signing schema. I'm leaning towards suggesting a + or , separated list for `-mabi` with a default of aapcs (hard-float) so we don't end up doubling the number of options. So we would have `-mabi=pauth<signing-schema>,aapcs-soft` rather than
`-mabi=aapcs-soft-pauth<signing-schema>`. I don't think that would need to be implemented until there is an actual need for it.
#### Two options using -mabi and -msigning-schema:
This is functionally equivalent to the single `-mabi=pauth<signing-schema>` split into two options.
* `-mabi=pauth enables pauthabi`
* `-msigning-schema=<signing-schema>`
if `-msigning-schema` is absent then the default signing schema for the platform is used.
This has the advantage of being easier to parse, but has a couple of drawbacks:
* Each `-msigning-schema` is a different ABI so it is logical to have a single `-mabi` option with disjoint choices.
* `-msigning-schema` without `-mabi=pauth` is meaningless.
#### Use the environment part of the triple:
The ARM target uses the environment part of the triple to record the float abi, `arm-linux-gnueabi` for soft-float and `arm-linux-gnueabihf` for hard-float. With `-mfloat-abi` being normalised into the environment.
The signing schema could be added to the environment part of the triple, for example `aarch64-linux-gnupauth` or `aarch64-linux-gnupauth<signing-schema>`. The `-mabi=pauth<signing-schema>` or the alternative `-mabi=pauth`
`-msigning-schema=<signing-schema>` are normalised into the triple.
One disadvantage of doing this is that we can't use a `-` in the name of a signing schema as it would affect the triple parsing.
### Recommendation:
Right now we only have a single signing schema used for upstream LLVM testing on the Linux target. We expect the first concrete use in downstrean platforms. We don't need to add support upstream for multiple signing schemas until they are needed. We would therefore only need to implement a default signing schema for `-mabi=pauth`
We could choose to implement -msigning-schema or `-mabi=pauth<signing-schema>` at a later time.
I don't have enough experience with triples to know whether encoding the information in the triple is useful or not. I think it is important to have options outside of the triple that a possible implementation in GCC could use, but whether these are normalised into the triple or not doesn't seem to be a problem.
I think we should require the `+pauth` feature (default in armv8.3-A) for `-mabi=pauth<signing-schema>` to be accepted.
I think the combinations of `-mbranch-protection` that are not compatible with pauth should be errors, or ignored with a warning.
#### Open question:
If we are being as careful to avoid prematurly fixing a signing schema for the linux target we could use a <signing-schema> of test and no `-mabi=pauth` default. For example `-mabi=pauthtest`.
I think we could use `-mabi=pauth` if we mark the feature as experimental or alpha, this default signing schema may change until a future release when experimental/alpha is removed.
https://github.com/llvm/llvm-project/pull/97237
More information about the cfe-commits
mailing list