master
c 1,657 lines 39.7 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 Namespace.c
8
9 Abstract:
10
11 This file is a Namespace test.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <fcntl.h>
18 #include <unistd.h>
19 #include <sys/mount.h>
20 #include <sys/sysmacros.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <sys/socket.h>
24 #include <fcntl.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stddef.h>
28 #include <dirent.h>
29 #include <ctype.h>
30 #include <sys/mman.h>
31 #include <sys/utsname.h>
32 #include <sys/ipc.h>
33 #include <sys/shm.h>
34 #include <sys/ioctl.h>
35 #include <sys/wait.h>
36 #include <net/if.h>
37 #include <bits/local_lim.h>
38 #include <linux/capability.h>
39 #include <linux/futex.h>
40 #include <linux/net_namespace.h>
41 #include <linux/netlink.h>
42 #include <linux/rtnetlink.h>
43 #include <linux/reboot.h>
44
45 #define LXT_NAME "Namespace"
46 #define SOCKET_LOOPBACK_IF_NAME "lo"
47
48 #define LxtReboot(_magic1, _magic2, _cmd, _arg) (syscall(SYS_reboot, (_magic1), (_magic2), (_cmd), (_arg)))
49
50 int NamespaceNetwork(PLXT_ARGS Args);
51
52 int NamespaceNetworkProcfs(PLXT_ARGS Args);
53
54 int NamespaceNetworkProcfsCheckFile(char* File, int ExpectedLineCount);
55
56 int NamespaceSetNs(PLXT_ARGS Args);
57
58 int NamespaceStat(PLXT_ARGS Args);
59
60 int NamespacePid(PLXT_ARGS Args);
61
62 int NamespacePidCheckProcPidStatStatusFiles(char* Dir);
63
64 void* NamespacePidChildPThread(void* Args);
65
66 int NamespacePidGetProcPidFolderCount(char* Dir, int* Count);
67
68 int NamespacePidBasic(int Level);
69
70 int NamespacePidBasicChild(void* Param);
71
72 int NamespacePidParentPThread(void);
73
74 int NamespaceUts(PLXT_ARGS Args);
75
76 int NamespaceIpc(PLXT_ARGS Args);
77
78 int NamespaceCloneInvalid(PLXT_ARGS Args);
79
80 //
81 // Global constants
82 //
83
84 static const LXT_VARIATION g_LxtVariations[] = {
85 {"NamespaceSetNs", NamespaceSetNs},
86 {"NamespaceStat", NamespaceStat},
87 {"Namespace UTS", NamespaceUts},
88 {"Namespace PID", NamespacePid},
89 {"Namespace Network", NamespaceNetwork},
90 {"Namespace Network - reading /proc/<pid>/net", NamespaceNetworkProcfs},
91 {"Namespace IPC", NamespaceIpc},
92 {"Namespace Clone - invalid namespace flags", NamespaceCloneInvalid}};
93
94 typedef struct _LXT_NAMESPACE_DATA
95 {
96 const char* Name;
97 int NsType;
98 } LXT_NAMESPACE_DATA, *PLXT_NAMESPACE_DATA;
99
100 static const LXT_NAMESPACE_DATA g_LxtNamespaces[] = {
101 {"ipc", CLONE_NEWIPC}, {"mnt", CLONE_NEWNS}, {"net", CLONE_NEWNET}, {"pid", CLONE_NEWPID}, {"user", CLONE_NEWUSER}, {"uts", CLONE_NEWUTS}};
102
103 int NamespaceTestEntry(int Argc, char* Argv[])
104
105 /*++
106 --*/
107
108 {
109
110 LXT_ARGS Args;
111 int Result;
112
113 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
114 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
115
116 ErrorExit:
117 LxtUninitialize();
118 return !LXT_SUCCESS(Result);
119 }
120
121 void NamespaceSetNsChild(int NsFd)
122
123 /*++
124 --*/
125
126 {
127
128 struct __user_cap_data_struct CapData[2];
129 struct __user_cap_header_struct CapHeader;
130 int Result;
131
132 //
133 // Drop the CAP_SYS_ADMIN capability.
134 //
135
136 memset(&CapData, 0, sizeof(CapData));
137 memset(&CapHeader, 0, sizeof(CapHeader));
138 CapHeader.version = _LINUX_CAPABILITY_VERSION_3;
139 LxtCheckErrno(LxtCapGet(&CapHeader, CapData)) CapData[CAP_TO_INDEX(CAP_SYS_ADMIN)].effective &= ~CAP_TO_MASK(CAP_SYS_ADMIN);
140 LxtCheckErrno(LxtCapSet(&CapHeader, CapData));
141
142 //
143 // Try to setns without CAP_SYS_ADMIN.
144 //
145
146 LxtCheckErrnoFailure(setns(NsFd, 0), EPERM);
147
148 ErrorExit:
149 _exit(Result);
150 }
151
152 int NamespaceSetNs(PLXT_ARGS Args)
153
154 /*++
155 --*/
156
157 {
158
159 char Buffer[32];
160 pid_t ChildPid;
161 int Index;
162 int NsFd;
163 int Result;
164
165 NsFd = -1;
166
167 //
168 // Pass invalid parameters to setns
169 //
170
171 LxtCheckErrnoFailure(setns(0, CLONE_NEWPID), EINVAL);
172 LxtCheckErrnoFailure(setns(0, -1), EINVAL);
173 LxtCheckErrnoFailure(setns(-1, 0), EBADF);
174
175 //
176 // Pass the self fds to sets.
177 //
178
179 for (Index = 0; Index < LXT_COUNT_OF(g_LxtNamespaces); ++Index)
180 {
181 snprintf(Buffer, sizeof(Buffer), "/proc/self/ns/%s", g_LxtNamespaces[Index].Name);
182 printf("%s\n", Buffer);
183 LxtCheckErrno(NsFd = open(Buffer, O_RDONLY));
184 if (g_LxtNamespaces[Index].NsType != CLONE_NEWUSER)
185 {
186 LxtCheckErrno(setns(NsFd, 0));
187 LxtCheckErrno(setns(NsFd, g_LxtNamespaces[Index].NsType));
188 LxtCheckErrno(ChildPid = fork());
189 if (ChildPid == 0)
190 {
191 NamespaceSetNsChild(NsFd);
192 }
193
194 LxtWaitPidPoll(ChildPid, 0);
195 }
196 else
197 {
198 LxtCheckErrnoFailure(setns(NsFd, 0), EINVAL);
199 LxtCheckErrnoFailure(setns(NsFd, g_LxtNamespaces[Index].NsType), EINVAL);
200 }
201
202 LxtCheckErrnoFailure(setns(NsFd, g_LxtNamespaces[(Index + 1) % LXT_COUNT_OF(g_LxtNamespaces)].NsType), EINVAL);
203 LxtCheckErrnoFailure(setns(NsFd, -1), EINVAL);
204 LxtClose(NsFd);
205 NsFd = -1;
206 }
207
208 ErrorExit:
209 if (NsFd != -1)
210 {
211 LxtClose(NsFd);
212 }
213
214 return Result;
215 }
216
217 int NamespaceStat(PLXT_ARGS Args)
218
219 {
220
221 char Buffer[32];
222 int Index;
223 int NsFd;
224 int Result;
225 struct stat StatData;
226
227 NsFd = -1;
228
229 //
230 // stat each namespace file and check the result.
231 //
232
233 for (Index = 0; Index < LXT_COUNT_OF(g_LxtNamespaces); ++Index)
234 {
235 snprintf(Buffer, sizeof(Buffer), "/proc/self/ns/%s", g_LxtNamespaces[Index].Name);
236 printf("%s\n", Buffer);
237 LxtCheckErrno(NsFd = open(Buffer, O_RDONLY));
238 LxtCheckErrno(fstat(NsFd, &StatData));
239
240 //
241 // TODO: st_dev is reported as 0 for files.
242 //
243
244 LxtCheckEqual(major(StatData.st_dev), 0, "%d");
245 LxtCheckNotEqual(StatData.st_ino, 0, "%d");
246 LxtCheckNotEqual(StatData.st_mode, 0, "%d");
247 LxtCheckEqual(StatData.st_nlink, 1, "%d");
248 LxtCheckEqual(StatData.st_uid, 0, "%d");
249 LxtCheckEqual(StatData.st_gid, 0, "%d");
250 LxtCheckEqual(StatData.st_rdev, 0, "%d");
251 LxtCheckEqual(StatData.st_size, 0, "%d");
252 LxtCheckEqual(StatData.st_blksize, 4096, "%d");
253 LxtCheckEqual(StatData.st_blocks, 0, "%d");
254 LxtClose(NsFd);
255 NsFd = -1;
256 }
257
258 Result = 0;
259
260 ErrorExit:
261 if (NsFd != -1)
262 {
263 LxtClose(NsFd);
264 }
265
266 return Result;
267 }
268
269 int VerifyUtsData(struct utsname* ExpectedValues)
270
271 {
272
273 struct utsname ActualValues;
274 int Fd;
275 int Length;
276 char ProcfsDomain[HOST_NAME_MAX];
277 char ProcfsHost[HOST_NAME_MAX];
278 int Result;
279
280 memset(&ActualValues, 0, sizeof(ActualValues));
281 LxtCheckErrno(uname(&ActualValues));
282 LxtCheckMemoryEqual(ExpectedValues, &ActualValues, sizeof(ActualValues));
283 LxtCheckErrno(Fd = open("/proc/sys/kernel/hostname", O_RDONLY));
284 LxtCheckErrno(Length = read(Fd, ProcfsHost, sizeof(ProcfsHost)));
285 ProcfsHost[Length - 1] = 0;
286 LxtClose(Fd);
287 Fd = -1;
288 LxtCheckStringEqual(ExpectedValues->nodename, ProcfsHost);
289 LxtCheckErrno(Fd = open("/proc/sys/kernel/domainname", O_RDONLY));
290 LxtCheckErrno(Length = read(Fd, ProcfsDomain, sizeof(ProcfsDomain)));
291 ProcfsDomain[Length - 1] = 0;
292 LxtClose(Fd);
293 Fd = -1;
294 LxtCheckStringEqual(ExpectedValues->domainname, ProcfsDomain);
295 Result = 0;
296
297 ErrorExit:
298 if (Fd != -1)
299 {
300 LxtClose(Fd);
301 }
302
303 return Result;
304 }
305
306 #define CHILD_HOST "childmachine"
307 #define CHILD_DOMAIN "childdomain"
308
309 int NamespaceUtsChild(struct utsname* ParentValues)
310
311 {
312
313 int Fd;
314 char Path[64];
315 pid_t Ppid;
316 int Result;
317 struct utsname UtsBuffer;
318
319 Fd = -1;
320
321 //
322 // Check the uts namespace behavior for before\after unshare.
323 //
324
325 memcpy(&UtsBuffer, ParentValues, sizeof(UtsBuffer));
326 LxtCheckResult(VerifyUtsData(&UtsBuffer));
327 LxtCheckErrno(unshare(CLONE_NEWUTS));
328 LxtCheckResult(VerifyUtsData(&UtsBuffer));
329 LxtCheckErrno(sethostname(CHILD_HOST, sizeof(CHILD_HOST)));
330 LxtCheckErrno(setdomainname(CHILD_DOMAIN, sizeof(CHILD_DOMAIN)));
331 memset(UtsBuffer.nodename, 0, sizeof(UtsBuffer.nodename));
332 memcpy(UtsBuffer.nodename, CHILD_HOST, sizeof(CHILD_HOST));
333 memset(UtsBuffer.domainname, 0, sizeof(UtsBuffer.domainname));
334 memcpy(UtsBuffer.domainname, CHILD_DOMAIN, sizeof(CHILD_DOMAIN));
335 LxtCheckResult(VerifyUtsData(&UtsBuffer));
336
337 //
338 // Check the uts namespace behavior after switching back to the parent
339 // uts namespace.
340 //
341
342 Ppid = getppid();
343 sprintf(Path, "/proc/%d/ns/uts", Ppid);
344 LxtCheckErrno(Fd = open(Path, O_RDONLY));
345 LxtCheckErrno(setns(Fd, CLONE_NEWUTS));
346 memcpy(&UtsBuffer, ParentValues, sizeof(UtsBuffer));
347 LxtCheckResult(VerifyUtsData(&UtsBuffer));
348
349 Result = 0;
350
351 ErrorExit:
352 if (Fd != -1)
353 {
354 LxtClose(Fd);
355 }
356
357 return Result;
358 }
359
360 void NamespaceUtsFork(struct utsname* ParentValues)
361
362 {
363
364 int Result;
365
366 Result = NamespaceUtsChild(ParentValues);
367 _exit(Result);
368 }
369
370 void* NamespaceUtsThread(void* Args)
371
372 {
373
374 struct utsname* ParentValues;
375 int Result;
376
377 ParentValues = Args;
378 Result = NamespaceUtsChild(Args);
379 pthread_exit(&Result);
380 }
381
382 int NamespaceUts(PLXT_ARGS Args)
383
384 {
385
386 pid_t ChildPid;
387 char* Name;
388 char NameBuffer[HOST_NAME_MAX];
389 int Result;
390 pthread_t ThreadId = {0};
391 struct utsname UtsBuffer;
392
393 //
394 // Check the UTS behavior for fork()
395 //
396
397 memset(&UtsBuffer, 0, sizeof(UtsBuffer));
398 LxtCheckErrno(uname(&UtsBuffer));
399 LxtCheckResult(VerifyUtsData(&UtsBuffer));
400 LxtCheckErrno(ChildPid = fork());
401 if (ChildPid == 0)
402 {
403 NamespaceUtsFork(&UtsBuffer);
404 }
405
406 LxtWaitPidPoll(ChildPid, 0);
407 LxtCheckResult(VerifyUtsData(&UtsBuffer));
408
409 //
410 // Check the UTS behavior for a pthread.
411 //
412
413 LxtCheckErrnoZeroSuccess(pthread_create(&ThreadId, NULL, NamespaceUtsThread, &UtsBuffer));
414
415 pthread_join(ThreadId, NULL);
416 LxtCheckResult(VerifyUtsData(&UtsBuffer));
417
418 //
419 // Test behavior for NULL names.
420 //
421
422 Name = NULL;
423 LxtCheckErrno(sethostname(Name, 0));
424 LxtCheckErrno(setdomainname(Name, 0));
425 memset(NameBuffer, 1, sizeof(NameBuffer));
426 LxtCheckErrno(gethostname(NameBuffer, sizeof(NameBuffer)));
427 LxtCheckEqual(NameBuffer[0], 0, "%c");
428 memset(NameBuffer, 1, sizeof(NameBuffer));
429 LxtCheckErrno(getdomainname(NameBuffer, sizeof(NameBuffer)));
430 LxtCheckEqual(NameBuffer[0], 0, "%c");
431
432 Result = 0;
433
434 ErrorExit:
435 return Result;
436 }
437
438 int NamespacePidCheckProcPidStatStatusFiles(char* Dir)
439
440 {
441
442 char Command[80];
443 int Gid;
444 int IntValue;
445 char Line[40];
446 char Name[20];
447 int Pid;
448 int Ppid;
449 int Result;
450 char State[10];
451 FILE* StatFile;
452 char StatFileName[30];
453 FILE* StatusFile;
454 char StatusFileName[30];
455 int Tid;
456 int Tgid;
457
458 //
459 // Check the stat file in ProcFs.
460 //
461
462 sprintf(StatFileName, "%s/%s", Dir, "/stat");
463 StatFile = fopen(StatFileName, "r");
464 LxtCheckNotEqual(StatFile, NULL, "%p");
465 LxtCheckEqual(fscanf(StatFile, "%d %s %s %d %d", &Tid, Command, State, &Ppid, &Gid), 5, "%d");
466 LxtLogInfo("%d %s %s %d %d", Tid, Command, State, Ppid, Gid);
467 LxtCheckEqual(Tid, 1, "%d");
468 LxtCheckEqual(Ppid, 0, "%d");
469 LxtCheckEqual(Gid, 0, "%d");
470
471 //
472 // Check the status file in ProcFs.
473 //
474
475 sprintf(StatusFileName, "%s/%s", Dir, "/status");
476 StatusFile = fopen(StatusFileName, "r");
477 LxtCheckNotEqual(StatusFile, NULL, "%p");
478 Tgid = -1;
479 Pid = -1;
480 Ppid = -1;
481 while (fgets(Line, LXT_COUNT_OF(Line), StatusFile) != NULL)
482 {
483 if (sscanf(Line, "%s %d", Name, &IntValue) == 2)
484 {
485 if (strcmp(Name, "Tgid:") == 0)
486 {
487 Tgid = IntValue;
488 }
489 else if (strcmp(Name, "Pid:") == 0)
490 {
491 Pid = IntValue;
492 }
493 else if (strcmp(Name, "PPid:") == 0)
494 {
495 Ppid = IntValue;
496 }
497 }
498 }
499
500 LxtCheckEqual(Tgid, 1, "%d");
501 LxtCheckEqual(Pid, 1, "%d");
502 LxtCheckEqual(Ppid, 0, "%d");
503 Result = LXT_RESULT_SUCCESS;
504
505 ErrorExit:
506
507 //
508 // Intentionally do not close the files. These files are leaked to ensure
509 // the private procfs instance is cleaned up correctly when there are
510 // file descriptors that need to be closed during thread group end.
511 //
512
513 return Result;
514 }
515
516 void* NamespacePidChildPThread(void* Args)
517
518 {
519
520 int Result;
521
522 LxtLogError("Child pthread ran unexpectedly in new namespace");
523 Result = -1;
524 pthread_exit(&Result);
525 }
526
527 int NamespacePidGetProcPidFolderCount(char* Dir, int* Count)
528
529 {
530
531 int CountLocal;
532 struct dirent* DirEnt;
533 DIR* Fd;
534 char FullPath[257];
535 int Result;
536 struct stat StatBuffer;
537
538 //
539 // Get the number of /proc/<pid> folders.
540 //
541
542 Fd = opendir(Dir);
543 if (Fd == NULL)
544 {
545 LxtLogError("opendir failed, errno: %d (%s)", errno, strerror(errno));
546 Result = LXT_RESULT_FAILURE;
547 goto ErrorExit;
548 }
549
550 CountLocal = 0;
551 while ((DirEnt = readdir(Fd)) != NULL)
552 {
553 sprintf(FullPath, "%s/%s", Dir, DirEnt->d_name);
554 LxtLogInfo("Calling stat() on proc folder %s", FullPath);
555 LxtCheckErrnoZeroSuccess(stat(FullPath, &StatBuffer));
556
557 //
558 // Must be a directory, and its name must start with a digit.
559 //
560
561 if ((StatBuffer.st_mode & S_IFDIR) != S_IFDIR)
562 {
563 continue;
564 }
565
566 if (isdigit(DirEnt->d_name[0]) == FALSE)
567 {
568 continue;
569 }
570
571 CountLocal += 1;
572 }
573
574 Result = LXT_RESULT_SUCCESS;
575
576 ErrorExit:
577 if (Fd != NULL)
578 {
579 closedir(Fd);
580 }
581
582 *Count = CountLocal;
583 return Result;
584 }
585
586 int PidBasicPipesA[2];
587 int PidBasicPipesB[2];
588
589 #define NAMESPACE_PID_BASIC_TOKEN (0x12345678)
590
591 #define PID_BASIC_PARENT_PIPE_READ (PidBasicPipesA[0])
592 #define PID_BASIC_PARENT_PIPE_WRITE (PidBasicPipesB[1])
593 #define PID_BASIC_CHILD_PIPE_READ (PidBasicPipesB[0])
594 #define PID_BASIC_CHILD_PIPE_WRITE (PidBasicPipesA[1])
595
596 int NamespacePidBasic(int Level)
597
598 {
599
600 pid_t ChildId;
601 LXT_CLONE_ARGS CloneArgs;
602 pid_t CurrentId;
603 int Result;
604 int Size;
605 int Token;
606
607 //
608 // Create a set of pipes to synchronize with the child PID namespaces.
609 //
610
611 LxtCheckErrnoZeroSuccess(pipe(PidBasicPipesA));
612 LxtCheckErrnoZeroSuccess(pipe(PidBasicPipesB));
613
614 //
615 // Clone a child into a new PID namespace.
616 //
617
618 LxtCheckResult(LxtClone(NamespacePidBasicChild, &Level, CLONE_NEWPID | SIGCHLD, &CloneArgs));
619
620 //
621 // Close the child pipes.
622 //
623
624 LxtCheckErrnoZeroSuccess(close(PID_BASIC_CHILD_PIPE_READ));
625 PID_BASIC_CHILD_PIPE_READ = -1;
626 LxtCheckErrnoZeroSuccess(close(PID_BASIC_CHILD_PIPE_WRITE));
627 PID_BASIC_CHILD_PIPE_WRITE = -1;
628
629 //
630 // Wait for the entire hierarchy to be created.
631 //
632
633 LxtCheckErrno(Size = read(PID_BASIC_PARENT_PIPE_READ, &Token, sizeof(Token)));
634
635 LxtCheckEqual(Size, sizeof(Token), "%d");
636 LxtCheckEqual(Token, NAMESPACE_PID_BASIC_TOKEN, "%x");
637
638 //
639 // Validate the PGID of the child.
640 //
641
642 LxtCheckErrno(CurrentId = getpgid(0));
643 LxtCheckErrno(ChildId = getpgid(CloneArgs.CloneId));
644 LxtCheckEqual(CurrentId, ChildId, "%d");
645
646 //
647 // Validate the SID of the child.
648 //
649
650 LxtCheckErrno(CurrentId = getsid(0));
651 LxtCheckErrno(ChildId = getsid(CloneArgs.CloneId));
652 LxtCheckEqual(CurrentId, ChildId, "%d");
653
654 //
655 // Notify the hierarchy to exit and wait.
656 //
657
658 LxtCheckErrno(Size = write(PID_BASIC_PARENT_PIPE_WRITE, &Token, sizeof(Token)));
659
660 LxtCheckEqual(Size, sizeof(Token), "%d");
661 LxtCheckResult(LxtWaitPidPoll(CloneArgs.CloneId, 0));
662 Result = 0;
663
664 ErrorExit:
665 return Result;
666 }
667
668 int NamespacePidBasicChild(void* Param)
669
670 {
671
672 pid_t ChildPid;
673 LXT_CLONE_ARGS CloneArgs;
674 int Level;
675 pid_t Pgid;
676 pid_t Pid;
677 int PidFolderCount;
678 pid_t Ppid;
679 int Result;
680 pid_t Sid;
681 int Size;
682 pid_t Tid;
683 int Token;
684
685 Level = *((int*)Param);
686
687 //
688 // Close the parent pipes.
689 //
690
691 if (Level == 0)
692 {
693 LxtCheckErrnoZeroSuccess(close(PID_BASIC_PARENT_PIPE_READ));
694 PID_BASIC_PARENT_PIPE_READ = -1;
695 LxtCheckErrnoZeroSuccess(close(PID_BASIC_PARENT_PIPE_WRITE));
696 PID_BASIC_PARENT_PIPE_WRITE = -1;
697 }
698
699 usleep(1000 * 80);
700
701 //
702 // Validate that the first thread/threadgroup in a PID namespace has PID 1.
703 //
704
705 LxtCheckErrno(Tid = gettid());
706 LxtCheckEqual(Tid, 1, "%d");
707 LxtCheckErrno(Pid = getpid());
708 LxtCheckEqual(Pid, 1, "%d");
709
710 //
711 // Validate that the first thread in a PID namespace cannot see its current
712 // process group, session or parent.
713 //
714
715 LxtCheckErrno(Pgid = getpgid(0));
716 LxtCheckEqual(Pgid, 0, "%d");
717 LxtCheckErrno(Sid = getsid(0));
718 LxtCheckEqual(Sid, 0, "%d");
719 LxtCheckErrno(Ppid = getppid());
720 LxtCheckEqual(Ppid, 0, "%d");
721
722 //
723 // Run the following in its own mount namespace and mark all mounts in the
724 // new namespace private so changes cannot propagate to the rest of the
725 // system.
726 //
727
728 LxtCheckErrno(unshare(CLONE_NEWNS));
729 LxtCheckErrnoZeroSuccess(mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL));
730
731 //
732 // Re-mount /proc. This version of /proc should not contain any PIDs from
733 // the parent PID namespace.
734 //
735
736 LxtCheckErrnoZeroSuccess(mount(NULL, "/proc", "proc", 0, NULL));
737
738 //
739 // Do some basic validation.
740 //
741
742 LxtCheckErrnoZeroSuccess(access("/proc", R_OK));
743 LxtCheckErrnoZeroSuccess(access("/proc/1", R_OK));
744 LxtCheckErrnoZeroSuccess(access("/proc/1/cmdline", R_OK));
745 LxtCheckErrnoZeroSuccess(access("/proc/self", R_OK));
746 LxtCheckErrnoZeroSuccess(access("/proc/self/cmdline", R_OK));
747 LxtCheckErrnoFailure(access("/proc/0", R_OK), ENOENT);
748 LxtCheckErrnoFailure(access("/proc/1234567890", R_OK), ENOENT);
749
750 //
751 // Check that there is only 1 /proc/<pid> folder.
752 //
753
754 LxtLogInfo("Checking /proc/<pid> folders, before clone, nested level %d", Level);
755 LxtCheckResult(NamespacePidGetProcPidFolderCount("/proc", &PidFolderCount));
756 LxtCheckEqual(PidFolderCount, 1, "%d");
757
758 //
759 // Check the /proc/1/stat, /proc/1/status, /proc/1/task/1/stat
760 // and /proc/1/task/1/status files.
761 //
762
763 NamespacePidCheckProcPidStatStatusFiles("/proc/1/");
764 NamespacePidCheckProcPidStatStatusFiles("/proc/1/task/1");
765
766 //
767 // Test nested PID namespaces.
768 //
769
770 if (Level < 3)
771 {
772 Level += 1;
773 LxtCheckResult(LxtClone(NamespacePidBasicChild, &Level, CLONE_NEWPID | SIGCHLD, &CloneArgs));
774
775 //
776 // After the clone, check that there are now at least 2 /proc/<pid>
777 // folders.
778 //
779 // N.B. The cloned process will recursively create more cloned PID
780 // namespaces, causing more PIDs to appear under this /proc mount.
781 //
782
783 LxtLogInfo("Checking /proc/<pid> folders, after clone, nested level %d", Level);
784 LxtCheckResult(NamespacePidGetProcPidFolderCount("/proc", &PidFolderCount));
785 LxtCheckGreaterOrEqual(PidFolderCount, 2, "%d");
786
787 //
788 // Check the /proc/1/stat, /proc/1/status, /proc/1/task/1/stat
789 // and /proc/1/task/1/status files.
790 //
791
792 NamespacePidCheckProcPidStatStatusFiles("/proc/1/");
793 NamespacePidCheckProcPidStatStatusFiles("/proc/1/task/1");
794
795 //
796 // Wait for the child to exit.
797 //
798
799 LxtCheckResult(LxtWaitPidPoll(CloneArgs.CloneId, 0));
800 }
801 else
802 {
803
804 //
805 // Signal to the test that the hierarchy is created.
806 //
807
808 Token = NAMESPACE_PID_BASIC_TOKEN;
809 LxtCheckErrno(Size = write(PID_BASIC_CHILD_PIPE_WRITE, &Token, sizeof(Token)));
810
811 LxtCheckEqual(Size, sizeof(Token), "%d");
812
813 //
814 // Wait for the notification to exit.
815 //
816
817 LxtCheckErrno(Size = read(PID_BASIC_CHILD_PIPE_READ, &Token, sizeof(Token)));
818
819 LxtCheckEqual(Size, sizeof(Token), "%d");
820 LxtCheckEqual(Token, NAMESPACE_PID_BASIC_TOKEN, "%x");
821 }
822
823 Result = 0;
824
825 ErrorExit:
826 return Result;
827 }
828
829 int NamespacePidParentPThread(void)
830
831 {
832
833 pthread_t ThreadId = {0};
834 int Result;
835
836 //
837 // Create a new child PID namespace and check that pthread creation fails.
838 //
839
840 LxtCheckErrno(unshare(CLONE_NEWPID));
841 LxtCheckEqual(pthread_create(&ThreadId, NULL, NamespacePidChildPThread, NULL), EINVAL, "%d");
842
843 Result = 0;
844
845 ErrorExit:
846 return Result;
847 }
848
849 int NamespacePidTerminate(int Level, int* Ready)
850
851 {
852
853 pid_t ChildPid;
854 int Index;
855 int Result;
856
857 LxtLogInfo("[%d/%d] PID namespace leader", Level, getpid());
858
859 //
860 // Create 10 child threadgroups that loop sleeping.
861 //
862
863 for (Index = 0; Index < 10; Index += 1)
864 {
865 LxtCheckErrno(ChildPid = fork());
866 if (ChildPid == 0)
867 {
868 for (;;)
869 {
870 sleep(-1);
871 }
872 }
873
874 LxtLogInfo("[%d/%d] PID namespace sleeper %d", Level, getpid(), ChildPid);
875 }
876
877 //
878 // Create 3 levels of nested PID namespaces and then signal the ready futex.
879 //
880
881 if (Level < 3)
882 {
883 LxtCheckErrno(ChildPid = fork());
884 if (ChildPid == 0)
885 {
886 LxtLogInfo("[%d/%d] PID namespace trampoline", Level, getpid());
887 LxtCheckErrno(unshare(CLONE_NEWPID));
888 LxtCheckErrno(ChildPid = fork());
889 if (ChildPid == 0)
890 {
891 _exit(NamespacePidTerminate(Level + 1, Ready));
892 }
893
894 _exit(0);
895 }
896 }
897 else
898 {
899 LxtLogInfo("[%d/%d] Signaling ready futex...", Level, getpid());
900 *Ready = 1;
901 LxtCheckErrno(LxtFutex(Ready, FUTEX_WAKE, 1, NULL, NULL, 0));
902 }
903
904 //
905 // Sleep.
906 //
907
908 for (;;)
909 {
910 sleep(-1);
911 }
912
913 Result = 0;
914
915 ErrorExit:
916 return Result;
917 }
918
919 int NamespacePidTestTerminate()
920
921 {
922
923 pid_t ChildPid;
924 void* MapResult;
925 int* Ready;
926 int Result;
927 struct timespec Time;
928 int WaitStatus;
929
930 //
931 // Create the ready futex.
932 //
933
934 LxtCheckMapErrno(Ready = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0));
935 *Ready = 0;
936
937 //
938 // Create the top-level PID namespace.
939 //
940
941 LxtCheckErrno(unshare(CLONE_NEWPID));
942 LxtCheckErrno(ChildPid = fork());
943 if (ChildPid == 0)
944 {
945 _exit(NamespacePidTerminate(0, Ready));
946 }
947
948 //
949 // Wait for the ready futex.
950 //
951
952 Time.tv_sec = 10;
953 Time.tv_nsec = 0;
954 LxtLogInfo("[%d] Waiting for all child threadgroups and namespaces to be created...", getpid());
955 while (*Ready == 0)
956 {
957 Result = LxtFutex(Ready, FUTEX_WAIT, 0, &Time, NULL, 0);
958 if ((Result == -1) && (errno != EAGAIN) && (errno != EINTR))
959 {
960 LxtCheckErrno(Result);
961 }
962 }
963
964 //
965 // Terminate the top-level PID namespace and wait on the leader.
966 //
967
968 LxtCheckErrnoZeroSuccess(kill(ChildPid, SIGKILL));
969 LxtWaitPidPoll(ChildPid, SIGKILL);
970
971 //
972 // Sleep and make sure that there are no other waits pending.
973 //
974
975 sleep(1);
976 LxtCheckErrnoFailure(waitpid(-1, &WaitStatus, WNOHANG), ECHILD);
977 Result = 0;
978
979 ErrorExit:
980 return Result;
981 }
982
983 int NamespacePidTestReboot()
984
985 {
986
987 pid_t ChildPid;
988 pid_t Pid;
989 int* Ready;
990 int Result;
991 int WaitStatus;
992
993 Pid = getpid();
994
995 //
996 // Create a child process of init that calls reboot.
997 //
998 // N.B. Init is terminated with SIGINT and the signal handler is not
999 // invoked.
1000 //
1001
1002 LxtCheckErrno(unshare(CLONE_NEWPID));
1003 LxtCheckErrno(ChildPid = fork());
1004 if (ChildPid == 0)
1005 {
1006 LxtCheckErrnoFailure(LxtReboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_CAD_ON, NULL), EINVAL);
1007 LxtCheckErrnoFailure(LxtReboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_CAD_OFF, NULL), EINVAL);
1008 LxtCheckResult(LxtSignalInitialize());
1009 LxtCheckResult(LxtSignalSetupHandler(SIGINT, SA_SIGINFO));
1010 LxtLogInfo("Forking...");
1011 LxtCheckErrno(ChildPid = fork());
1012 if (ChildPid == 0)
1013 {
1014 LxtCheckResult(LxtReboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL));
1015 _exit(0);
1016 }
1017
1018 LxtLogInfo("Waiting...");
1019 LxtSignalWait();
1020 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
1021 _exit(0);
1022 }
1023
1024 //
1025 // Wait for the reboot signal.
1026 //
1027
1028 LxtCheckResult(LxtWaitPidPoll(ChildPid, SIGINT));
1029
1030 //
1031 // Sleep and make sure that there are no other waits pending.
1032 //
1033
1034 sleep(1);
1035 LxtCheckErrnoFailure(waitpid(-1, &WaitStatus, WNOHANG), ECHILD);
1036 Result = 0;
1037
1038 ErrorExit:
1039 if (Pid != getpid())
1040 {
1041 _exit(Result);
1042 }
1043
1044 return Result;
1045 }
1046
1047 int NamespacePid(PLXT_ARGS Args)
1048
1049 {
1050
1051 pid_t ChildPid;
1052 int Result;
1053
1054 //
1055 // Check basic PID namespace behavior.
1056 //
1057
1058 LxtCheckErrno(ChildPid = fork());
1059 if (ChildPid == 0)
1060 {
1061 _exit(NamespacePidBasic(0));
1062 }
1063
1064 LxtWaitPidPoll(ChildPid, 0);
1065
1066 //
1067 // Check the pid namespace behavior for a pthread.
1068 //
1069
1070 LxtCheckErrno(ChildPid = fork());
1071 if (ChildPid == 0)
1072 {
1073 _exit(NamespacePidParentPThread());
1074 }
1075
1076 LxtWaitPidPoll(ChildPid, 0);
1077
1078 //
1079 // Check the pid namespace behavior for signals, termination and waits.
1080 //
1081
1082 LxtCheckErrno(ChildPid = fork());
1083 if (ChildPid == 0)
1084 {
1085 _exit(NamespacePidTestTerminate());
1086 }
1087
1088 LxtWaitPidPoll(ChildPid, 0);
1089
1090 //
1091 // Check the pid namespace behavior for reboot.
1092 //
1093
1094 LxtCheckErrno(ChildPid = fork());
1095 if (ChildPid == 0)
1096 {
1097 _exit(NamespacePidTestReboot());
1098 }
1099
1100 LxtWaitPidPoll(ChildPid, 0);
1101
1102 Result = 0;
1103
1104 ErrorExit:
1105 return Result;
1106 }
1107
1108 int NamespaceNetworkGetNSID(int* NetworkNamespaceId)
1109 {
1110
1111 socklen_t AddressLength;
1112 struct rtattr* Attribute;
1113 struct sockaddr_nl BindAddress;
1114 struct nlmsgerr* Error;
1115 struct nlmsghdr* Header;
1116 int Index;
1117 int NetworkNamespaceFd;
1118 int ReceiveResult;
1119 int RemainingLength;
1120 struct
1121 {
1122 struct nlmsghdr nlh;
1123 struct rtgenmsg msg __attribute__((aligned(NLMSG_ALIGNTO)));
1124 struct
1125 {
1126 struct rtattr rta __attribute__((aligned(RTA_ALIGNTO)));
1127 int val __attribute__((aligned(RTA_ALIGNTO)));
1128 } data[5];
1129 } Request, Response;
1130 int Result;
1131 struct rtgenmsg* RtGenMsg;
1132 int Socket;
1133
1134 //
1135 // Open network namespace file descriptor.
1136 //
1137
1138 LxtCheckErrno(NetworkNamespaceFd = open("/proc/self/ns/net", O_RDONLY));
1139
1140 //
1141 // Create and bind socket. Create a RTM_GETNSID request.
1142 //
1143
1144 LxtCheckErrno(Socket = socket(AF_NETLINK, SOCK_RAW, 0));
1145 memset(&BindAddress, 0, sizeof(BindAddress));
1146 BindAddress.nl_family = AF_NETLINK;
1147 AddressLength = sizeof(BindAddress);
1148 LxtCheckErrno(bind(Socket, (struct sockaddr*)&BindAddress, AddressLength));
1149
1150 memset(&Request, 0, sizeof(Request));
1151 Request.nlh.nlmsg_len = NLMSG_SPACE(sizeof(Request.msg)) + RTA_SPACE(sizeof(int));
1152
1153 Request.nlh.nlmsg_type = RTM_GETNSID;
1154 Request.nlh.nlmsg_seq = 0x4567;
1155 Request.msg.rtgen_family = AF_UNSPEC;
1156 Request.nlh.nlmsg_flags = NLM_F_REQUEST;
1157 Request.data[0].rta.rta_len = RTA_LENGTH(sizeof(int));
1158 Request.data[0].rta.rta_type = NETNSA_FD;
1159 Request.data[0].val = NetworkNamespaceFd;
1160 LxtCheckErrno(sendto(Socket, &Request, sizeof(Request), 0, NULL, 0));
1161 memset(&Response, 0, sizeof(Response));
1162 LxtCheckErrno(ReceiveResult = recvfrom(Socket, &Response, sizeof(Response), 0, NULL, 0));
1163
1164 LxtCheckTrue(NLMSG_OK(&Response.nlh, ReceiveResult));
1165 LxtCheckEqual(Response.nlh.nlmsg_type, RTM_NEWNSID, "%hd");
1166 LxtCheckTrue(Response.nlh.nlmsg_len >= NLMSG_LENGTH(sizeof(Response.msg)));
1167
1168 Attribute = &Response.data[0].rta;
1169 RemainingLength = Response.nlh.nlmsg_len - NLMSG_LENGTH(sizeof(Response.msg));
1170
1171 LxtCheckTrue(RTA_OK(Attribute, RemainingLength));
1172 *NetworkNamespaceId = *(int*)RTA_DATA(Attribute);
1173 Attribute = RTA_NEXT(Attribute, RemainingLength);
1174 LxtCheckTrue(RTA_OK(Attribute, RemainingLength) == FALSE);
1175 LxtCheckTrue(NLMSG_OK(NLMSG_NEXT(&Response.nlh, ReceiveResult), ReceiveResult) == FALSE);
1176
1177 Result = 0;
1178
1179 ErrorExit:
1180 if (Socket > 0)
1181 {
1182 close(Socket);
1183 }
1184
1185 if (NetworkNamespaceFd > 0)
1186 {
1187 close(NetworkNamespaceFd);
1188 }
1189
1190 return Result;
1191 }
1192
1193 int NamespaceNetwork(PLXT_ARGS Args)
1194
1195 {
1196
1197 int NetworkNamespaceId;
1198 int OriginalNetworkNamespaceFd;
1199 int Result;
1200 DIR* SysClassNetDirectory;
1201
1202 //
1203 // Open file descriptor of default network namespace.
1204 //
1205
1206 LxtCheckErrno(OriginalNetworkNamespaceFd = open("/proc/self/ns/net", 0));
1207
1208 //
1209 // Verify default namespace ID is set.
1210 //
1211
1212 LxtCheckErrno(NamespaceNetworkGetNSID(&NetworkNamespaceId));
1213 LxtCheckEqual(NetworkNamespaceId, -1, "%d");
1214
1215 //
1216 // Switch to a new network namespace.
1217 //
1218
1219 LxtCheckErrno(unshare(CLONE_NEWNET));
1220
1221 //
1222 // Verify default namespace ID is set.
1223 //
1224
1225 LxtCheckErrno(NamespaceNetworkGetNSID(&NetworkNamespaceId));
1226 LxtCheckEqual(NetworkNamespaceId, -1, "%d");
1227
1228 //
1229 // Switch back to original network namespace.
1230 //
1231
1232 LxtCheckErrno(setns(OriginalNetworkNamespaceFd, CLONE_NEWNET));
1233 Result = 0;
1234
1235 ErrorExit:
1236 if (OriginalNetworkNamespaceFd >= 0)
1237 {
1238 LxtClose(OriginalNetworkNamespaceFd);
1239 }
1240
1241 return Result;
1242 }
1243
1244 int NamespaceNetworkProcfs(PLXT_ARGS Args)
1245
1246 {
1247
1248 pid_t ChildPid;
1249 char FileName[50];
1250 struct ifreq InterfaceUpRequest;
1251 int Result;
1252 int Socket;
1253
1254 //
1255 // Create a child process and switch it to a new network namespace.
1256 // From the parent, read the child's /proc/<pid>/net entries and verify
1257 // that those entries reflect the network state of the child.
1258 //
1259
1260 LxtCheckErrno(ChildPid = fork());
1261 if (ChildPid == 0)
1262 {
1263 LxtCheckErrnoZeroSuccess(unshare(CLONE_NEWNET));
1264
1265 //
1266 // Bring the loopback up so that it shows up in procfs. (Needed for native
1267 // Ubuntu only - on WSL the loopback is automatically UP on namespace creation.)
1268 //
1269
1270 LxtCheckErrno(Socket = socket(AF_UNIX, SOCK_DGRAM, 0));
1271 memset(&InterfaceUpRequest, 0, sizeof(InterfaceUpRequest));
1272 strncpy(InterfaceUpRequest.ifr_name, SOCKET_LOOPBACK_IF_NAME, sizeof(InterfaceUpRequest.ifr_name) - 1);
1273
1274 usleep(1000 * 100);
1275 LxtCheckErrnoZeroSuccess(ioctl(Socket, SIOCGIFFLAGS, &InterfaceUpRequest));
1276 LxtCheckEqual(InterfaceUpRequest.ifr_flags & IFF_LOOPBACK, IFF_LOOPBACK, "%d");
1277 InterfaceUpRequest.ifr_flags |= IFF_UP;
1278 LxtCheckErrnoZeroSuccess(ioctl(Socket, SIOCSIFFLAGS, &InterfaceUpRequest));
1279 close(Socket);
1280
1281 //
1282 // Keep the child alive so that the parent can examine its /proc/<pid>/net entries.
1283 //
1284
1285 while (1)
1286 ;
1287 exit(0);
1288 }
1289
1290 //
1291 // N.B. The sleep is because it can take some time for the lxcore cache to get
1292 // the new network interface notification.
1293 //
1294
1295 usleep(1000 * 200);
1296
1297 //
1298 // Check the /proc/<pid>/net/dev file. This file should have 3 lines
1299 // (2 lines header and one line for lo).
1300 //
1301
1302 sprintf(FileName, "/proc/%d/net/dev", ChildPid);
1303 LxtCheckResult(NamespaceNetworkProcfsCheckFile(FileName, 3));
1304
1305 //
1306 // Check the /proc/<pid>/net/if_inet6 file. This file should have 1 line,
1307 // for lo.
1308 //
1309
1310 sprintf(FileName, "/proc/%d/net/if_inet6", ChildPid);
1311 LxtCheckResult(NamespaceNetworkProcfsCheckFile(FileName, 1));
1312
1313 //
1314 // Check the /proc/<pid>/net/route file. This file has one line on Ubuntu
1315 // (1 line header and no routing entries) and multiple lines on WSL. Therefore,
1316 // don't check the line count for this file.
1317 //
1318
1319 sprintf(FileName, "/proc/%d/net/route", ChildPid);
1320 LxtCheckResult(NamespaceNetworkProcfsCheckFile(FileName, -1));
1321
1322 //
1323 // All done, the child should die now.
1324 //
1325
1326 kill(ChildPid, SIGKILL);
1327 LxtCheckResult(LxtWaitPidPoll(ChildPid, SIGKILL));
1328 Result = LXT_RESULT_SUCCESS;
1329
1330 ErrorExit:
1331 return Result;
1332 }
1333
1334 int NamespaceNetworkProcfsCheckFile(char* FileName, int ExpectedLineCount)
1335
1336 {
1337
1338 char Buffer[200];
1339 FILE* File;
1340 int LineCount;
1341 int Result;
1342
1343 //
1344 // Open the file up and check how many lines it has.
1345 //
1346
1347 LineCount = 0;
1348 File = fopen(FileName, "r");
1349 LxtCheckTrue(File != NULL);
1350 while (fgets(Buffer, LXT_COUNT_OF(Buffer), File) != NULL)
1351 {
1352 LineCount += 1;
1353
1354 //
1355 // The following strings should not be seen, since the only network
1356 // interface in the file should be lo.
1357 //
1358
1359 LxtCheckTrue(strstr(Buffer, "eth") == NULL);
1360 LxtCheckTrue(strstr(Buffer, "wlan") == NULL);
1361 LxtCheckTrue(strstr(Buffer, "wifi") == NULL);
1362 LxtCheckTrue(strstr(Buffer, "und") == NULL);
1363 }
1364
1365 if (ExpectedLineCount != -1)
1366 {
1367 LxtCheckEqual(LineCount, ExpectedLineCount, "%d");
1368 }
1369
1370 Result = LXT_RESULT_SUCCESS;
1371
1372 ErrorExit:
1373 if (File != NULL)
1374 {
1375 fclose(File);
1376 }
1377
1378 return Result;
1379 }
1380
1381 typedef struct _LXT_NAMESPACE_IPC_DATA
1382 {
1383 int Id;
1384 void* Address;
1385 } LXT_NAMESPACE_IPC_DATA, *PLXT_NAMESPACE_IPC_DATA;
1386
1387 int NamespaceIpcChild(PLXT_NAMESPACE_IPC_DATA Data)
1388
1389 {
1390
1391 int Fd;
1392 char Path[64];
1393 pid_t Ppid;
1394 int Result;
1395 struct shmid_ds Stat;
1396
1397 Fd = -1;
1398
1399 //
1400 // Check the ipc namespace behavior for before\after unshare.
1401 //
1402
1403 LxtCheckErrno(LxtShmCtl(Data->Id, IPC_STAT, &Stat));
1404 LxtCheckErrno(unshare(CLONE_NEWIPC));
1405 LxtCheckErrnoFailure(LxtShmCtl(Data->Id, IPC_STAT, &Stat), EINVAL);
1406
1407 //
1408 // shmdt should still succeed in the new namespace.
1409 //
1410
1411 LxtCheckErrno(LxtShmDt(Data->Address));
1412 //
1413 // Check the ipc namespace behavior after switching back to the parent
1414 // ipc namespace.
1415 //
1416
1417 Ppid = getppid();
1418 sprintf(Path, "/proc/%d/ns/ipc", Ppid);
1419 LxtCheckErrno(Fd = open(Path, O_RDONLY));
1420 LxtCheckErrno(setns(Fd, CLONE_NEWIPC));
1421 LxtCheckErrno(LxtShmCtl(Data->Id, IPC_STAT, &Stat));
1422
1423 Result = 0;
1424
1425 ErrorExit:
1426 if (Fd != -1)
1427 {
1428 LxtClose(Fd);
1429 }
1430
1431 return Result;
1432 }
1433
1434 void NamespaceIpcFork(PLXT_NAMESPACE_IPC_DATA Data)
1435
1436 {
1437
1438 int Result;
1439
1440 Result = NamespaceIpcChild(Data);
1441 _exit(Result);
1442 }
1443
1444 void* NamespaceIpcThread(void* Args)
1445
1446 {
1447
1448 PLXT_NAMESPACE_IPC_DATA Data;
1449 int Result;
1450
1451 Data = Args;
1452 Result = NamespaceIpcChild(Data);
1453 pthread_exit(&Result);
1454 }
1455
1456 int NamespaceIpc(PLXT_ARGS Args)
1457
1458 {
1459
1460 int ChildPid;
1461 LXT_NAMESPACE_IPC_DATA Data;
1462 void* MapResult;
1463 int Result;
1464 struct shmid_ds Stat;
1465 pthread_t ThreadId = {0};
1466
1467 Data.Id = -1;
1468 Data.Address = NULL;
1469
1470 //
1471 // Check the IPC behavior for fork()
1472 //
1473
1474 LxtCheckErrno(Data.Id = LxtShmGet(IPC_PRIVATE, PAGE_SIZE, 0));
1475 LxtCheckMapErrno(Data.Address = LxtShmAt(Data.Id, NULL, 0));
1476 LxtCheckErrno(ChildPid = fork());
1477 if (ChildPid == 0)
1478 {
1479 NamespaceIpcFork(&Data);
1480 }
1481
1482 LxtWaitPidPoll(ChildPid, 0);
1483 LxtCheckErrno(LxtShmCtl(Data.Id, IPC_STAT, &Stat));
1484
1485 //
1486 // Verify shmdt succeeds and create a new mapping.
1487 //
1488
1489 LxtCheckErrno(LxtShmDt(Data.Address));
1490 LxtCheckMapErrno(Data.Address = LxtShmAt(Data.Id, NULL, 0));
1491
1492 //
1493 // Check the IPC behavior for a pthread.
1494 //
1495
1496 LxtCheckErrnoZeroSuccess(pthread_create(&ThreadId, NULL, NamespaceIpcThread, &Data));
1497
1498 pthread_join(ThreadId, NULL);
1499 LxtCheckErrno(LxtShmCtl(Data.Id, IPC_STAT, &Stat));
1500
1501 //
1502 // Verify shmdt fails (was unmapped by the pthread).
1503 //
1504
1505 LxtCheckErrnoFailure(LxtShmDt(Data.Address), EINVAL);
1506 Data.Address = NULL;
1507
1508 Result = 0;
1509
1510 ErrorExit:
1511 if (Data.Id != -1)
1512 {
1513 LxtShmCtl(Data.Id, IPC_RMID, NULL);
1514 }
1515
1516 if (Data.Address != NULL)
1517 {
1518 LxtShmDt(Data.Address);
1519 }
1520
1521 return Result;
1522 }
1523
1524 int NamespaceCloneInvalidChild(unsigned long Flags, PLXT_PIPE Pipe)
1525
1526 /*++
1527
1528 Description:
1529
1530 This routine is the child process for WaitPidVariationCloneParent.
1531
1532 Arguments:
1533
1534 None..
1535
1536 Return Value:
1537
1538 Returns 0 on success, -1 on failure.
1539
1540 --*/
1541
1542 {
1543
1544 pid_t ChildPid;
1545 pid_t GrandChildParent;
1546 pid_t ChildParent;
1547 int Result;
1548 int WaitPidStatus;
1549
1550 Result = 0;
1551
1552 //
1553 // Create a child process with the requested CLONE_PARENT and other flag.
1554 //
1555 // The new process should not be reported as a child.
1556 //
1557
1558 ChildParent = getppid();
1559 LxtLogInfo("ChildParent %d", ChildParent);
1560 LxtCheckResult(ChildPid = LxtCloneSyscall(Flags | SIGCHLD, NULL, NULL, NULL, NULL));
1561 if (ChildPid == 0)
1562 {
1563 GrandChildParent = getppid();
1564 if ((Flags & CLONE_NEWPID) != 0)
1565 {
1566 LxtCheckEqual(0, GrandChildParent, "%d");
1567 }
1568 else
1569 {
1570 LxtCheckEqual(ChildParent, GrandChildParent, "%d");
1571 }
1572
1573 LxtLogInfo("Grand child %d exiting", LxtGetTid());
1574 }
1575 else
1576 {
1577 LxtCheckErrnoFailure(waitpid(ChildPid, &WaitPidStatus, 0), ECHILD);
1578 LxtCheckResult(write(Pipe->Write, &ChildPid, sizeof(ChildPid)));
1579 LxtLogInfo("Child %d exiting", LxtGetTid());
1580 }
1581
1582 Result = 0;
1583
1584 ErrorExit:
1585 _exit(Result);
1586 }
1587
1588 int NamespaceCloneInvalid(PLXT_ARGS Args)
1589
1590 /*++
1591 --*/
1592
1593 {
1594
1595 int ChildPid;
1596 LXT_PIPE Pipe = {-1, -1};
1597 int PipeData;
1598 int Result;
1599
1600 ChildPid = -1;
1601 LxtCheckResult(LxtCreatePipe(&Pipe));
1602
1603 //
1604 // CLONE_NEWPID and CLONE_NEWUSER can't be specified with CLONE_THREAD.
1605 //
1606
1607 LxtCheckErrnoFailure(ChildPid = LxtCloneSyscall(CLONE_NEWPID | CLONE_THREAD, NULL, NULL, NULL, NULL), EINVAL);
1608 LxtCheckErrnoFailure(ChildPid = LxtCloneSyscall(CLONE_NEWUSER | CLONE_THREAD, NULL, NULL, NULL, NULL), EINVAL);
1609
1610 //
1611 // CLONE_NEWPID and CLONE_NEWUSER can be specified with CLONE_PARENT
1612 // (incorrect man pages).
1613 //
1614
1615 LxtCheckErrno(ChildPid = fork());
1616 if (ChildPid == 0)
1617 {
1618 NamespaceCloneInvalidChild(CLONE_NEWPID | CLONE_PARENT, &Pipe);
1619 }
1620
1621 LxtCheckResult(read(Pipe.Read, &PipeData, sizeof(PipeData)));
1622 LxtCheckResult(LxtWaitPidPoll(PipeData, 0));
1623 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
1624
1625 //
1626 // CLONE_NEWIPC and CLONE_SYSVSEM are not allowed together.
1627 //
1628
1629 LxtCheckErrnoFailure(ChildPid = LxtCloneSyscall(CLONE_NEWIPC | CLONE_SYSVSEM, NULL, NULL, NULL, NULL), EINVAL);
1630
1631 //
1632 // TODO_LX: Enable the variation below when CLONE_NEWUSER is supported on
1633 // WSL.
1634 //
1635
1636 /*
1637 LxtCheckErrno(ChildPid = fork());
1638 if (ChildPid == 0) {
1639 NamespaceCloneInvalidChild(CLONE_NEWUSER | CLONE_PARENT, &Pipe);
1640 }
1641
1642 LxtCheckResult(read(Pipe.Read, &PipeData, sizeof(PipeData)));
1643 LxtCheckResult(LxtWaitPidPoll(PipeData, 0));
1644 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
1645 */
1646
1647 Result = 0;
1648
1649 ErrorExit:
1650 if (ChildPid == 0)
1651 {
1652 _exit(Result);
1653 }
1654
1655 LxtClosePipe(&Pipe);
1656 return Result;
1657 }