Ou o unshare (1) está quebrado ou eu sou idiota.
Eu modifiquei o código no link para que funcionasse para mim. Tinha que desmontar / proc preguiçosamente com umount2
e incluir linux/sched.h
em vez de sched.h
.
Para compilar do gcc foo.c -ofoo
.
Você notará que, após a exibição, por exemplo, ./foo ls /proc
, / proc no sistema host não será eliminado.
//
// This compiles and works on Amazon Linux 2016.03 (kernel 4.4.5-15.26.amzn1.x86_64)
//
#include <stdio.h>
#include <stdlib.h>
// was <sched.h>, but wouldn't compile on Amazon Linux
#include <linux/sched.h>
// for umount2()
#include <sys/mount.h>
#include <sys/wait.h>
#include <errno.h>
#define STACKSIZE (1024*1024)
static char child_stack[STACKSIZE];
struct clone_args {
char **argv;
};
static int child_exec(void *stuff) {
struct clone_args *args = (struct clone_args *)stuff;
// the fprintf()s crash. Not sure why.
// changed from umount(), lazy umount succeeds
if (umount2("/proc", MNT_DETACH) != 0) {
fprintf(stderr, "failed to unmount /proc: %s\n", strerror(errno));
exit(-1);
}
if (mount("proc", "/proc", "proc", 0, "") != 0) {
fprintf(stderr, "failed to mount /proc: %s\n", strerror(errno));
exit(-1);
}
if (execvp(args->argv[0], args->argv) != 0) {
fprintf(stderr, "failed to execvp arguments: %s\n", strerror(errno));
exit(-1);
}
// unreachable
exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
struct clone_args args;
args.argv = &argv[1];
int clone_flags = CLONE_NEWPID | CLONE_NEWNS | SIGCHLD;
pid_t pid = clone(child_exec, child_stack + STACKSIZE, clone_flags, &args);
if (pid < 0) {
fprintf(stderr, "clone failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (waitpid(pid, NULL, 0) == -1) {
fprintf(stderr, "failed to wait pid %d\n", pid);
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}