~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/rlimits/rlimits-per-userns.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php