summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2023-05-18 04:26:07 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2023-05-18 04:26:07 +0000
commita850f103421bdfbbe4c4aed448aa08bed1da6a6d (patch)
tree5554eaaf4a52e85921554c87119362ae51ba1d29 /lib
parentb7f28ecbff4f9e8b75fbeb94a12db177f38c83a9 (diff)
Make two corrections to the vfork(2) stub:
* with IBT, it can't return via an indirect jump as that would require the *caller* to have an endbr64 * to support a potential vmspace-sharing implementation, keep the retguard value in an arg register across the underlying syscall ok kettenis@ deraadt@
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/arch/amd64/sys/Ovfork.S23
1 files changed, 15 insertions, 8 deletions
diff --git a/lib/libc/arch/amd64/sys/Ovfork.S b/lib/libc/arch/amd64/sys/Ovfork.S
index 3d129eeb222..5ed6cbb24a2 100644
--- a/lib/libc/arch/amd64/sys/Ovfork.S
+++ b/lib/libc/arch/amd64/sys/Ovfork.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: Ovfork.S,v 1.9 2023/01/11 01:55:17 mortimer Exp $ */
+/* $OpenBSD: Ovfork.S,v 1.10 2023/05/18 04:26:06 guenther Exp $ */
/* $NetBSD: Ovfork.S,v 1.2 2002/06/03 18:30:33 fvdl Exp $ */
/*-
@@ -39,17 +39,24 @@
#include "SYS.h"
+/*
+ * This is written to support a potential vfork(2) that would share
+ * the parent's vmspace to the child. For that, the parent must
+ * not rely on anything on the stack at the time of the syscall,
+ * as the child will overwrite it. So, keep both the return address
+ * and retguard value in registers (r9 and r8) across the call.
+ * This used to do an indirect jump on success, but that doesn't
+ * work if indirect-branch-tracking is enabled as the _caller_ of
+ * this vfork() stub won't know to place an endbr64 instruction
+ * after the call. So, just push it back on the stack and return.
+ */
SYSENTRY_HIDDEN(vfork)
+ RETGUARD_SETUP(_thread_sys_vfork, r8);
popq %r9 /* my rta into r9 */
- RETGUARD_SETUP(_thread_sys_vfork, r11);
- RETGUARD_PUSH(r11);
SYSTRAP(vfork)
- RETGUARD_POP(r11)
- jc 1f
- jmp *%r9
-1:
pushq %r9
+ jnc 1f
SET_ERRNO
- RETGUARD_CHECK(_thread_sys_vfork, r11);
+1: RETGUARD_CHECK(_thread_sys_vfork, r8);
ret
SYSCALL_END_HIDDEN(vfork)