podman
1//go:build !remote
2
3
4#define _GNU_SOURCE5#include <errno.h>6#include <stdio.h>7#include <stdlib.h>8#include <sys/mount.h>9#include <sys/wait.h>10#include <unistd.h>11
12/* keep special_exit_code in sync with container_top_linux.go */
13int special_exit_code = 255;14char **argv = NULL;15
16void
17create_argv (int len)18{
19/* allocate one extra element because we need a final NULL in c */20argv = malloc (sizeof (char *) * (len + 1));21if (argv == NULL)22{23fprintf (stderr, "failed to allocate ps argv");24exit (special_exit_code);25}26/* add final NULL */27argv[len] = NULL;28}
29
30void
31set_argv (int pos, char *arg)32{
33argv[pos] = arg;34}
35
36/*
37We use cgo code here so we can fork then exec separately,
38this is done so we can mount proc after the fork because the pid namespace is
39only active after spawning children.
40*/
41void
42fork_exec_ps ()43{
44int r, status = 0;45pid_t pid;46
47if (argv == NULL)48{49fprintf (stderr, "argv not initialized");50exit (special_exit_code);51}52
53pid = fork ();54if (pid < 0)55{56fprintf (stderr, "fork: %m");57exit (special_exit_code);58}59if (pid == 0)60{61r = mount ("proc", "/proc", "proc", 0, NULL);62if (r < 0)63{64fprintf (stderr, "mount proc: %m");65exit (special_exit_code);66}67/* use execve to unset all env vars, we do not want to leak anything into the container */68execve (argv[0], argv, NULL);69fprintf (stderr, "execve: %m");70exit (special_exit_code);71}72
73r = waitpid (pid, &status, 0);74if (r < 0)75{76fprintf (stderr, "waitpid: %m");77exit (special_exit_code);78}79if (WIFEXITED (status))80exit (WEXITSTATUS (status));81if (WIFSIGNALED (status))82exit (128 + WTERMSIG (status));83exit (special_exit_code);84}
85