Eu escrevi algum código assembly arm64 seguindo a convenção de chamada AAPCS64.
Agora eu gostaria de integrar esse código em um projeto C/C++ construído com PAC e BTI habilitados. Eu notei o problema pela primeira vez quando o linker me disse que estava faltando a GNU_PROPERTY_AARCH64_FEATURE_1_BTI
propriedade:
ld: error: md5block_arm64.o: -z bti-report: file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property
Embora seja trivial apenas definir essa propriedade, estou ciente de que provavelmente preciso alterar partes do meu código para torná-las compatíveis com PAC/BTI. Quais são as alterações necessárias para isso? Estou interessado em uma resposta geral que possa ser usada como um guia para adaptar qualquer código, daí a falta de código a ser adaptado nesta questão.
O BTI é bem simples e não depende de ABI de software (além do BTI estar habilitado em primeiro lugar). Na versão atual (
K.a
) do manual , o comportamento é documentado na seção "D8.4.5.3 PSTATE.BTYPE". Em essência:As instruções de ramificação de borda para frente se dividem em duas categorias:
br
,braa
,braaz
,brab
ebrabz
blr
,blraa
,blraaz
,blrab
,blrabz
Usarei
br
eblr
como uma abreviação para essas categorias.Há três novas instruções:
bti c
,bti j
ebti jc
.blr
os ramos devem pousar em uma instruçãobti c
oubti jc
.br
ramificações que usam um registrador diferente dex16
ex17
para o endereço de destino devem pousar em uma instruçãobti j
oubti jc
.br
ramificações que usamx16
oux17
para o endereço de destino podem pousar em qualquerbti
instrução.paciasp
epacibsp
agir comobti c
oubti jc
com base em alguns bitsSCTLR_ELn
para o regime de tradução relevante - apenas assumabti c
que está seguro.Então, para ser compatível com o código BTI, você precisa:
paciasp
,pacibsp
oubti c
.br
para chamar funções reais) usemx16
orx17
.bti j
a todos os alvos possíveis do estilo switchbr
s.PAC é uma fera completamente diferente. Isso depende do ABI exato de tudo em sua pilha -
gnu
vsmusl
, C vs C++,__attribute__
especificadores em arquivos de cabeçalho, ...A especificação AAPCS64 não define uma ABI de autenticação de ponteiro. PAUTHELF64 tem algumas definições sobre como codificar coisas no formato de arquivo ELF, mas crucialmente não define como essas coisas devem ser escolhidas .
Basicamente, qualquer síntese de ponteiro de código, qualquer ramificação indireta e potencialmente até mesmo cargas de memória podem precisar de instruções PAC, totalmente definidas pela implementação.
Agora, para sua sorte,
-mbranch-protection=standard
parece usar PAC quase nada. Da documentação do flag :Basicamente, isso usa apenas PAC para proteger frames de pilha, o que não afeta o ABI entre diferentes unidades de compilação. Se você quiser manter as propriedades de segurança da opção, todas as suas funções que vazarem
x30
precisarão de umpaciasp
antes do vazamento e umautiasp
entre o reload e oret
. (Se seu código não precisa ser capaz de rodar em hardware sem suporte a PAC, você pode combinar oautiasp
+ret
em um únicoretaa
).