'Wrong /proc/self/root after unshare(CLONE_NEWNS) syscall

I have ARMv7 device with linux kernel 4.4 and I have a simple test case:

/* thread.c */
#define _GNU_SOURCE
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <sched.h>

void readlink_my(const char* when)
{
    char buf[100];
    int len = readlink("/proc/self/root", buf, sizeof(buf));
    buf[len] = '\0';
    printf("%s: %s\n", when, buf);
}

void *first_func(void * ptr)
{
    readlink_my("before unshare()..");
    if(unshare(CLONE_NEWNS) == -1)
        perror("error in unshare()..\n");
    readlink_my("after unshare()..");
    return NULL;
}

int main()
{
    pthread_t first_t;
    pthread_create(&first_t, NULL, first_func, NULL);
    pthread_join(first_t, NULL);
    return 0;
}

After executing this binary I have the output:

# before unshare()..: /
# after unshare()..: /new_root

If I'm removing multithreading from test case:

/* thread.c */
#include <unistd.h>
#include <stdio.h>
#include <sched.h>

void readlink_my(const char* when)
{
    char buf[100];
    int len = readlink("/proc/self/root", buf, sizeof(buf));
    buf[len] = '\0';
    printf("%s: %s\n", when, buf);
}

int main()
{
    readlink_my("before unshare()..");
    if(unshare(CLONE_NEWNS) == -1)
        perror("error in unshare()..\n");
    readlink_my("after unshare()..");
    return 0;
}

I will get ouput without /new_root after unshare():

# before unshare()..: /
# after unshare()..: /

As I think after unshare(CLONE_NEWNS) it will copy mount namespace.

Where from did I get /new_root in first multithreading example?



Solution 1:[1]

/proc/self refers to the initial thread of a POSIX process, use /proc/thread-self to refer to the current thread.

unshare only effects the current thread.

The symlinks under /proc/self read as relative to the root of the examining thread if possible, if not they are relative to the root of mount namespace containing the object they refer to.

The root directory of the process in question is /new_root relative to the root directory of the mount namespace.

In the threaded test case, /proc/self/root is not root directory of the examining thread as it is in a different mount namespace, nor is it a sub-directory, so it is read as relative to the root of it's mount namespace.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Timothy Baldwin