diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT index f81b89f82..ac8db62e0 100644 --- a/libc/SYSCALLS.TXT +++ b/libc/SYSCALLS.TXT @@ -77,7 +77,6 @@ int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*) arm,mips,x8 int setgroups:setgroups32(int, const gid_t*) arm,x86 int setgroups:setgroups(int, const gid_t*) arm64,mips,mips64,x86_64 int setpgid(pid_t, pid_t) all -pid_t vfork(void) arm int setregid:setregid32(gid_t, gid_t) arm,x86 int setregid:setregid(gid_t, gid_t) arm64,mips,mips64,x86_64 int chroot(const char*) all diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk index d72a160d0..b5283f6d2 100644 --- a/libc/arch-arm/arm.mk +++ b/libc/arch-arm/arm.mk @@ -42,6 +42,7 @@ libc_bionic_src_files_arm += \ arch-arm/bionic/__restore.S \ arch-arm/bionic/setjmp.S \ arch-arm/bionic/syscall.S \ + arch-arm/bionic/vfork.S \ libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c diff --git a/libc/arch-arm/bionic/vfork.S b/libc/arch-arm/bionic/vfork.S new file mode 100644 index 000000000..1b7cbad75 --- /dev/null +++ b/libc/arch-arm/bionic/vfork.S @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +ENTRY(vfork) + // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0 + mrc p15, 0, r3, c13, c0, 3 + ldr r3, [r3, #4] + mov r0, #0 + str r0, [r3, #12] + + mov ip, r7 + ldr r7, =__NR_vfork + swi #0 + mov r7, ip + cmn r0, #(MAX_ERRNO + 1) + bxls lr + neg r0, r0 + b __set_errno_internal +END(vfork) diff --git a/libc/arch-arm/syscalls/vfork.S b/libc/arch-arm/syscalls/vfork.S deleted file mode 100644 index 5f4cb3dbd..000000000 --- a/libc/arch-arm/syscalls/vfork.S +++ /dev/null @@ -1,14 +0,0 @@ -/* Generated by gensyscalls.py. Do not edit. */ - -#include - -ENTRY(vfork) - mov ip, r7 - ldr r7, =__NR_vfork - swi #0 - mov r7, ip - cmn r0, #(MAX_ERRNO + 1) - bxls lr - neg r0, r0 - b __set_errno_internal -END(vfork) diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S index b6a672d43..92fa333d5 100644 --- a/libc/arch-arm64/bionic/vfork.S +++ b/libc/arch-arm64/bionic/vfork.S @@ -31,6 +31,11 @@ #include ENTRY(vfork) + // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0 + mrs x0, tpidr_el0 + ldr x0, [x0, #8] + str wzr, [x0, #20] + mov x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD) mov x1, xzr mov x2, xzr diff --git a/libc/arch-x86/bionic/vfork.S b/libc/arch-x86/bionic/vfork.S index ca7af0f7a..5c71b8dbc 100644 --- a/libc/arch-x86/bionic/vfork.S +++ b/libc/arch-x86/bionic/vfork.S @@ -34,6 +34,12 @@ ENTRY(vfork) popl %ecx // Grab the return address. .cfi_adjust_cfa_offset 4 .cfi_rel_offset ecx, 0 + + // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0 + movl %gs:0, %eax + movl 4(%eax), %eax + movl $0, 12(%eax) + movl $__NR_vfork, %eax int $0x80 cmpl $-MAX_ERRNO, %eax diff --git a/libc/arch-x86_64/bionic/vfork.S b/libc/arch-x86_64/bionic/vfork.S index 129f1dbd2..3b32c6652 100644 --- a/libc/arch-x86_64/bionic/vfork.S +++ b/libc/arch-x86_64/bionic/vfork.S @@ -32,6 +32,12 @@ ENTRY(vfork) popq %rdi // Grab the return address. + + // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0 + mov %fs:0, %rax + mov 8(%rax), %rax + movl $0, 20(%rax) + movl $__NR_vfork, %eax syscall pushq %rdi // Restore the return address. diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp index b29c6f314..8e1f41245 100644 --- a/tests/unistd_test.cpp +++ b/tests/unistd_test.cpp @@ -402,11 +402,11 @@ static void AssertGetPidCorrect() { } } -TEST(unistd, getpid_caching_and_fork) { +static void TestGetPidCachingWithFork(int (*fork_fn)()) { pid_t parent_pid = getpid(); ASSERT_EQ(syscall(__NR_getpid), parent_pid); - pid_t fork_result = fork(); + pid_t fork_result = fork_fn(); ASSERT_NE(fork_result, -1); if (fork_result == 0) { // We're the child. @@ -424,6 +424,14 @@ TEST(unistd, getpid_caching_and_fork) { } } +TEST(unistd, getpid_caching_and_fork) { + TestGetPidCachingWithFork(fork); +} + +TEST(unistd, getpid_caching_and_vfork) { + TestGetPidCachingWithFork(vfork); +} + static int GetPidCachingCloneStartRoutine(void*) { AssertGetPidCorrect(); return 123;