1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
| #include <cstring> #include <iostream> #include <sys/wait.h> #include <unistd.h>
#include <fcntl.h> #include <sys/mount.h> #include <sys/stat.h> #include <sys/types.h>
static void run(int argc, char *argv[]); static std::string cmd(int argc, char *argv[]); static void run_child(int argc, char *argv[]);
int main(int argc, char *argv[]) {
if (argc < 3) { std::cerr << "Too few arguments" << std::endl; exit(-1); } if (!strcmp(argv[1], "run")) { run(argc - 2, &argv[2]); } return 0; } static void run(int argc, char *argv[]) { std::cout << "parent running " << cmd(argc, argv) << " as " << getpid() << std::endl;
if (unshare(CLONE_NEWPID) < 0) { std::cerr << "failed to unshare in child: PID" << std::endl; exit(-1); }
pid_t child_pid = fork(); if (child_pid < 0) { std::cerr << "failed to fork" << std::endl; return; } if (child_pid)
{ if (waitpid(child_pid, NULL, 0) < 0) { std::cerr << "failed to wait for child" << std::endl; } else { std::cout << "child terminited" << std::endl; } } else { run_child(argc, argv); } }
const char *child_hostname = "container";
static void run_child(int argc, char *argv[]) { std::cout << "child running " << cmd(argc, argv) << " as " << getpid() << std::endl; int flags = CLONE_NEWUTS | CLONE_NEWNS; if (unshare(flags) < 0) { std::cerr << "failed to share in child: UTS" << std::endl; exit(-1); } if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0) { std::cerr << "failed to mount /" << std::endl; }
if (chroot("./ubuntu_rootfs") < 0) { std::cerr << "failed to chroot" << std::endl; exit(-1); } if (chdir("/") < 0) { std::cerr << "failed to chdir to /" << std::endl; exit(-1); }
if (mount("proc", "proc", "proc", 0, NULL) < 0) { std::cerr << "failed to mount /proc" << std::endl; }
if (sethostname(child_hostname, strlen(child_hostname)) < 0) { std::cerr << "failed to changge hostname" << std::endl; }
if (execvp(argv[0], argv)) { perror("execvp failed"); } }
static std::string cmd(int argc, char *argv[]) { std::string cmd = ""; for (int i = 0; i < argc; i++) { cmd.append(argv[i] + std::string(" ")); } return cmd; }
|