Reputation: 41
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? .
Upvotes: 3
Views: 2986
Reputation: 4883
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)
.
Upvotes: 3