• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0
2  #define _GNU_SOURCE
3  #include <sched.h>
4  #include <unistd.h>
5  #include <stdio.h>
6  #include <stdlib.h>
7  #include <signal.h>
8  #include <errno.h>
9  #include <sys/types.h>
10  #include <sys/stat.h>
11  #include <fcntl.h>
12  #include <sys/ioctl.h>
13  #include <sys/prctl.h>
14  #include <sys/wait.h>
15  
16  #define pr_err(fmt, ...) \
17  		({ \
18  			fprintf(stderr, "%s:%d:" fmt ": %m\n", \
19  				__func__, __LINE__, ##__VA_ARGS__); \
20  			1; \
21  		})
22  
23  #define NSIO	0xb7
24  #define NS_GET_USERNS   _IO(NSIO, 0x1)
25  #define NS_GET_PARENT   _IO(NSIO, 0x2)
26  
27  #define __stack_aligned__	__attribute__((aligned(16)))
28  struct cr_clone_arg {
29  	char stack[128] __stack_aligned__;
30  	char stack_ptr[0];
31  };
32  
child(void * args)33  static int child(void *args)
34  {
35  	prctl(PR_SET_PDEATHSIG, SIGKILL);
36  	while (1)
37  		sleep(1);
38  	exit(0);
39  }
40  
main(int argc,char * argv[])41  int main(int argc, char *argv[])
42  {
43  	char *ns_strs[] = {"pid", "user"};
44  	char path[] = "/proc/0123456789/ns/pid";
45  	struct cr_clone_arg ca;
46  	struct stat st1, st2;
47  	int ns, pns, i;
48  	pid_t pid;
49  
50  	pid = clone(child, ca.stack_ptr, CLONE_NEWUSER | CLONE_NEWPID | SIGCHLD, NULL);
51  	if (pid < 0)
52  		return pr_err("clone");
53  
54  	for (i = 0; i < 2; i++) {
55  		snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns_strs[i]);
56  		ns = open(path, O_RDONLY);
57  		if (ns < 0)
58  			return pr_err("Unable to open %s", path);
59  
60  		pns = ioctl(ns, NS_GET_PARENT);
61  		if (pns < 0)
62  			return pr_err("Unable to get a parent pidns");
63  
64  		snprintf(path, sizeof(path), "/proc/self/ns/%s", ns_strs[i]);
65  		if (stat(path, &st2))
66  			return pr_err("Unable to stat %s", path);
67  		if (fstat(pns, &st1))
68  			return pr_err("Unable to stat the parent pidns");
69  		if (st1.st_ino != st2.st_ino)
70  			return pr_err("NS_GET_PARENT returned a wrong namespace");
71  
72  		if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != EPERM)
73  			return pr_err("Don't get EPERM");
74  	}
75  
76  	kill(pid, SIGKILL);
77  	wait(NULL);
78  	return 0;
79  }
80