Skip to content

Commit 8fd5d03

Browse files
committed
aarch64: mask off SME and unknown/future hwcap bits
as stated in the comment added, the ABI for SME requires libc to be aware of and support the extension to the register file. this is necessary to handle lazy saving correctly across setjmp/longjmp, and on older kernels, in order not to introduce memory corruption bugs that may be exploitable vulnerabilities when creating new threads. previously, we did not expose __getauxval, the interface libgcc uses to determine runtime availability of SME, so it was not usable when following the intended ABI. since commit ab4635f has now exposed this interface, a mitigation is needed to ensure SME is not used unless/until we have proper support for it. while SME is the current hwcap feature that needs this treatment, as-yet-undefined hwcap bits are also masked in case other new cpu features have similar ABI issues. this could be re-evaluated at some point in the future. for now, the masking is only on aarch64. arguably it should be considered for all archs, but whether it's needed is really a matter of how ABI policy & stability are handled by the maintainers of the arch psABI, and aarch64 is the one that's demonstrated a necessity. if it turns out something like this is needed for more/all archs, making a generalized framework for it would make sense. for now, it's stuffed into __set_thread_area the same way atomics detection is stuffed there for 32-bit arm and sh, as it's a convenient point for "arch-specific early setup code" without invasive changes.
1 parent 709fee5 commit 8fd5d03

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
1+
#include <elf.h>
2+
#include "libc.h"
3+
4+
#define BITRANGE(a,b) (2*(1UL<<(b))-(1UL<<(a)))
5+
16
int __set_thread_area(void *p)
27
{
38
__asm__ __volatile__ ("msr tpidr_el0,%0" : : "r"(p) : "memory");
9+
10+
/* Mask off hwcap bits for SME and unknown future features. This is
11+
* necessary because SME is not safe to use without libc support for
12+
* it, and we do not (yet) have such support. */
13+
for (size_t *v = libc.auxv; *v; v+=2) {
14+
if (v[0]==AT_HWCAP) {
15+
v[1] &= ~BITRANGE(42,63); /* 42-47 are SME */
16+
} else if (v[0]==AT_HWCAP2) {
17+
v[1] &= ~(BITRANGE(23,30)
18+
| BITRANGE(37,42)
19+
| BITRANGE(57,62));
20+
} else if (v[0]==AT_HWCAP3 || v[0]==AT_HWCAP4) {
21+
v[0] = AT_IGNORE;
22+
v[1] = 0;
23+
}
24+
}
25+
426
return 0;
527
}

0 commit comments

Comments
 (0)