mirror of
https://github.com/containers/podman.git
synced 2025-05-17 15:18:43 +08:00

As this file uses open it needs to include fcntl.h. This should fix the build error seen on epel9[1], not sure why it works on the other platforms. [1] https://download.copr.fedorainfracloud.org/results/packit/containers-podman-23113/epel-9-aarch64/07672197-podman/builder-live.log.gz Fixes 65ed96585d ("podman top: join the container userns") Signed-off-by: Paul Holzinger <pholzing@redhat.com>
111 lines
2.4 KiB
C
111 lines
2.4 KiB
C
//go:build !remote
|
|
|
|
|
|
#define _GNU_SOURCE
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <sched.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
/* keep special_exit_code in sync with container_top_linux.go */
|
|
int special_exit_code = 255;
|
|
int join_userns = 0;
|
|
char **argv = NULL;
|
|
|
|
void
|
|
create_argv (int len)
|
|
{
|
|
/* allocate one extra element because we need a final NULL in c */
|
|
argv = malloc (sizeof (char *) * (len + 1));
|
|
if (argv == NULL)
|
|
{
|
|
fprintf (stderr, "failed to allocate ps argv");
|
|
exit (special_exit_code);
|
|
}
|
|
/* add final NULL */
|
|
argv[len] = NULL;
|
|
}
|
|
|
|
void
|
|
set_argv (int pos, char *arg)
|
|
{
|
|
argv[pos] = arg;
|
|
}
|
|
|
|
void
|
|
set_userns ()
|
|
{
|
|
join_userns = 1;
|
|
}
|
|
|
|
/*
|
|
We use cgo code here so we can fork then exec separately,
|
|
this is done so we can mount proc after the fork because the pid namespace is
|
|
only active after spawning children.
|
|
*/
|
|
void
|
|
fork_exec_ps ()
|
|
{
|
|
int r, status = 0;
|
|
pid_t pid;
|
|
|
|
if (argv == NULL)
|
|
{
|
|
fprintf (stderr, "argv not initialized");
|
|
exit (special_exit_code);
|
|
}
|
|
|
|
pid = fork ();
|
|
if (pid < 0)
|
|
{
|
|
fprintf (stderr, "fork: %m");
|
|
exit (special_exit_code);
|
|
}
|
|
if (pid == 0)
|
|
{
|
|
r = mount ("proc", "/proc", "proc", 0, NULL);
|
|
if (r < 0)
|
|
{
|
|
fprintf (stderr, "mount proc: %m");
|
|
exit (special_exit_code);
|
|
}
|
|
if (join_userns)
|
|
{
|
|
// join the userns to make sure uid mapping match
|
|
// we are already part of the pidns so so pid 1 is the main container process
|
|
r = open ("/proc/1/ns/user", O_CLOEXEC | O_RDONLY);
|
|
if (r < 0)
|
|
{
|
|
fprintf (stderr, "open /proc/1/ns/user: %m");
|
|
exit (special_exit_code);
|
|
}
|
|
if ((status = setns (r, CLONE_NEWUSER)) < 0)
|
|
{
|
|
fprintf (stderr, "setns NEWUSER: %m");
|
|
exit (special_exit_code);
|
|
}
|
|
}
|
|
|
|
/* use execve to unset all env vars, we do not want to leak anything into the container */
|
|
execve (argv[0], argv, NULL);
|
|
fprintf (stderr, "execve: %m");
|
|
exit (special_exit_code);
|
|
}
|
|
|
|
r = waitpid (pid, &status, 0);
|
|
if (r < 0)
|
|
{
|
|
fprintf (stderr, "waitpid: %m");
|
|
exit (special_exit_code);
|
|
}
|
|
if (WIFEXITED (status))
|
|
exit (WEXITSTATUS (status));
|
|
if (WIFSIGNALED (status))
|
|
exit (128 + WTERMSIG (status));
|
|
exit (special_exit_code);
|
|
}
|