master
c 701 lines 23.3 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 resourcelimit.c
8
9 Abstract:
10
11 This file contains unit test for set and get resource limits.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <sys/prctl.h>
18 #include <sys/types.h>
19 #include <sys/resource.h>
20 #include <sys/stat.h>
21 #include <sys/wait.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26
27 #if !defined(__amd64__) && !defined(__aarch64__)
28
29 #include <sys/capability.h>
30
31 #else
32
33 #include <sys/cdefs.h>
34 #include <linux/capability.h>
35
36 #define _LINUX_CAPABILITY_VERSION_3 0x20080522
37
38 #ifndef O_PATH
39 #define O_PATH 010000000
40 #endif
41
42 #endif
43
44 #define LXT_NAME "resourcelimits"
45 #define LXT_RESOURCE_LIMIT_TEST_FILE "rlimit_testfile"
46 #define LXT_RESOURCE_LIMIT_UID 1024
47 #define LXT_RESOURCE_LIMIT_GID 1024
48 #define LXT_NOFILE (10)
49 #define LXT_NR_OPEN (1024 * 1024)
50
51 int ResourceLimitTest(PLXT_ARGS Args);
52
53 int ResourceLimitNoFile(PLXT_ARGS Args);
54
55 int PrlimitTest(PLXT_ARGS Args);
56
57 //
58 // Global constants
59 //
60
61 static const LXT_VARIATION g_LxtVariations[] = {
62 {"Resource Limit Test", ResourceLimitTest}, {"RLIMIT_NOFILE", ResourceLimitNoFile}, {"prlimit64 test", PrlimitTest}};
63
64 int ResourceLimitsTestEntry(int Argc, char* Argv[])
65
66 /*++
67 --*/
68
69 {
70
71 LXT_ARGS Args;
72 int Result;
73
74 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
75 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
76
77 ErrorExit:
78 LxtUninitialize();
79 return !LXT_SUCCESS(Result);
80 }
81
82 int ResourceLimitTest(PLXT_ARGS Args)
83
84 /*++
85 --*/
86
87 {
88
89 int Index;
90 struct rlimit ResourceLimit;
91 int Result;
92 int Status;
93
94 //
95 // Get all resource limits.
96 //
97
98 LxtLogInfo("Getting all resource limits:");
99 for (Index = 0; Index < 16; Index += 1)
100 {
101 LxtCheckErrno(getrlimit(Index, &ResourceLimit));
102 LxtLogInfo("Resource# %d: current %llu, max %llu", Index, ResourceLimit.rlim_cur, ResourceLimit.rlim_max)
103 }
104
105 //
106 // Set/Get invalid resources.
107 //
108 LxtCheckErrnoFailure(setrlimit(17, &ResourceLimit), EINVAL);
109 LxtCheckErrnoFailure(getrlimit(17, &ResourceLimit), EINVAL);
110 LxtCheckErrnoFailure(setrlimit(-1, &ResourceLimit), EINVAL);
111 LxtCheckErrnoFailure(getrlimit(-1, &ResourceLimit), EINVAL);
112 LxtCheckErrnoFailure(setrlimit(16, NULL), EINVAL);
113 LxtCheckErrnoFailure(setrlimit(16, (struct rlimit*)-1), EFAULT);
114 LxtCheckErrnoFailure(getrlimit(16, NULL), EINVAL);
115 LxtCheckErrnoFailure(getrlimit(16, (struct rlimit*)-1), EINVAL);
116 LxtCheckErrnoFailure(setrlimit(LXT_NR_OPEN, NULL), EINVAL);
117 LxtCheckErrnoFailure(setrlimit(LXT_NR_OPEN, (struct rlimit*)-1), EFAULT);
118 LxtCheckErrnoFailure(getrlimit(LXT_NR_OPEN, NULL), EINVAL);
119 LxtCheckErrnoFailure(getrlimit(LXT_NR_OPEN, (struct rlimit*)-1), EINVAL);
120
121 //
122 // Set invalid resource limits.
123 //
124
125 ResourceLimit.rlim_cur = 2;
126 ResourceLimit.rlim_max = 1;
127 LxtLogInfo("Setting resource limit with soft limit being greater than hard limit");
128 LxtCheckErrnoFailure(setrlimit(RLIMIT_NPROC, &ResourceLimit), EINVAL);
129
130 //
131 // Set NoFile limit past the WSL max, to NR_OPEN, and past NR_OPEN
132 //
133
134 ResourceLimit.rlim_cur = 2049;
135 ResourceLimit.rlim_max = 2050;
136 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
137
138 ResourceLimit.rlim_cur = LXT_NR_OPEN - 1;
139 ResourceLimit.rlim_max = LXT_NR_OPEN;
140 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
141
142 ResourceLimit.rlim_cur = LXT_NR_OPEN;
143 ResourceLimit.rlim_max = LXT_NR_OPEN;
144 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
145
146 ResourceLimit.rlim_cur = LXT_NR_OPEN + 1;
147 ResourceLimit.rlim_max = LXT_NR_OPEN + 1;
148 LxtCheckErrnoFailure(setrlimit(RLIMIT_NOFILE, &ResourceLimit), EPERM);
149
150 //
151 // Test RLIMIT_NPROC.
152 //
153
154 ResourceLimit.rlim_cur = 7823;
155 ResourceLimit.rlim_max = 7824;
156 LxtCheckErrno(setrlimit(RLIMIT_NPROC, &ResourceLimit));
157
158 ResourceLimit.rlim_cur = 0x7ffffffffffffffe;
159 ResourceLimit.rlim_max = 0x7fffffffffffffff;
160 LxtCheckErrno(setrlimit(RLIMIT_NPROC, &ResourceLimit));
161 LxtCheckErrno(getrlimit(RLIMIT_NPROC, &ResourceLimit));
162 LxtCheckEqual(ResourceLimit.rlim_cur, 0x7ffffffffffffffe, "%Iu");
163 LxtCheckEqual(ResourceLimit.rlim_max, 0x7fffffffffffffff, "%Iu");
164
165 Result = LXT_RESULT_SUCCESS;
166
167 ErrorExit:
168 return Result;
169 }
170
171 int ResourceLimitNoFile(PLXT_ARGS Args)
172
173 {
174
175 int ChildPid;
176 int FileDescriptorCount;
177 int* FileDescriptors;
178 int Index;
179 int InitialFileDescriptorCount;
180 struct rlimit InitialResourceLimit;
181 struct rlimit ResourceLimit;
182 int Result;
183 struct stat Stat;
184
185 ChildPid = -1;
186 FileDescriptors = NULL;
187 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &InitialResourceLimit));
188 LxtLogInfo("Initial rlim_cur %Iu rlim_max %Iu", InitialResourceLimit.rlim_cur, InitialResourceLimit.rlim_max);
189
190 ResourceLimit = InitialResourceLimit;
191
192 //
193 // Lower the current file descriptor limit.
194 //
195
196 ResourceLimit.rlim_cur = LXT_NOFILE;
197 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
198 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
199 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
200
201 //
202 // Determine how many file descriptors are already open.
203 //
204
205 InitialFileDescriptorCount = 0;
206 for (Index = 0; Index < ResourceLimit.rlim_cur; Index += 1)
207 {
208 if (fstat(Index, &Stat) == 0)
209 {
210
211 //
212 // Ensure that the file descriptor number matches the index. This
213 // is strictly to make the validation later in this test more
214 // straightforward.
215 //
216
217 LxtCheckEqual(Index, InitialFileDescriptorCount, "%d");
218 InitialFileDescriptorCount += 1;
219 }
220 }
221
222 //
223 // Determine how many file descriptors are already open and allocate an
224 // array large enough to open the maximum number of file descriptors.
225 //
226
227 LxtLogInfo("%d currently open file descriptors", InitialFileDescriptorCount);
228 FileDescriptorCount = ResourceLimit.rlim_cur - InitialFileDescriptorCount;
229 FileDescriptors = malloc(sizeof(int) * FileDescriptorCount);
230 if (FileDescriptors == NULL)
231 {
232 LxtLogError("alloc failed");
233 Result = LXT_RESULT_FAILURE;
234 goto ErrorExit;
235 }
236
237 memset(FileDescriptors, -1, sizeof(FileDescriptors));
238 LxtCheckErrno(FileDescriptors[0] = creat(LXT_RESOURCE_LIMIT_TEST_FILE, 0655));
239
240 //
241 // Ensure that a file descriptor with a value greater than the current
242 // rlimit cannot be created.
243 //
244
245 LxtCheckErrnoFailure(dup2(FileDescriptors[0], ResourceLimit.rlim_cur), EBADF);
246 LxtCheckErrnoFailure(dup2(FileDescriptors[0], (ResourceLimit.rlim_cur + 1)), EBADF);
247
248 //
249 // Open enough file descriptors to completely fill the table.
250 //
251
252 for (Index = 1; Index < FileDescriptorCount; Index += 1)
253 {
254 LxtCheckErrno(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY));
255 }
256
257 LxtLogInfo("Opened %d file descriptors", Index);
258
259 //
260 // Ensure that opening one more file descriptor fails.
261 //
262
263 LxtCheckErrnoFailure(open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
264
265 //
266 // Lower the limit to the initial file descriptor count and close all but
267 // the highest numbered file descriptor.
268 //
269
270 ResourceLimit.rlim_cur = InitialFileDescriptorCount;
271 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
272 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
273 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
274
275 for (Index = 0; Index < (FileDescriptorCount - 1); Index += 1)
276 {
277 LxtClose(FileDescriptors[Index]);
278 FileDescriptors[Index] = -1;
279 }
280
281 //
282 // Try to open file descriptors up to the max value.
283 //
284
285 for (Index = 0; Index < (FileDescriptorCount - 1); Index += 1)
286 {
287 LxtCheckErrnoFailure(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
288 }
289
290 //
291 // Ensure that a child process inherits the same file descriptor limits.
292 //
293
294 LxtCheckErrno(ChildPid = fork());
295 if (ChildPid == 0)
296 {
297 for (Index = 0; Index < (FileDescriptorCount - 1); Index += 1)
298 {
299 LxtCheckErrnoFailure(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
300 }
301
302 goto ErrorExit;
303 }
304
305 //
306 // Wait for the child to exit.
307 //
308
309 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
310
311 //
312 // Increment the rlimit and open a single file descriptor.
313 //
314
315 ResourceLimit.rlim_cur += 1;
316 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
317 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
318 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
319
320 LxtCheckErrno(FileDescriptors[0] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY));
321 LxtCheckEqual(InitialFileDescriptorCount, FileDescriptors[0], "%d");
322
323 //
324 // Reset the rlimit to the original value.
325 //
326
327 ResourceLimit.rlim_cur = LXT_NOFILE;
328 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
329 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
330 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
331
332 //
333 // Attempt to reopen the rest of the file descriptors now that the limit has
334 // been increased.
335 //
336
337 for (Index = 1; Index < (FileDescriptorCount - 1); Index += 1)
338 {
339 LxtCheckErrno(FileDescriptors[Index] = open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY));
340 LxtCheckEqual((Index + InitialFileDescriptorCount), FileDescriptors[Index], "%d");
341 }
342
343 //
344 // Attempt to open one more file descriptor (should fail).
345 //
346
347 LxtCheckErrnoFailure(open(LXT_RESOURCE_LIMIT_TEST_FILE, O_RDONLY), EMFILE);
348
349 //
350 // Set the current resource limit to the max.
351 //
352
353 ResourceLimit.rlim_cur = ResourceLimit.rlim_max;
354 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
355 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
356 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
357
358 //
359 // Make the file descriptor limit very large.
360 //
361
362 ResourceLimit.rlim_max = 0x100000;
363 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
364 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
365 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
366
367 ResourceLimit.rlim_cur = ResourceLimit.rlim_max;
368 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &ResourceLimit));
369 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
370 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
371
372 //
373 // Attempt to set the file descriptor limit larger than the maximum allowed.
374 //
375
376 ResourceLimit.rlim_cur = ResourceLimit.rlim_max;
377 ResourceLimit.rlim_max += 1;
378 LxtCheckErrnoFailure(setrlimit(RLIMIT_NOFILE, &ResourceLimit), EPERM);
379 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
380 LxtLogInfo("rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
381
382 //
383 // Restore the original rlimit.
384 //
385
386 LxtCheckErrno(setrlimit(RLIMIT_NOFILE, &InitialResourceLimit));
387 LxtCheckErrno(getrlimit(RLIMIT_NOFILE, &ResourceLimit));
388 LxtLogInfo("Restored rlim_cur %Iu rlim_max %Iu", ResourceLimit.rlim_cur, ResourceLimit.rlim_max);
389
390 Result = LXT_RESULT_SUCCESS;
391
392 ErrorExit:
393 if (FileDescriptors != NULL)
394 {
395 for (Index = 0; Index < FileDescriptorCount; Index += 1)
396 {
397 if (FileDescriptors[Index] >= 0)
398 {
399 LxtClose(FileDescriptors[Index]);
400 }
401 }
402
403 free(FileDescriptors);
404 }
405
406 if (ChildPid == 0)
407 {
408 _exit(Result);
409 }
410 else
411 {
412 unlink(LXT_RESOURCE_LIMIT_TEST_FILE);
413 }
414 }
415
416 int PrlimitTest(PLXT_ARGS Args)
417
418 {
419
420 struct __user_cap_data_struct CapData[2];
421 struct __user_cap_header_struct CapHeader;
422 int ChildPid;
423 int CurrentPid;
424 int Index;
425 struct rlimit NewLimit;
426 struct rlimit OldLimit;
427 int ParentPid;
428 int Result;
429 int Status;
430
431 ChildPid = -1;
432 ParentPid = getpid();
433
434 //
435 // Get and set all resource limits.
436 //
437
438 for (Index = 0; Index < 16; Index += 1)
439 {
440 LxtCheckErrno(LxtPrlimit64(0, Index, NULL, &NewLimit));
441 LxtCheckErrno(LxtPrlimit64(0, Index, &NewLimit, &OldLimit));
442 LxtCheckEqual(OldLimit.rlim_max, NewLimit.rlim_max, "%Iu");
443 LxtCheckEqual(OldLimit.rlim_cur, NewLimit.rlim_cur, "%Iu");
444 LxtCheckErrno(LxtPrlimit64(ParentPid, Index, &NewLimit, &OldLimit));
445 }
446
447 //
448 // Pid != 0 variations.
449 //
450
451 LxtCheckErrno(ChildPid = fork());
452 if (ChildPid == 0)
453 {
454 CurrentPid = getpid();
455 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
456 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
457 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
458 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
459 goto ErrorExit;
460 }
461
462 //
463 // Wait for the child to exit.
464 //
465
466 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
467
468 //
469 // UID variations.
470 //
471
472 LxtCheckErrno(ChildPid = fork());
473 if (ChildPid == 0)
474 {
475 memset(&CapData, 0, sizeof(CapData));
476 memset(&CapHeader, 0, sizeof(CapHeader));
477 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
478 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
479 CapData[0].effective = CapData[0].permitted;
480 CapData[1].effective = CapData[1].permitted;
481 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
482 LxtCheckErrno(LxtSetresuid(-1, -1, LXT_RESOURCE_LIMIT_UID));
483 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
484 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
485 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
486
487 LxtCheckErrno(LxtSetresuid(-1, LXT_RESOURCE_LIMIT_UID, -1));
488 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
489 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
490
491 LxtCheckErrno(LxtSetresuid(LXT_RESOURCE_LIMIT_UID, -1, -1));
492 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
493 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
494
495 CurrentPid = getpid();
496 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
497 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
498 goto ErrorExit;
499 }
500
501 //
502 // Wait for the child to exit.
503 //
504
505 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
506
507 LxtCheckErrno(ChildPid = fork());
508 if (ChildPid == 0)
509 {
510
511 //
512 // Change the UID and verify that querying the parent's resource limits
513 // succeeds with the CAP_SYS_RESOURCE capability.
514 //
515
516 memset(&CapData, 0, sizeof(CapData));
517 memset(&CapHeader, 0, sizeof(CapHeader));
518 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
519 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
520 CapData[CAP_TO_INDEX(CAP_SYS_RESOURCE)].permitted |= CAP_TO_MASK(CAP_SYS_RESOURCE);
521 CapData[0].effective = CapData[0].permitted;
522 CapData[1].effective = CapData[1].permitted;
523 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
524 LxtCheckErrno(LxtSetresuid(LXT_RESOURCE_LIMIT_UID, LXT_RESOURCE_LIMIT_UID, LXT_RESOURCE_LIMIT_UID));
525 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
526 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
527 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
528
529 //
530 // Drop the CAP_SYS_RESOURCE capability and verify querying the parents
531 // resource limits fails.
532 //
533
534 memset(&CapData, 0, sizeof(CapData));
535 memset(&CapHeader, 0, sizeof(CapHeader));
536 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
537 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
538 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
539 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
540
541 CurrentPid = getpid();
542 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
543 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
544 goto ErrorExit;
545 }
546
547 //
548 // Wait for the child to exit.
549 //
550
551 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
552
553 LxtCheckErrno(ChildPid = fork());
554 if (ChildPid == 0)
555 {
556 goto ErrorExit;
557 }
558
559 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
560
561 //
562 // GID variations.
563 //
564
565 LxtCheckErrno(ChildPid = fork());
566 if (ChildPid == 0)
567 {
568 memset(&CapData, 0, sizeof(CapData));
569 memset(&CapHeader, 0, sizeof(CapHeader));
570 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
571 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
572 CapData[0].effective = CapData[0].permitted;
573 CapData[1].effective = CapData[1].permitted;
574 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
575 LxtCheckErrno(LxtSetresgid(-1, -1, LXT_RESOURCE_LIMIT_GID));
576 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
577 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
578 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
579
580 LxtCheckErrno(LxtSetresgid(-1, LXT_RESOURCE_LIMIT_GID, -1));
581 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
582 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
583
584 LxtCheckErrno(LxtSetresgid(LXT_RESOURCE_LIMIT_GID, -1, -1));
585 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
586 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
587
588 CurrentPid = getpid();
589 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
590 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
591 goto ErrorExit;
592 }
593
594 //
595 // Wait for the child to exit.
596 //
597
598 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
599
600 LxtCheckErrno(ChildPid = fork());
601 if (ChildPid == 0)
602 {
603
604 //
605 // Change the GID and verify that querying the parent's resource limits
606 // succeeds with the CAP_SYS_RESOURCE capability.
607 //
608
609 memset(&CapData, 0, sizeof(CapData));
610 memset(&CapHeader, 0, sizeof(CapHeader));
611 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
612 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
613 CapData[CAP_TO_INDEX(CAP_SYS_RESOURCE)].permitted |= CAP_TO_MASK(CAP_SYS_RESOURCE);
614 CapData[0].effective = CapData[0].permitted;
615 CapData[1].effective = CapData[1].permitted;
616 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
617 LxtCheckErrno(LxtSetresgid(LXT_RESOURCE_LIMIT_GID, LXT_RESOURCE_LIMIT_GID, LXT_RESOURCE_LIMIT_GID));
618 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
619 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit));
620 LxtCheckErrno(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
621
622 //
623 // Drop the CAP_SYS_RESOURCE capability and verify querying the parents
624 // resource limits fails.
625 //
626
627 memset(&CapData, 0, sizeof(CapData));
628 memset(&CapHeader, 0, sizeof(CapHeader));
629 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
630 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
631 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, NULL, &NewLimit), EPERM);
632 LxtCheckErrnoFailure(LxtPrlimit64(ParentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit), EPERM);
633
634 CurrentPid = getpid();
635 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, NULL, &NewLimit));
636 LxtCheckErrno(LxtPrlimit64(CurrentPid, RLIMIT_NOFILE, &NewLimit, &OldLimit));
637 goto ErrorExit;
638 }
639
640 //
641 // Wait for the child to exit.
642 //
643
644 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
645
646 //
647 // The new limit should still be set even if old limit buffer is invalid.
648 //
649
650 LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NOFILE, NULL, &OldLimit));
651 NewLimit = OldLimit;
652 NewLimit.rlim_cur -= 1;
653 LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NOFILE, &NewLimit, -1), EFAULT);
654 LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NOFILE, NULL, &NewLimit));
655 LxtCheckNotEqual(OldLimit.rlim_cur, NewLimit.rlim_cur, "%Iu");
656
657 //
658 // Verify that if the new limit is invalid, the old limit is not returned.
659 //
660
661 LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NOFILE, NULL, &OldLimit));
662 NewLimit = OldLimit;
663 NewLimit.rlim_cur = NewLimit.rlim_max + 1;
664 memset(&OldLimit, 0, sizeof(OldLimit));
665 LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NOFILE, &NewLimit, &OldLimit), EINVAL);
666 LxtCheckEqual(OldLimit.rlim_max, 0, "%Iu");
667 LxtCheckEqual(OldLimit.rlim_cur, 0, "%Iu");
668 LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NOFILE, -1, &OldLimit), EFAULT);
669 LxtCheckEqual(OldLimit.rlim_max, 0, "%Iu");
670 LxtCheckEqual(OldLimit.rlim_cur, 0, "%Iu");
671
672 //
673 // Negative variations.
674 //
675
676 LxtCheckErrno(LxtPrlimit64(0, RLIMIT_NPROC, NULL, NULL));
677 LxtCheckErrnoFailure(LxtPrlimit64(0, 16, NULL, NULL), EINVAL);
678 LxtCheckErrnoFailure(LxtPrlimit64(-1, 16, NULL, NULL), ESRCH);
679 LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, NULL, NULL), ESRCH);
680 LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, NULL), EFAULT);
681 LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, NULL, -1), ESRCH);
682 LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, -1), EFAULT);
683 LxtCheckErrnoFailure(LxtPrlimit64(0, 16, NULL, &OldLimit), EINVAL);
684 LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NPROC, -1, NULL), EFAULT);
685 LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NPROC, NULL, -1), EFAULT);
686 LxtCheckErrnoFailure(LxtPrlimit64(0, RLIMIT_NPROC, -1, -1), EFAULT);
687 LxtCheckErrnoFailure(LxtPrlimit64(0, 16, -1, -1), EFAULT);
688 LxtCheckErrnoFailure(LxtPrlimit64(-1, 16, NULL, &OldLimit), ESRCH);
689 LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, NULL), EFAULT);
690 LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, NULL, -1), ESRCH);
691 LxtCheckErrnoFailure(LxtPrlimit64(-1, RLIMIT_NPROC, -1, -1), EFAULT);
692 LxtCheckErrnoFailure(LxtPrlimit64(-1, 16, -1, -1), EFAULT);
693
694 ErrorExit:
695 if (ChildPid == 0)
696 {
697 _exit(Result);
698 }
699
700 return Result;
701 }