Description of problem: F33/aarch64 has BTI enabled for arm v8.5+ machines. glibc enables BTI validation on executable segments by calling mprotect with PROT_EXEC|PROC_BTI on executable marked as supporting BTI. Of course this is trapped by the secomp filter in systemd which is enabled on services with MemoryDenyWriteExecute. So 50/50, this is a glibc+systemd interaction. Version-Release number of selected component (if applicable): f33 How reproducible: 100 when running on an emulator that support BTI. The code in question in systemd is seccomp-util.c r = add_seccomp_syscall_filter(seccomp, arch, SCMP_SYS(mprotect), 1,SCMP_A2(SCMP_CMP_MASKED_EQ, PROT_EXEC, PROT_EXEC)); and in glibc i'm carrying a patch like: diff --git a/sysdeps/aarch64/dl-bti.c b/sysdeps/aarch64/dl-bti.c index 196e462520..d580ac581c 100644 --- a/sysdeps/aarch64/dl-bti.c +++ b/sysdeps/aarch64/dl-bti.c @@ -40,12 +40,8 @@ enable_bti (struct link_map *map, const char *program) if (__mprotect (start, len, prot) < 0) { - if (program) - _dl_fatal_printf ("%s: mprotect failed to turn on BTI\n", - map->l_name); - else - _dl_signal_error (errno, map->l_name, "dlopen", - N_("mprotect failed to turn on BTI")); + _dl_printf ("%s: mprotect failed to turn on BTI %d\n", + map->l_name, errno); } } return 0; That patch keeps BTI enable failures from killing the application. So its a bit of a question of whether BTI or secomp provide more security here. But this patch leaves both enabled except when secomp filters mprotect, in which case BTI is being disabled.
Yeah, that's unfortunate. I don't see any easy way out though: - if we allow PROT_EXEC|PROC_BTI to pass through, the protection provided by MemoryDenyWriteExecute is gone. - we could ignore MemoryDenyWriteExecute on aarch64 or maybe only on hardware that supports BTI, but that still drops that protection on those systems - we could try to figure out if the mapping is already executable and allow PROT_EXEC|PROC_BTI in those cases. That would not be at all trivial, not easily done with seccomp. Ideally we would have a way to enable both. Are the start+len somehow predictable? Or maybe we could allow one and just one call with PROT_EXEC|PROT_BTI? Could you please open an issue upstream under https://github.com/systemd/systemd/issues?
https://github.com/systemd/systemd/issues/17368
Cross mailing list discussion here: https://www.spinics.net/lists/arm-kernel/msg847728.html https://www.spinics.net/lists/arm-kernel/msg847799.html
I've opened a pull request, to carry the above patch until the glibc/kernel patches land. This will resolve boot failures in BTI environments.
Whops forgot the link: https://src.fedoraproject.org/rpms/glibc/pull-request/20
glibc posting here https://www.spinics.net/lists/arm-kernel/msg851408.html
I'm going to change the component too since this is mostly going to be a glibc/kernel fix. https://sourceware.org/bugzilla/show_bug.cgi?id=26831
This bug is going to be fixed in upstream glibc and we'll inherit the fix into Fedora Rawhide and any subsequent stable branch backports. https://sourceware.org/pipermail/libc-alpha/2020-November/119305.html Having this fixed upstream will fix all downstream distributions. If you need anything further we should discuss this upstream.
When this gets backported to release/2.32/master in upstream glibc we can then sync this to Fedora 33 for a fix in the distribution. You can file a bug for that if you want once the commits are there.