master
c 2,625 lines 84.5 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 shm.c
8
9 Abstract:
10
11 This file is a test for the system V shared memory family of system calls.
12
13 --*/
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/xattr.h>
22 #include <sys/mman.h>
23 #include <fcntl.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/ipc.h>
27 #include <sys/shm.h>
28 #include <sys/prctl.h>
29 #include <sys/wait.h>
30 #include <grp.h>
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #include <time.h>
34 #include <linux/random.h>
35
36 #if !defined(__amd64__) && !defined(__aarch64__)
37
38 #include <sys/capability.h>
39
40 #else
41
42 #include <sys/cdefs.h>
43 #include <linux/capability.h>
44
45 #define _LINUX_CAPABILITY_VERSION_3 0x20080522
46
47 #ifndef O_PATH
48 #define O_PATH 010000000
49 #endif
50
51 #endif
52
53 #include "lxtcommon.h"
54 #include "unittests.h"
55
56 #define LXT_NAME "shm"
57
58 #define SHM_ACCESS_UID 1004
59 #define SHM_ACCESS_GID 1004
60
61 //
62 // Globals.
63 //
64
65 bool g_RunningOnNative = false;
66 bool g_VerboseShm = false;
67
68 int ShmAtAccess(PLXT_ARGS Args);
69
70 int ShmAtDtSyscall(PLXT_ARGS Args);
71
72 int ShmCtlSyscall(PLXT_ARGS Args);
73
74 int ShmGetAccess(PLXT_ARGS Args);
75
76 int ShmGetSyscall(PLXT_ARGS Args);
77
78 int ShmPidNamespace(PLXT_ARGS Args);
79
80 void ShmPrintInfo(struct shmid_ds* Stat);
81
82 void ShmPrintInfoAttach(struct shmid_ds* Stat);
83
84 static const LXT_VARIATION g_LxtVariations[] = {
85 {"shmget syscall", ShmGetSyscall},
86 {"shmget access", ShmGetAccess},
87 {"shmctl syscall", ShmCtlSyscall},
88 {"shmat / shmdt syscalls", ShmAtDtSyscall},
89 {"shmat access", ShmAtAccess},
90 {"shm pid namespace", ShmPidNamespace}};
91
92 int ShmTestEntry(int Argc, char* Argv[])
93 {
94
95 LXT_ARGS Args;
96 int Result;
97
98 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
99 LXT_SYNCHRONIZATION_POINT_INIT();
100 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
101
102 ErrorExit:
103 LxtUninitialize();
104 return 0;
105 }
106
107 int ShmAtAccess(PLXT_ARGS Args)
108
109 {
110
111 unsigned char* Address;
112 struct __user_cap_data_struct CapData[2];
113 struct __user_cap_header_struct CapHeader;
114 int ChildPid;
115 int Id;
116 void* MapResult;
117 int Result;
118
119 Address = NULL;
120 ChildPid = -1;
121 Id = -1;
122
123 //
124 // Create a shared memory region that should be unmappable by a process
125 // without the CAP_IPC_OWNER capability.
126 //
127
128 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0));
129 LxtCheckErrno(ChildPid = fork());
130 if (ChildPid == 0)
131 {
132 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
133 LxtCheckErrno(setgid(SHM_ACCESS_GID));
134 LxtCheckErrno(setuid(SHM_ACCESS_UID));
135 memset(&CapData, 0, sizeof(CapData));
136 memset(&CapHeader, 0, sizeof(CapHeader));
137 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
138 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
139 CapData[0].effective = CapData[0].permitted;
140 CapData[1].effective = CapData[1].permitted;
141 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
142 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
143 LxtCheckErrno(LxtShmDt(Address));
144 Address = NULL;
145
146 //
147 // Drop the CAP_IPC_OWNER capability and attempt to map again (should fail).
148 //
149
150 memset(&CapData, 0, sizeof(CapData));
151 memset(&CapHeader, 0, sizeof(CapHeader));
152 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
153 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
154 Address = LxtShmAt(Id, NULL, 0);
155 if (Address != MAP_FAILED)
156 {
157 Result = LXT_RESULT_FAILURE;
158 LxtLogError("Unexpectedly able to shmat");
159 goto ErrorExit;
160 }
161
162 goto ErrorExit;
163 }
164
165 //
166 // Wait for the child to exit.
167 //
168
169 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
170 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
171 Id = -1;
172
173 //
174 // Create a read only memory region and verify that it is only mappable as
175 // read only by the owner.
176 //
177
178 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0400));
179 LxtCheckErrno(ChildPid = fork());
180 if (ChildPid == 0)
181 {
182 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
183 memset(&CapData, 0, sizeof(CapData));
184 memset(&CapHeader, 0, sizeof(CapHeader));
185 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
186 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
187 CapData[0].effective = CapData[0].permitted;
188 CapData[1].effective = CapData[1].permitted;
189 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
190 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
191 LxtCheckErrno(LxtShmDt(Address));
192 Address = NULL;
193
194 //
195 // Drop the CAP_IPC_OWNER capability and attempt to with the readonly
196 // flag.
197 //
198
199 memset(&CapData, 0, sizeof(CapData));
200 memset(&CapHeader, 0, sizeof(CapHeader));
201 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
202 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
203 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_RDONLY));
204 LxtCheckErrno(LxtShmDt(Address));
205 Address = NULL;
206
207 //
208 // Attempt to map as read / write (should fail).
209 //
210
211 Address = LxtShmAt(Id, NULL, 0);
212 if (Address != MAP_FAILED)
213 {
214 Result = LXT_RESULT_FAILURE;
215 LxtLogError("Unexpectedly able to shmat");
216 goto ErrorExit;
217 }
218
219 //
220 // Attempt to map as execute (should fail).
221 //
222
223 Address = LxtShmAt(Id, NULL, SHM_EXEC);
224 if (Address != MAP_FAILED)
225 {
226 Result = LXT_RESULT_FAILURE;
227 LxtLogError("Unexpectedly able to shmat");
228 goto ErrorExit;
229 }
230
231 Id = -1;
232 goto ErrorExit;
233 }
234
235 //
236 // Wait for the child to exit.
237 //
238
239 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
240 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
241 Id = -1;
242
243 //
244 // Create a group read only memory region and verify that it is only
245 // mappable by members of the same group.
246 //
247
248 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0040));
249 LxtCheckErrno(ChildPid = fork());
250 if (ChildPid == 0)
251 {
252 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
253 LxtCheckErrno(setuid(SHM_ACCESS_UID));
254 memset(&CapData, 0, sizeof(CapData));
255 memset(&CapHeader, 0, sizeof(CapHeader));
256 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
257 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
258 CapData[0].effective = CapData[0].permitted;
259 CapData[1].effective = CapData[1].permitted;
260 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
261 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
262 LxtCheckErrno(LxtShmDt(Address));
263 Address = NULL;
264
265 //
266 // Drop the CAP_IPC_OWNER capability and attempt to with the readonly
267 // flag.
268 //
269
270 memset(&CapData, 0, sizeof(CapData));
271 memset(&CapHeader, 0, sizeof(CapHeader));
272 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
273 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
274 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_RDONLY));
275 LxtCheckErrno(LxtShmDt(Address));
276 Address = NULL;
277
278 //
279 // Attempt to map as read / write (should fail).
280 //
281
282 Address = LxtShmAt(Id, NULL, 0);
283 if (Address != MAP_FAILED)
284 {
285 Result = LXT_RESULT_FAILURE;
286 LxtLogError("Unexpectedly able to shmat");
287 goto ErrorExit;
288 }
289
290 //
291 // Attempt to map as execute (should fail).
292 //
293
294 Address = LxtShmAt(Id, NULL, SHM_EXEC);
295 if (Address != MAP_FAILED)
296 {
297 Result = LXT_RESULT_FAILURE;
298 LxtLogError("Unexpectedly able to shmat");
299 goto ErrorExit;
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 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
311 Id = -1;
312
313 //
314 // Create another read only memory region and verify that it is
315 // mappable.
316 //
317
318 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0004));
319 LxtCheckErrno(ChildPid = fork());
320 if (ChildPid == 0)
321 {
322 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
323 LxtCheckErrno(setgid(SHM_ACCESS_GID));
324 LxtCheckErrno(setuid(SHM_ACCESS_UID));
325 memset(&CapData, 0, sizeof(CapData));
326 memset(&CapHeader, 0, sizeof(CapHeader));
327 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
328 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
329 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
330 CapData[0].effective = CapData[0].permitted;
331 CapData[1].effective = CapData[1].permitted;
332 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
333 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
334 LxtCheckErrno(LxtShmDt(Address));
335 Address = NULL;
336
337 //
338 // Remove all group membership, drop the CAP_IPC_OWNER capability, and
339 // attempt to with the readonly flag.
340 //
341
342 LxtCheckErrno(Result = setgroups(0, NULL));
343 memset(&CapData, 0, sizeof(CapData));
344 memset(&CapHeader, 0, sizeof(CapHeader));
345 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
346 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
347 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_RDONLY));
348 LxtCheckErrno(LxtShmDt(Address));
349 Address = NULL;
350
351 //
352 // Attempt to map as read / write (should fail).
353 //
354
355 Address = LxtShmAt(Id, NULL, 0);
356 if (Address != MAP_FAILED)
357 {
358 Result = LXT_RESULT_FAILURE;
359 LxtLogError("Unexpectedly able to shmat");
360 goto ErrorExit;
361 }
362
363 //
364 // Attempt to map as execute (should fail).
365 //
366
367 Address = LxtShmAt(Id, NULL, SHM_EXEC);
368 if (Address != MAP_FAILED)
369 {
370 Result = LXT_RESULT_FAILURE;
371 LxtLogError("Unexpectedly able to shmat");
372 goto ErrorExit;
373 }
374
375 goto ErrorExit;
376 }
377
378 //
379 // Wait for the child to exit.
380 //
381
382 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
383 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
384 Id = -1;
385
386 //
387 // Create a shared memory region that is write only This should be
388 // unmappable by processes without the CAP_IPC_OWNER capability.
389 //
390
391 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0222));
392 LxtCheckErrno(ChildPid = fork());
393 if (ChildPid == 0)
394 {
395 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
396 memset(&CapData, 0, sizeof(CapData));
397 memset(&CapHeader, 0, sizeof(CapHeader));
398 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
399 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
400 CapData[0].effective = CapData[0].permitted;
401 CapData[1].effective = CapData[1].permitted;
402 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
403 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
404 LxtCheckErrno(LxtShmDt(Address));
405 Address = NULL;
406
407 //
408 // Drop the CAP_IPC_OWNER capability and attempt to map again (should fail).
409 //
410
411 memset(&CapData, 0, sizeof(CapData));
412 memset(&CapHeader, 0, sizeof(CapHeader));
413 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
414 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
415 Address = LxtShmAt(Id, NULL, SHM_RDONLY);
416 if (Address != MAP_FAILED)
417 {
418 Result = LXT_RESULT_FAILURE;
419 LxtLogError("Unexpectedly able to shmat");
420 goto ErrorExit;
421 }
422
423 Address = LxtShmAt(Id, NULL, 0);
424 if (Address != MAP_FAILED)
425 {
426 Result = LXT_RESULT_FAILURE;
427 LxtLogError("Unexpectedly able to shmat");
428 goto ErrorExit;
429 }
430
431 //
432 // Attempt to map as execute (should fail).
433 //
434
435 Address = LxtShmAt(Id, NULL, SHM_EXEC);
436 if (Address != MAP_FAILED)
437 {
438 Result = LXT_RESULT_FAILURE;
439 LxtLogError("Unexpectedly able to shmat");
440 goto ErrorExit;
441 }
442
443 goto ErrorExit;
444 }
445
446 //
447 // Wait for the child to exit.
448 //
449
450 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
451 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
452 Id = -1;
453
454 //
455 // Create a shared memory region that can only be read or written by the
456 // owner.
457 //
458
459 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0700));
460 LxtCheckErrno(ChildPid = fork());
461 if (ChildPid == 0)
462 {
463
464 //
465 // Drop the CAP_IPC_OWNER capability and attempt to map (should fail).
466 //
467
468 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
469 LxtCheckErrno(setgid(SHM_ACCESS_GID));
470 memset(&CapData, 0, sizeof(CapData));
471 memset(&CapHeader, 0, sizeof(CapHeader));
472 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
473 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
474 CapData[0].effective = CapData[0].permitted;
475 CapData[1].effective = CapData[1].permitted;
476 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
477 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
478 LxtCheckErrno(LxtShmDt(Address));
479 Address = NULL;
480
481 //
482 // Change the UID and verify the mapping fails.
483 //
484
485 LxtCheckErrno(setuid(SHM_ACCESS_UID));
486 Address = LxtShmAt(Id, NULL, SHM_RDONLY);
487 if (Address != MAP_FAILED)
488 {
489 Result = LXT_RESULT_FAILURE;
490 LxtLogError("Unexpectedly able to shmat");
491 goto ErrorExit;
492 }
493
494 Address = LxtShmAt(Id, NULL, 0);
495 if (Address != MAP_FAILED)
496 {
497 Result = LXT_RESULT_FAILURE;
498 LxtLogError("Unexpectedly able to shmat");
499 goto ErrorExit;
500 }
501
502 goto ErrorExit;
503 }
504
505 //
506 // Wait for the child to exit.
507 //
508
509 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
510 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
511 Id = -1;
512
513 //
514 // Create a shared memory region that is only mappable by other.
515 //
516
517 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0007));
518 LxtCheckErrno(ChildPid = fork());
519 if (ChildPid == 0)
520 {
521
522 //
523 // Verify the region is mappable with CAP_IPC_OWNER.
524 //
525
526 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
527 memset(&CapData, 0, sizeof(CapData));
528 memset(&CapHeader, 0, sizeof(CapHeader));
529 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
530 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
531 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
532 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
533 CapData[0].effective = CapData[0].permitted;
534 CapData[1].effective = CapData[1].permitted;
535 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
536 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
537 LxtCheckErrno(LxtShmDt(Address));
538 Address = NULL;
539
540 //
541 // Drop the CAP_IPC_OWNER capability and attempt to map again this
542 // should fail because the caller is still has a matching UID.
543 //
544
545 memset(&CapData, 0, sizeof(CapData));
546 memset(&CapHeader, 0, sizeof(CapHeader));
547 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
548 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
549 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
550 CapData[0].effective = CapData[0].permitted;
551 CapData[1].effective = CapData[1].permitted;
552 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
553 Address = LxtShmAt(Id, NULL, SHM_RDONLY);
554 if (Address != MAP_FAILED)
555 {
556 Result = LXT_RESULT_FAILURE;
557 LxtLogError("Unexpectedly able to shmat");
558 goto ErrorExit;
559 }
560
561 //
562 // Change the UID and attempt to map, this should still fail because
563 // the caller has group ownership.
564 //
565
566 LxtCheckErrno(setuid(SHM_ACCESS_UID));
567 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
568 Address = LxtShmAt(Id, NULL, SHM_RDONLY);
569 if (Address != MAP_FAILED)
570 {
571 Result = LXT_RESULT_FAILURE;
572 LxtLogError("Unexpectedly able to shmat");
573 goto ErrorExit;
574 }
575
576 //
577 // Change the caller GID and attempt to map, this should still fail
578 // because the caller has a supplementary group membership.
579 //
580
581 LxtCheckErrno(setgid(SHM_ACCESS_GID));
582 Address = LxtShmAt(Id, NULL, SHM_RDONLY);
583 if (Address != MAP_FAILED)
584 {
585 Result = LXT_RESULT_FAILURE;
586 LxtLogError("Unexpectedly able to shmat");
587 goto ErrorExit;
588 }
589
590 //
591 // Drop supplementary group membership, finally this should succeed.
592 //
593
594 LxtCheckErrno(Result = setgroups(0, NULL));
595 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
596 LxtCheckErrno(LxtShmDt(Address));
597 Address = NULL;
598 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_RDONLY));
599 LxtCheckErrno(LxtShmDt(Address));
600 Address = NULL;
601 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_EXEC));
602 LxtCheckErrno(LxtShmDt(Address));
603 Address = NULL;
604 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_RDONLY | SHM_EXEC));
605 LxtCheckErrno(LxtShmDt(Address));
606 Address = NULL;
607 goto ErrorExit;
608 }
609
610 //
611 // Create a shared memory region that is only mappable as read / execute.
612 //
613
614 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0555));
615 LxtCheckErrno(ChildPid = fork());
616 if (ChildPid == 0)
617 {
618
619 //
620 // Drop the CAP_IPC_OWNER capability and try to map read / write and
621 // read / write / execute (should fail).
622 //
623
624 memset(&CapData, 0, sizeof(CapData));
625 memset(&CapHeader, 0, sizeof(CapHeader));
626 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
627 CapData[0].effective = CapData[0].permitted;
628 CapData[1].effective = CapData[1].permitted;
629 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
630 Address = LxtShmAt(Id, NULL, 0);
631 if (Address != MAP_FAILED)
632 {
633 Result = LXT_RESULT_FAILURE;
634 LxtLogError("Unexpectedly able to shmat");
635 goto ErrorExit;
636 }
637
638 Address = LxtShmAt(Id, NULL, SHM_EXEC);
639 if (Address != MAP_FAILED)
640 {
641 Result = LXT_RESULT_FAILURE;
642 LxtLogError("Unexpectedly able to shmat");
643 goto ErrorExit;
644 }
645
646 //
647 // Map the region as readonly, read / execute.
648 //
649
650 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_RDONLY));
651 LxtCheckErrno(LxtShmDt(Address));
652 Address = NULL;
653 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, SHM_RDONLY | SHM_EXEC));
654 LxtCheckErrno(LxtShmDt(Address));
655 Address = NULL;
656 goto ErrorExit;
657 }
658
659 //
660 // Wait for the child to exit.
661 //
662
663 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
664 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
665 Id = -1;
666
667 ErrorExit:
668 if (Address != NULL)
669 {
670 LxtShmDt(Address);
671 }
672
673 if (ChildPid == 0)
674 {
675 _exit(Result);
676 }
677
678 //
679 // N.B. The identifier should not be removed by any child processes.
680 //
681
682 if (Id != -1)
683 {
684 LxtShmCtl(Id, IPC_RMID, NULL);
685 }
686
687 return Result;
688 }
689
690 int ShmAtDtSyscall(PLXT_ARGS Args)
691
692 {
693
694 unsigned char* Address;
695 unsigned char* Address2;
696 int ChildPid;
697 int Id;
698 key_t Key;
699 void* MapResult;
700 struct shmid_ds ParentStat;
701 unsigned char* RemappedMemory;
702 size_t Result;
703 struct shmid_ds Stat;
704
705 Address = NULL;
706 Address2 = NULL;
707 ChildPid = -1;
708 Id = -1;
709
710 //
711 // (1) Create a shared memory region.
712 //
713
714 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE * 3, 0));
715 LxtLogInfo("Id = %d", Id);
716 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &ParentStat));
717 LxtCheckEqual(PAGE_SIZE * 3, ParentStat.shm_segsz, "%Iu");
718 LxtCheckEqual(0, ParentStat.shm_atime, "%Iu");
719 LxtCheckEqual(0, ParentStat.shm_dtime, "%Iu");
720 LxtCheckNotEqual(0, ParentStat.shm_ctime, "%Iu");
721 LxtCheckEqual(ParentStat.shm_nattch, 0, "%Iu");
722
723 //
724 // Map the shared memory region.
725 //
726
727 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
728 LxtLogInfo("Address = %p", Address);
729 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &ParentStat));
730 ShmPrintInfoAttach(&ParentStat);
731 LxtCheckNotEqual(0, ParentStat.shm_atime, "%Iu");
732 LxtCheckEqual(0, ParentStat.shm_dtime, "%Iu");
733 LxtCheckEqual(ParentStat.shm_nattch, 1, "%Iu");
734 LxtCheckEqual(getpid(), ParentStat.shm_lpid, "%Iu");
735
736 //
737 // Sleep for 2 seconds then fork and verify that attach statics are
738 // updated correctly. The attach count and attach time should be updated
739 // but the last attach pid should not change.
740 //
741
742 sleep(2);
743 LxtCheckErrno(ChildPid = fork());
744 if (ChildPid == 0)
745 {
746 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
747 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
748 LxtCheckEqual(ParentStat.shm_lpid, Stat.shm_lpid, "%Iu");
749 LxtCheckNotEqual(ParentStat.shm_atime, Stat.shm_atime, "%Iu");
750 goto ErrorExit;
751 }
752
753 //
754 // Wait for the child to exit.
755 //
756
757 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
758 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
759 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
760 LxtCheckNotEqual(0, Stat.shm_dtime, "%Iu");
761
762 //
763 // Attempt to map the region in an area that already is mapped.
764 //
765
766 Address2 = LxtShmAt(Id, Address, 0);
767 if (Address2 != MAP_FAILED)
768 {
769 Result = LXT_RESULT_FAILURE;
770 LxtLogError("shmat on a used region should fail without SHM_REMAP flag %p %d", Address2, errno);
771
772 goto ErrorExit;
773 }
774
775 Address2 = LxtShmAt(Id, Address + PAGE_SIZE, 0);
776 if (Address2 != MAP_FAILED)
777 {
778 Result = LXT_RESULT_FAILURE;
779 LxtLogError("shmat on a used region should fail without SHM_REMAP flag %p %d", Address2, errno);
780
781 goto ErrorExit;
782 }
783
784 Address2 = LxtShmAt(Id, Address + (PAGE_SIZE * 2), 0);
785 if (Address2 != MAP_FAILED)
786 {
787 Result = LXT_RESULT_FAILURE;
788 LxtLogError("shmat on a used region should fail without SHM_REMAP flag %p %d", Address2, errno);
789
790 goto ErrorExit;
791 }
792
793 if (g_RunningOnNative == false)
794 {
795 LxtLogInfo("WARNING: these variations are expected to fail on native Ubuntu");
796 Address2 = LxtShmAt(Id, Address, SHM_REMAP);
797 if (Address2 != MAP_FAILED)
798 {
799 Result = LXT_RESULT_FAILURE;
800 LxtLogError("shmat with SHM_REMAP replacing entire region");
801 goto ErrorExit;
802 }
803
804 Address2 = LxtShmAt(Id, Address + PAGE_SIZE, SHM_REMAP);
805 if (Address2 != MAP_FAILED)
806 {
807 Result = LXT_RESULT_FAILURE;
808 LxtLogError("shmat with SHM_REMAP replacing last two pages.");
809 goto ErrorExit;
810 }
811
812 //
813 // Unmap the first page in the range.
814 //
815
816 LxtCheckErrnoFailure(munmap(Address, PAGE_SIZE), EINVAL);
817
818 //
819 // Unmap the middle page of the three-page range.
820 //
821
822 LxtCheckErrnoFailure(munmap(Address + PAGE_SIZE, PAGE_SIZE), EINVAL);
823
824 //
825 // Unmap the last page in the range.
826 //
827
828 LxtCheckErrnoFailure(munmap(Address + (2 * PAGE_SIZE), PAGE_SIZE), EINVAL);
829
830 //
831 // Use the remap system call to resize the region.
832 //
833
834 RemappedMemory = LxtMremap(Address, PAGE_SIZE * 3, PAGE_SIZE * 4, MREMAP_MAYMOVE, NULL);
835
836 if (RemappedMemory != MAP_FAILED)
837 {
838 Result = LXT_RESULT_FAILURE;
839 LxtLogError("mremap moving the region.");
840 goto ErrorExit;
841 }
842
843 goto ErrorExit;
844 }
845
846 //
847 // Use the SHM_REMAP flag to replace the entire region.
848 //
849
850 LxtCheckMapErrno(Address2 = LxtShmAt(Id, Address, SHM_REMAP));
851 LxtCheckEqual(Address, Address2, "%p");
852 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
853 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
854 LxtCheckErrno(LxtShmDt(Address));
855 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
856 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
857 LxtCheckErrnoFailure(LxtShmDt(Address), EINVAL);
858
859 //
860 // Use the SHM_REMAP flag to replace the last two pages of the original
861 // region.
862 //
863
864 LxtCheckMapErrno(Address = LxtShmAt(Id, Address, 0));
865 LxtCheckMapErrno(Address2 = LxtShmAt(Id, Address + PAGE_SIZE, SHM_REMAP));
866 LxtCheckEqual(Address + PAGE_SIZE, Address2, "%p");
867 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
868 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
869 LxtCheckErrno(LxtShmDt(Address));
870 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
871 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
872 LxtCheckErrno(LxtShmDt(Address2));
873 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
874 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
875 LxtCheckErrnoFailure(LxtShmDt(Address), EINVAL);
876 LxtCheckErrnoFailure(LxtShmDt(Address2), EINVAL);
877 Address = NULL;
878 Address2 = NULL;
879
880 //
881 // Unmap the middle page of the three-page range to split the region,
882 // this should increment the attach count.
883 //
884
885 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
886 LxtCheckErrno(munmap(Address + PAGE_SIZE, PAGE_SIZE));
887 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
888 ShmPrintInfoAttach(&Stat);
889 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
890 LxtCheckNotEqual(0, Stat.shm_dtime, "%Iu");
891
892 //
893 // Unmap the last page in the range.
894 //
895
896 LxtCheckErrno(munmap(Address + (2 * PAGE_SIZE), PAGE_SIZE));
897 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
898 ShmPrintInfoAttach(&Stat);
899 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
900
901 //
902 // Use detach to clear the range.
903 //
904
905 LxtCheckErrno(LxtShmDt(Address));
906 Address = NULL;
907 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
908 ShmPrintInfoAttach(&Stat);
909 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
910
911 //
912 // (2) Map the region again. Unmap the middle page of the three-page range.
913 //
914
915 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
916 LxtLogInfo("Address = %p", Address);
917 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
918 ShmPrintInfoAttach(&Stat);
919 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
920 LxtCheckErrno(munmap(Address + PAGE_SIZE, PAGE_SIZE));
921 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
922 ShmPrintInfoAttach(&Stat);
923 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
924
925 //
926 // Use shmdt to remove both remaining mapped regions, this should unmap
927 // both attached regions.
928 //
929
930 LxtCheckErrno(LxtShmDt(Address));
931 Address = NULL;
932 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
933 ShmPrintInfoAttach(&Stat);
934 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
935
936 //
937 // (3) Use the remap system call to resize the region.
938 //
939
940 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
941 LxtLogInfo("Address = %p", Address);
942 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
943 ShmPrintInfoAttach(&Stat);
944 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
945 LxtCheckMapErrno(RemappedMemory = LxtMremap(Address, PAGE_SIZE * 3, PAGE_SIZE * 4, MREMAP_MAYMOVE, NULL));
946
947 LxtLogInfo("RemappedMemory = %p", RemappedMemory);
948
949 //
950 // If the address changed, attempt to remap the old address.
951 //
952
953 if (Address != RemappedMemory)
954 {
955 LxtCheckErrnoFailure(LxtShmDt(Address), EINVAL);
956 Address = RemappedMemory;
957 }
958
959 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
960 ShmPrintInfoAttach(&Stat);
961 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
962
963 //
964 // Unmap the middle two pages in the range.
965 //
966
967 LxtCheckErrno(munmap(Address + PAGE_SIZE, (2 * PAGE_SIZE)));
968 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
969 ShmPrintInfoAttach(&Stat);
970 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
971
972 //
973 // Unmap the first page in the range.
974 //
975
976 LxtCheckErrno(munmap(Address, PAGE_SIZE));
977 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
978 ShmPrintInfoAttach(&Stat);
979 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
980
981 //
982 // Use shmdt to remove the remaining region (the last page in the range).
983 //
984
985 LxtCheckErrno(LxtShmDt(Address));
986 Address = NULL;
987 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
988 ShmPrintInfoAttach(&Stat);
989 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
990
991 //
992 // (4) Map the region again. Use the mremap system call to shrink the
993 // region and validate that the global shared memory region remains the
994 // same size.
995 //
996
997 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
998 LxtLogInfo("Address = %p", Address);
999 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1000 ShmPrintInfoAttach(&Stat);
1001 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1002 LxtCheckEqual(Stat.shm_segsz, (PAGE_SIZE * 3), "%Iu");
1003 LxtCheckMapErrno(RemappedMemory = LxtMremap(Address, PAGE_SIZE * 3, PAGE_SIZE, 0, NULL));
1004
1005 LxtLogInfo("RemappedMemory = %p", RemappedMemory);
1006 LxtCheckEqual(Address, RemappedMemory, "%p");
1007 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1008 ShmPrintInfoAttach(&Stat);
1009 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1010 LxtCheckEqual(Stat.shm_segsz, PAGE_SIZE * 3, "%Iu");
1011
1012 //
1013 // Use shmdt to remove the region.
1014 //
1015
1016 LxtCheckErrno(LxtShmDt(Address));
1017 Address = NULL;
1018 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1019 ShmPrintInfoAttach(&Stat);
1020 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
1021
1022 //
1023 // (5) Map the region twice.
1024 //
1025
1026 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
1027 LxtLogInfo("Address = %p", Address);
1028 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1029 ShmPrintInfoAttach(&Stat);
1030 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1031
1032 LxtCheckMapErrno(Address2 = LxtShmAt(Id, NULL, 0));
1033 LxtLogInfo("Address2 = %p", Address2);
1034 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1035 ShmPrintInfoAttach(&Stat);
1036 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
1037
1038 //
1039 // Ensure the shared memory region were mapped to different locations and
1040 // detach both.
1041 //
1042
1043 LxtCheckNotEqual(Address, Address2, "%p");
1044 LxtCheckErrno(LxtShmDt(Address2));
1045 Address2 = NULL;
1046 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1047 ShmPrintInfoAttach(&Stat);
1048 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1049 LxtCheckErrno(LxtShmDt(Address));
1050 Address = NULL;
1051 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1052 ShmPrintInfoAttach(&Stat);
1053 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
1054
1055 //
1056 // (6) Map the region, delete the region, and validate that the region is
1057 // still able to be mapped.
1058 //
1059
1060 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
1061 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1062
1063 //
1064 // Delete the region again (should succeed).
1065 //
1066
1067 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1068 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1069 ShmPrintInfoAttach(&Stat);
1070 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1071 Address[0] = 'a';
1072 LxtCheckMapErrno(Address2 = LxtShmAt(Id, NULL, 0));
1073 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1074 Address2[0] = 'a';
1075 ShmPrintInfoAttach(&Stat);
1076 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
1077
1078 //
1079 // Detach both mapped regions.
1080 //
1081
1082 LxtCheckErrno(LxtShmDt(Address));
1083 Address = NULL;
1084 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1085 ShmPrintInfoAttach(&Stat);
1086 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1087 LxtCheckErrno(LxtShmDt(Address2));
1088 Address2 = NULL;
1089
1090 //
1091 // The region should be deleted at this point to the shmctl should fail.
1092 //
1093
1094 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, &Stat), EINVAL);
1095 Id = -1;
1096
1097 //
1098 // (7) Delete the shared memory region and attempt to attach it afterwards.
1099 //
1100
1101 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE * 3, 0));
1102 LxtLogInfo("Id = %d", Id);
1103 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1104 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
1105
1106 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1107 Address = LxtShmAt(Id, NULL, 0);
1108 if ((Address != MAP_FAILED) && (errno != EINVAL))
1109 {
1110 Result = LXT_RESULT_FAILURE;
1111 LxtLogError("unexpectedly able to attach deleted memory region %p, %d", Address, errno);
1112
1113 goto ErrorExit;
1114 }
1115
1116 //
1117 // Attempt to stat the deleted region.
1118 //
1119
1120 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, &Stat), EINVAL);
1121 Id = -1;
1122
1123 //
1124 // (8) Use mremap to move the last page to a new location.
1125 //
1126
1127 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE * 3, 0));
1128 LxtLogInfo("Id = %d", Id);
1129 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
1130 LxtLogInfo("Address = %p", Address);
1131 LxtCheckMapErrno(Address2 = LxtMremap(Address + (2 * PAGE_SIZE), PAGE_SIZE, PAGE_SIZE * 4, MREMAP_MAYMOVE, NULL));
1132
1133 LxtLogInfo("Address2 = %p", Address2);
1134 LxtCheckNotEqual(Address + (2 * PAGE_SIZE), Address2, "%p");
1135 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1136 LxtCheckEqual(Stat.shm_nattch, 2, "%Iu");
1137
1138 //
1139 // Detach the original address and validate the second region remains.
1140 //
1141
1142 LxtCheckErrno(LxtShmDt(Address));
1143 Address = NULL;
1144 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1145 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1146
1147 //
1148 // Ensure that shmdt does not work for the new address.
1149 //
1150
1151 LxtCheckErrnoFailure(LxtShmDt(Address2), EINVAL);
1152 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1153 LxtCheckEqual(Stat.shm_nattch, 1, "%Iu");
1154
1155 //
1156 // Call shmdt on what would have been the start of the new region.
1157 //
1158 // N.B. This functions like a new mapping of the memory where the first two
1159 // pages have been unmapped.
1160 //
1161
1162 LxtCheckErrno(LxtShmDt(Address2 - (2 * PAGE_SIZE)));
1163 Address2 = NULL;
1164 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1165 LxtCheckEqual(Stat.shm_nattch, 0, "%Iu");
1166
1167 ErrorExit:
1168 if (Address != NULL)
1169 {
1170 LxtShmDt(Address);
1171 }
1172
1173 if (Address2 != NULL)
1174 {
1175 LxtShmDt(Address2);
1176 }
1177
1178 if (ChildPid == 0)
1179 {
1180 _exit(Result);
1181 }
1182
1183 if (Id != -1)
1184 {
1185 LxtShmCtl(Id, IPC_RMID, NULL);
1186 }
1187
1188 return Result;
1189 }
1190
1191 int ShmGetAccess(PLXT_ARGS Args)
1192
1193 {
1194
1195 struct __user_cap_data_struct CapData[2];
1196 struct __user_cap_header_struct CapHeader;
1197 int ChildPid;
1198 int Id;
1199 key_t Key;
1200 int Mode;
1201 int Result;
1202
1203 ChildPid = -1;
1204 Id = -1;
1205
1206 LxtCheckErrno(LxtGetrandom(&Key, sizeof(Key), 0));
1207 LxtLogInfo("Key = %u", Key);
1208
1209 //
1210 // Create a shared memory region with a mode of all zeros.
1211 //
1212
1213 Mode = 0000;
1214 LxtCheckErrno(Id = LxtShmGet(Key, PAGE_SIZE, (IPC_CREAT | IPC_EXCL | Mode)));
1215 LxtCheckErrno(ChildPid = fork());
1216 if (ChildPid == 0)
1217 {
1218
1219 //
1220 // First attempt with the CAP_IPC_OWNER capability.
1221 //
1222
1223 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
1224 memset(&CapData, 0, sizeof(CapData));
1225 memset(&CapHeader, 0, sizeof(CapHeader));
1226 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1227 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1228 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1229 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
1230 CapData[0].effective = CapData[0].permitted;
1231 CapData[1].effective = CapData[1].permitted;
1232 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1233 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1234
1235 //
1236 // Drop the CAP_IPC_OWNER capability.
1237 //
1238
1239 memset(&CapData, 0, sizeof(CapData));
1240 memset(&CapHeader, 0, sizeof(CapHeader));
1241 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1242 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1243 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1244 CapData[0].effective = CapData[0].permitted;
1245 CapData[1].effective = CapData[1].permitted;
1246 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1247 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1248 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1249 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1250 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1251 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1252 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1253
1254 //
1255 // Change the UID.
1256 //
1257
1258 LxtCheckErrno(setuid(SHM_ACCESS_UID));
1259 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1260 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1261 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1262 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1263 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1264 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1265 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1266
1267 //
1268 // Change the GID.
1269 //
1270
1271 LxtCheckErrno(setgid(SHM_ACCESS_GID));
1272 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1273 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1274 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1275 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1276 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1277 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1278 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1279
1280 //
1281 // Drop supplementary group membership.
1282 //
1283
1284 LxtCheckErrno(Result = setgroups(0, NULL));
1285 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1286 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1287 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1288 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1289 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1290 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1291 goto ErrorExit;
1292 }
1293
1294 //
1295 // Wait for the child to exit.
1296 //
1297
1298 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
1299 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1300 Id = -1;
1301
1302 //
1303 // Create a shared memory region with a user read / write / execute mode.
1304 //
1305
1306 Mode = 0700;
1307 LxtCheckErrno(Id = LxtShmGet(Key, PAGE_SIZE, (IPC_CREAT | IPC_EXCL | Mode)));
1308 LxtCheckErrno(ChildPid = fork());
1309 if (ChildPid == 0)
1310 {
1311
1312 //
1313 // First attempt with the CAP_IPC_OWNER capability.
1314 //
1315
1316 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
1317 memset(&CapData, 0, sizeof(CapData));
1318 memset(&CapHeader, 0, sizeof(CapHeader));
1319 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1320 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1321 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1322 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
1323 CapData[0].effective = CapData[0].permitted;
1324 CapData[1].effective = CapData[1].permitted;
1325 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1326 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1327
1328 //
1329 // Drop the CAP_IPC_OWNER capability.
1330 //
1331
1332 memset(&CapData, 0, sizeof(CapData));
1333 memset(&CapHeader, 0, sizeof(CapHeader));
1334 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1335 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1336 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1337 CapData[0].effective = CapData[0].permitted;
1338 CapData[1].effective = CapData[1].permitted;
1339 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1340 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1341 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0700), "%Iu");
1342 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0070), "%Iu");
1343 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0007), "%Iu");
1344 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0124), "%Iu");
1345 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1346
1347 //
1348 // Change the UID.
1349 //
1350
1351 LxtCheckErrno(setuid(SHM_ACCESS_UID));
1352 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1353 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1354 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1355 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1356 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1357 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1358 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1359
1360 //
1361 // Change the GID.
1362 //
1363
1364 LxtCheckErrno(setgid(SHM_ACCESS_GID));
1365 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1366 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1367 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1368 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1369 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1370 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1371 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1372
1373 //
1374 // Drop supplementary group membership.
1375 //
1376
1377 LxtCheckErrno(Result = setgroups(0, NULL));
1378 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1379 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1380 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1381 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1382 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1383 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1384 goto ErrorExit;
1385 }
1386
1387 //
1388 // Wait for the child to exit.
1389 //
1390
1391 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
1392 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1393 Id = -1;
1394
1395 //
1396 // Create a shared memory region with a group read / write / execute mode.
1397 //
1398
1399 Mode = 0070;
1400 LxtCheckErrno(Id = LxtShmGet(Key, PAGE_SIZE, (IPC_CREAT | IPC_EXCL | Mode)));
1401 LxtCheckErrno(ChildPid = fork());
1402 if (ChildPid == 0)
1403 {
1404
1405 //
1406 // First attempt with the CAP_IPC_OWNER capability.
1407 //
1408
1409 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
1410 memset(&CapData, 0, sizeof(CapData));
1411 memset(&CapHeader, 0, sizeof(CapHeader));
1412 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1413 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1414 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1415 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
1416 CapData[0].effective = CapData[0].permitted;
1417 CapData[1].effective = CapData[1].permitted;
1418 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1419 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1420
1421 //
1422 // Drop the CAP_IPC_OWNER capability.
1423 //
1424
1425 memset(&CapData, 0, sizeof(CapData));
1426 memset(&CapHeader, 0, sizeof(CapHeader));
1427 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1428 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1429 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1430 CapData[0].effective = CapData[0].permitted;
1431 CapData[1].effective = CapData[1].permitted;
1432 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1433 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1434 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1435 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1436 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1437 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1438 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1439
1440 //
1441 // Change the UID (group still matches so this should succeed).
1442 //
1443
1444 LxtCheckErrno(setuid(SHM_ACCESS_UID));
1445 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1446 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1447 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0700), "%Iu");
1448 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0070), "%Iu");
1449 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0007), "%Iu");
1450 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0124), "%Iu");
1451 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1452
1453 //
1454 // Change the GID (callers still has supplementary group membership so
1455 // this should succeed).
1456 //
1457
1458 LxtCheckErrno(setgid(SHM_ACCESS_GID));
1459 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1460 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1461 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0700), "%Iu");
1462 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0070), "%Iu");
1463 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0007), "%Iu");
1464 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0124), "%Iu");
1465 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1466
1467 //
1468 // Drop supplementary group membership.
1469 //
1470
1471 LxtCheckErrno(Result = setgroups(0, NULL));
1472 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1473 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1474 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1475 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1476 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1477 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1478 goto ErrorExit;
1479 }
1480
1481 //
1482 // Wait for the child to exit.
1483 //
1484
1485 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
1486 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1487 Id = -1;
1488
1489 //
1490 // Create a shared memory region with a other read / write / execute mode.
1491 //
1492
1493 Mode = 0007;
1494 LxtCheckErrno(Id = LxtShmGet(Key, PAGE_SIZE, (IPC_CREAT | IPC_EXCL | Mode)));
1495 LxtCheckErrno(ChildPid = fork());
1496 if (ChildPid == 0)
1497 {
1498
1499 //
1500 // First attempt with the CAP_IPC_OWNER capability.
1501 //
1502
1503 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
1504 memset(&CapData, 0, sizeof(CapData));
1505 memset(&CapHeader, 0, sizeof(CapHeader));
1506 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1507 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1508 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1509 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
1510 CapData[0].effective = CapData[0].permitted;
1511 CapData[1].effective = CapData[1].permitted;
1512 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1513 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1514
1515 //
1516 // Drop the CAP_IPC_OWNER capability.
1517 //
1518
1519 memset(&CapData, 0, sizeof(CapData));
1520 memset(&CapHeader, 0, sizeof(CapHeader));
1521 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1522 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1523 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1524 CapData[0].effective = CapData[0].permitted;
1525 CapData[1].effective = CapData[1].permitted;
1526 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1527 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1528 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1529 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1530 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1531 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1532 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1533
1534 //
1535 // Change the UID.
1536 //
1537
1538 LxtCheckErrno(setuid(SHM_ACCESS_UID));
1539 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1540 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1541 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1542 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1543 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1544 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1545 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1546
1547 //
1548 // Change the GID (callers still has supplementary group membership so
1549 // this should succeed).
1550 //
1551
1552 LxtCheckErrno(setgid(SHM_ACCESS_GID));
1553 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1554 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1555 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1556 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1557 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1558 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1559 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1560
1561 //
1562 // Drop supplementary group membership (this should succeed).
1563 //
1564
1565 LxtCheckErrno(Result = setgroups(0, NULL));
1566 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1567 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0700), "%Iu");
1568 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0070), "%Iu");
1569 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0007), "%Iu");
1570 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0124), "%Iu");
1571 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1572 goto ErrorExit;
1573 }
1574
1575 //
1576 // Wait for the child to exit.
1577 //
1578
1579 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
1580 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1581 Id = -1;
1582
1583 //
1584 // Create a shared memory region with a other read / write mode.
1585 //
1586
1587 Mode = 0006;
1588 LxtCheckErrno(Id = LxtShmGet(Key, PAGE_SIZE, (IPC_CREAT | IPC_EXCL | Mode)));
1589 LxtCheckErrno(ChildPid = fork());
1590 if (ChildPid == 0)
1591 {
1592
1593 //
1594 // First attempt with the CAP_IPC_OWNER capability.
1595 //
1596
1597 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
1598 memset(&CapData, 0, sizeof(CapData));
1599 memset(&CapHeader, 0, sizeof(CapHeader));
1600 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1601 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1602 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1603 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
1604 CapData[0].effective = CapData[0].permitted;
1605 CapData[1].effective = CapData[1].permitted;
1606 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1607 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1608
1609 //
1610 // Drop the CAP_IPC_OWNER capability.
1611 //
1612
1613 memset(&CapData, 0, sizeof(CapData));
1614 memset(&CapHeader, 0, sizeof(CapHeader));
1615 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1616 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1617 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1618 CapData[0].effective = CapData[0].permitted;
1619 CapData[1].effective = CapData[1].permitted;
1620 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1621 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1622 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1623 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1624 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1625 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1626 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0006), EACCES);
1627 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0004), EACCES);
1628 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0002), EACCES);
1629 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0001), EACCES);
1630 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1631
1632 //
1633 // Change the UID.
1634 //
1635
1636 LxtCheckErrno(setuid(SHM_ACCESS_UID));
1637 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1638 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1639 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1640 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1641 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1642 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1643 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0006), EACCES);
1644 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0004), EACCES);
1645 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0002), EACCES);
1646 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0001), EACCES);
1647 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1648
1649 //
1650 // Change the GID (callers still has supplementary group membership so
1651 // this should succeed).
1652 //
1653
1654 LxtCheckErrno(setgid(SHM_ACCESS_GID));
1655 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1656 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1657 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1658 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1659 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1660 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1661 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0006), EACCES);
1662 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0004), EACCES);
1663 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0002), EACCES);
1664 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0001), EACCES);
1665 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1666
1667 //
1668 // Drop supplementary group membership (this should succeed).
1669 //
1670
1671 LxtCheckErrno(Result = setgroups(0, NULL));
1672 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1673 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0700), EACCES);
1674 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0070), EACCES);
1675 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0007), EACCES);
1676 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0124), EACCES);
1677 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0666), "%Iu");
1678 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0600), "%Iu");
1679 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0060), "%Iu");
1680 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0006), "%Iu");
1681 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0024), "%Iu");
1682 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0424), "%Iu");
1683 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0024), "%Iu");
1684 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0000), "%Iu");
1685 goto ErrorExit;
1686 }
1687
1688 //
1689 // Wait for the child to exit.
1690 //
1691
1692 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
1693 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1694 Id = -1;
1695
1696 ErrorExit:
1697 if (ChildPid == 0)
1698 {
1699 _exit(Result);
1700 }
1701
1702 //
1703 // N.B. The identifier should not be removed by any child processes.
1704 //
1705
1706 if (Id != -1)
1707 {
1708 LxtShmCtl(Id, IPC_RMID, NULL);
1709 }
1710
1711 return Result;
1712 }
1713
1714 int ShmGetSyscall(PLXT_ARGS Args)
1715
1716 {
1717
1718 struct __user_cap_data_struct CapData[2];
1719 struct __user_cap_header_struct CapHeader;
1720 int ChildPid;
1721 int Id;
1722 key_t Key;
1723 int Mode;
1724 size_t Result;
1725 struct shmid_ds Stat;
1726 time_t Time;
1727
1728 ChildPid = -1;
1729 Id = -1;
1730
1731 //
1732 // Create a key, verify that creating the key with the IPC_EXCL flag fails.
1733 //
1734
1735 Mode = 0000;
1736 LxtLogInfo("Mode %o", Mode);
1737 LxtCheckErrno(LxtGetrandom(&Key, sizeof(Key), 0));
1738 LxtLogInfo("Key = %u", Key);
1739 LxtCheckErrno(Id = LxtShmGet(Key, PAGE_SIZE, (IPC_CREAT | IPC_EXCL | Mode)));
1740 LxtLogInfo("Id = %d", Id);
1741 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1742 ShmPrintInfo(&Stat);
1743 LxtCheckEqual(Key, Stat.shm_perm.__key, "%Iu");
1744 LxtCheckEqual(PAGE_SIZE, Stat.shm_segsz, "%Iu");
1745 LxtCheckEqual(getpid(), Stat.shm_cpid, "%Iu");
1746 LxtCheckEqual(0, Stat.shm_lpid, "%Iu");
1747 LxtCheckEqual(0, Stat.shm_atime, "%Iu");
1748 LxtCheckEqual(0, Stat.shm_dtime, "%Iu");
1749 LxtCheckNotEqual(0, Stat.shm_ctime, "%Iu");
1750 LxtCheckEqual(Mode, Stat.shm_perm.mode, "%o");
1751 LxtCheckEqual(getuid(), Stat.shm_perm.cuid, "%d");
1752 LxtCheckEqual(getuid(), Stat.shm_perm.uid, "%d");
1753 LxtCheckEqual(getgid(), Stat.shm_perm.cgid, "%d");
1754 LxtCheckEqual(getgid(), Stat.shm_perm.gid, "%d");
1755
1756 //
1757 // shmget with IPC_CREAT or IPC_EXCL when the region already exists.
1758 //
1759
1760 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, IPC_CREAT), "%Iu");
1761 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, IPC_EXCL), "%Iu");
1762 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0), "%Iu");
1763
1764 //
1765 // Create a child with a different uid and gid that does not have the
1766 // IPC_OWNER capability.
1767 //
1768
1769 LxtCheckErrno(ChildPid = fork());
1770 if (ChildPid == 0)
1771 {
1772 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
1773 LxtCheckErrno(setgid(SHM_ACCESS_GID));
1774 LxtCheckErrno(setuid(SHM_ACCESS_UID));
1775 memset(&CapData, 0, sizeof(CapData));
1776 memset(&CapHeader, 0, sizeof(CapHeader));
1777 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1778 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1779 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
1780 CapData[0].effective = CapData[0].permitted;
1781 CapData[1].effective = CapData[1].permitted;
1782 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1783
1784 //
1785 // These should succeed because the child still has the IPC_OWNER cap.
1786 //
1787
1788 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, IPC_CREAT), "%Iu");
1789 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, IPC_EXCL), "%Iu");
1790 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0777), "%Iu");
1791 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0666), "%Iu");
1792 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0600), "%Iu");
1793 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0060), "%Iu");
1794 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0006), "%Iu");
1795 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0), "%Iu");
1796
1797 //
1798 // Drop all group membership and the CAP_IPC_OWNER capability and
1799 // attempt to call shmget with unmatching mode bits.
1800 //
1801
1802 LxtCheckErrno(Result = setgroups(0, NULL));
1803 memset(&CapData, 0, sizeof(CapData));
1804 memset(&CapHeader, 0, sizeof(CapHeader));
1805 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1806 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1807 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0777), EACCES);
1808 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0666), EACCES);
1809 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0600), EACCES);
1810 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0060), EACCES);
1811 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, 0006), EACCES);
1812
1813 //
1814 // Use the same permission as before, these should succeed.
1815 //
1816
1817 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, IPC_CREAT), "%Iu");
1818 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, IPC_EXCL), "%Iu");
1819 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, 0), "%Iu");
1820 goto ErrorExit;
1821 }
1822
1823 //
1824 // Wait for the child to exit.
1825 //
1826
1827 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
1828
1829 //
1830 // shmget with size = 0 should succeed.
1831 //
1832
1833 LxtCheckEqual(Id, LxtShmGet(Key, 0, 0), "%Iu");
1834
1835 //
1836 // Invalid parameter variations.
1837 //
1838
1839 //
1840 // shmget with IPC_CREAT | IPC_EXCL when the region already exists, should
1841 // succeed with only IPC_EXCL.
1842 //
1843
1844 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, (IPC_CREAT | IPC_EXCL)), EEXIST);
1845
1846 //
1847 // shmget with a known key and a size that does not match.
1848 //
1849
1850 LxtCheckErrnoFailure(LxtShmGet(Key, (PAGE_SIZE * 2), 0), EINVAL);
1851 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE + 1, 0), EINVAL);
1852
1853 //
1854 // N.B. There appears to be no error checking for invalid flags, only the
1855 // presence of valid flags.
1856 //
1857 // -1 includes the IPC_EXCL flag so this should return EEXIST.
1858 //
1859
1860 LxtCheckErrnoFailure(LxtShmGet(Key, PAGE_SIZE, -1), EEXIST);
1861 LxtCheckEqual(Id, LxtShmGet(Key, PAGE_SIZE, (-1 & ~IPC_EXCL)), "%Iu");
1862
1863 //
1864 // Delete the region and create a new one with a size of one byte.
1865 //
1866
1867 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, &Stat));
1868 Id = -1;
1869 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, 1, 0));
1870 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1871 LxtCheckEqual(1, Stat.shm_segsz, "%Iu");
1872
1873 //
1874 // Delete the region and create a new region with a size of zero bytes
1875 // (should fail).
1876 //
1877
1878 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, &Stat));
1879 Id = -1;
1880 LxtCheckErrnoFailure(Id = LxtShmGet(IPC_PRIVATE, 0, 0), EINVAL);
1881
1882 ErrorExit:
1883 if (ChildPid == 0)
1884 {
1885 _exit(Result);
1886 }
1887
1888 if (Id != -1)
1889 {
1890 LxtShmCtl(Id, IPC_RMID, &Stat);
1891 }
1892
1893 return Result;
1894 }
1895
1896 int ShmCtlSyscall(PLXT_ARGS Args)
1897
1898 {
1899
1900 struct __user_cap_data_struct CapData[2];
1901 struct __user_cap_header_struct CapHeader;
1902 int ChildPid;
1903 int Id;
1904 struct shminfo IpcInfo;
1905 key_t Key;
1906 struct shmid_ds OldStat;
1907 int RandomId;
1908 size_t Result;
1909 struct shm_info ShmInfo;
1910 struct shmid_ds Stat = {0};
1911
1912 Id = -1;
1913
1914 //
1915 // Test permissions for the IPC_STAT.
1916 //
1917
1918 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0));
1919 LxtCheckErrno(ChildPid = fork());
1920 if (ChildPid == 0)
1921 {
1922
1923 //
1924 // First attempt with the CAP_IPC_OWNER capability.
1925 //
1926
1927 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
1928 memset(&CapData, 0, sizeof(CapData));
1929 memset(&CapHeader, 0, sizeof(CapHeader));
1930 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1931 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1932 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1933 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
1934 CapData[0].effective = CapData[0].permitted;
1935 CapData[1].effective = CapData[1].permitted;
1936 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1937 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1938
1939 //
1940 // Drop the CAP_IPC_OWNER capability and verify that the region cannot
1941 // be queried.
1942 //
1943
1944 memset(&CapData, 0, sizeof(CapData));
1945 memset(&CapHeader, 0, sizeof(CapHeader));
1946 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
1947 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
1948 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
1949 CapData[0].effective = CapData[0].permitted;
1950 CapData[1].effective = CapData[1].permitted;
1951 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
1952 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, &Stat), EACCES);
1953
1954 //
1955 // Create a no access shared memory region and verify that it cannot be
1956 // queried without the CAP_IPC_OWNER (even by its owner).
1957 //
1958
1959 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0));
1960 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, &Stat), EACCES);
1961 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1962
1963 //
1964 // Create a write only shared memory region and verify that it cannot be
1965 // queried without the CAP_IPC_OWNER (even by its owner).
1966 //
1967
1968 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0200));
1969 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, &Stat), EACCES);
1970 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1971
1972 //
1973 // Create a read only shared memory region and verify that it can be
1974 // queried.
1975 //
1976
1977 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0400));
1978 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
1979 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
1980 goto ErrorExit;
1981 }
1982
1983 //
1984 // Wait for the child to exit.
1985 //
1986
1987 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
1988
1989 //
1990 // Test permissions for IPC_SET.
1991 //
1992
1993 LxtCheckErrno(ChildPid = fork());
1994 if (ChildPid == 0)
1995 {
1996
1997 //
1998 // First attempt with the CAP_IPC_OWNER capability.
1999 //
2000
2001 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
2002 memset(&CapData, 0, sizeof(CapData));
2003 memset(&CapHeader, 0, sizeof(CapHeader));
2004 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2005 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
2006 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
2007 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
2008 CapData[0].effective = CapData[0].permitted;
2009 CapData[1].effective = CapData[1].permitted;
2010 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2011 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2012 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2013
2014 //
2015 // Drop the CAP_IPC_OWNER capability and verify that IPC_SET can still
2016 // be called by the owner.
2017 //
2018
2019 memset(&CapData, 0, sizeof(CapData));
2020 memset(&CapHeader, 0, sizeof(CapHeader));
2021 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2022 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
2023 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
2024 CapData[0].effective = CapData[0].permitted;
2025 CapData[1].effective = CapData[1].permitted;
2026 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2027 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2028
2029 //
2030 // Change the GID.
2031 //
2032
2033 LxtCheckErrno(setgid(SHM_ACCESS_GID));
2034 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2035 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2036
2037 //
2038 // Drop supplementary group membership.
2039 //
2040
2041 LxtCheckErrno(Result = setgroups(0, NULL));
2042 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2043
2044 //
2045 // Change the UID (this should fail).
2046 //
2047
2048 LxtCheckErrno(setuid(SHM_ACCESS_UID));
2049 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2050 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_SET, NULL), EFAULT);
2051 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_SET, &Stat), EPERM);
2052 goto ErrorExit;
2053 }
2054
2055 //
2056 // Wait for the child to exit.
2057 //
2058
2059 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
2060
2061 //
2062 // Test permissions for IPC_SET.
2063 //
2064
2065 LxtCheckErrno(ChildPid = fork());
2066 if (ChildPid == 0)
2067 {
2068
2069 //
2070 // First attempt with the CAP_IPC_OWNER capability.
2071 //
2072
2073 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
2074 memset(&CapData, 0, sizeof(CapData));
2075 memset(&CapHeader, 0, sizeof(CapHeader));
2076 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2077 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
2078 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
2079 CapData[CAP_TO_INDEX(CAP_IPC_OWNER)].permitted |= CAP_TO_MASK(CAP_IPC_OWNER);
2080 CapData[0].effective = CapData[0].permitted;
2081 CapData[1].effective = CapData[1].permitted;
2082 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2083 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2084 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2085
2086 //
2087 // Drop the CAP_IPC_OWNER capability and verify that IPC_SET can still
2088 // be called by the creator and owner.
2089 //
2090
2091 memset(&CapData, 0, sizeof(CapData));
2092 memset(&CapHeader, 0, sizeof(CapHeader));
2093 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2094 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
2095 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
2096 CapData[0].effective = CapData[0].permitted;
2097 CapData[1].effective = CapData[1].permitted;
2098 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2099 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2100
2101 //
2102 // Change the owner UID.
2103 //
2104
2105 Stat.shm_perm.uid = SHM_ACCESS_UID;
2106 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2107
2108 //
2109 // Change the GID.
2110 //
2111
2112 LxtCheckErrno(setgid(SHM_ACCESS_GID));
2113 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2114 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2115
2116 //
2117 // Drop supplementary group membership.
2118 //
2119
2120 LxtCheckErrno(Result = setgroups(0, NULL));
2121 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2122
2123 //
2124 // Change the UID to match (this should succeed).
2125 //
2126
2127 LxtCheckErrno(setuid(SHM_ACCESS_UID));
2128 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2129 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2130
2131 //
2132 // IPC_STAT should still fail.
2133 //
2134
2135 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, &Stat), EACCES);
2136 goto ErrorExit;
2137 }
2138
2139 //
2140 // Wait for the child to exit.
2141 //
2142
2143 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
2144
2145 //
2146 // Reset the region's UID.
2147 //
2148
2149 Stat.shm_perm.uid = getuid();
2150 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2151
2152 //
2153 // Test permissions for SHM_LOCK / SHM_UNLOCK.
2154 //
2155
2156 LxtCheckErrno(ChildPid = fork());
2157 if (ChildPid == 0)
2158 {
2159
2160 //
2161 // Drop the CAP_IPC_LOCK capability.
2162 //
2163
2164 memset(&CapHeader, 0, sizeof(CapHeader));
2165 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2166 LxtCheckErrno(LxtCapGet(&CapHeader, CapData)) LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
2167 CapData[CAP_TO_INDEX(CAP_IPC_LOCK)].permitted &= ~CAP_TO_MASK(CAP_IPC_LOCK);
2168 CapData[0].effective = CapData[0].permitted;
2169 CapData[1].effective = CapData[1].permitted;
2170 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2171
2172 //
2173 // Change the UID and verify SHM_LOCK and SHM_UNLOCK fail.
2174 //
2175
2176 LxtCheckErrno(setuid(SHM_ACCESS_UID));
2177 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2178 LxtCheckErrnoFailure(LxtShmCtl(Id, SHM_LOCK, NULL), EPERM);
2179 LxtCheckErrnoFailure(LxtShmCtl(Id, SHM_UNLOCK, NULL), EPERM);
2180 goto ErrorExit;
2181 }
2182
2183 //
2184 // Wait for the child to exit.
2185 //
2186
2187 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
2188
2189 //
2190 // Test permissions for IPC_RMID.
2191 //
2192
2193 LxtCheckErrno(ChildPid = fork());
2194 if (ChildPid == 0)
2195 {
2196
2197 //
2198 // Drop the CAP_IPC_OWNER capability.
2199 //
2200
2201 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
2202 memset(&CapData, 0, sizeof(CapData));
2203 memset(&CapHeader, 0, sizeof(CapHeader));
2204 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2205 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
2206 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
2207 CapData[0].effective = CapData[0].permitted;
2208 CapData[1].effective = CapData[1].permitted;
2209 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2210
2211 //
2212 // Change the UID and verify IPC_RMID fails.
2213 //
2214
2215 LxtCheckErrno(setuid(SHM_ACCESS_UID));
2216 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2217 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_RMID, NULL), EPERM);
2218 goto ErrorExit;
2219 }
2220
2221 //
2222 // Wait for the child to exit.
2223 //
2224
2225 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
2226
2227 //
2228 // Verify IPC_RMID can be called by the memory region's owner.
2229 //
2230
2231 LxtCheckErrno(ChildPid = fork());
2232 if (ChildPid == 0)
2233 {
2234
2235 //
2236 // Drop the CAP_IPC_OWNER capability.
2237 //
2238
2239 LxtCheckErrno(prctl(PR_SET_KEEPCAPS, 1));
2240 memset(&CapData, 0, sizeof(CapData));
2241 memset(&CapHeader, 0, sizeof(CapHeader));
2242 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
2243 CapData[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
2244 CapData[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
2245 CapData[0].effective = CapData[0].permitted;
2246 CapData[1].effective = CapData[1].permitted;
2247 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2248
2249 //
2250 // Change the owner UID.
2251 //
2252
2253 Stat.shm_perm.uid = SHM_ACCESS_UID;
2254 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2255
2256 //
2257 // Change the caller's UID to match.
2258 //
2259
2260 LxtCheckErrno(setuid(SHM_ACCESS_UID));
2261 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
2262 LxtCheckErrno(LxtShmCtl(Id, IPC_RMID, NULL));
2263 goto ErrorExit;
2264 }
2265
2266 //
2267 // Wait for the child to exit.
2268 //
2269
2270 LxtCheckErrno(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
2271
2272 //
2273 // Create a new shared memory region since the previous was just deleted.
2274 //
2275
2276 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0));
2277
2278 //
2279 // Verify IPC_INFO.
2280 //
2281
2282 LxtCheckErrno(LxtShmCtl(Id, IPC_INFO, &IpcInfo));
2283 LxtCheckErrno(LxtShmCtl(0, IPC_INFO, &IpcInfo));
2284 LxtLogInfo("shminfo.shmmax %Iu", IpcInfo.shmmax);
2285 LxtLogInfo("shminfo.shmmin %Iu", IpcInfo.shmmin);
2286 LxtLogInfo("shminfo.shmmni %Iu", IpcInfo.shmmni);
2287 LxtLogInfo("shminfo.shmseg %Iu", IpcInfo.shmseg);
2288 LxtLogInfo("shminfo.shmall %Iu", IpcInfo.shmall);
2289 LxtCheckEqual(IpcInfo.shmmin, 1, "%Iu");
2290
2291 //
2292 // Verify SHM_INFO.
2293 //
2294
2295 LxtCheckErrno(LxtShmCtl(Id, SHM_INFO, &ShmInfo));
2296 LxtCheckErrno(LxtShmCtl(0, SHM_INFO, &ShmInfo));
2297 LxtLogInfo("shm_info.used_ids %Iu", ShmInfo.used_ids);
2298 LxtLogInfo("shm_info.shm_tot %Iu", ShmInfo.shm_tot);
2299 LxtLogInfo("shm_info.shm_rss %Iu", ShmInfo.shm_rss);
2300 LxtLogInfo("shm_info.shm_swp %Iu", ShmInfo.shm_swp);
2301 LxtLogInfo("shm_info.swap_attempts %Iu", ShmInfo.swap_attempts);
2302 LxtLogInfo("shm_info.swap_successes %Iu", ShmInfo.swap_successes);
2303 LxtCheckNotEqual(ShmInfo.used_ids, 0, "%Iu");
2304
2305 //
2306 // Verify SHM_LOCK and SHM_UNLOCK. The locked state is boolean (there is
2307 // no count for locked / unlocked).
2308 //
2309
2310 LxtCheckErrno(LxtShmCtl(Id, SHM_LOCK, NULL));
2311 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2312 LxtCheckEqual(SHM_LOCKED, Stat.shm_perm.mode & SHM_LOCKED, "%o");
2313 LxtCheckErrno(LxtShmCtl(Id, SHM_LOCK, NULL));
2314 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2315 LxtCheckEqual(SHM_LOCKED, Stat.shm_perm.mode & SHM_LOCKED, "%o");
2316 LxtCheckErrno(LxtShmCtl(Id, SHM_UNLOCK, NULL));
2317 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2318 LxtCheckEqual(0, Stat.shm_perm.mode & SHM_LOCKED, "%o");
2319 LxtCheckErrno(LxtShmCtl(Id, SHM_UNLOCK, NULL));
2320 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2321 LxtCheckEqual(0, Stat.shm_perm.mode & SHM_LOCKED, "%o");
2322
2323 //
2324 // Invalid parameter variations.
2325 //
2326
2327 //
2328 // Ensure IPC_SET cannot set invalid mode bits (they are silently ignored).
2329 //
2330
2331 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2332 Stat.shm_perm.mode = -1;
2333 LxtCheckErrno(LxtShmCtl(Id, IPC_SET, &Stat));
2334 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2335 LxtCheckEqual(Stat.shm_perm.mode, 0777, "%o");
2336
2337 //
2338 // Ensure the uid and gid cannot be set to -1.
2339 //
2340
2341 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &OldStat));
2342 Stat = OldStat;
2343 Stat.shm_perm.uid = -1;
2344 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_SET, &Stat), EINVAL);
2345 Stat = OldStat;
2346 Stat.shm_perm.gid = -1;
2347 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_SET, &Stat), EINVAL);
2348 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2349 LxtCheckEqual(Stat.shm_perm.uid, OldStat.shm_perm.uid, "%d");
2350 LxtCheckEqual(Stat.shm_perm.gid, OldStat.shm_perm.gid, "%d");
2351
2352 LxtCheckErrnoFailure(LxtShmCtl(-1, IPC_STAT, NULL), EINVAL);
2353 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, NULL), EFAULT);
2354 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_STAT, -1), EFAULT);
2355 LxtCheckErrnoFailure(LxtShmCtl(-1, IPC_SET, NULL), EINVAL);
2356 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_SET, NULL), EFAULT);
2357 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_SET, -1), EFAULT);
2358 LxtCheckErrnoFailure(LxtShmCtl(-1, IPC_INFO, NULL), EINVAL);
2359 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_INFO, NULL), EFAULT);
2360 LxtCheckErrnoFailure(LxtShmCtl(Id, IPC_INFO, -1), EFAULT);
2361 LxtCheckErrnoFailure(LxtShmCtl(-1, SHM_INFO, NULL), EINVAL);
2362 LxtCheckErrnoFailure(LxtShmCtl(Id, SHM_INFO, NULL), EFAULT);
2363 LxtCheckErrnoFailure(LxtShmCtl(Id, SHM_INFO, -1), EFAULT);
2364 LxtCheckErrnoFailure(LxtShmCtl(-1, SHM_LOCK, NULL), EINVAL);
2365 LxtCheckErrnoFailure(LxtShmCtl(-1, SHM_UNLOCK, NULL), EINVAL);
2366
2367 //
2368 // Generate an ID that does not refer to a valid memory region and attempt
2369 // operations on the nonexistent region.
2370 //
2371
2372 do
2373 {
2374 LxtCheckErrno(LxtGetrandom(&RandomId, sizeof(RandomId), 0));
2375 Result = LxtShmCtl(RandomId, IPC_STAT, &Stat);
2376 } while ((Result == 0) && (errno != EINVAL));
2377
2378 LxtCheckErrnoFailure(LxtShmCtl(RandomId, IPC_RMID, NULL), EINVAL);
2379 LxtCheckErrnoFailure(LxtShmCtl(RandomId, IPC_STAT, &Stat), EINVAL);
2380 LxtCheckErrnoFailure(LxtShmCtl(RandomId, IPC_SET, &Stat), EINVAL);
2381 LxtCheckErrnoFailure(LxtShmCtl(RandomId, SHM_LOCK, NULL), EINVAL);
2382 LxtCheckErrnoFailure(LxtShmCtl(RandomId, SHM_UNLOCK, NULL), EINVAL);
2383
2384 ErrorExit:
2385 if (ChildPid == 0)
2386 {
2387 _exit(Result);
2388 }
2389
2390 if (Id != -1)
2391 {
2392 LxtShmCtl(Id, IPC_RMID, NULL);
2393 }
2394
2395 return Result;
2396 }
2397
2398 int ShmPidNamespaceWork(void)
2399
2400 /*++
2401
2402 Routine Description:
2403
2404 This routine tests the behavior of System V shared memory across IPC
2405 namespaces. A child threadgroup is forked into a new IPC namespace,
2406
2407
2408 and the parent and
2409 child communicate across a unix socket connection. Each side queries the
2410 credentials of the other side via SO_PEERCRED and ancillary messages and
2411 validates that the appropriate credentials are returned.
2412
2413 Arguments:
2414
2415 None.
2416
2417 Return Value:
2418
2419 0 on success, -1 on failure.
2420
2421 --*/
2422
2423 {
2424
2425 void* Address;
2426 void* Address2;
2427 pid_t ChildPid = 0;
2428 int Id;
2429 void* MapResult;
2430 pid_t ParentPid;
2431 struct shmid_ds ParentStat;
2432 int Result;
2433 struct shmid_ds Stat;
2434 int Status;
2435
2436 Address = NULL;
2437 Address2 = NULL;
2438 Id = -1;
2439
2440 LXT_SYNCHRONIZATION_POINT_START();
2441
2442 //
2443 // Create and map a shared memory region.
2444 //
2445
2446 LxtCheckErrno(Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0));
2447 LxtCheckMapErrno(Address = LxtShmAt(Id, NULL, 0));
2448 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &ParentStat));
2449
2450 //
2451 // Unshare the PID namespace used for children.
2452 //
2453
2454 LxtLogInfo("Unsharing CLONE_NEWPID");
2455 LxtCheckErrno(unshare(CLONE_NEWPID));
2456
2457 //
2458 // Fork a child that will exist in a new IPC namespace.
2459 //
2460
2461 ParentPid = getpid();
2462 LxtLogInfo("ParentPid %d", ParentPid);
2463 LxtCheckErrno(ChildPid = fork());
2464 if (ChildPid == 0)
2465 {
2466
2467 LxtLogInfo("Child's view of ChildPid %d", getpid());
2468
2469 //
2470 // Attach the shared segment.
2471 //
2472
2473 LxtCheckMapErrno(Address2 = LxtShmAt(Id, NULL, 0));
2474 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2475 LxtCheckEqual(getpid(), Stat.shm_lpid, "%d");
2476
2477 LXT_SYNCHRONIZATION_POINT();
2478
2479 //
2480 // Wait for the parent to query credentials.
2481 //
2482
2483 LXT_SYNCHRONIZATION_POINT();
2484
2485 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2486 LxtCheckEqual(ParentPid, Stat.shm_lpid, "%d");
2487 }
2488 else
2489 {
2490
2491 LxtLogInfo("Parent's view of ChildPid %d", ChildPid);
2492
2493 //
2494 // Wait for the child to attach.
2495 //
2496
2497 LXT_SYNCHRONIZATION_POINT();
2498
2499 //
2500 // Query the last attach pid (should NOT match ChildPid) and create
2501 // a new mapping.
2502 //
2503
2504 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2505 LxtCheckNotEqual(ChildPid, Stat.shm_lpid, "%d");
2506 LxtCheckMapErrno(Address2 = LxtShmAt(Id, NULL, 0));
2507 LxtCheckErrno(LxtShmCtl(Id, IPC_STAT, &Stat));
2508 LxtCheckEqual(getpid(), Stat.shm_lpid, "%d");
2509
2510 LXT_SYNCHRONIZATION_POINT();
2511 }
2512
2513 Result = LXT_RESULT_SUCCESS;
2514
2515 ErrorExit:
2516 LXT_SYNCHRONIZATION_POINT_END();
2517 if (Address != NULL)
2518 {
2519 LxtShmDt(Address);
2520 }
2521
2522 if (Address2 != NULL)
2523 {
2524 LxtShmDt(Address2);
2525 }
2526
2527 if (ChildPid == 0)
2528 {
2529 _exit(Result);
2530 }
2531
2532 if (Id != -1)
2533 {
2534 LxtShmCtl(Id, IPC_RMID, NULL);
2535 }
2536
2537 return Result;
2538 }
2539
2540 int ShmPidNamespace(PLXT_ARGS Args)
2541
2542 /*++
2543
2544 Routine Description:
2545
2546 This routine tests the behavior of System V shared memory across IPC
2547 namespaces.
2548
2549 Arguments:
2550
2551 Args - Supplies the command line arguments.
2552
2553 Return Value:
2554
2555 0 on success, -1 on failure.
2556
2557 --*/
2558
2559 {
2560
2561 pid_t ChildPid;
2562 int Result;
2563
2564 //
2565 // Fork into a new parent so that the existing threadgroup does not have its
2566 // IPC namespaces altered for later tests.
2567 //
2568
2569 LxtCheckErrno(ChildPid = fork());
2570 if (ChildPid == 0)
2571 {
2572 _exit(ShmPidNamespaceWork());
2573 }
2574
2575 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
2576 Result = LXT_RESULT_SUCCESS;
2577
2578 ErrorExit:
2579 return Result;
2580 }
2581
2582 void ShmPrintInfo(struct shmid_ds* Stat)
2583
2584 {
2585
2586 if (g_VerboseShm == false)
2587 {
2588 return;
2589 }
2590
2591 LxtLogInfo("shm_perm.__key %u", Stat->shm_perm.__key);
2592 LxtLogInfo("shm_perm.uid %u", Stat->shm_perm.uid);
2593 LxtLogInfo("shm_perm.gid %u", Stat->shm_perm.gid);
2594 LxtLogInfo("shm_perm.cuid %u", Stat->shm_perm.cuid);
2595 LxtLogInfo("shm_perm.cgid %u", Stat->shm_perm.cgid);
2596 LxtLogInfo("shm_perm.mode %o", Stat->shm_perm.mode);
2597 LxtLogInfo("shm_perm.__seq %d", Stat->shm_perm.__seq);
2598 LxtLogInfo("shm_segsz %Iu", Stat->shm_segsz);
2599 LxtLogInfo("shm_atime %Iu", Stat->shm_atime);
2600 LxtLogInfo("shm_dtime %Iu", Stat->shm_dtime);
2601 LxtLogInfo("shm_ctime %Iu", Stat->shm_ctime);
2602 LxtLogInfo("shm_cpid %Iu", Stat->shm_cpid);
2603 LxtLogInfo("shm_lpid %Iu", Stat->shm_lpid);
2604 LxtLogInfo("shm_nattch %Iu", Stat->shm_nattch);
2605 return;
2606 }
2607
2608 void ShmPrintInfoAttach(struct shmid_ds* Stat)
2609
2610 {
2611
2612 if (g_VerboseShm == false)
2613 {
2614 return;
2615 }
2616
2617 LxtLogInfo("shm_segsz %Iu", Stat->shm_segsz);
2618 LxtLogInfo("shm_atime %Iu", Stat->shm_atime);
2619 LxtLogInfo("shm_dtime %Iu", Stat->shm_dtime);
2620 LxtLogInfo("shm_ctime %Iu", Stat->shm_ctime);
2621 LxtLogInfo("shm_cpid %Iu", Stat->shm_cpid);
2622 LxtLogInfo("shm_lpid %Iu", Stat->shm_lpid);
2623 LxtLogInfo("shm_nattch %Iu", Stat->shm_nattch);
2624 return;
2625 }