Bug 1888842

Summary: MemoryDenyWriteExecute causes BTI enabled services to abort.
Product: [Fedora] Fedora Reporter: Jeremy Linton <jeremy.linton>
Component: glibcAssignee: Carlos O'Donell <codonell>
Status: CLOSED UPSTREAM QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 33CC: 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   
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:
Bug Depends On:    
Bug Blocks: 245418    

Description Jeremy Linton 2020-10-15 22:14:47 UTC
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),

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.

Comment 1 Zbigniew Jędrzejewski-Szmek 2020-10-16 13:20:45 UTC
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?

Comment 2 Jeremy Linton 2020-10-16 16:05:45 UTC

Comment 4 Jeremy Linton 2020-10-29 18:55:32 UTC
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.

Comment 5 Jeremy Linton 2020-10-29 18:56:07 UTC
Whops forgot the link: https://src.fedoraproject.org/rpms/glibc/pull-request/20

Comment 6 Jeremy Linton 2020-11-03 15:24:12 UTC
glibc posting here https://www.spinics.net/lists/arm-kernel/msg851408.html

Comment 7 Jeremy Linton 2020-11-03 15:52:02 UTC
I'm going to change the component too since this is mostly going to be a glibc/kernel fix.


Comment 8 Carlos O'Donell 2020-11-10 14:32:21 UTC
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.


Having this fixed upstream will fix all downstream distributions.

If you need anything further we should discuss this upstream.

Comment 9 Carlos O'Donell 2020-11-10 14:33:17 UTC
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.