1 /* Copyright (C) 2018-2021 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <errno.h>
19 #include <stdio.h>
20 #include <sys/resource.h>
21 #include <support/check.h>
22 
23 static int resources[] = {
24   /* The following 7 limits are part of POSIX and must exist.  */
25   RLIMIT_CORE,
26   RLIMIT_CPU,
27   RLIMIT_DATA,
28   RLIMIT_FSIZE,
29   RLIMIT_NOFILE,
30   RLIMIT_STACK,
31   RLIMIT_AS
32 };
33 
34 #define nresources (sizeof (resources) / sizeof (resources[0]))
35 
36 /* Assume that the prlimit64 function calls the prlimit64 syscall without
37    mangling the arguments.  */
38 #define PRLIMIT64_INFINITY	((rlim64_t) -1)
39 
40 /* As we don't know which limit will be modified, use a sufficiently high
41    value to not shoot ourself in the foot.  Use a 32-bit value to test
42    both the 32- and 64-bit versions, and keep the highest bit clear to
43    avoid sign extension.  */
44 #define PRLIMIT64_TESTVAL	((rlim64_t) 0x42420000)
45 
46 static void
test_getrlimit(int resource,rlim_t exp_cur,rlim_t exp_max)47 test_getrlimit (int resource, rlim_t exp_cur, rlim_t exp_max)
48 {
49   struct rlimit r;
50   TEST_VERIFY_EXIT (getrlimit (resource, &r) == 0);
51   TEST_COMPARE (r.rlim_cur, exp_cur);
52   TEST_COMPARE (r.rlim_max, exp_max);
53 }
54 
55 static void
test_getrlimit64(int resource,rlim64_t exp_cur,rlim64_t exp_max)56 test_getrlimit64 (int resource, rlim64_t exp_cur, rlim64_t exp_max)
57 {
58   struct rlimit64 r;
59   TEST_VERIFY_EXIT (getrlimit64 (resource, &r) == 0);
60   TEST_COMPARE (r.rlim_cur, exp_cur);
61   TEST_COMPARE (r.rlim_max, exp_max);
62 }
63 
64 static void
test_prlimit_get(int resource,rlim_t exp_cur,rlim_t exp_max)65 test_prlimit_get (int resource, rlim_t exp_cur, rlim_t exp_max)
66 {
67   struct rlimit r;
68   TEST_VERIFY_EXIT (prlimit (0, resource, NULL, &r) == 0);
69   TEST_COMPARE (r.rlim_cur, exp_cur);
70   TEST_COMPARE (r.rlim_max, exp_max);
71 }
72 
73 static void
test_prlimit64_get(int resource,rlim64_t exp_cur,rlim64_t exp_max)74 test_prlimit64_get (int resource, rlim64_t exp_cur, rlim64_t exp_max)
75 {
76   struct rlimit64 r;
77   TEST_COMPARE (prlimit64 (0, resource, NULL, &r), 0);
78   TEST_COMPARE (r.rlim_cur, exp_cur);
79   TEST_COMPARE (r.rlim_max, exp_max);
80 }
81 
82 static void
test_setrlimit(int resource,rlim_t new_cur,rlim_t new_max)83 test_setrlimit (int resource, rlim_t new_cur, rlim_t new_max)
84 {
85   struct rlimit r = { new_cur, new_max };
86   TEST_COMPARE (setrlimit (resource, &r), 0);
87 }
88 
89 static void
test_setrlimit64(int resource,rlim64_t new_cur,rlim64_t new_max)90 test_setrlimit64 (int resource, rlim64_t new_cur, rlim64_t new_max)
91 {
92   struct rlimit64 r = { new_cur, new_max };
93   TEST_COMPARE (setrlimit64 (resource, &r), 0);
94 }
95 
96 static void
test_prlimit_set(int resource,rlim_t new_cur,rlim_t new_max)97 test_prlimit_set (int resource, rlim_t new_cur, rlim_t new_max)
98 {
99   struct rlimit r = { new_cur, new_max };
100   TEST_COMPARE (prlimit (0, resource, &r, NULL), 0);
101 }
102 
103 static void
test_prlimit64_set(int resource,rlim64_t new_cur,rlim64_t new_max)104 test_prlimit64_set (int resource, rlim64_t new_cur, rlim64_t new_max)
105 {
106   struct rlimit64 r = { new_cur, new_max };
107   TEST_COMPARE (prlimit64 (0, resource, &r, NULL), 0);
108 }
109 
110 static int
do_test(void)111 do_test (void)
112 {
113   int resource = -1;
114 
115   /* Find a resource with hard limit set to infinity, so that the soft limit
116      can be manipulated to any value.  */
117   for (int i = 0; i < nresources; ++i)
118     {
119       struct rlimit64 r64;
120       int res = prlimit64 (0, resources[i], NULL, &r64);
121       if ((res == 0) && (r64.rlim_max == PRLIMIT64_INFINITY))
122 	{
123 	  resource = resources[i];
124 	  break;
125 	}
126     }
127 
128   if (resource == -1)
129     FAIL_UNSUPPORTED
130       ("Could not find and limit with hard limit set to infinity.");
131 
132   /* First check that the get functions work correctly with the test value.  */
133   test_prlimit64_set (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
134   test_getrlimit (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
135   test_getrlimit64 (resource, PRLIMIT64_TESTVAL, RLIM64_INFINITY);
136   test_prlimit_get (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
137   test_prlimit64_get (resource, PRLIMIT64_TESTVAL, RLIM64_INFINITY);
138 
139   /* Then check that the get functions work correctly with infinity.  */
140   test_prlimit64_set (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
141   test_getrlimit (resource, RLIM_INFINITY, RLIM_INFINITY);
142   test_getrlimit64 (resource, RLIM64_INFINITY, RLIM64_INFINITY);
143   test_prlimit_get (resource, RLIM_INFINITY, RLIM_INFINITY);
144   test_prlimit64_get (resource, RLIM64_INFINITY, RLIM64_INFINITY);
145 
146   /* Then check that setrlimit works correctly with the test value.  */
147   test_setrlimit (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
148   test_prlimit64_get (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
149 
150   /* Then check that setrlimit works correctly with infinity.  */
151   test_setrlimit (resource, RLIM_INFINITY, RLIM_INFINITY);
152   test_prlimit64_get (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
153 
154   /* Then check that setrlimit64 works correctly with the test value.  */
155   test_setrlimit64 (resource, PRLIMIT64_TESTVAL, RLIM64_INFINITY);
156   test_prlimit64_get (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
157 
158   /* Then check that setrlimit64 works correctly with infinity.  */
159   test_setrlimit64 (resource, RLIM64_INFINITY, RLIM64_INFINITY);
160   test_prlimit64_get (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
161 
162   /* Then check that prlimit works correctly with the test value.  */
163   test_prlimit_set (resource, RLIM_INFINITY, RLIM_INFINITY);
164   test_prlimit64_get (resource, PRLIMIT64_INFINITY, PRLIMIT64_INFINITY);
165 
166   /* Finally check that prlimit works correctly with infinity.  */
167   test_prlimit_set (resource, PRLIMIT64_TESTVAL, RLIM_INFINITY);
168   test_prlimit64_get (resource, PRLIMIT64_TESTVAL, PRLIMIT64_INFINITY);
169 
170   return 0;
171 }
172 
173 #include <support/test-driver.c>
174