루트는 네트워크 네임 스페이스 testns
을 만들고 사용자 네임 스페이스 내부에서 자식을 얻으려면 CLONE_NEWUSER
플래그로 복제합니다. 그런 다음 자녀는 setns
으로 전화하여 testns
에 가입하려고 시도합니다. 이는 사용 권한이 거부되었음을 나타냅니다. 사용자 네임 스페이스 내부의 자식이 네트워크 네임 스페이스에 참여할 수있는 다른 방법이 있습니까?내부 사용자 네임 스페이스에서 네트워크 네임 스페이스에 조인
그냥이 다음 테스트를 썼습니다 : (실행하기 전에, 내가 sudo ip netns add testns
를 호출하여 testns
을 만든)
#define _GNU_SOURCE
#include <sched.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <limits.h>
#define STACK_SIZE (1024 * 1024)
static char child_stack[STACK_SIZE];
static void update_map(char *mapping, char *map_file) {
int fd, j;
size_t map_len;
map_len = strlen(mapping);
for (j = 0; j < map_len; j++)
if (mapping[j] == ',')
mapping[j] = '\n';
fd = open(map_file, O_RDWR);
if (fd == -1) {
fprintf(stderr, "open %s: %s\n", map_file, strerror(errno));
exit(EXIT_FAILURE);
}
if (write(fd, mapping, map_len) != map_len) {
fprintf(stderr, "write %s: %s\n", map_file, strerror(errno));
exit(EXIT_FAILURE);
}
close(fd);
}
static void proc_setgroups_write(pid_t child_pid, char *str) {
char setgroups_path[PATH_MAX];
int fd;
snprintf(setgroups_path, PATH_MAX, "/proc/%ld/setgroups",
(long) child_pid);
fd = open(setgroups_path, O_RDWR);
if (fd == -1) {
if (errno != ENOENT)
fprintf(stderr, "ERROR: open %s: %s\n", setgroups_path,
strerror(errno));
return;
}
if (write(fd, str, strlen(str)) == -1)
fprintf(stderr, "ERROR: write %s: %s\n", setgroups_path,
strerror(errno));
close(fd);
}
static void update_userns(pid_t pid, char *uidMap, char *gidMap) {
char map_path[PATH_MAX];
snprintf(map_path, PATH_MAX, "/proc/%ld/uid_map", (long) pid);
update_map(uidMap, map_path);
proc_setgroups_write(pid, "deny");
snprintf(map_path, PATH_MAX, "/proc/%ld/gid_map", (long) pid);
update_map(gidMap, map_path);
}
static int join_netns(char *netns_name) {
char netns_path[256];
snprintf(netns_path, sizeof(netns_path), "/var/run/netns/%s", netns_name);
int fd = open(netns_path, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "open netns path failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (setns(fd, CLONE_NEWNET) == -1) {
fprintf(stderr, "set netns failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
return 0;
}
static int child(void* arg) {
// Sleep so that userns has the correct mapping.
sleep(1);
return join_netns("testns");
}
int main(int argc, char *argv[]) {
uid_t uid = getuid();
char mapping[10];
snprintf(mapping, 10, "0 %d 1", uid);
int pid1 = clone(child, child_stack + STACK_SIZE, CLONE_NEWUSER | SIGCHLD, NULL);
if (pid1 == -1) {
perror("Clone");
exit(EXIT_FAILURE);
}
update_userns(pid1, mapping, mapping);
if (waitpid(pid1, NULL, 0) == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
}