Recently, I am learning about linux namespaces. 
I hope even if the process ends, I could still attach the namespace that process is in.
Someone told I could use mount --bind /proc/<pid>/ns/pid ./pid to keep this file open. So I tried it.
When I mount uts, user, ipc, pid, net... They are all okay..
root@ubuntu:/home/jiashenh/workspace# touch uts
root@ubuntu:/home/jiashenh/workspace# mount --bind /proc/171/ns/uts ./uts
But when it comes to mnt.... I used it in the same way ...
root@ubuntu:/home/jiashenh/workspace# touch mnt    
root@ubuntu:/home/jiashenh/workspace# mount --bind /proc/171/ns/mnt ./mnt
mount: wrong fs type, bad option, bad superblock on /proc/171/ns/mnt,
       missing codepage or helper program, or other error
       In some cases useful info is found in syslog - try
       dmesg | tail or so
It failed.....So could anyone told me how to fix it? .
Bind mount for /proc/<pid>/ns/mnt really doesn't work if called within the same mount namespace.
However, bind mount for ns/mnt works if:
mount() is called from a process with another mount namespace, andmount() is called from a process where the ns/mnt being mounted is visible.Both requirements are met if mount() is called from a process forked before unshare() call that created ns/mnt entry being mounted.
(Note that after unshare() call, previously visible ns/mnt entries are no more visible and become broken symlinks).
Here is a test:
#define _GNU_SOURCE
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sched.h>
#include <sys/types.h>
#include <sys/mount.h>
int main(int argc, char** argv) {
    int fd = open("/tmp/mnt.ns", O_CREAT | O_RDWR);
    close(fd);
    if (argc > 1) {
        if (fork() == 0) {
            sleep(1);
        } else {
            unshare(CLONE_NEWNS);
            wait(NULL);
            return 0;
        }
    }
    char src[PATH_MAX] = {};
    snprintf(src, sizeof(src), "/proc/%u/ns/mnt", (unsigned)getppid());
    if (mount(src, "/tmp/mnt.ns", NULL, MS_BIND, NULL) != 0) {
        printf("mount failed: %s\n", strerror(errno));
        return 1;
    }
    else {
        printf("mount ok\n");
    }
    return 0;
}
This test fails without fork() and unshare():
$ sudo ./a.out  
mount failed: Invalid argument
But works if it calls fork() and unshare() before mount() (note the x arg):
$ sudo ./a.out x
mount ok
See this commit for unshare tool and also this patch.
Unfortunately, this behaviour specific to ns/mnt is not documented in namespaces(7).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With