Я побежал

unshare -mfp sh -c 'mount -tproc none /proc ; ls /proc'

Как и ожидалось, это напечатало /proc только с каталогами для PID 1 и PID 3, и вышло, оставив меня обратно в моем старом приглашении в корневом пространстве имен.

Тогда я сделал

ls /proc

и я получил список без каталогов PID. Я ожидал, что мой обычный / процесс полон процессов. Мне пришлось снова смонтировать proc, чтобы все исправить.

Почему это происходит? Как мне все исправить, чтобы /proc, который я смонтировал в пространстве имен PID, оставался для него локальным?

Я попытался передать --mount-private для монтирования, но, похоже, это не дало никакого эффекта.

Я нахожусь на Amazon Linux 2016.03, который поставляется с util-linux 2.23.2.

1 ответ1

0

Либо unshare(1) не работает, либо я тупой.

Я изменил код в http://crosbymichael.com/creating-containers-part-1.html, чтобы он действительно работал для меня. Пришлось лениво размонтировать /proc с помощью umount2 и включить linux/sched.h вместо sched.h .

Для компиляции сделайте gcc foo.c -ofoo .

Вы заметите, что после запуска, например ./foo ls /proc , /proc на хост-системе не будет удален.

//
// 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);
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .