...

Text file src/github.com/opencontainers/runc/libcontainer/userns/userns_maps.c

Documentation: github.com/opencontainers/runc/libcontainer/userns

     1#define _GNU_SOURCE
     2#include <fcntl.h>
     3#include <sched.h>
     4#include <stdio.h>
     5#include <unistd.h>
     6#include <stdarg.h>
     7#include <stdlib.h>
     8
     9/*
    10 * All of the code here is run inside an aync-signal-safe context, so we need
    11 * to be careful to not call any functions that could cause issues. In theory,
    12 * since we are a Go program, there are fewer restrictions in practice, it's
    13 * better to be safe than sorry.
    14 *
    15 * The only exception is exit, which we need to call to make sure we don't
    16 * return into runc.
    17 */
    18
    19void bail(int pipefd, const char *fmt, ...)
    20{
    21	va_list args;
    22
    23	va_start(args, fmt);
    24	vdprintf(pipefd, fmt, args);
    25	va_end(args);
    26
    27	exit(1);
    28}
    29
    30int spawn_userns_cat(char *userns_path, char *path, int outfd, int errfd)
    31{
    32	char buffer[4096] = { 0 };
    33
    34	pid_t child = fork();
    35	if (child != 0)
    36		return child;
    37	/* in child */
    38
    39	/* Join the target userns. */
    40	int nsfd = open(userns_path, O_RDONLY);
    41	if (nsfd < 0)
    42		bail(errfd, "open userns path %s failed: %m", userns_path);
    43
    44	int err = setns(nsfd, CLONE_NEWUSER);
    45	if (err < 0)
    46		bail(errfd, "setns %s failed: %m", userns_path);
    47
    48	close(nsfd);
    49
    50	/* Pipe the requested file contents. */
    51	int fd = open(path, O_RDONLY);
    52	if (fd < 0)
    53		bail(errfd, "open %s in userns %s failed: %m", path, userns_path);
    54
    55	int nread, ntotal = 0;
    56	while ((nread = read(fd, buffer, sizeof(buffer))) != 0) {
    57		if (nread < 0)
    58			bail(errfd, "read bytes from %s failed (after %d total bytes read): %m", path, ntotal);
    59		ntotal += nread;
    60
    61		int nwritten = 0;
    62		while (nwritten < nread) {
    63			int n = write(outfd, buffer, nread - nwritten);
    64			if (n < 0)
    65				bail(errfd, "write %d bytes from %s failed (after %d bytes written): %m",
    66				     nread - nwritten, path, nwritten);
    67			nwritten += n;
    68		}
    69		if (nread != nwritten)
    70			bail(errfd, "mismatch for bytes read and written: %d read != %d written", nread, nwritten);
    71	}
    72
    73	close(fd);
    74	close(outfd);
    75	close(errfd);
    76
    77	/* We must exit here, otherwise we would return into a forked runc. */
    78	exit(0);
    79}

View as plain text