Shared Memory Separate Descriptors

This code creates a new task with clone(). Note which flags are present and which are not.

static int shared_fd = -1;

static int child_fn(void *arg) {
    shared_fd = open("/tmp/data", O_RDONLY);   /* returns 3 in the child */
    return 0;
}

int main(void) {
    char *stack = malloc(STACK_SZ) + STACK_SZ;

    clone(child_fn, stack,
          CLONE_VM | CLONE_FS | CLONE_SIGHAND | CLONE_THREAD,
          NULL);

    wait_for_child();                 /* returns after child_fn has returned */

    char buf[16];
    ssize_t n = read(shared_fd, buf, sizeof buf);

What does main observe?

A

read fails with EFAULT, because buf lives on main's stack and the child was given a different stack

B

shared_fd is 3, but read fails with EBADF (or reads some unrelated file), because CLONE_FILES was omitted so the two tasks have separate descriptor tables

C

shared_fd is 3 and read returns data from /tmp/data, because CLONE_VM makes the two tasks share everything the child creates

D

shared_fd is still -1, because the child received a copy-on-write copy of the global on creation