Commit 604b96de authored by Ramon Nou's avatar Ramon Nou
Browse files

control vfork on libc

parent c29b3098
Loading
Loading
Loading
Loading
+48 −26
Original line number Diff line number Diff line
@@ -303,37 +303,59 @@ DLSYM_WRAPPER(int, closedir, (DIR * dirp), (dirp), "closedir")
DLSYM_WRAPPER(void, seekdir, (DIR * dirp, long loc), (dirp, loc), "seekdir")
DLSYM_WRAPPER(long, telldir, (DIR * dirp), (dirp), "telldir")

static int (*real_fork)(void) = nullptr;
int
dlsym_fork(void) {
    if(!real_fork) {
        real_fork =
                reinterpret_cast<int (*)(void)>(dlsym(((void*) -1l), "fork"));
        if(!real_fork) {
            fprintf(stderr, "dlsym failed for %s: %s\n", "fork", dlerror());
            (*__errno_location()) = 38;
            return (int) -1;
        }
    }
    log_arguments("fork");
    return real_fork();
}
static int (*real_vfork)(void) = nullptr;
int
dlsym_vfork(void) {
    if(!real_vfork) {

static pid_t (*real_fork)(void) = NULL;
static pid_t (*real_vfork)(void) = NULL;
static pid_t (*real_clone)(int (*fn)(void*), void*, int, void*, ...) = NULL;


/*pid_t fork(void) {
    if (!real_fork) reinterpret_cast<int (*)(void)>(dlsym(((void*) -1l),
"fork"));

    destroy_libc();
    pid_t pid = real_fork();
    (pid == 0) ? init_libc() : init_libc();
    return pid;
}*/

pid_t
vfork(void) {
    if(!real_vfork)
        real_vfork =
                reinterpret_cast<int (*)(void)>(dlsym(((void*) -1l), "vfork"));
        if(!real_vfork) {
            fprintf(stderr, "dlsym failed for %s: %s\n", "vfork", dlerror());
            (*__errno_location()) = 38;
            return (int) -1;

    destroy_libc();
    pid_t pid = real_vfork();
    // vfork child shares memory until execve, so:
    if(pid == 0) {
        init_libc(); // Dangerous! Must be async-signal-safe
    } else {
        init_libc();
    }
    return pid;
}
    log_arguments("vfork");
    return real_vfork();

pid_t
clone(int (*fn)(void*), void* stack, int flags, void* arg, ...) {
    if(!real_clone)
        real_clone =
                reinterpret_cast<decltype(&::clone)>(dlsym(RTLD_NEXT, "clone"));

    // Only handle process-creation clones
    if(flags & (SIGCHLD | CLONE_VFORK)) {
        destroy_libc();
    }

    pid_t pid = real_clone(fn, stack, flags, arg);

    if(flags & (SIGCHLD | CLONE_VFORK)) {
        (pid == 0) ? init_libc() : init_libc();
    }
    return pid;
}


DLSYM_WRAPPER(int, pipe, (int pipefd[2]), (pipefd), "pipe")
DLSYM_WRAPPER(int, dup, (int fd), (fd), "dup")
DLSYM_WRAPPER(int, dup2, (int fd, int fd2), (fd, fd2), "dup2")
+2 −4
Original line number Diff line number Diff line
@@ -359,8 +359,7 @@ init_preload() {
    // The original errno value will be restored after initialization to not
    // leak internal error codes
    auto oerrno = errno;
    if(!init) {
        init = true;
    if (atomic_exchange(&init, 1) == 0) {
        pthread_atfork(&at_fork_syscall, &at_parent_syscall, &at_child_syscall);
    }
    CTX->enable_interception();
@@ -515,8 +514,7 @@ init_libc() {
        CTX->protect_user_fds();
    }

    if(!init) {
        init = true;
    if (atomic_exchange(&init, 1) == 0) {
        pthread_atfork(&at_fork, &at_parent, &at_child);
    }