mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 22:37:14 +08:00
30b530ca94
Commit4316df8b53isolated RunningInUserNS to a separate package to make it easier to consume without bringing in additional dependencies, and with the potential to move it separate in a similar fashion as libcontainer/user was moved to a separate module in commitca32014adb. While RunningInUserNS is fairly trivial to implement, it (or variants of this utility) is used in many codebases, and moving to a separate module could consolidate those implementations, as well as making it easier to consume without large dependency trees (when being a package as part of a larger code base). Commit1912d5988band follow-ups introduced cgo code into the userns package, and code introduced in those commits are not intended for external use, therefore complicating the potential of moving the userns package separate. This commit moves the new code to a separate package; some of this code was included in v1.1.11 and up, but I could not find external consumers of `GetUserNamespaceMappings` and `IsSameMapping`. The `Mapping` and `Handles` types (added inba0b5e2698) only exist in main and in non-stable releases (v1.2.0-rc.x), so don't need an alias / deprecation. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
80 lines
1.9 KiB
C
80 lines
1.9 KiB
C
#define _GNU_SOURCE
|
|
#include <fcntl.h>
|
|
#include <sched.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
|
|
/*
|
|
* All of the code here is run inside an aync-signal-safe context, so we need
|
|
* to be careful to not call any functions that could cause issues. In theory,
|
|
* since we are a Go program, there are fewer restrictions in practice, it's
|
|
* better to be safe than sorry.
|
|
*
|
|
* The only exception is exit, which we need to call to make sure we don't
|
|
* return into runc.
|
|
*/
|
|
|
|
void bail(int pipefd, const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
vdprintf(pipefd, fmt, args);
|
|
va_end(args);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
int spawn_userns_cat(char *userns_path, char *path, int outfd, int errfd)
|
|
{
|
|
char buffer[4096] = { 0 };
|
|
|
|
pid_t child = fork();
|
|
if (child != 0)
|
|
return child;
|
|
/* in child */
|
|
|
|
/* Join the target userns. */
|
|
int nsfd = open(userns_path, O_RDONLY);
|
|
if (nsfd < 0)
|
|
bail(errfd, "open userns path %s failed: %m", userns_path);
|
|
|
|
int err = setns(nsfd, CLONE_NEWUSER);
|
|
if (err < 0)
|
|
bail(errfd, "setns %s failed: %m", userns_path);
|
|
|
|
close(nsfd);
|
|
|
|
/* Pipe the requested file contents. */
|
|
int fd = open(path, O_RDONLY);
|
|
if (fd < 0)
|
|
bail(errfd, "open %s in userns %s failed: %m", path, userns_path);
|
|
|
|
int nread, ntotal = 0;
|
|
while ((nread = read(fd, buffer, sizeof(buffer))) != 0) {
|
|
if (nread < 0)
|
|
bail(errfd, "read bytes from %s failed (after %d total bytes read): %m", path, ntotal);
|
|
ntotal += nread;
|
|
|
|
int nwritten = 0;
|
|
while (nwritten < nread) {
|
|
int n = write(outfd, buffer, nread - nwritten);
|
|
if (n < 0)
|
|
bail(errfd, "write %d bytes from %s failed (after %d bytes written): %m",
|
|
nread - nwritten, path, nwritten);
|
|
nwritten += n;
|
|
}
|
|
if (nread != nwritten)
|
|
bail(errfd, "mismatch for bytes read and written: %d read != %d written", nread, nwritten);
|
|
}
|
|
|
|
close(fd);
|
|
close(outfd);
|
|
close(errfd);
|
|
|
|
/* We must exit here, otherwise we would return into a forked runc. */
|
|
exit(0);
|
|
}
|