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