Why does kretprobe _do_fork () only return once?

When I write a small script with fork, syscall returns two processes (once per process):

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int pid = fork();

    if (pid == 0) {
        // child
    } else if (pid > 0) {
        // parent
    }
}

      

If I use the systemtap tool, I only find one return value:

// fork() in libc calls clone on Linux
probe syscall.clone.return {
    printf("Return from clone\n")
}

      

( SystemTap sets probes to_do_fork

instead of cloning, but that doesn't change anything.)

This confuses me. Several related questions:

  • Why does syscall only return once?
  • If I understand the _do_fork

    code
    correctly , the process is cloned in the middle of the function. ( copy_process

    and wake_up_new_task

    ). Should the following code work in both processes?
  • Is the kernel code after syscall executed in the same thread / process as the user code before syscall?
+3


source to share


1 answer


  • child element creation may fail, so errors must be caught and handled
  • the child has a different return value and this should be handled as well
  • Perhaps the parent has a cleanup / extra action

Thus, the code will have to distinguish between execution as parent and child. But there are no checks of this kind, which is already a strong hint that the child is not executing this code in the first place. Thus, one should look for a dedicated place where new children return.

Since the code is quite large and hairy, you can try to cheat and just look for a fork in the pivot code, which ret_from_fork quickly finds.

Starting point is set -> do_fork -> copy_process -> copy_thread_tls http://lxr.free-electrons.com/source/arch/x86/kernel/process_64.c#L158

Thus,

Why does syscall only return once?



It doesn't come back once. There are 2 streams returned, except the other uses a different code path. Since the probe is only installed on the first one, you cannot see the other. Also see below.

If I understand the _do_fork code correctly, the process is cloned in the middle of the function. (copy_process and wake_up_new_task). Should the following code work in both processes?

I noticed that this is not correct. The real question is what could help bring the child back to the same place as the parent. I can't see anything and that would be annoying (optional special enclosure as above). To reinstall: Forcing the child to return yet, let the callers not have to handle the returning child. They only need to check for errors.

Is the kernel code after syscall executed in the same thread / process as the user code before syscall?

What is "kernel code after syscall"? If you are an X thread and enter the kernel, you are still an X thread.

+4


source







All Articles