master
c 1,123 lines 27.5 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 Fork.c
8
9 Abstract:
10
11 This file is a Fork test.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <sys/types.h>
18 #include <sys/wait.h>
19 #include <sys/syscall.h>
20 #include <linux/futex.h>
21 #include <sys/time.h>
22 #include <fpu_control.h>
23 #include <alloca.h>
24 #include <stdlib.h>
25 #include <sys/prctl.h>
26
27 #if defined(__amd64__)
28
29 #include <asm/prctl.h>
30
31 #endif
32
33 #if defined(__i386__)
34 #define GET_STACK_POINTER asm("esp")
35 #elif defined(__amd64__)
36 #define GET_STACK_POINTER asm("rsp")
37 #elif defined(__arm__) || defined(__aarch64__)
38 #define GET_STACK_POINTER asm("sp")
39 #else
40 #error "Unsupported architecture"
41 #endif
42
43 #include <fcntl.h>
44 #include <unistd.h>
45
46 #define LXT_NAME "Fork"
47
48 #define LXT_INVALID_TID_VALUE -1
49 #define LXT_INVALID_TID_ADDRESS ((void*)LXT_INVALID_TID_VALUE)
50 #define LXT_THREAD_UMASK 0555
51 #define LXT_CONTROL_WORD_DEFAULT 0x37f
52 #define LXT_CONTROL_WORD_NEW 0x40
53 #define LXT_STACK_SIZE (1 * 1024 * 1024)
54 #define LXT_TEST_CWD "/"
55
56 int SetTidAddress(PLXT_ARGS Args);
57
58 int ForkPids(PLXT_ARGS Args);
59
60 int ExecvFailure(PLXT_ARGS Args);
61
62 int RobustFutex(PLXT_ARGS Args);
63
64 int CloneFs(PLXT_ARGS Args);
65
66 int CloneInvalidFlags(PLXT_ARGS Args);
67
68 int CloneThread(PLXT_ARGS Args);
69
70 int VForkTestBasic(PLXT_ARGS Args);
71
72 int VForkTest(PLXT_ARGS Args);
73
74 int CloneTestFlags(PLXT_ARGS Args);
75
76 int CloneTestSignalParent(PLXT_ARGS Args);
77
78 //
79 // Global constants
80 //
81 // N.B. Test ordering is important for child process variations.
82 //
83 // TODO_LX: Enable fork tests.
84 //
85
86 #define LXT_DEFAULT_VARIATIONS ((unsigned long)(-1))
87 #define LXT_CHILD_VARIATIONS 0
88
89 static const LXT_VARIATION g_LxtVariations[] = {
90 {"Fork check pids", ForkPids},
91 {"Set tid address", SetTidAddress},
92 {"Execv failure", ExecvFailure},
93 {"Get / Set Robust Futex List", RobustFutex},
94 {"Clone CLONE_FS", CloneFs},
95 {"Clone invalid flags", CloneInvalidFlags},
96 {"VFork test basic", VForkTestBasic},
97 {"Clone thread", CloneThread},
98 {"Vfork behavior", VForkTest},
99 {"Clone test flags", CloneTestFlags},
100 {"Clone signal parent test", CloneTestSignalParent},
101 };
102
103 int ForkTestEntry(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 if (Args.VariationMask == LXT_DEFAULT_VARIATIONS)
115 {
116 Args.VariationMask &= ~LXT_CHILD_VARIATIONS;
117 }
118
119 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
120
121 ErrorExit:
122 LxtUninitialize();
123 return !LXT_SUCCESS(Result);
124 }
125
126 long my_set_tid_address(int* tid)
127
128 {
129 return syscall(SYS_set_tid_address, tid);
130 }
131
132 int my_futex(int* uaddr, int op, int val, const struct timespec* timeout, int* uaddr2, int val3)
133
134 {
135 return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val3);
136 }
137
138 int my_set_robust_list(struct robust_list_head* head, size_t len)
139
140 {
141 return syscall(SYS_set_robust_list, head, len);
142 }
143
144 int my_get_robust_list(int pid, struct robust_list_head** head_ptr, size_t* len_ptr)
145
146 {
147 return syscall(SYS_get_robust_list, pid, head_ptr, len_ptr);
148 }
149
150 mode_t my_umask(mode_t mask)
151
152 {
153 return syscall(SYS_umask, mask);
154 }
155
156 void* SetChildTidThread(void* Args)
157
158 {
159
160 int* TidPointer = Args;
161 int tid;
162 mode_t umaskTemp;
163
164 tid = my_set_tid_address(TidPointer);
165 LxtLogInfo("In pthread tid = %d", tid);
166 if (TidPointer != LXT_INVALID_TID_ADDRESS)
167 {
168 *TidPointer = tid;
169 }
170
171 umaskTemp = my_umask(LXT_THREAD_UMASK);
172 LxtLogInfo("In pthread tid = %d, initial umask %u, umask set to %u", tid, umaskTemp, LXT_THREAD_UMASK);
173
174 sleep(2);
175 return 0;
176 }
177
178 int SetTidAddress(PLXT_ARGS Args)
179 {
180
181 pid_t ChildPid;
182 mode_t ChildUmask;
183 int ForkTid;
184 mode_t OriginalUmask;
185 int ParentTid;
186 int Result = LXT_RESULT_FAILURE;
187 int Return;
188 int SavedThread1Tid = 0;
189 pthread_t Thread1 = {0};
190 int Thread1Tid;
191 pthread_t Thread2 = {0};
192 int Thread2Tid;
193 mode_t UmaskTemp;
194
195 ChildUmask = 0770;
196 OriginalUmask = 0777;
197 ForkTid = -1;
198 UmaskTemp = my_umask(OriginalUmask);
199 LxtLogInfo("Initial umask %u", UmaskTemp);
200 LxtLogInfo("OriginalUmask %u", OriginalUmask);
201 ParentTid = -1;
202 Thread1Tid = -1;
203 Thread2Tid = -1;
204 ParentTid = my_set_tid_address(&ParentTid);
205 LxtCheckResult(ChildPid = fork());
206 if (ChildPid == 0)
207 {
208
209 //
210 // Set the clear child tid value for the new process.
211 //
212
213 ForkTid = my_set_tid_address(&ForkTid);
214 UmaskTemp = my_umask(ChildUmask);
215 LxtLogInfo("Before Thread1");
216 LxtLogInfo("Initial child umask %u", UmaskTemp);
217 LxtLogInfo("ChildUmask %u", ChildUmask);
218 LxtLogInfo("ParentTid %d", ParentTid);
219 LxtLogInfo("ForkTid %d", ForkTid);
220 LxtLogInfo("Thread1Tid %d", Thread1Tid);
221 LxtLogInfo("Thread2Tid %d", Thread2Tid);
222
223 //
224 // Spawn two threads and set a different address for each child tid.
225 //
226
227 LxtCheckErrno(pthread_create(&Thread1, NULL, SetChildTidThread, &Thread1Tid));
228 LxtCheckErrno(pthread_create(&Thread2, NULL, SetChildTidThread, LXT_INVALID_TID_ADDRESS));
229 sleep(1);
230 SavedThread1Tid = Thread1Tid;
231 UmaskTemp = my_umask(ChildUmask);
232 LxtLogInfo("After thread creation");
233 LxtLogInfo("Original umask %u", UmaskTemp);
234 LxtLogInfo("set back to ChildUmask %u", ChildUmask);
235 LxtLogInfo("ParentTid %d", ParentTid);
236 LxtLogInfo("ForkTid %d", ForkTid);
237 LxtLogInfo("Thread1Tid %d", Thread1Tid);
238 LxtLogInfo("Thread2Tid %d", Thread2Tid);
239 if (Thread1Tid == 0)
240 {
241 LxtLogError("Thread1Tid == 0 after calling set_tid_address");
242 }
243
244 //
245 // Do a futex wait on Thread1Tid and validate that it has been set to 0
246 // by the kernel. Futex will fail with EAGAIN if the value has already
247 // been set.
248 //
249
250 Return = my_futex(&Thread1Tid, FUTEX_WAIT, SavedThread1Tid, NULL, NULL, 0);
251 if (Return != 0)
252 {
253 if (errno != EAGAIN)
254 {
255 LxtLogError("futex returned unexpected error %d - %s", errno, strerror(errno));
256 }
257 }
258
259 //
260 // Don't join thread 1; pthread_join is implemented using the clear
261 // tid address, so since it has been changed it won't work.
262 //
263
264 pthread_join(Thread2, NULL);
265
266 LxtLogInfo("After Thread join and futex wait");
267 LxtLogInfo("ParentTid %d", ParentTid);
268 LxtLogInfo("ForkTid %d", ForkTid);
269 LxtLogInfo("Thread1Tid %d", Thread1Tid);
270 LxtLogInfo("Thread2Tid %d", Thread2Tid);
271 if (Thread1Tid != 0)
272 {
273 LxtLogError("Thread1Tid != 0, was %d", Thread1Tid);
274 }
275
276 if (Thread2Tid != LXT_INVALID_TID_VALUE)
277 {
278 LxtLogError("Thread2Tid != -1, was %d", Thread2Tid);
279 }
280
281 _exit(0);
282 }
283
284 LxtWaitPidPollOptions(ChildPid, 0, 0, 5);
285 LxtLogInfo("Parent after fork");
286 LxtLogInfo("ParentTid %d", ParentTid);
287 LxtLogInfo("ForkTid %d", ForkTid);
288 LxtLogInfo("Thread1Tid %d", Thread1Tid);
289 LxtLogInfo("Thread2Tid %d", Thread2Tid);
290
291 Result = LXT_RESULT_SUCCESS;
292
293 ErrorExit:
294 return Result;
295 }
296
297 int ForkPids(PLXT_ARGS Args)
298
299 /*++
300 --*/
301
302 {
303
304 pid_t ChildPid;
305 int Result;
306 pid_t ParentPid;
307 pid_t Pid;
308 pid_t WaitPidResult;
309 int WaitPidStatus;
310
311 //
312 // Basic test for fork and vfork that confirms pids are incremented by 1 to
313 // ensure syscalls were plumbed correctly. Additional tests should be added
314 // to check the many other cases for fork.
315 //
316
317 Pid = getpid();
318 if (Pid == 0)
319 {
320 Result = LXT_RESULT_FAILURE;
321 LxtLogError("getpid returned 0 for parent");
322 goto ErrorExit;
323 }
324
325 //
326 // Fork should return parent + 1 (assumes no other processes are running).
327 //
328
329 LxtCheckResult(ChildPid = fork());
330 if (ChildPid == 0)
331 {
332 Result = LXT_RESULT_SUCCESS;
333 ChildPid = getpid();
334 if (ChildPid == 0)
335 {
336 Result = LXT_RESULT_FAILURE;
337 LxtLogError("getpid returned 0 for child");
338 }
339
340 ParentPid = getppid();
341 if (ParentPid != Pid)
342 {
343 Result = LXT_RESULT_FAILURE;
344 LxtLogError("fork() Unexpected parent pid %d for child pid %d", ParentPid, ChildPid);
345 }
346
347 _exit(Result);
348 }
349
350 LxtCheckResult((WaitPidResult = waitpid(ChildPid, &WaitPidStatus, 0)));
351 if ((WIFEXITED(WaitPidStatus) == 0) || (WEXITSTATUS(WaitPidStatus) != 0))
352 {
353 Result = LXT_RESULT_FAILURE;
354 LxtLogError("Unexpected child pid exit status %d", WaitPidStatus);
355 goto ErrorExit;
356 }
357
358 LxtCheckResult(ChildPid = vfork());
359 if (ChildPid == 0)
360 {
361 Result = LXT_RESULT_SUCCESS;
362 ChildPid = getpid();
363 if (ChildPid == 0)
364 {
365 Result = LXT_RESULT_FAILURE;
366 LxtLogError("getpid returned 0 for child");
367 }
368
369 ParentPid = getppid();
370 if (ParentPid != Pid)
371 {
372 Result = LXT_RESULT_FAILURE;
373 LxtLogError("vfork() Unexpected parent pid %d for child pid %d", ParentPid, ChildPid);
374 }
375
376 _exit(Result);
377 }
378
379 LxtCheckResult((WaitPidResult = waitpid(ChildPid, &WaitPidStatus, 0)));
380 if ((WIFEXITED(WaitPidStatus) == 0) || (WEXITSTATUS(WaitPidStatus) != 0))
381 {
382 Result = LXT_RESULT_FAILURE;
383 LxtLogError("Unexpected child pid exit status %d", WaitPidStatus);
384 goto ErrorExit;
385 }
386
387 Result = LXT_RESULT_SUCCESS;
388
389 ErrorExit:
390 return Result;
391 }
392
393 int ExecvFailure(PLXT_ARGS Args)
394
395 /*++
396 --*/
397
398 {
399
400 char* CommandLine1[] = {"/foo/bar/foo/bar", NULL};
401 char* CommandLine2[] = {"/data/test/Makefile", NULL};
402 int Result;
403
404 //
405 // Check that execv fails for an invalid file name and an invalid elf file.
406 //
407
408 LxtCheckErrnoFailure(execv(CommandLine1[0], CommandLine1), ENOENT);
409 LxtCheckErrnoFailure(execv(CommandLine2[0], CommandLine2), ENOEXEC);
410
411 Result = LXT_RESULT_SUCCESS;
412
413 ErrorExit:
414 return Result;
415 }
416
417 int RobustFutex(PLXT_ARGS Args)
418
419 {
420
421 struct robust_list_head Head;
422 struct robust_list_head* HeadReturned;
423 int Result = LXT_RESULT_FAILURE;
424 size_t SizeReturned;
425
426 //
427 // Set and get the robust list.
428 //
429
430 LxtCheckResult(my_set_robust_list(&Head, sizeof(struct robust_list_head)));
431 LxtCheckResult(my_get_robust_list(0, &HeadReturned, &SizeReturned));
432
433 if (HeadReturned != &Head)
434 {
435 LxtLogError("HeadReturned %p != &Head %p", HeadReturned, &Head);
436 goto ErrorExit;
437 }
438
439 if (SizeReturned != sizeof(struct robust_list_head))
440 {
441 LxtLogError("SizeReturned %u != sizeof(struct robust_list_head) %u", SizeReturned, sizeof(struct robust_list_head));
442
443 goto ErrorExit;
444 }
445
446 //
447 // set_robust_list validates the size of the buffer.
448 //
449
450 LxtCheckErrnoFailure(my_set_robust_list(&Head, 0), EINVAL);
451 LxtCheckErrnoFailure(my_set_robust_list(&Head, (sizeof(struct robust_list_head) + 1)), EINVAL);
452
453 //
454 // get_robust_list validates the buffers.
455 //
456
457 LxtCheckErrnoFailure(my_get_robust_list(0, NULL, &SizeReturned), EFAULT);
458 LxtCheckErrnoFailure(my_get_robust_list(0, &HeadReturned, NULL), EFAULT);
459
460 //
461 // No validation is done on the buffer for set_robust_list.
462 //
463
464 LxtCheckResult(my_set_robust_list(NULL, sizeof(struct robust_list_head)));
465 LxtCheckResult(my_set_robust_list((void*)-1, sizeof(struct robust_list_head)));
466
467 Result = LXT_RESULT_SUCCESS;
468
469 ErrorExit:
470 return Result;
471 }
472
473 int CloneFs(PLXT_ARGS Args)
474
475 /*++
476 --*/
477
478 {
479
480 char BackupCwd[256];
481 pid_t ChildPid;
482 char Path[256];
483 bool RestoreCwd;
484 int Result;
485
486 ChildPid = -1;
487 RestoreCwd = false;
488 LxtLogInfo("cwd = %s", getcwd(BackupCwd, sizeof(BackupCwd)));
489 LxtCheckResult(ChildPid = LxtCloneSyscall((CLONE_FS | SIGCHLD), NULL, NULL, NULL, NULL));
490 if (ChildPid == 0)
491 {
492 LxtCheckErrno(chdir(LXT_TEST_CWD));
493 LxtLogInfo("child cwd = %s", getcwd(Path, sizeof(Path)));
494 goto ErrorExit;
495 }
496
497 //
498 // Wait for the child to exit.
499 //
500
501 RestoreCwd = true;
502 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
503
504 //
505 // Ensure the parent's current working directory was changed.
506 //
507
508 LxtLogInfo("parent cwd = %s", getcwd(Path, sizeof(Path)));
509 LxtCheckStringEqual(Path, LXT_TEST_CWD);
510
511 ErrorExit:
512 if (ChildPid == 0)
513 {
514 _exit(Result);
515 }
516
517 if (RestoreCwd != false)
518 {
519 chdir(BackupCwd);
520 }
521
522 return Result;
523 }
524
525 int CloneInvalidFlags(PLXT_ARGS Args)
526
527 /*++
528 --*/
529
530 {
531
532 pid_t ChildPid;
533 int Result;
534
535 ChildPid = -1;
536
537 //
538 // Check for failure cases.
539 //
540
541 LxtCheckErrnoFailure(ChildPid = LxtCloneSyscall(CLONE_SIGHAND, NULL, NULL, NULL, NULL), EINVAL);
542 LxtCheckErrnoFailure(ChildPid = LxtCloneSyscall(CLONE_THREAD, NULL, NULL, NULL, NULL), EINVAL);
543 LxtCheckErrnoFailure(ChildPid = LxtCloneSyscall((CLONE_FS | CLONE_NEWNS), NULL, NULL, NULL, NULL), EINVAL);
544
545 ErrorExit:
546 if (ChildPid == 0)
547 {
548 _exit(Result);
549 }
550
551 return Result;
552 }
553
554 struct CloneThreadArgs
555 {
556 long Fs0;
557 unsigned long FsBase;
558 unsigned long GsBase;
559 };
560
561 int CloneThreadEntry(void* Argument)
562
563 {
564
565 struct CloneThreadArgs* Args;
566 unsigned long FsBase;
567 int Result;
568
569 Args = Argument;
570 Result = 0;
571
572 //
573 // Make sure TLS values can be read without SIGSEGV.
574 //
575
576 #if defined(__amd64__)
577
578 __asm("movq %%fs:0, %0" : "=r"(Args->Fs0));
579 syscall(SYS_arch_prctl, ARCH_GET_FS, &FsBase);
580 Result = (Args->FsBase != FsBase);
581 Args->FsBase = FsBase;
582 syscall(SYS_arch_prctl, ARCH_GET_GS, &Args->GsBase);
583
584 #endif
585
586 syscall(SYS_exit, Result);
587 return Result;
588 }
589
590 int CloneThread(PLXT_ARGS Args)
591
592 {
593
594 struct CloneThreadArgs ThreadArgs;
595 int Flags;
596 unsigned long FsBase;
597 pid_t Pid;
598 int Result;
599 char* Stack;
600 size_t StackSize;
601 int Status;
602 pid_t Tid;
603 long Tls[1];
604
605 StackSize = 1024 * 1024;
606 Stack = malloc(StackSize);
607 Tls[0] = (long)&Tls[0];
608 Flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
609
610 //
611 // Clone without setting TLS.
612 //
613
614 LxtCheckErrno(clone(CloneThreadEntry, Stack + StackSize, Flags, &ThreadArgs, &Tid, NULL, &Tid));
615 LxtCheckErrno(LxtJoinThread(&Tid));
616
617 #if defined(__amd64__)
618
619 LxtCheckErrno(syscall(SYS_arch_prctl, ARCH_GET_FS, &FsBase));
620 LxtCheckEqual(ThreadArgs.FsBase, FsBase, "%lx");
621
622 #endif
623
624 //
625 // Clone and set TLS.
626 //
627
628 ThreadArgs.Fs0 = 0;
629 ThreadArgs.FsBase = 0;
630 ThreadArgs.GsBase = 0;
631
632 #if defined(__amd64__)
633
634 LxtCheckErrno(syscall(SYS_arch_prctl, ARCH_SET_GS, &ThreadArgs));
635
636 #endif
637
638 LxtCheckErrno(clone(CloneThreadEntry, Stack + StackSize, Flags | CLONE_SETTLS, &ThreadArgs, &Tid, Tls, &Tid));
639 LxtCheckErrno(LxtJoinThread(&Tid));
640
641 #if defined(__amd64__)
642
643 LxtCheckEqual(ThreadArgs.Fs0, Tls[0], "%ld");
644 LxtCheckEqual(ThreadArgs.FsBase, (unsigned long)&Tls[0], "%lx");
645
646 //
647 // Ensure GS base is inherited.
648 //
649
650 LxtCheckEqual(ThreadArgs.GsBase, (unsigned long)&ThreadArgs, "%lx");
651
652 #endif
653
654 //
655 // Disallow invalid TLS values.
656 //
657
658 LxtCheckErrnoFailure(clone(CloneThreadEntry, Stack + StackSize, Flags | CLONE_SETTLS, NULL, &Tid, (void*)-1, &Tid), EPERM);
659 LxtCheckErrno(LxtJoinThread(&Tid));
660
661 //
662 // Set TLS on thread group clone too.
663 //
664
665 ThreadArgs.FsBase = (unsigned long)&Tls[0];
666 LxtCheckErrno(Pid = clone(CloneThreadEntry, Stack + StackSize, CLONE_SETTLS | SIGCHLD, &ThreadArgs, NULL, Tls, NULL));
667 LxtCheckErrno(waitpid(Pid, &Status, 0));
668 if (!WIFEXITED(Status) || WEXITSTATUS(Status) != 0)
669 {
670 LxtLogError("FS check failed: %x", Status);
671 }
672
673 ErrorExit:
674 free(Stack);
675 return Result;
676 }
677
678 int VForkTestBasicChild(void* Param)
679
680 {
681
682 return 0;
683 }
684
685 int VForkTestBasic(PLXT_ARGS Args)
686
687 /*++
688 --*/
689
690 {
691
692 LXT_CLONE_ARGS CloneArgs;
693 pid_t ChildPid;
694 pid_t Pid;
695 int Result;
696
697 ChildPid = -1;
698
699 //
700 // Check that vfork runs in a new threadgroup.
701 //
702
703 Pid = LxtGetTid();
704 LxtCheckErrno(ChildPid = vfork());
705 if (ChildPid == 0)
706 {
707 _exit(LXT_RESULT_SUCCESS);
708 }
709
710 LxtCheckNotEqual(Pid, ChildPid, "%d");
711 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
712
713 //
714 // Repeat the above with the clone variant of vfork.
715 //
716
717 LxtCheckErrno(ChildPid = LxtCloneSyscall(CLONE_VM | CLONE_VFORK | SIGCHLD, NULL, NULL, NULL, NULL));
718 if (ChildPid == 0)
719 {
720 _exit(LXT_RESULT_SUCCESS);
721 }
722
723 LxtCheckNotEqual(Pid, ChildPid, "%d");
724 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
725 Result = LXT_RESULT_SUCCESS;
726
727 ErrorExit:
728 if ((Result < 0) && (ChildPid != 0))
729 {
730 _exit(Result);
731 }
732
733 return Result;
734 }
735
736 int VForkTest(PLXT_ARGS Args)
737
738 /*++
739 --*/
740
741 {
742
743 char* ChildCmdLine[] = {WSL_UNIT_TEST_BINARY, Args->Argv[0], "-l", "2", "-v", "32", NULL};
744
745 LxtLogInfo("VForkTest ChildCmdLine: %s %s", ChildCmdLine[0], ChildCmdLine[1]);
746
747 pid_t ChildPid;
748 pid_t ChildPidFromChild;
749 pid_t ChildPidFromChildNested;
750 pid_t ChildPidNested;
751 unsigned short ControlWord;
752 unsigned short OriginalControlWord;
753 char* InvalidCmdLine[] = {"/data/test/Makefile", NULL};
754 pid_t Pid;
755 int Result;
756
757 ChildPid = -1;
758 ChildPidFromChild = -1;
759 ChildPidFromChild = -1;
760 ChildPidFromChildNested = -1;
761 ChildPidNested = -1;
762 LxtCheckResult(LxtSignalInitialize());
763
764 //
765 // Check that vfork runs in a new threadgroup but in the same address space.
766 //
767
768 Pid = LxtGetTid();
769 LxtCheckErrno(ChildPid = vfork());
770 if (ChildPid == 0)
771 {
772 ChildPidFromChild = LxtGetTid();
773 _exit(LXT_RESULT_SUCCESS);
774 }
775
776 LxtCheckNotEqual(Pid, ChildPidFromChild, "%d");
777 LxtCheckEqual(ChildPid, ChildPidFromChild, "%d");
778 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
779
780 //
781 // Release the above with execv.
782 //
783
784 ChildPidFromChild = -1;
785 Pid = LxtGetTid();
786 LxtCheckErrno(ChildPid = vfork());
787 if (ChildPid == 0)
788 {
789 ChildPidFromChild = LxtGetTid();
790 LxtCheckErrno(execv(ChildCmdLine[0], ChildCmdLine));
791 _exit(LXT_RESULT_FAILURE);
792 }
793
794 LxtCheckNotEqual(Pid, ChildPidFromChild, "%d");
795 LxtCheckEqual(ChildPid, ChildPidFromChild, "%d");
796 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
797
798 //
799 // Repeat the above with execv failure.
800 //
801
802 ChildPidFromChild = -1;
803 Pid = LxtGetTid();
804 LxtCheckErrno(ChildPid = vfork());
805 if (ChildPid == 0)
806 {
807 ChildPidFromChild = LxtGetTid();
808 LxtCheckErrnoFailure(execv(InvalidCmdLine[0], InvalidCmdLine), ENOEXEC);
809 _exit(LXT_RESULT_SUCCESS);
810 }
811
812 LxtCheckNotEqual(Pid, ChildPidFromChild, "%d");
813 LxtCheckEqual(ChildPid, ChildPidFromChild, "%d");
814 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
815
816 //
817 // Check that signals sent to the parent after the
818 // parent releases the address space.
819 //
820
821 LxtCheckResult(LxtSignalSetupHandler(SIGUSR1, 0));
822 ChildPidFromChild = -1;
823 Pid = LxtGetTid();
824 LxtCheckErrno(ChildPid = vfork());
825 if (ChildPid == 0)
826 {
827 ChildPidFromChild = LxtGetTid();
828 LxtSignalInitializeThread();
829 LxtCheckErrno(LxtTKill(Pid, SIGUSR1));
830 LxtCheckResult(LxtSignalCheckNoSignal());
831 _exit(LXT_RESULT_SUCCESS);
832 }
833
834 LxtCheckNotEqual(Pid, ChildPidFromChild, "%d");
835 LxtCheckEqual(ChildPid, ChildPidFromChild, "%d");
836 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
837 LxtCheckResult(LxtSignalCheckReceived(SIGUSR1));
838 LxtSignalResetReceived();
839
840 //
841 // Check the behavior for nested vfork.
842 //
843
844 Pid = LxtGetTid();
845 LxtCheckErrno(ChildPid = vfork());
846 if (ChildPid == 0)
847 {
848 ChildPidFromChild = LxtGetTid();
849 LxtCheckErrno(ChildPidNested = vfork());
850 if (ChildPidNested == 0)
851 {
852 ChildPidFromChildNested = LxtGetTid();
853 _exit(LXT_RESULT_SUCCESS);
854 }
855
856 LxtCheckNotEqual(ChildPid, ChildPidFromChildNested, "%d");
857 LxtCheckEqual(ChildPidNested, ChildPidFromChildNested, "%d");
858 LxtCheckResult(LxtWaitPidPoll(ChildPidNested, LXT_RESULT_SUCCESS));
859 _exit(LXT_RESULT_SUCCESS);
860 }
861
862 LxtCheckNotEqual(Pid, ChildPidFromChild, "%d");
863 LxtCheckEqual(ChildPid, ChildPidFromChild, "%d");
864 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
865
866 #if defined(__i386__) || defined(__amd64__)
867
868 //
869 // Check that floating point context is preserved across vfork.
870 //
871
872 _FPU_GETCW(OriginalControlWord);
873 // LX_TODO: Initial control word is not being set correctly
874 // LxtCheckEqual(LXT_CONTROL_WORD_DEFAULT, OriginalControlWord, "%hu");
875 Pid = LxtGetTid();
876 LxtCheckErrno(ChildPid = vfork());
877 if (ChildPid == 0)
878 {
879 ChildPidFromChild = LxtGetTid();
880 ControlWord = LXT_CONTROL_WORD_NEW;
881 _FPU_SETCW(ControlWord);
882 _FPU_GETCW(ControlWord);
883 LxtCheckEqual(LXT_CONTROL_WORD_NEW, ControlWord, "%hu");
884 _exit(LXT_RESULT_SUCCESS);
885 }
886
887 _FPU_GETCW(ControlWord);
888 LxtCheckEqual(OriginalControlWord, ControlWord, "%hu");
889 LxtCheckNotEqual(Pid, ChildPidFromChild, "%d");
890 LxtCheckEqual(ChildPid, ChildPidFromChild, "%d");
891 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
892
893 #endif
894
895 //
896 // Check the stack pointer isn't modified across vfork.
897 //
898
899 {
900 register unsigned long Rsp GET_STACK_POINTER;
901 LxtCheckNotEqual(Rsp, 0, "%lu");
902 Pid = LxtGetTid();
903 alloca(1024);
904 LxtCheckErrno(ChildPid = vfork());
905 if (ChildPid == 0)
906 {
907 register unsigned long RspChild GET_STACK_POINTER;
908 LxtCheckEqual(Rsp, RspChild, "%lu");
909 ChildPidFromChild = LxtGetTid();
910 _exit(LXT_RESULT_SUCCESS);
911 }
912
913 LxtCheckNotEqual(Pid, ChildPidFromChild, "%d");
914 LxtCheckEqual(ChildPid, ChildPidFromChild, "%d");
915 LxtCheckResult(LxtWaitPidPoll(ChildPid, LXT_RESULT_SUCCESS));
916 }
917
918 Result = LXT_RESULT_SUCCESS;
919
920 ErrorExit:
921 if (ChildPid == 0)
922 {
923 _exit(Result);
924 }
925
926 return Result;
927 }
928
929 struct CloneFlagArgs
930 {
931 int Test;
932 int Flags;
933 int Fd;
934 };
935
936 int CloneFlags[] = {
937 SIGCHLD,
938 SIGCHLD | CLONE_FS,
939 SIGCHLD | CLONE_FILES,
940 SIGCHLD | CLONE_FS | CLONE_FILES,
941 SIGCHLD | CLONE_VFORK,
942 SIGUSR1,
943 0,
944 125, // invalid signal
945 CLONE_THREAD | CLONE_VM | CLONE_SIGHAND,
946 CLONE_THREAD | CLONE_VM | CLONE_SIGHAND | CLONE_FS,
947 CLONE_THREAD | CLONE_VM | CLONE_SIGHAND | CLONE_FILES,
948 CLONE_THREAD | CLONE_VM | CLONE_SIGHAND | CLONE_FS | CLONE_FILES,
949 CLONE_THREAD | CLONE_VM | CLONE_SIGHAND | CLONE_VFORK,
950 SIGCHLD | CLONE_THREAD | CLONE_VM | CLONE_SIGHAND,
951 125 | CLONE_THREAD | CLONE_VM | CLONE_SIGHAND,
952 };
953
954 int CloneFlagEntry(void* Arg)
955
956 {
957
958 struct CloneFlagArgs* FlagArgs = Arg;
959 close(FlagArgs->Fd);
960 chdir("/");
961 syscall(SYS_exit, 0);
962 return 0;
963 }
964
965 int CloneTestFlags(PLXT_ARGS Args)
966
967 {
968
969 int Result;
970 char __attribute__((aligned(16))) Stack[65536];
971
972 int Root;
973 LxtCheckErrno(Root = open(".", O_RDONLY));
974
975 for (int Test = 0; Test < sizeof(CloneFlags) / sizeof(CloneFlags[0]); Test++)
976 {
977 int Flags = CloneFlags[Test];
978
979 int Fd;
980 LxtCheckErrno(Fd = dup(Root));
981
982 int TermSignal = Flags & 0xff;
983 if ((Flags & CLONE_THREAD) != 0 || TermSignal < 1 || TermSignal > 64)
984 {
985 TermSignal = 0;
986 }
987
988 if (TermSignal != 0 && TermSignal != SIGCHLD)
989 {
990 signal(TermSignal, SIG_IGN);
991 }
992
993 LxtLogInfo("Test %d: Flags 0x%x", Test, Flags);
994
995 struct CloneFlagArgs FlagArgs = {0};
996 FlagArgs.Test = Test;
997 FlagArgs.Flags = Flags;
998 FlagArgs.Fd = Fd;
999
1000 if (Flags & CLONE_THREAD)
1001 {
1002 Flags |= CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID;
1003 }
1004
1005 int Pid;
1006 int Tid;
1007 LxtCheckErrno(Pid = clone(CloneFlagEntry, Stack + sizeof(Stack), Flags, &FlagArgs, &Tid, NULL, &Tid));
1008
1009 if (Flags & CLONE_THREAD)
1010 {
1011 LxtCheckErrnoFailure(waitpid(Pid, NULL, __WALL), ECHILD);
1012 LxtCheckErrno(LxtJoinThread(&Tid));
1013 }
1014 else if (TermSignal == SIGCHLD)
1015 {
1016 LxtCheckErrnoFailure(waitpid(Pid, NULL, __WCLONE), ECHILD);
1017 LxtCheckErrno(waitpid(Pid, NULL, 0));
1018 }
1019 else
1020 {
1021 LxtCheckErrnoFailure(waitpid(Pid, NULL, 0), ECHILD);
1022 LxtCheckErrno(waitpid(Pid, NULL, __WCLONE));
1023 }
1024
1025 if (TermSignal != 0)
1026 {
1027 signal(TermSignal, SIG_DFL);
1028 }
1029
1030 if (Flags & CLONE_FILES)
1031 {
1032 // Make sure Fd is not open.
1033 LxtCheckErrnoFailure(fcntl(Fd, F_GETFL), EBADF);
1034 }
1035 else
1036 {
1037 // Make sure Fd is still open.
1038 LxtCheckErrno(fcntl(Fd, F_GETFL));
1039 close(Fd);
1040 }
1041
1042 char Path[1024] = {0};
1043 LxtCheckErrno(LxtGetcwd(Path, sizeof(Path)));
1044 if (Flags & CLONE_FS)
1045 {
1046 if (strcmp(Path, "/") != 0)
1047 {
1048 LxtLogError("Root directory did not change from %s.", Path);
1049 }
1050 fchdir(Root);
1051 }
1052 else
1053 {
1054 if (strcmp(Path, "/") == 0)
1055 {
1056 LxtLogError("Root directory changed.");
1057 }
1058 }
1059 }
1060
1061 Result = 0;
1062
1063 ErrorExit:
1064 return Result;
1065 }
1066
1067 int CloneTestSignalEntry(void* Arg)
1068 {
1069 //
1070 // Make sure the two SIGCHLD signals don't coalesce.
1071 //
1072
1073 usleep(500000);
1074 syscall(SYS_exit, 0);
1075 return 1;
1076 }
1077
1078 static int CloneTestSignalArrived;
1079
1080 void CloneTestSignalHandler(int Signal, siginfo_t* Info, void* Extra)
1081 {
1082
1083 CloneTestSignalArrived++;
1084 }
1085
1086 int CloneTestSignalParent(PLXT_ARGS Args)
1087 {
1088
1089 int Result;
1090
1091 LxtCheckErrno(LxtSignalInitialize());
1092 LxtCheckErrno(LxtSignalBlock(SIGCHLD));
1093
1094 int Pid = 0;
1095 volatile int ChildPid = 0;
1096 LxtCheckErrno(Pid = vfork());
1097 if (Pid == 0)
1098 {
1099 char Stack[65536];
1100
1101 //
1102 // Even though SIGUSR1 is passed here, SIGCHLD should be the
1103 // received signal since CLONE_PARENT is also passed
1104 // (SIGCHLD comes from the vfork call above).
1105 //
1106
1107 ChildPid = clone(CloneTestSignalEntry, Stack + sizeof(Stack), SIGUSR1 | CLONE_PARENT, NULL);
1108
1109 _exit(0);
1110 }
1111
1112 LxtCheckErrno(LxtSignalWaitBlocked(SIGCHLD, Pid, 1));
1113 int Status;
1114 LxtCheckErrno(waitpid(Pid, &Status, 0));
1115
1116 LxtCheckErrno(ChildPid);
1117 LxtCheckErrno(LxtSignalWaitBlocked(SIGCHLD, ChildPid, 1));
1118 LxtCheckErrno(waitpid(ChildPid, NULL, 0));
1119 Result = 0;
1120
1121 ErrorExit:
1122 return Result;
1123 }