mirror of
				https://github.com/containers/podman.git
				synced 2025-11-01 02:42:11 +08:00 
			
		
		
		
	 6db8ff7f7b
			
		
	
	6db8ff7f7b
	
	
	
		
			
			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);
 | |
| }
 |