Make fork equivalent to vfork when HWASan or MTE stack tagging is enabled.
Bug: 274056091
Change-Id: Iac029ca6b0e26f57f20c0a54822b75e3cae67344
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index 9eb82d8..9b19232 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -28,6 +28,7 @@
#include <platform/bionic/tls_defines.h>
#include <private/bionic_asm.h>
+#include <private/bionic_asm_offsets.h>
#include <asm/signal.h>
#include <linux/sched.h>
@@ -42,10 +43,29 @@
ldr w10, [x9, #20]
str w0, [x9, #20]
- // Clear vfork_child_stack_bottom_.
- str xzr, [x9, #776]
+ mov x0, #SIGCHLD
- mov x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
+ // If either HWASan or stack MTE is enabled, set up the clone() flags to
+ // make vfork() act like fork(). We don't call the atfork handlers, so we
+ // may deadlock if the child allocates, but we have seen badly written
+ // atfork handlers themselves cause deadlocks [1]. ndk_translation already
+ // implements vfork() as fork() without calling handlers, so we have some
+ // evidence that it isn't necessary to call them.
+ //
+ // POSIX.1 defines vfork() to have the same effect as fork() except that
+ // most behavior, including heap allocation, becomes undefined in the child,
+ // so we aren't violating POSIX by doing this.
+ //
+ // [1] https://cs.android.com/android/platform/superproject/+/master:system/extras/simpleperf/app_api/cpp/simpleperf.cpp;drc=788fa4183441f4977ddbd5a055e42a7fe7691d21;l=308
+#if !__has_feature(hwaddress_sanitizer)
+ // if (!__libc_globals->memtag_stack) x0 |= CLONE_VM | CLONE_VFORK;
+ adrp x1, __libc_globals + OFFSETOF_libc_globals_memtag_stack
+ ldrb w1, [x1, :lo12:__libc_globals + OFFSETOF_libc_globals_memtag_stack]
+ cbnz w1, 1f
+ orr x0, x0, #CLONE_VM
+ orr x0, x0, #CLONE_VFORK
+1:
+#endif
mov x1, xzr
mov x2, xzr
mov x3, xzr
@@ -62,25 +82,6 @@
cneg x0, x0, hi
b.hi __set_errno_internal
- // Clean up stack shadow in the parent process.
- // https://github.com/google/sanitizers/issues/925
- paciasp
- .cfi_negate_ra_state
- stp x0, x30, [sp, #-16]!
- .cfi_adjust_cfa_offset 16
- .cfi_rel_offset x0, 0
- .cfi_rel_offset x30, 8
-
- add x0, sp, #16
- bl memtag_handle_vfork
-
- ldp x0, x30, [sp], #16
- .cfi_adjust_cfa_offset -16
- .cfi_restore x0
- .cfi_restore x30
- autiasp
- .cfi_negate_ra_state
-
.L_exit:
ret
END(vfork)