Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #define _GNU_SOURCE
0003 #include <sched.h>
0004 #include <unistd.h>
0005 #include <stdio.h>
0006 #include <stdlib.h>
0007 #include <signal.h>
0008 #include <errno.h>
0009 #include <sys/types.h>
0010 #include <sys/stat.h>
0011 #include <fcntl.h>
0012 #include <sys/ioctl.h>
0013 #include <sys/prctl.h>
0014 #include <sys/wait.h>
0015 
0016 #define NSIO    0xb7
0017 #define NS_GET_USERNS   _IO(NSIO, 0x1)
0018 
0019 #define pr_err(fmt, ...) \
0020         ({ \
0021             fprintf(stderr, "%s:%d:" fmt ": %m\n", \
0022                 __func__, __LINE__, ##__VA_ARGS__); \
0023             1; \
0024         })
0025 
0026 int main(int argc, char *argvp[])
0027 {
0028     int pfd[2], ns, uns, init_uns;
0029     struct stat st1, st2;
0030     char path[128];
0031     pid_t pid;
0032     char c;
0033 
0034     if (pipe(pfd))
0035         return 1;
0036 
0037     pid = fork();
0038     if (pid < 0)
0039         return pr_err("fork");
0040     if (pid == 0) {
0041         prctl(PR_SET_PDEATHSIG, SIGKILL);
0042         if (unshare(CLONE_NEWUTS | CLONE_NEWUSER))
0043             return pr_err("unshare");
0044         close(pfd[0]);
0045         close(pfd[1]);
0046         while (1)
0047             sleep(1);
0048         return 0;
0049     }
0050     close(pfd[1]);
0051     if (read(pfd[0], &c, 1) != 0)
0052         return pr_err("Unable to read from pipe");
0053     close(pfd[0]);
0054 
0055     snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid);
0056     ns = open(path, O_RDONLY);
0057     if (ns < 0)
0058         return pr_err("Unable to open %s", path);
0059 
0060     uns = ioctl(ns, NS_GET_USERNS);
0061     if (uns < 0)
0062         return pr_err("Unable to get an owning user namespace");
0063 
0064     if (fstat(uns, &st1))
0065         return pr_err("fstat");
0066 
0067     snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
0068     if (stat(path, &st2))
0069         return pr_err("stat");
0070 
0071     if (st1.st_ino != st2.st_ino)
0072         return pr_err("NS_GET_USERNS returned a wrong namespace");
0073 
0074     init_uns = ioctl(uns, NS_GET_USERNS);
0075     if (uns < 0)
0076         return pr_err("Unable to get an owning user namespace");
0077 
0078     if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
0079         return pr_err("Don't get EPERM");
0080 
0081     if (unshare(CLONE_NEWUSER))
0082         return pr_err("unshare");
0083 
0084     if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM)
0085         return pr_err("Don't get EPERM");
0086     if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
0087         return pr_err("Don't get EPERM");
0088 
0089     kill(pid, SIGKILL);
0090     wait(NULL);
0091     return 0;
0092 }