CLONE_NEWNS在Android上无效

时间:2015-08-26 10:47:57

标签: android namespaces

我正在学习mount命名空间,这是Linux内核提供的隔离机制。我写了一个简单的C程序来测试它。

#define _GNU_SOURCE
#include <sys/types.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <asm/unistd.h>
#include <sys/mount.h>
#include <errno.h>
#include <string.h>

#define STACK_SIZE (1024 * 1024)
static char container_stack[STACK_SIZE];

char* const container_args[] = {
    "/bin/bash",
    NULL
};

void mounts(void)
{
    syscall(__NR_mount, "proc", "/home/aaa/nstest/", "proc", 0, NULL);
}

int container_main(void* arg)
{
    printf("Container - inside the container!\n");
    errno = 0;
    mounts();
    perror("mount");
    execv(container_args[0], container_args); 
    printf("Something's wrong!\n");
    return 1;
}

int main()
{
    printf("Parent - start a container!\n");
    int pid = syscall(__NR_clone, CLONE_NEWNS | SIGCHLD, NULL, NULL, NULL,     NULL);
    if (pid < 0) {
        perror("clone failed");
        exit(-1);
    } else if (pid == 0) {
        container_main(NULL);
        exit(0);
    }
    waitpid(pid, NULL, 0);
    printf("Parent - container stopped!\n");
    return 0;
}

这段代码在我的Ubuntu上运行良好。目录&#34; / home / aaa / nstest /&#34;在根装入命名空间中挂载后,它在新安装命名空间中为空。

但是,它并不适用于Android模拟器。安装程序传播到根安装命名空间。首先我认为它可能是由内核引起的,不支持命名空间。所以我用所有相对的CONFIG开关编译金鱼,比如CONFIG_NAMESPACE。而且它也不起作用。

1 个答案:

答案 0 :(得分:1)

即使在使用所有CONFIG_NAMESPACE重新编译内核之后,我也遇到了同样的问题。我已经尝试了unshare -m /bin/bash命令,它可以在我的archlinux x86_64框中运行,

所以我深入研究了命令的strace unshare -m /bin/bash

...
unshare(CLONE_NEWNS)                    = 0
mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL) = 0
execve("/bin/bash", ["/bin/bash"], [/* 19 vars */]) = 0
...

接缝需要额外拨打mount(...)。将调用添加到我的代码中,它可以工作!

int main(int argc, const char* argv[]) {
    const char * source=argv[1];
    const char * target=argv[2];

    if (unshare(CLONE_NEWNS) == -1) {
        printf("Failed to unshare(): %s\n", strerror(errno));
        return -1;
    }
    mount("none", "/", NULL, MS_REC|MS_PRIVATE, NULL);

    if (mount(source, target, NULL, MS_BIND, NULL) == -1) {
        printf("Failed to mount %s to %s: %s\n", source, target, strerror(errno));
        return -1;
    }
    sleep(50);
    return 0;
}