Bug 1888842
| Summary: | MemoryDenyWriteExecute causes BTI enabled services to abort. | ||
|---|---|---|---|
| Product: | [Fedora] Fedora | Reporter: | Jeremy Linton <jeremy.linton> |
| Component: | glibc | Assignee: | Carlos O'Donell <codonell> |
| Status: | CLOSED UPSTREAM | QA Contact: | Fedora Extras Quality Assurance <extras-qa> |
| Severity: | unspecified | Docs Contact: | |
| Priority: | unspecified | ||
| Version: | 33 | CC: | aoliva, ashankar, codonell, dj, fedoraproject, filbranden, flepied, fweimer, law, lnykryn, mfabian, msekleta, pbrobinson, pfrankli, rth, sipoyare, ssahani, s, systemd-maint, yuwatana, zbyszek, z |
| Target Milestone: | --- | ||
| Target Release: | --- | ||
| Hardware: | aarch64 | ||
| OS: | Unspecified | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | If docs needed, set a value | |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | 2020-11-10 14:32:21 UTC | Type: | Bug |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
| Bug Depends On: | |||
| Bug Blocks: | 245418 | ||
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? 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. |
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.