#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include int main() { const char *child = "/tmp/child"; int ret; printf("main pid = %d\n", getpid()); /* make our own private playground ... */ ret = unshare(CLONE_NEWNS); if (ret) { perror("unshare"); exit(1); } ret = mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL); if (ret) { perror("mount"); exit(1); } ret = mount("none", "/", NULL, MS_REC|MS_SHARED, NULL); if (ret) { perror("mount2"); exit(1); } /* fork monitor ... */ ret = fork(); if (ret < 0) { perror("fork"); exit(1); } else if (!ret) { printf("monitor pid = %d\n", getpid()); ret = unshare(CLONE_NEWNS); if (ret) { perror("unshare in monitor"); exit(1); } ret = mount("none", "/", NULL, MS_REC|MS_SHARED, NULL); if (ret) { perror("mount in monitor"); exit(1); } ret = mount("none", "/", NULL, MS_REC|MS_SLAVE, NULL); if (ret) { perror("mount2 in monitor"); exit(1); } sleep(-1); } /* wait monitor to setup */ sleep(1); /* fork child ... */ ret = fork(); if (ret < 0) { perror("fork"); exit(1); } else if (!ret) { printf("child pid = %d\n", getpid()); ret = unshare(CLONE_NEWNS); if (ret) { perror("unshare in child"); exit(1); } ret = mount("none", "/", NULL, MS_REC|MS_SLAVE, NULL); if (ret) { perror("mount in child"); exit(1); } ret = mount(NULL, "/", NULL, MS_REC|MS_SHARED, NULL); if (ret) { perror("mount2 in child"); exit(1); } if (!fork()) { /* grand-child */ printf("grand-child pid = %d\n", getpid()); ret = unshare(CLONE_NEWNS); if (ret) { perror("unshare in grand-child"); exit(1); } ret = mount("none", "/", NULL, MS_REC|MS_SHARED, NULL); if (ret) { perror("mount in grand-child"); exit(1); } ret = mount("none", "/", NULL, MS_REC|MS_SLAVE, NULL); if (ret) { perror("mount2 in grand-child"); exit(1); } sleep(-1); } sleep(-1); } /* wait child and grand-child to setup */ sleep(1); ret = mkdir(child, 0755); if (ret && errno != EEXIST) { perror("mkdir"); exit(1); } /* let "child" mount slip to everyone' namespaces ... */ ret = mount(child, child, NULL, MS_BIND, NULL); if (ret) { perror("bind mount"); exit(1); } sleep(-1); }