<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/134247>134247</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
lldb cannot call a function via a pointer that includes non-address bits (that aren't part of Top Byte Ignore)
</td>
</tr>
<tr>
<th>Labels</th>
<td>
lldb
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
DavidSpickett
</td>
</tr>
</table>
<pre>
While looking into debug support for https://discourse.llvm.org/t/rfc-structure-protection-a-family-of-uaf-mitigation-techniques/85555/7 I found that I cannot call a function via a pointer if it has non-address bits that the processor still pays attention to.
The main use case of this is AArch64 pointer authentication. The existing test case `lldb/test/API/linux/aarch64/non_address_bit_code_break/main.c` can be used to show the problem:
```
#include <stdint.h>
void foo(void) {}
typedef void (*FooPtr)(void);
int main() {
FooPtr fnptr = foo;
// Set top byte.
fnptr = (FooPtr)((uintptr_t)fnptr | (uintptr_t)0xff << 56);
// Then apply a PAuth signature to it.
__asm__ __volatile__("pacdza %0" : "=r"(fnptr) : "r"(fnptr));
// fnptr is now:
// <8 bit top byte tag><pointer signature><virtual address>
foo(); // Set break point at this line.
return 0;
}
```
Once we hit the breakpoint, `fnptr` will have a top byte tag and a pointer signature. The top byte tag isn't a problem because the hardware will ignore it (I'm on AArch64 with Top Byte Ignore enabled), but the signature will not be ignored.
This leads to a fault when you try to call the function:
```
(lldb) p fnptr()
error: Expression execution was interrupted: signal SIGSEGV: address not mapped to object (fault address=0x1faaaaaaaa0714).
The process has been returned to the state before expression evaluation.
```
That address is the value of `fnptr`, minus the top byte, presumably because the hardware or kernel removed that for us.
LLDB does know that there are non address bits, and can remove them for other commands:
```
(lldb) p fnptr
(FooPtr) 0xff1faaaaaaaa0714 (actual=0x0000aaaaaaaa0714 test.o`foo at test.c:3:17)
(lldb) memory read fnptr
0xaaaaaaaa0714: 1f 20 03 d5 c0 03 5f d6 fd 7b be a9 fd 03 00 91 . ...._..{......
0xaaaaaaaa0724: 00 00 00 90 00 50 1c 91 e0 0f 00 f9 e0 0f 40 f9 .....P........@.
(lldb) process status -v
<...>
Addressable code address mask: 0xff7f000000000000
Addressable data address mask: 0xff7f000000000000
Number of bits used in addressing (code): 49
```
So at first I thought we just needed to add an `abi->FixCodeAddress` call somewhere, but nothing helped.
Then I realised, the problem is that we insert this `fnptr` into the JIT'd code as a symbol, it's not something we take the address of normally and we may not even care to check if it will be used for a function call.
`log enable lldb expr` shows:
```
lldb == [UserExpression::Evaluate] Parsing expression fnptr() ==
lldb ClangUserExpression::ScanContext()
lldb Parsing the following code:
#line 1 "<lldb wrapper prefix>"
<...>
void
$__lldb_expr(void *$__lldb_arg)
{
using $__lldb_local_vars::fnptr;
;
#line 1 "<user expression 0>"
fnptr()
;
#line 1 "<lldb wrapper suffix>"
}
<...>
lldb Examining _ZN18$__lldb_local_varsL5fnptrE, DeclForGlobalValue returns 0x0000AB432C2BB4F8
lldb MaybeHandleVariable (@"_ZN18$__lldb_local_varsL5fnptrE" = external constant ptr, align 8)
lldb Type of "fnptr" is [clang "FooPtr &", llvm "ptr"] [size 8, align 8]
lldb Adding value for (NamedDecl*)0x0000AB432C2BB4F8 [fnptr - fnptr] to the structure
lldb Placed at 0x0
lldb Element arrangement:
lldb Arg: "ptr %"$__lldb_arg""
lldb "fnptr" ("fnptr") placed at 0
lldb Replacing [@"_ZN18$__lldb_local_varsL5fnptrE" = external constant ptr, align 8]
```
So we are placing the raw value of `fnptr` into the JIT context and trying to call that, which causes the fault.
```
(lldb) setting set target.process.unwind-on-error-in-expressions false
(lldb) p fnptr()
error: Expression execution was interrupted: signal SIGSEGV: address not mapped to object (fault address=0x50aaaaaaaa0714).
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
Process 226746 stopped
* thread #1, name = 'test.o', stop reason = signal SIGSEGV: address not mapped to object (fault address=0x50aaaaaaaa0714)
frame #0: 0x0000aaaaaaaa0714 test.o`foo at test.c:3:17
1 #include <stdint.h>
2
-> 3 void foo(void) {}
<...>
(lldb) bt
* thread #1, name = 'test.o', stop reason = signal SIGSEGV: address not mapped to object (fault address=0x50aaaaaaaa0714)
* frame #0: 0x0000aaaaaaaa0714 test.o`foo at test.c:3:17
frame #1: 0x0000fffff7ff508c $__lldb_expr`$__lldb_expr($__lldb_arg=0x0000fffff7ff3000) at <user expression 0>:1
frame #2: 0x0000aaaaaaaa0600 test.o`abort + 16
(lldb) up
frame #1: 0x0000fffff7ff508c $__lldb_expr`$__lldb_expr($__lldb_arg=0x0000fffff7ff3000) at <user expression 0>:1
(lldb) dis
$__lldb_expr`$__lldb_expr:
<...>
0xfffff7ff5088 <+88>: blr x8
-> 0xfffff7ff508c <+92>: ldr x19, [sp, #0x10]
```
The same issue applies if you're trying to emulate the effect of Pointer Authentication and use the `target.process.virtual-addressable-bits` setting to ignore bits.
In a program like the one above we have no way to know if a pointer is signed, but we might with a program compiled for an ABI that always does that.
We could check whether the type is a function pointer when we set up the JIT context, and fix it then. Though you could break that, by casting something into a function pointer, but at that point you're asking for trouble anyway.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzMWVuP67YR_jXcl4ENmbJ8edgH27tOt0jTRc9pAvTFoCTKYpYiVZLyJb--mKHktb2b9ARI0QgHZ22RnBvn8s1YeK_2RspHlq1Z9vQgulBb9_gkDqr80qriTYbwkNvy_PhTrbQEbe2bMntQJlgoZd7twXdta12AyjqoQ2g9S1eMbxnflsoXtnNejrU-NGPr9oxvA-NbVxUjH1xXhM7JUetskEVQ1ozEqBKN0ueRrUadqEaNCmovaCnIojbq3530jG8XWZZljG_n8AKV7UwJoRYBXqAQxtgAhdAaBFSdIbpwUAIEtFaZIB2oClSAWngwyLMsnfQechV8JBNqCa2zhfTeOvBBaQ2tOHsQIUhDBIMds2TFktXXWkIjlIHOSyiEl2ArCLXyoDysVq6oZ9MLY7QuEihIpTHgYXlSPqBJg_QhUmCzROsyR2NJj_Zavb4wvtXKdCfGt0IQVca3xppdL_4uV2FX2FLucifFG-NblGpcsFmCRoFcooQlBAu-tsdBx1zLBu8rWbFZ0v9LVoynyhS6KyWwdONDqUwY1yx9jjofrCqhspbxBX5kfAlsvmbzJ5aswrmVpayA9jC-YHy1tfY1OMaX7_tZuo6klAlkPtoZySQrgHgEKtMGByx9Im5pXIu-BV9kgGBbyM9BjmnhfTfji2umjC86ZUIb3C4wvuz3zTdwt5CcqgoVZukGstlFzAvLr7U0INpWn0HA66oLNWD0CPRiNKwKUZDdTvhmt4Pd7mC1CErL3Y7E4K0oyl8EMJ4ljHNg6QoY5yx9cviHL0g0MkRcuXv9UaSoi0JPPsZ7vCyxdLNAp75YCYLY4x2mm8EfL9LH1wflQic09C51uW_oLzuyv74A8rXo3kCBozxoZeR4OOhk6JyBpL9wcpFrT_u7KSQcJdQqhh0RJHqMbzAQouqzBI4YhbU4SBA3GoEw5VVsX1SK0XWzU3nD-Dzg7uj5kMtCYOAi61q48iicjJzU3lgnMU8wvnhhfN6ANZeAPqpQw1fbwhppv8S90ohcS3JvvoG8ixq9ewjRxeyUy558eUkiaDcpSo9uJKASnQ5wRHc72w6CO-N7SmpIckhrnwXuImaOJbTQew1dG95F_7BkJZ2zDl3s-dTiTWNGkydZdJTbjsIDGdN1bZAl7iMlNHx5-e7L83c_4psha6I-jWjbmFps_rMsyGRRhYsnPSWnSSX6J5lPpowvx3367FMtJeRcStM7TaRIJgwiSMhlRVa-EvkgdBdT6Z0dvmIaH0RUnqjgZsrOV16FF9Uo08Udg7PgW2TSNSLX58-dxDp4k85IDU429iD7CoRFsPP9tX7__dMaSis9vBlKubG2OAlIwVgD17UHuaIvY7aONHFzQyQtHoPCNo0wpf-me6eXlywImNtubwBvSRQY8HQ9SZIkN8tYe8YWjWUtBTd-L1i6Slm6msyjV10xbmRj3RmcFOVFhOR0c-fpCiYV8ASSFMoMCvqQVVDOoCphnmNkiCV-TlJIElhOAMYwHo_Hu_GYzddjeu7ocqKbJP2_Jf2fJTAp8LxMIKnwTbXsP0_pM1Edv477h02T8Z0de69E5-s8jA64nG5wL-XFVbw6DHnAunu5y0b4N5LoVFXzKrl67k6VIohvO_VD1-TSoe8SSKFCri7eg-CB8QUKQRl6BdPlnX98oRuslPMIkkJtu30dMO_-3PkARsoyRpsoSxAGI0TkasTS5606bWwpe7EjmNAavG3kET15yHTGhhrlqKVur9KaNPCCHqGVx8S4uYYdMS4FiaGMl66vH9dJn2Amnvnry1fG52VvaQ8C_LnJrUaaKjA-j5kI5YqCHDHlv8WgHWxsKzDWNUJjATcl7mnEmQ7KgzRQiFjHi1oWbz1KpKQ9gCcMxStUiaboVUXIZvd9CQD0IUpUqAPCrU9ClvZcPyx9IuySrf_ppXvPzHg0XT3HXCdZ9gSvwtGlX6XCq1zfExpYbLQw-88ofimE2VgT5ClcisQHoQZWVHas1vaI38jVokY8xXoPk4hjNkTg6LAgOMyhlTphuHB-Fz0RHuL56W6Hh3ZkrggQgfGrBYFtwxKu6xebr6EvaV3v_sNubQuhdwfhfNQyGiaij3QNv_J8oknnpbu2cHLR47au9rR_yw6-q27sMH-CO3N8sPvzSTTKoGq7f_0wWXym3_cZCfKMIfAkC7217jttc6F_pEIXi6iHmNlX62nKN3y9nm4XA7-_iXMu_yJMqeWPwinyXFRritj0G9hywtryFKRDcFBY44MwAcg6GxBa7Q38mmN9PbexGHPe25NjQmDZukCHxfd9E8D4jFDwBrCLxIW4HSOBZWuvfpHI5Z1h9vQZw1VZojkjCsBAZnzxg2hkibYjh1t-NBUyiBB71IdY9vSOSvoGduD2qkUhS0y0yenTCH_WspGIlJ0TZk-fYxTRzpXb96if2hOekdY3UcCjA30gDDdmjK3G8JVq2btknx8H-IfETRRL2fqPdoHsHvZ_sZh8Md0OXNGiThw_RWk3ZQCZYM6iDB7cmQ5fwLGgvuFYq6IGQm0R2REafU_Vn-EmLwO14R77SuH2Mox7CDDuzFGZcmTNiIDzSJnRe2LwUAnt5X8B3_8v0J0l3wq6taz6Hk72DR0VeKqBd7LxDU07GOehJrjXd3mjE3pEsMP33wXfX3uBOJ_NpzPwwaJ-ZNYV9HwYTyfI3YhG9o3-vIepfI4LeArxhreG1v8nJuwrT-VICp4mEbf9bgBNZCZUfZa_NXEBAN7vSlYIyiCNX39rDnNdXa4cMw9_WouiVH-MTd_JTN7JVPjMqypLFgXcwQ5sBO9wyG3mHRqkgUiKuJwvUYJfgwrpanIvDf9EqVmSvCslcuvQZmuYzOD24roWkcefRq8ryUrlPwK5D5wjWrxySrQMNjsX6Rc0euPrxSKyAci1w12nxeD3tweK_sCSDwd0GQ9MaAKD4KClDzxNTpPkYxnqc6FHqyrvO0nTPSU9gv-z7RifY0dwKTKy6TTmMsxqsqrQwW0Fr_3oaXUz3aX6NIwN2Cy5qyn9rG2YPiP4GtEUADuGvhQFO4yhcKUvXy8mzq_2TjSgVd_iWCNB5PYQh2niIMFYOAqaG9HwQVXXA3BPcRxTObZv2AkpaglVqK_oF7ZplR46HwOr9Uvs2YQ-irOPww180Qv3E_bCnS77FupYSxpc0HAFAZ_y1_3TIA4Nuo6SSm_X3hf6YS5SqRPEKSFNzrGFpelYZBgnkQMAyM9QiDhWf28JCUV8ZD_YgGqfCH3xu9y-8PSDBxogONshSBbmfBTn8UP5mJbLdCke5ONkPk1ni1mWTh_qRyGKUmbzQswm8zyTeSGzdFJUspTzSZFW2YN65AnPkmmSTlLOJ-k4qcp8uSyW83kyK8VixqaJbITSlx9OHsg9HyfplE_nD1rkUnv6zYbzGIcIhx_cI-4f5d3es2milQ_-nUJQQctHAn_f9CsJGaMvSp_8UsL4InqCk3Gq2gpH4XA3FmV8-dA5_Xj709BehbrLx4VtGN-iiP2fUessFg7Gt6SxZ3zbK3145P8JAAD__6-IXmA">