2017-02-21 2 views
0

Root erstellt einen Netzwerknamespace testns, und klonen mit CLONE_NEWUSER Flag, um das untergeordnete Element in einem Benutzernamespace zu erhalten. Dann versucht das Kind, testns beizutreten, indem setns aufruft, das die Berechtigung zeigt, die verweigert wird. Gibt es eine Alternative, das Kind in einem Benutzernamespace einem Netzwerknamespace beizutreten?Verknüpfen Sie Netzwerknamespace aus dem Benutzernamespace

schrieben einfach diesen folgenden Test auf: (Vor dem Ausführen, ich testns erstellt sudo ip netns add testns durch Aufruf)

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

Antwort

0

Der Kernel wird eine Sicherheitsüberprüfung tun, dass der userns „Besitzer“/Schöpfer der Netzwerk-Namespace Streichhölzer bevor Sie eine Verbindung zu einem vorhandenen Netzwerk-Namespace zulassen.

Sie können definitiv einem Netzwerknamespace innerhalb eines Benutzernamespace beitreten, aber dieser anfängliche Netzwerknamespace muss mit demselben Benutzernamespace erstellt werden. In Containerlaufzeiten wie dem Tool runc können Sie dies überprüfen, indem Sie einen einfachen Container in einem Benutzernamespace mit einem erstellten Netzwerknamespace starten und dann einen zweiten Container mit den Benutzern und Netzwerk Namespacepfade starten. Ich habe dies unter Verwendung runc bei einer früheren DockerCon Demo; Sie können sehen, wie ich den Namespace und den Netzwerk-Namespace teilen in this segment starting at 41:24

Verwandte Themen