1*053f45beSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*053f45beSAndroid Build Coastguard Worker /*
3*053f45beSAndroid Build Coastguard Worker * Author: Alexey Gladkov <[email protected]>
4*053f45beSAndroid Build Coastguard Worker */
5*053f45beSAndroid Build Coastguard Worker #define _GNU_SOURCE
6*053f45beSAndroid Build Coastguard Worker #include <sys/types.h>
7*053f45beSAndroid Build Coastguard Worker #include <sys/wait.h>
8*053f45beSAndroid Build Coastguard Worker #include <sys/time.h>
9*053f45beSAndroid Build Coastguard Worker #include <sys/resource.h>
10*053f45beSAndroid Build Coastguard Worker #include <sys/prctl.h>
11*053f45beSAndroid Build Coastguard Worker #include <sys/stat.h>
12*053f45beSAndroid Build Coastguard Worker
13*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
14*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
15*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
16*053f45beSAndroid Build Coastguard Worker #include <string.h>
17*053f45beSAndroid Build Coastguard Worker #include <sched.h>
18*053f45beSAndroid Build Coastguard Worker #include <signal.h>
19*053f45beSAndroid Build Coastguard Worker #include <limits.h>
20*053f45beSAndroid Build Coastguard Worker #include <fcntl.h>
21*053f45beSAndroid Build Coastguard Worker #include <errno.h>
22*053f45beSAndroid Build Coastguard Worker #include <err.h>
23*053f45beSAndroid Build Coastguard Worker
24*053f45beSAndroid Build Coastguard Worker #define NR_CHILDS 2
25*053f45beSAndroid Build Coastguard Worker
26*053f45beSAndroid Build Coastguard Worker static char *service_prog;
27*053f45beSAndroid Build Coastguard Worker static uid_t user = 60000;
28*053f45beSAndroid Build Coastguard Worker static uid_t group = 60000;
29*053f45beSAndroid Build Coastguard Worker
setrlimit_nproc(rlim_t n)30*053f45beSAndroid Build Coastguard Worker static void setrlimit_nproc(rlim_t n)
31*053f45beSAndroid Build Coastguard Worker {
32*053f45beSAndroid Build Coastguard Worker pid_t pid = getpid();
33*053f45beSAndroid Build Coastguard Worker struct rlimit limit = {
34*053f45beSAndroid Build Coastguard Worker .rlim_cur = n,
35*053f45beSAndroid Build Coastguard Worker .rlim_max = n
36*053f45beSAndroid Build Coastguard Worker };
37*053f45beSAndroid Build Coastguard Worker
38*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): Setting RLIMIT_NPROC=%ld", pid, n);
39*053f45beSAndroid Build Coastguard Worker
40*053f45beSAndroid Build Coastguard Worker if (setrlimit(RLIMIT_NPROC, &limit) < 0)
41*053f45beSAndroid Build Coastguard Worker err(EXIT_FAILURE, "(pid=%d): setrlimit(RLIMIT_NPROC)", pid);
42*053f45beSAndroid Build Coastguard Worker }
43*053f45beSAndroid Build Coastguard Worker
fork_child(void)44*053f45beSAndroid Build Coastguard Worker static pid_t fork_child(void)
45*053f45beSAndroid Build Coastguard Worker {
46*053f45beSAndroid Build Coastguard Worker pid_t pid = fork();
47*053f45beSAndroid Build Coastguard Worker
48*053f45beSAndroid Build Coastguard Worker if (pid < 0)
49*053f45beSAndroid Build Coastguard Worker err(EXIT_FAILURE, "fork");
50*053f45beSAndroid Build Coastguard Worker
51*053f45beSAndroid Build Coastguard Worker if (pid > 0)
52*053f45beSAndroid Build Coastguard Worker return pid;
53*053f45beSAndroid Build Coastguard Worker
54*053f45beSAndroid Build Coastguard Worker pid = getpid();
55*053f45beSAndroid Build Coastguard Worker
56*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): New process starting ...", pid);
57*053f45beSAndroid Build Coastguard Worker
58*053f45beSAndroid Build Coastguard Worker if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
59*053f45beSAndroid Build Coastguard Worker err(EXIT_FAILURE, "(pid=%d): prctl(PR_SET_PDEATHSIG)", pid);
60*053f45beSAndroid Build Coastguard Worker
61*053f45beSAndroid Build Coastguard Worker signal(SIGUSR1, SIG_DFL);
62*053f45beSAndroid Build Coastguard Worker
63*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): Changing to uid=%d, gid=%d", pid, user, group);
64*053f45beSAndroid Build Coastguard Worker
65*053f45beSAndroid Build Coastguard Worker if (setgid(group) < 0)
66*053f45beSAndroid Build Coastguard Worker err(EXIT_FAILURE, "(pid=%d): setgid(%d)", pid, group);
67*053f45beSAndroid Build Coastguard Worker if (setuid(user) < 0)
68*053f45beSAndroid Build Coastguard Worker err(EXIT_FAILURE, "(pid=%d): setuid(%d)", pid, user);
69*053f45beSAndroid Build Coastguard Worker
70*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): Service running ...", pid);
71*053f45beSAndroid Build Coastguard Worker
72*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): Unshare user namespace", pid);
73*053f45beSAndroid Build Coastguard Worker if (unshare(CLONE_NEWUSER) < 0)
74*053f45beSAndroid Build Coastguard Worker err(EXIT_FAILURE, "unshare(CLONE_NEWUSER)");
75*053f45beSAndroid Build Coastguard Worker
76*053f45beSAndroid Build Coastguard Worker char *const argv[] = { "service", NULL };
77*053f45beSAndroid Build Coastguard Worker char *const envp[] = { "I_AM_SERVICE=1", NULL };
78*053f45beSAndroid Build Coastguard Worker
79*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): Executing real service ...", pid);
80*053f45beSAndroid Build Coastguard Worker
81*053f45beSAndroid Build Coastguard Worker execve(service_prog, argv, envp);
82*053f45beSAndroid Build Coastguard Worker err(EXIT_FAILURE, "(pid=%d): execve", pid);
83*053f45beSAndroid Build Coastguard Worker }
84*053f45beSAndroid Build Coastguard Worker
main(int argc,char ** argv)85*053f45beSAndroid Build Coastguard Worker int main(int argc, char **argv)
86*053f45beSAndroid Build Coastguard Worker {
87*053f45beSAndroid Build Coastguard Worker size_t i;
88*053f45beSAndroid Build Coastguard Worker pid_t child[NR_CHILDS];
89*053f45beSAndroid Build Coastguard Worker int wstatus[NR_CHILDS];
90*053f45beSAndroid Build Coastguard Worker int childs = NR_CHILDS;
91*053f45beSAndroid Build Coastguard Worker pid_t pid;
92*053f45beSAndroid Build Coastguard Worker
93*053f45beSAndroid Build Coastguard Worker if (getenv("I_AM_SERVICE")) {
94*053f45beSAndroid Build Coastguard Worker pause();
95*053f45beSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
96*053f45beSAndroid Build Coastguard Worker }
97*053f45beSAndroid Build Coastguard Worker
98*053f45beSAndroid Build Coastguard Worker service_prog = argv[0];
99*053f45beSAndroid Build Coastguard Worker pid = getpid();
100*053f45beSAndroid Build Coastguard Worker
101*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d) Starting testcase", pid);
102*053f45beSAndroid Build Coastguard Worker
103*053f45beSAndroid Build Coastguard Worker /*
104*053f45beSAndroid Build Coastguard Worker * This rlimit is not a problem for root because it can be exceeded.
105*053f45beSAndroid Build Coastguard Worker */
106*053f45beSAndroid Build Coastguard Worker setrlimit_nproc(1);
107*053f45beSAndroid Build Coastguard Worker
108*053f45beSAndroid Build Coastguard Worker for (i = 0; i < NR_CHILDS; i++) {
109*053f45beSAndroid Build Coastguard Worker child[i] = fork_child();
110*053f45beSAndroid Build Coastguard Worker wstatus[i] = 0;
111*053f45beSAndroid Build Coastguard Worker usleep(250000);
112*053f45beSAndroid Build Coastguard Worker }
113*053f45beSAndroid Build Coastguard Worker
114*053f45beSAndroid Build Coastguard Worker while (1) {
115*053f45beSAndroid Build Coastguard Worker for (i = 0; i < NR_CHILDS; i++) {
116*053f45beSAndroid Build Coastguard Worker if (child[i] <= 0)
117*053f45beSAndroid Build Coastguard Worker continue;
118*053f45beSAndroid Build Coastguard Worker
119*053f45beSAndroid Build Coastguard Worker errno = 0;
120*053f45beSAndroid Build Coastguard Worker pid_t ret = waitpid(child[i], &wstatus[i], WNOHANG);
121*053f45beSAndroid Build Coastguard Worker
122*053f45beSAndroid Build Coastguard Worker if (!ret || (!WIFEXITED(wstatus[i]) && !WIFSIGNALED(wstatus[i])))
123*053f45beSAndroid Build Coastguard Worker continue;
124*053f45beSAndroid Build Coastguard Worker
125*053f45beSAndroid Build Coastguard Worker if (ret < 0 && errno != ECHILD)
126*053f45beSAndroid Build Coastguard Worker warn("(pid=%d): waitpid(%d)", pid, child[i]);
127*053f45beSAndroid Build Coastguard Worker
128*053f45beSAndroid Build Coastguard Worker child[i] *= -1;
129*053f45beSAndroid Build Coastguard Worker childs -= 1;
130*053f45beSAndroid Build Coastguard Worker }
131*053f45beSAndroid Build Coastguard Worker
132*053f45beSAndroid Build Coastguard Worker if (!childs)
133*053f45beSAndroid Build Coastguard Worker break;
134*053f45beSAndroid Build Coastguard Worker
135*053f45beSAndroid Build Coastguard Worker usleep(250000);
136*053f45beSAndroid Build Coastguard Worker
137*053f45beSAndroid Build Coastguard Worker for (i = 0; i < NR_CHILDS; i++) {
138*053f45beSAndroid Build Coastguard Worker if (child[i] <= 0)
139*053f45beSAndroid Build Coastguard Worker continue;
140*053f45beSAndroid Build Coastguard Worker kill(child[i], SIGUSR1);
141*053f45beSAndroid Build Coastguard Worker }
142*053f45beSAndroid Build Coastguard Worker }
143*053f45beSAndroid Build Coastguard Worker
144*053f45beSAndroid Build Coastguard Worker for (i = 0; i < NR_CHILDS; i++) {
145*053f45beSAndroid Build Coastguard Worker if (WIFEXITED(wstatus[i]))
146*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): pid %d exited, status=%d",
147*053f45beSAndroid Build Coastguard Worker pid, -child[i], WEXITSTATUS(wstatus[i]));
148*053f45beSAndroid Build Coastguard Worker else if (WIFSIGNALED(wstatus[i]))
149*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): pid %d killed by signal %d",
150*053f45beSAndroid Build Coastguard Worker pid, -child[i], WTERMSIG(wstatus[i]));
151*053f45beSAndroid Build Coastguard Worker
152*053f45beSAndroid Build Coastguard Worker if (WIFSIGNALED(wstatus[i]) && WTERMSIG(wstatus[i]) == SIGUSR1)
153*053f45beSAndroid Build Coastguard Worker continue;
154*053f45beSAndroid Build Coastguard Worker
155*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): Test failed", pid);
156*053f45beSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
157*053f45beSAndroid Build Coastguard Worker }
158*053f45beSAndroid Build Coastguard Worker
159*053f45beSAndroid Build Coastguard Worker warnx("(pid=%d): Test passed", pid);
160*053f45beSAndroid Build Coastguard Worker exit(EXIT_SUCCESS);
161*053f45beSAndroid Build Coastguard Worker }
162