0001
0002
0003
0004
0005 #define _GNU_SOURCE
0006 #include <sys/types.h>
0007 #include <sys/wait.h>
0008 #include <sys/time.h>
0009 #include <sys/resource.h>
0010 #include <sys/prctl.h>
0011 #include <sys/stat.h>
0012
0013 #include <unistd.h>
0014 #include <stdlib.h>
0015 #include <stdio.h>
0016 #include <string.h>
0017 #include <sched.h>
0018 #include <signal.h>
0019 #include <limits.h>
0020 #include <fcntl.h>
0021 #include <errno.h>
0022 #include <err.h>
0023
0024 #define NR_CHILDS 2
0025
0026 static char *service_prog;
0027 static uid_t user = 60000;
0028 static uid_t group = 60000;
0029
0030 static void setrlimit_nproc(rlim_t n)
0031 {
0032 pid_t pid = getpid();
0033 struct rlimit limit = {
0034 .rlim_cur = n,
0035 .rlim_max = n
0036 };
0037
0038 warnx("(pid=%d): Setting RLIMIT_NPROC=%ld", pid, n);
0039
0040 if (setrlimit(RLIMIT_NPROC, &limit) < 0)
0041 err(EXIT_FAILURE, "(pid=%d): setrlimit(RLIMIT_NPROC)", pid);
0042 }
0043
0044 static pid_t fork_child(void)
0045 {
0046 pid_t pid = fork();
0047
0048 if (pid < 0)
0049 err(EXIT_FAILURE, "fork");
0050
0051 if (pid > 0)
0052 return pid;
0053
0054 pid = getpid();
0055
0056 warnx("(pid=%d): New process starting ...", pid);
0057
0058 if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
0059 err(EXIT_FAILURE, "(pid=%d): prctl(PR_SET_PDEATHSIG)", pid);
0060
0061 signal(SIGUSR1, SIG_DFL);
0062
0063 warnx("(pid=%d): Changing to uid=%d, gid=%d", pid, user, group);
0064
0065 if (setgid(group) < 0)
0066 err(EXIT_FAILURE, "(pid=%d): setgid(%d)", pid, group);
0067 if (setuid(user) < 0)
0068 err(EXIT_FAILURE, "(pid=%d): setuid(%d)", pid, user);
0069
0070 warnx("(pid=%d): Service running ...", pid);
0071
0072 warnx("(pid=%d): Unshare user namespace", pid);
0073 if (unshare(CLONE_NEWUSER) < 0)
0074 err(EXIT_FAILURE, "unshare(CLONE_NEWUSER)");
0075
0076 char *const argv[] = { "service", NULL };
0077 char *const envp[] = { "I_AM_SERVICE=1", NULL };
0078
0079 warnx("(pid=%d): Executing real service ...", pid);
0080
0081 execve(service_prog, argv, envp);
0082 err(EXIT_FAILURE, "(pid=%d): execve", pid);
0083 }
0084
0085 int main(int argc, char **argv)
0086 {
0087 size_t i;
0088 pid_t child[NR_CHILDS];
0089 int wstatus[NR_CHILDS];
0090 int childs = NR_CHILDS;
0091 pid_t pid;
0092
0093 if (getenv("I_AM_SERVICE")) {
0094 pause();
0095 exit(EXIT_SUCCESS);
0096 }
0097
0098 service_prog = argv[0];
0099 pid = getpid();
0100
0101 warnx("(pid=%d) Starting testcase", pid);
0102
0103
0104
0105
0106 setrlimit_nproc(1);
0107
0108 for (i = 0; i < NR_CHILDS; i++) {
0109 child[i] = fork_child();
0110 wstatus[i] = 0;
0111 usleep(250000);
0112 }
0113
0114 while (1) {
0115 for (i = 0; i < NR_CHILDS; i++) {
0116 if (child[i] <= 0)
0117 continue;
0118
0119 errno = 0;
0120 pid_t ret = waitpid(child[i], &wstatus[i], WNOHANG);
0121
0122 if (!ret || (!WIFEXITED(wstatus[i]) && !WIFSIGNALED(wstatus[i])))
0123 continue;
0124
0125 if (ret < 0 && errno != ECHILD)
0126 warn("(pid=%d): waitpid(%d)", pid, child[i]);
0127
0128 child[i] *= -1;
0129 childs -= 1;
0130 }
0131
0132 if (!childs)
0133 break;
0134
0135 usleep(250000);
0136
0137 for (i = 0; i < NR_CHILDS; i++) {
0138 if (child[i] <= 0)
0139 continue;
0140 kill(child[i], SIGUSR1);
0141 }
0142 }
0143
0144 for (i = 0; i < NR_CHILDS; i++) {
0145 if (WIFEXITED(wstatus[i]))
0146 warnx("(pid=%d): pid %d exited, status=%d",
0147 pid, -child[i], WEXITSTATUS(wstatus[i]));
0148 else if (WIFSIGNALED(wstatus[i]))
0149 warnx("(pid=%d): pid %d killed by signal %d",
0150 pid, -child[i], WTERMSIG(wstatus[i]));
0151
0152 if (WIFSIGNALED(wstatus[i]) && WTERMSIG(wstatus[i]) == SIGUSR1)
0153 continue;
0154
0155 warnx("(pid=%d): Test failed", pid);
0156 exit(EXIT_FAILURE);
0157 }
0158
0159 warnx("(pid=%d): Test passed", pid);
0160 exit(EXIT_SUCCESS);
0161 }