Add script to devel-static as well
[platform/upstream/glibc.git] / nptl / tst-setuid1.c
1 /* Copyright (C) 2004-2023 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17
18 #include <pthread.h>
19 #include <pwd.h>
20 #include <grp.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <sys/wait.h>
24 #include <unistd.h>
25
26
27 static pthread_barrier_t b3, b4;
28 static uid_t prev_ruid, prev_euid, prev_suid, nobody_uid;
29 static gid_t prev_rgid, prev_egid, prev_sgid, nobody_gid;
30 enum ACTION { PREPARE, SET, CHECK_BEFORE, CHECK_AFTER };
31 #define TESTNO(arg) ((long int) (arg) & 0xff)
32 #define THREADNO(arg) ((long int) (arg) >> 8)
33
34
35 static void
36 check_prev_uid (int tno)
37 {
38   uid_t ruid, euid, suid;
39   if (getresuid (&ruid, &euid, &suid) < 0)
40     {
41       printf ("getresuid failed: %d %m\n", tno);
42       exit (1);
43     }
44
45   if (ruid != prev_ruid || euid != prev_euid || suid != prev_suid)
46     {
47       printf ("uids before in %d (%d %d %d) != (%d %d %d)\n", tno,
48               ruid, euid, suid, prev_ruid, prev_euid, prev_suid);
49       exit (1);
50     }
51 }
52
53
54 static void
55 check_prev_gid (int tno)
56 {
57   gid_t rgid, egid, sgid;
58   if (getresgid (&rgid, &egid, &sgid) < 0)
59     {
60       printf ("getresgid failed: %d %m\n", tno);
61       exit (1);
62     }
63
64   if (rgid != prev_rgid || egid != prev_egid || sgid != prev_sgid)
65     {
66       printf ("gids before in %d (%d %d %d) != (%d %d %d)\n", tno,
67               rgid, egid, sgid, prev_rgid, prev_egid, prev_sgid);
68       exit (1);
69     }
70 }
71
72
73 static void
74 test_setuid1 (enum ACTION action, int tno)
75 {
76   if (action == PREPARE)
77     return;
78
79   if (action != CHECK_AFTER)
80     check_prev_uid (tno);
81
82   if (action == SET && setuid (nobody_uid) < 0)
83     {
84        printf ("setuid failed: %m\n");
85        exit (1);
86     }
87
88   if (action != CHECK_BEFORE)
89     {
90       uid_t ruid, euid, suid;
91       if (getresuid (&ruid, &euid, &suid) < 0)
92         {
93           printf ("getresuid failed: %d %m\n", tno);
94           exit (1);
95         }
96
97       if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
98         {
99           printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
100                   ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
101           exit (1);
102         }
103     }
104 }
105
106
107 static void
108 test_setuid2 (enum ACTION action, int tno)
109 {
110   if (action == PREPARE)
111     {
112       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
113         {
114           printf ("setresuid failed: %m\n");
115           exit (1);
116         }
117
118       prev_ruid = nobody_uid;
119       prev_euid = nobody_uid;
120       return;
121     }
122
123   if (action != CHECK_AFTER)
124     check_prev_uid (tno);
125
126   if (action == SET && setuid (prev_suid) < 0)
127     {
128       printf ("setuid failed: %m\n");
129       exit (1);
130     }
131
132   if (action != CHECK_BEFORE)
133     {
134       uid_t ruid, euid, suid;
135       if (getresuid (&ruid, &euid, &suid) < 0)
136         {
137           printf ("getresuid failed: %d %m\n", tno);
138           exit (1);
139         }
140
141       if (ruid != nobody_uid || euid != prev_suid || suid != prev_suid)
142         {
143           printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
144                   ruid, euid, suid, nobody_uid, prev_suid, prev_suid);
145           exit (1);
146         }
147     }
148 }
149
150
151 static void
152 test_seteuid1 (enum ACTION action, int tno)
153 {
154   if (action == PREPARE)
155     return;
156
157   if (action != CHECK_AFTER)
158     check_prev_uid (tno);
159
160   if (action == SET && seteuid (nobody_uid) < 0)
161     {
162        printf ("seteuid failed: %m\n");
163        exit (1);
164     }
165
166   if (action != CHECK_BEFORE)
167     {
168       uid_t ruid, euid, suid;
169       if (getresuid (&ruid, &euid, &suid) < 0)
170         {
171           printf ("getresuid failed: %d %m\n", tno);
172           exit (1);
173         }
174
175       if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
176         {
177           printf ("after seteuid %d (%d %d %d) != (%d %d %d)\n", tno,
178                   ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
179           exit (1);
180         }
181     }
182 }
183
184
185 static void
186 test_seteuid2 (enum ACTION action, int tno)
187 {
188   if (action == PREPARE)
189     {
190       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
191         {
192           printf ("setresuid failed: %m\n");
193           exit (1);
194         }
195
196       prev_ruid = nobody_uid;
197       prev_euid = nobody_uid;
198       nobody_uid = prev_suid;
199       return;
200     }
201
202   test_seteuid1 (action, tno);
203 }
204
205
206 static void
207 test_setreuid1 (enum ACTION action, int tno)
208 {
209   if (action == PREPARE)
210     return;
211
212   if (action != CHECK_AFTER)
213     check_prev_uid (tno);
214
215   if (action == SET && setreuid (-1, nobody_uid) < 0)
216     {
217        printf ("setreuid failed: %m\n");
218        exit (1);
219     }
220
221   if (action != CHECK_BEFORE)
222     {
223       uid_t ruid, euid, suid, esuid;
224       if (getresuid (&ruid, &euid, &suid) < 0)
225         {
226           printf ("getresuid failed: %d %m\n", tno);
227           exit (1);
228         }
229
230       if (prev_ruid != nobody_uid)
231         esuid = nobody_uid;
232       else
233         esuid = prev_suid;
234
235       if (ruid != prev_ruid || euid != nobody_uid || suid != esuid)
236         {
237           printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
238                   ruid, euid, suid, prev_ruid, nobody_uid, esuid);
239           exit (1);
240         }
241     }
242 }
243
244
245 static void
246 test_setreuid2 (enum ACTION action, int tno)
247 {
248   if (action == PREPARE)
249     return;
250
251   if (action != CHECK_AFTER)
252     check_prev_uid (tno);
253
254   if (action == SET && setreuid (nobody_uid, -1) < 0)
255     {
256        printf ("setreuid failed: %m\n");
257        exit (1);
258     }
259
260   if (action != CHECK_BEFORE)
261     {
262       uid_t ruid, euid, suid;
263       if (getresuid (&ruid, &euid, &suid) < 0)
264         {
265           printf ("getresuid failed: %d %m\n", tno);
266           exit (1);
267         }
268
269       if (ruid != nobody_uid || euid != prev_euid || suid != prev_euid)
270         {
271           printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
272                   ruid, euid, suid, nobody_uid, prev_euid, prev_euid);
273           exit (1);
274         }
275     }
276 }
277
278
279 static void
280 test_setreuid3 (enum ACTION action, int tno)
281 {
282   if (action == PREPARE)
283     return;
284
285   if (action != CHECK_AFTER)
286     check_prev_uid (tno);
287
288   if (action == SET && setreuid (nobody_uid, nobody_uid) < 0)
289     {
290        printf ("setreuid failed: %m\n");
291        exit (1);
292     }
293
294   if (action != CHECK_BEFORE)
295     {
296       uid_t ruid, euid, suid;
297       if (getresuid (&ruid, &euid, &suid) < 0)
298         {
299           printf ("getresuid failed: %d %m\n", tno);
300           exit (1);
301         }
302
303       if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
304         {
305           printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
306                   ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
307           exit (1);
308         }
309     }
310 }
311
312
313 static void
314 test_setreuid4 (enum ACTION action, int tno)
315 {
316   if (action == PREPARE)
317     {
318       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
319         {
320           printf ("setresuid failed: %m\n");
321           exit (1);
322         }
323
324       prev_ruid = nobody_uid;
325       prev_euid = nobody_uid;
326       nobody_uid = prev_suid;
327       return;
328     }
329
330   test_setreuid1 (action, tno);
331 }
332
333
334 static void
335 test_setresuid1 (enum ACTION action, int tno)
336 {
337   if (action == PREPARE)
338     return;
339
340   if (action != CHECK_AFTER)
341     check_prev_uid (tno);
342
343   if (action == SET && setresuid (-1, nobody_uid, -1) < 0)
344     {
345        printf ("setresuid failed: %m\n");
346        exit (1);
347     }
348
349   if (action != CHECK_BEFORE)
350     {
351       uid_t ruid, euid, suid;
352       if (getresuid (&ruid, &euid, &suid) < 0)
353         {
354           printf ("getresuid failed: %d %m\n", tno);
355           exit (1);
356         }
357
358       if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
359         {
360           printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
361                   ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
362           exit (1);
363         }
364     }
365 }
366
367
368 static void
369 test_setresuid2 (enum ACTION action, int tno)
370 {
371   if (action == PREPARE)
372     return;
373
374   if (action != CHECK_AFTER)
375     check_prev_uid (tno);
376
377   if (action == SET && setresuid (prev_euid, nobody_uid, nobody_uid) < 0)
378     {
379        printf ("setresuid failed: %m\n");
380        exit (1);
381     }
382
383   if (action != CHECK_BEFORE)
384     {
385       uid_t ruid, euid, suid;
386       if (getresuid (&ruid, &euid, &suid) < 0)
387         {
388           printf ("getresuid failed: %d %m\n", tno);
389           exit (1);
390         }
391
392       if (ruid != prev_euid || euid != nobody_uid || suid != nobody_uid)
393         {
394           printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
395                   ruid, euid, suid, prev_euid, nobody_uid, nobody_uid);
396           exit (1);
397         }
398     }
399 }
400
401
402 static void
403 test_setresuid3 (enum ACTION action, int tno)
404 {
405   if (action == PREPARE)
406     return;
407
408   if (action != CHECK_AFTER)
409     check_prev_uid (tno);
410
411   if (action == SET && setresuid (nobody_uid, nobody_uid, nobody_uid) < 0)
412     {
413        printf ("setresuid failed: %m\n");
414        exit (1);
415     }
416
417   if (action != CHECK_BEFORE)
418     {
419       uid_t ruid, euid, suid;
420       if (getresuid (&ruid, &euid, &suid) < 0)
421         {
422           printf ("getresuid failed: %d %m\n", tno);
423           exit (1);
424         }
425
426       if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
427         {
428           printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
429                   ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
430           exit (1);
431         }
432     }
433 }
434
435
436 static void
437 test_setresuid4 (enum ACTION action, int tno)
438 {
439   if (action == PREPARE)
440     {
441       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
442         {
443           printf ("setresuid failed: %m\n");
444           exit (1);
445         }
446
447       prev_ruid = nobody_uid;
448       prev_euid = nobody_uid;
449       nobody_uid = prev_suid;
450       return;
451     }
452
453   test_setresuid1 (action, tno);
454 }
455
456
457 static void
458 test_setgid1 (enum ACTION action, int tno)
459 {
460   if (action == PREPARE)
461     return;
462
463   if (action != CHECK_AFTER)
464     check_prev_gid (tno);
465
466   if (action == SET && setgid (nobody_gid) < 0)
467     {
468        printf ("setgid failed: %m\n");
469        exit (1);
470     }
471
472   if (action != CHECK_BEFORE)
473     {
474       gid_t rgid, egid, sgid;
475       if (getresgid (&rgid, &egid, &sgid) < 0)
476         {
477           printf ("getresgid failed: %d %m\n", tno);
478           exit (1);
479         }
480
481       if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
482         {
483           printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
484                   rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
485           exit (1);
486         }
487     }
488 }
489
490
491 static void
492 test_setgid2 (enum ACTION action, int tno)
493 {
494   if (action == PREPARE)
495     {
496       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
497         {
498           printf ("setresgid failed: %m\n");
499           exit (1);
500         }
501
502       prev_rgid = nobody_gid;
503       prev_egid = nobody_gid;
504
505       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
506         {
507           printf ("setresuid failed: %m\n");
508           exit (1);
509         }
510
511       prev_ruid = nobody_uid;
512       prev_euid = nobody_uid;
513       return;
514     }
515
516   if (action != CHECK_AFTER)
517     check_prev_gid (tno);
518
519   if (action == SET && setgid (prev_sgid) < 0)
520     {
521       printf ("setgid failed: %m\n");
522       exit (1);
523     }
524
525   if (action != CHECK_BEFORE)
526     {
527       gid_t rgid, egid, sgid;
528       if (getresgid (&rgid, &egid, &sgid) < 0)
529         {
530           printf ("getresgid failed: %d %m\n", tno);
531           exit (1);
532         }
533
534       if (rgid != nobody_gid || egid != prev_sgid || sgid != prev_sgid)
535         {
536           printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
537                   rgid, egid, sgid, nobody_gid, prev_sgid, prev_sgid);
538           exit (1);
539         }
540     }
541 }
542
543
544 static void
545 test_setegid1 (enum ACTION action, int tno)
546 {
547   if (action == PREPARE)
548     return;
549
550   if (action != CHECK_AFTER)
551     check_prev_gid (tno);
552
553   if (action == SET && setegid (nobody_gid) < 0)
554     {
555        printf ("setegid failed: %m\n");
556        exit (1);
557     }
558
559   if (action != CHECK_BEFORE)
560     {
561       gid_t rgid, egid, sgid;
562       if (getresgid (&rgid, &egid, &sgid) < 0)
563         {
564           printf ("getresgid failed: %d %m\n", tno);
565           exit (1);
566         }
567
568       if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
569         {
570           printf ("after setegid %d (%d %d %d) != (%d %d %d)\n", tno,
571                   rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
572           exit (1);
573         }
574     }
575 }
576
577
578 static void
579 test_setegid2 (enum ACTION action, int tno)
580 {
581   if (action == PREPARE)
582     {
583       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
584         {
585           printf ("setresgid failed: %m\n");
586           exit (1);
587         }
588
589       prev_rgid = nobody_gid;
590       prev_egid = nobody_gid;
591       nobody_gid = prev_sgid;
592       return;
593     }
594
595   test_setegid1 (action, tno);
596 }
597
598
599 static void
600 test_setregid1 (enum ACTION action, int tno)
601 {
602   if (action == PREPARE)
603     return;
604
605   if (action != CHECK_AFTER)
606     check_prev_gid (tno);
607
608   if (action == SET && setregid (-1, nobody_gid) < 0)
609     {
610        printf ("setregid failed: %m\n");
611        exit (1);
612     }
613
614   if (action != CHECK_BEFORE)
615     {
616       gid_t rgid, egid, sgid, esgid;
617       if (getresgid (&rgid, &egid, &sgid) < 0)
618         {
619           printf ("getresgid failed: %d %m\n", tno);
620           exit (1);
621         }
622
623       if (prev_rgid != nobody_gid)
624         esgid = nobody_gid;
625       else
626         esgid = prev_sgid;
627
628       if (rgid != prev_rgid || egid != nobody_gid || sgid != esgid)
629         {
630           printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
631                   rgid, egid, sgid, prev_rgid, nobody_gid, esgid);
632           exit (1);
633         }
634     }
635 }
636
637
638 static void
639 test_setregid2 (enum ACTION action, int tno)
640 {
641   if (action == PREPARE)
642     return;
643
644   if (action != CHECK_AFTER)
645     check_prev_gid (tno);
646
647   if (action == SET && setregid (nobody_gid, -1) < 0)
648     {
649        printf ("setregid failed: %m\n");
650        exit (1);
651     }
652
653   if (action != CHECK_BEFORE)
654     {
655       gid_t rgid, egid, sgid;
656       if (getresgid (&rgid, &egid, &sgid) < 0)
657         {
658           printf ("getresgid failed: %d %m\n", tno);
659           exit (1);
660         }
661
662       if (rgid != nobody_gid || egid != prev_egid || sgid != prev_egid)
663         {
664           printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
665                   rgid, egid, sgid, nobody_gid, prev_egid, prev_egid);
666           exit (1);
667         }
668     }
669 }
670
671
672 static void
673 test_setregid3 (enum ACTION action, int tno)
674 {
675   if (action == PREPARE)
676     return;
677
678   if (action != CHECK_AFTER)
679     check_prev_gid (tno);
680
681   if (action == SET && setregid (nobody_gid, nobody_gid) < 0)
682     {
683        printf ("setregid failed: %m\n");
684        exit (1);
685     }
686
687   if (action != CHECK_BEFORE)
688     {
689       gid_t rgid, egid, sgid;
690       if (getresgid (&rgid, &egid, &sgid) < 0)
691         {
692           printf ("getresgid failed: %d %m\n", tno);
693           exit (1);
694         }
695
696       if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
697         {
698           printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
699                   rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
700           exit (1);
701         }
702     }
703 }
704
705
706 static void
707 test_setregid4 (enum ACTION action, int tno)
708 {
709   if (action == PREPARE)
710     {
711       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
712         {
713           printf ("setresgid failed: %m\n");
714           exit (1);
715         }
716
717       prev_rgid = nobody_gid;
718       prev_egid = nobody_gid;
719       nobody_gid = prev_sgid;
720       return;
721     }
722
723   test_setregid1 (action, tno);
724 }
725
726
727 static void
728 test_setresgid1 (enum ACTION action, int tno)
729 {
730   if (action == PREPARE)
731     return;
732
733   if (action != CHECK_AFTER)
734     check_prev_gid (tno);
735
736   if (action == SET && setresgid (-1, nobody_gid, -1) < 0)
737     {
738        printf ("setresgid failed: %m\n");
739        exit (1);
740     }
741
742   if (action != CHECK_BEFORE)
743     {
744       gid_t rgid, egid, sgid;
745       if (getresgid (&rgid, &egid, &sgid) < 0)
746         {
747           printf ("getresgid failed: %d %m\n", tno);
748           exit (1);
749         }
750
751       if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
752         {
753           printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
754                   rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
755           exit (1);
756         }
757     }
758 }
759
760
761 static void
762 test_setresgid2 (enum ACTION action, int tno)
763 {
764   if (action == PREPARE)
765     return;
766
767   if (action != CHECK_AFTER)
768     check_prev_gid (tno);
769
770   if (action == SET && setresgid (prev_egid, nobody_gid, nobody_gid) < 0)
771     {
772        printf ("setresgid failed: %m\n");
773        exit (1);
774     }
775
776   if (action != CHECK_BEFORE)
777     {
778       gid_t rgid, egid, sgid;
779       if (getresgid (&rgid, &egid, &sgid) < 0)
780         {
781           printf ("getresgid failed: %d %m\n", tno);
782           exit (1);
783         }
784
785       if (rgid != prev_egid || egid != nobody_gid || sgid != nobody_gid)
786         {
787           printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
788                   rgid, egid, sgid, prev_egid, nobody_gid, nobody_gid);
789           exit (1);
790         }
791     }
792 }
793
794
795 static void
796 test_setresgid3 (enum ACTION action, int tno)
797 {
798   if (action == PREPARE)
799     return;
800
801   if (action != CHECK_AFTER)
802     check_prev_gid (tno);
803
804   if (action == SET && setresgid (nobody_gid, nobody_gid, nobody_gid) < 0)
805     {
806        printf ("setresgid failed: %m\n");
807        exit (1);
808     }
809
810   if (action != CHECK_BEFORE)
811     {
812       gid_t rgid, egid, sgid;
813       if (getresgid (&rgid, &egid, &sgid) < 0)
814         {
815           printf ("getresgid failed: %d %m\n", tno);
816           exit (1);
817         }
818
819       if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
820         {
821           printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
822                   rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
823           exit (1);
824         }
825     }
826 }
827
828
829 static void
830 test_setresgid4 (enum ACTION action, int tno)
831 {
832   if (action == PREPARE)
833     {
834       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
835         {
836           printf ("setresgid failed: %m\n");
837           exit (1);
838         }
839
840       prev_rgid = nobody_gid;
841       prev_egid = nobody_gid;
842       nobody_gid = prev_sgid;
843       return;
844     }
845
846   test_setresgid1 (action, tno);
847 }
848
849
850 static struct setuid_test
851 {
852   const char *name;
853   void (*test) (enum ACTION, int tno);
854 } setuid_tests[] =
855 {
856   { "setuid1", test_setuid1 },
857   { "setuid2", test_setuid2 },
858   { "seteuid1", test_seteuid1 },
859   { "seteuid2", test_seteuid2 },
860   { "setreuid1", test_setreuid1 },
861   { "setreuid2", test_setreuid2 },
862   { "setreuid3", test_setreuid3 },
863   { "setreuid4", test_setreuid4 },
864   { "setresuid1", test_setresuid1 },
865   { "setresuid2", test_setresuid2 },
866   { "setresuid3", test_setresuid3 },
867   { "setresuid4", test_setresuid4 },
868   { "setgid1", test_setgid1 },
869   { "setgid2", test_setgid2 },
870   { "setegid1", test_setegid1 },
871   { "setegid2", test_setegid2 },
872   { "setregid1", test_setregid1 },
873   { "setregid2", test_setregid2 },
874   { "setregid3", test_setregid3 },
875   { "setregid4", test_setregid4 },
876   { "setresgid1", test_setresgid1 },
877   { "setresgid2", test_setresgid2 },
878   { "setresgid3", test_setresgid3 },
879   { "setresgid4", test_setresgid4 }
880 };
881
882
883 static void *
884 tf2 (void *arg)
885 {
886   int e = pthread_barrier_wait (&b4);
887   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
888     {
889       puts ("barrier_wait failed");
890       exit (1);
891     }
892
893   setuid_tests[TESTNO (arg)].test (CHECK_AFTER, THREADNO (arg));
894   return NULL;
895 }
896
897
898 static void *
899 tf (void *arg)
900 {
901   setuid_tests[TESTNO (arg)].test (CHECK_BEFORE, THREADNO (arg));
902
903   int e = pthread_barrier_wait (&b3);
904   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
905     {
906       puts ("barrier_wait failed");
907       exit (1);
908     }
909
910   return tf2 (arg);
911 }
912
913
914 static int
915 do_one_test (long int testno)
916 {
917   printf ("%s test\n", setuid_tests[testno].name);
918
919   pid_t pid = fork ();
920   if (pid == 0)
921     {
922       setuid_tests[testno].test (PREPARE, 0);
923       setuid_tests[testno].test (SET, 0);
924       exit (0);
925     }
926
927   if (pid < 0)
928     {
929       printf ("fork failed: %m\n");
930       exit (1);
931     }
932
933   int status;
934   if (waitpid (pid, &status, 0) < 0)
935     {
936       printf ("waitpid failed: %m\n");
937       exit (1);
938     }
939
940   if (!WIFEXITED (status))
941     {
942       puts ("child did not exit");
943       exit (1);
944     }
945
946   if (WEXITSTATUS (status))
947     {
948       printf ("skipping %s test\n", setuid_tests[testno].name);
949       return 0;
950     }
951
952   pid = fork ();
953   if (pid == 0)
954     {
955       setuid_tests[testno].test (PREPARE, 0);
956
957       pthread_t th;
958       int e = pthread_create (&th, NULL, tf, (void *) (testno | 0x100L));
959       if (e != 0)
960         {
961           printf ("create failed: %m\n");
962           exit (1);
963         }
964
965       pthread_t th2;
966       e = pthread_create (&th2, NULL, tf, (void *) (testno | 0x200L));
967       if (e != 0)
968         {
969           printf ("create failed: %m\n");
970           exit (1);
971         }
972
973       e = pthread_barrier_wait (&b3);
974       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
975         {
976           puts ("barrier_wait failed");
977           exit (1);
978         }
979
980       setuid_tests[testno].test (SET, 0);
981
982       pthread_t th3;
983       e = pthread_create (&th3, NULL, tf2, (void *) (testno | 0x300L));
984       if (e != 0)
985         {
986           printf ("create failed: %m\n");
987           exit (1);
988         }
989
990       e = pthread_barrier_wait (&b4);
991       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
992         {
993           puts ("barrier_wait failed");
994           exit (1);
995         }
996
997       exit (0);
998     }
999
1000   if (pid < 0)
1001     {
1002       printf ("fork failed: %m\n");
1003       exit (1);
1004     }
1005
1006   if (waitpid (pid, &status, 0) < 0)
1007     {
1008       printf ("waitpid failed: %m\n");
1009       exit (1);
1010     }
1011
1012   if (!WIFEXITED (status))
1013     {
1014       puts ("second child did not exit");
1015       exit (1);
1016     }
1017
1018   if (WEXITSTATUS (status))
1019     exit (WEXITSTATUS (status));
1020
1021   return 0;
1022 }
1023
1024
1025 static int
1026 do_test (void)
1027 {
1028   struct passwd *pwd = getpwnam ("nobody");
1029   if (pwd == NULL)
1030     {
1031       puts ("User nobody doesn't exist");
1032       return 0;
1033     }
1034   nobody_uid = pwd->pw_uid;
1035   nobody_gid = pwd->pw_gid;
1036
1037   if (getresuid (&prev_ruid, &prev_euid, &prev_suid) < 0)
1038     {
1039       printf ("getresuid failed: %m\n");
1040       exit (1);
1041     }
1042
1043   if (getresgid (&prev_rgid, &prev_egid, &prev_sgid) < 0)
1044     {
1045       printf ("getresgid failed: %m\n");
1046       exit (1);
1047     }
1048
1049   if (prev_ruid == nobody_uid || prev_euid == nobody_uid
1050       || prev_suid == nobody_uid)
1051     {
1052       puts ("already running as user nobody, skipping tests");
1053       exit (0);
1054     }
1055
1056   if (prev_rgid == nobody_gid || prev_egid == nobody_gid
1057       || prev_sgid == nobody_gid)
1058     {
1059       puts ("already running as group nobody, skipping tests");
1060       exit (0);
1061     }
1062
1063   if (pthread_barrier_init (&b3, NULL, 3) != 0)
1064     {
1065       puts ("barrier_init failed");
1066       exit (1);
1067     }
1068
1069   if (pthread_barrier_init (&b4, NULL, 4) != 0)
1070     {
1071       puts ("barrier_init failed");
1072       exit (1);
1073     }
1074
1075   for (unsigned long int testno = 0;
1076        testno < sizeof (setuid_tests) / sizeof (setuid_tests[0]);
1077        ++testno)
1078     do_one_test (testno);
1079   return 0;
1080 }
1081
1082 #define TEST_FUNCTION do_test ()
1083 #include "../test-skeleton.c"