Home | History | Annotate | Download | only in nsfs
      1 #define _GNU_SOURCE
      2 #include <sched.h>
      3 #include <unistd.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <signal.h>
      7 #include <errno.h>
      8 #include <sys/types.h>
      9 #include <sys/stat.h>
     10 #include <fcntl.h>
     11 #include <sys/ioctl.h>
     12 #include <sys/prctl.h>
     13 #include <sys/wait.h>
     14 
     15 #define NSIO    0xb7
     16 #define NS_GET_USERNS   _IO(NSIO, 0x1)
     17 
     18 #define pr_err(fmt, ...) \
     19 		({ \
     20 			fprintf(stderr, "%s:%d:" fmt ": %m\n", \
     21 				__func__, __LINE__, ##__VA_ARGS__); \
     22 			1; \
     23 		})
     24 
     25 int main(int argc, char *argvp[])
     26 {
     27 	int pfd[2], ns, uns, init_uns;
     28 	struct stat st1, st2;
     29 	char path[128];
     30 	pid_t pid;
     31 	char c;
     32 
     33 	if (pipe(pfd))
     34 		return 1;
     35 
     36 	pid = fork();
     37 	if (pid < 0)
     38 		return pr_err("fork");
     39 	if (pid == 0) {
     40 		prctl(PR_SET_PDEATHSIG, SIGKILL);
     41 		if (unshare(CLONE_NEWUTS | CLONE_NEWUSER))
     42 			return pr_err("unshare");
     43 		close(pfd[0]);
     44 		close(pfd[1]);
     45 		while (1)
     46 			sleep(1);
     47 		return 0;
     48 	}
     49 	close(pfd[1]);
     50 	if (read(pfd[0], &c, 1) != 0)
     51 		return pr_err("Unable to read from pipe");
     52 	close(pfd[0]);
     53 
     54 	snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid);
     55 	ns = open(path, O_RDONLY);
     56 	if (ns < 0)
     57 		return pr_err("Unable to open %s", path);
     58 
     59 	uns = ioctl(ns, NS_GET_USERNS);
     60 	if (uns < 0)
     61 		return pr_err("Unable to get an owning user namespace");
     62 
     63 	if (fstat(uns, &st1))
     64 		return pr_err("fstat");
     65 
     66 	snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
     67 	if (stat(path, &st2))
     68 		return pr_err("stat");
     69 
     70 	if (st1.st_ino != st2.st_ino)
     71 		return pr_err("NS_GET_USERNS returned a wrong namespace");
     72 
     73 	init_uns = ioctl(uns, NS_GET_USERNS);
     74 	if (uns < 0)
     75 		return pr_err("Unable to get an owning user namespace");
     76 
     77 	if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
     78 		return pr_err("Don't get EPERM");
     79 
     80 	if (unshare(CLONE_NEWUSER))
     81 		return pr_err("unshare");
     82 
     83 	if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM)
     84 		return pr_err("Don't get EPERM");
     85 	if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
     86 		return pr_err("Don't get EPERM");
     87 
     88 	kill(pid, SIGKILL);
     89 	wait(NULL);
     90 	return 0;
     91 }
     92