1/* Copyright (C) 2004-2022 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
27static pthread_barrier_t b3, b4;
28static uid_t prev_ruid, prev_euid, prev_suid, nobody_uid;
29static gid_t prev_rgid, prev_egid, prev_sgid, nobody_gid;
30enum 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
35static void
36check_prev_uid (int tno)
37{
38 uid_t ruid, euid, suid;
39 if (getresuid (ruid: &ruid, euid: &euid, suid: &suid) < 0)
40 {
41 printf (format: "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 (format: "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
54static void
55check_prev_gid (int tno)
56{
57 gid_t rgid, egid, sgid;
58 if (getresgid (rgid: &rgid, egid: &egid, sgid: &sgid) < 0)
59 {
60 printf (format: "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 (format: "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
73static void
74test_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 (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
92 {
93 printf (format: "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 (format: "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
107static void
108test_setuid2 (enum ACTION action, int tno)
109{
110 if (action == PREPARE)
111 {
112 if (setresuid (ruid: nobody_uid, euid: nobody_uid, suid: -1) < 0)
113 {
114 printf (format: "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 (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
136 {
137 printf (format: "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 (format: "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
151static void
152test_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 (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
170 {
171 printf (format: "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 (format: "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
185static void
186test_seteuid2 (enum ACTION action, int tno)
187{
188 if (action == PREPARE)
189 {
190 if (setresuid (ruid: nobody_uid, euid: nobody_uid, suid: -1) < 0)
191 {
192 printf (format: "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
206static void
207test_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 (ruid: -1, euid: nobody_uid) < 0)
216 {
217 printf (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
225 {
226 printf (format: "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 (format: "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
245static void
246test_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 (ruid: nobody_uid, euid: -1) < 0)
255 {
256 printf (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
264 {
265 printf (format: "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 (format: "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
279static void
280test_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 (ruid: nobody_uid, euid: nobody_uid) < 0)
289 {
290 printf (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
298 {
299 printf (format: "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 (format: "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
313static void
314test_setreuid4 (enum ACTION action, int tno)
315{
316 if (action == PREPARE)
317 {
318 if (setresuid (ruid: nobody_uid, euid: nobody_uid, suid: -1) < 0)
319 {
320 printf (format: "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
334static void
335test_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 (ruid: -1, euid: nobody_uid, suid: -1) < 0)
344 {
345 printf (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
353 {
354 printf (format: "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 (format: "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
368static void
369test_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 (ruid: prev_euid, euid: nobody_uid, suid: nobody_uid) < 0)
378 {
379 printf (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
387 {
388 printf (format: "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 (format: "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
402static void
403test_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 (ruid: nobody_uid, euid: nobody_uid, suid: nobody_uid) < 0)
412 {
413 printf (format: "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: &ruid, euid: &euid, suid: &suid) < 0)
421 {
422 printf (format: "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 (format: "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
436static void
437test_setresuid4 (enum ACTION action, int tno)
438{
439 if (action == PREPARE)
440 {
441 if (setresuid (ruid: nobody_uid, euid: nobody_uid, suid: -1) < 0)
442 {
443 printf (format: "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
457static void
458test_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 (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
476 {
477 printf (format: "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 (format: "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
491static void
492test_setgid2 (enum ACTION action, int tno)
493{
494 if (action == PREPARE)
495 {
496 if (setresgid (rgid: nobody_gid, egid: nobody_gid, sgid: -1) < 0)
497 {
498 printf (format: "setresgid failed: %m\n");
499 exit (1);
500 }
501
502 prev_rgid = nobody_gid;
503 prev_egid = nobody_gid;
504
505 if (setresuid (ruid: nobody_uid, euid: nobody_uid, suid: -1) < 0)
506 {
507 printf (format: "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 (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
529 {
530 printf (format: "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 (format: "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
544static void
545test_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 (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
563 {
564 printf (format: "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 (format: "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
578static void
579test_setegid2 (enum ACTION action, int tno)
580{
581 if (action == PREPARE)
582 {
583 if (setresgid (rgid: nobody_gid, egid: nobody_gid, sgid: -1) < 0)
584 {
585 printf (format: "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
599static void
600test_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 (rgid: -1, egid: nobody_gid) < 0)
609 {
610 printf (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
618 {
619 printf (format: "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 (format: "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
638static void
639test_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 (rgid: nobody_gid, egid: -1) < 0)
648 {
649 printf (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
657 {
658 printf (format: "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 (format: "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
672static void
673test_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 (rgid: nobody_gid, egid: nobody_gid) < 0)
682 {
683 printf (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
691 {
692 printf (format: "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 (format: "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
706static void
707test_setregid4 (enum ACTION action, int tno)
708{
709 if (action == PREPARE)
710 {
711 if (setresgid (rgid: nobody_gid, egid: nobody_gid, sgid: -1) < 0)
712 {
713 printf (format: "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
727static void
728test_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 (rgid: -1, egid: nobody_gid, sgid: -1) < 0)
737 {
738 printf (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
746 {
747 printf (format: "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 (format: "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
761static void
762test_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 (rgid: prev_egid, egid: nobody_gid, sgid: nobody_gid) < 0)
771 {
772 printf (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
780 {
781 printf (format: "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 (format: "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
795static void
796test_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 (rgid: nobody_gid, egid: nobody_gid, sgid: nobody_gid) < 0)
805 {
806 printf (format: "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: &rgid, egid: &egid, sgid: &sgid) < 0)
814 {
815 printf (format: "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 (format: "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
829static void
830test_setresgid4 (enum ACTION action, int tno)
831{
832 if (action == PREPARE)
833 {
834 if (setresgid (rgid: nobody_gid, egid: nobody_gid, sgid: -1) < 0)
835 {
836 printf (format: "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
850static 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
883static void *
884tf2 (void *arg)
885{
886 int e = pthread_barrier_wait (barrier: &b4);
887 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
888 {
889 puts (s: "barrier_wait failed");
890 exit (1);
891 }
892
893 setuid_tests[TESTNO (arg)].test (CHECK_AFTER, THREADNO (arg));
894 return NULL;
895}
896
897
898static void *
899tf (void *arg)
900{
901 setuid_tests[TESTNO (arg)].test (CHECK_BEFORE, THREADNO (arg));
902
903 int e = pthread_barrier_wait (barrier: &b3);
904 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
905 {
906 puts (s: "barrier_wait failed");
907 exit (1);
908 }
909
910 return tf2 (arg);
911}
912
913
914static int
915do_one_test (long int testno)
916{
917 printf (format: "%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 (format: "fork failed: %m\n");
930 exit (1);
931 }
932
933 int status;
934 if (waitpid (pid: pid, stat_loc: &status, options: 0) < 0)
935 {
936 printf (format: "waitpid failed: %m\n");
937 exit (1);
938 }
939
940 if (!WIFEXITED (status))
941 {
942 puts (s: "child did not exit");
943 exit (1);
944 }
945
946 if (WEXITSTATUS (status))
947 {
948 printf (format: "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 (newthread: &th, NULL, start_routine: tf, arg: (void *) (testno | 0x100L));
959 if (e != 0)
960 {
961 printf (format: "create failed: %m\n");
962 exit (1);
963 }
964
965 pthread_t th2;
966 e = pthread_create (newthread: &th2, NULL, start_routine: tf, arg: (void *) (testno | 0x200L));
967 if (e != 0)
968 {
969 printf (format: "create failed: %m\n");
970 exit (1);
971 }
972
973 e = pthread_barrier_wait (barrier: &b3);
974 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
975 {
976 puts (s: "barrier_wait failed");
977 exit (1);
978 }
979
980 setuid_tests[testno].test (SET, 0);
981
982 pthread_t th3;
983 e = pthread_create (newthread: &th3, NULL, start_routine: tf2, arg: (void *) (testno | 0x300L));
984 if (e != 0)
985 {
986 printf (format: "create failed: %m\n");
987 exit (1);
988 }
989
990 e = pthread_barrier_wait (barrier: &b4);
991 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
992 {
993 puts (s: "barrier_wait failed");
994 exit (1);
995 }
996
997 exit (0);
998 }
999
1000 if (pid < 0)
1001 {
1002 printf (format: "fork failed: %m\n");
1003 exit (1);
1004 }
1005
1006 if (waitpid (pid: pid, stat_loc: &status, options: 0) < 0)
1007 {
1008 printf (format: "waitpid failed: %m\n");
1009 exit (1);
1010 }
1011
1012 if (!WIFEXITED (status))
1013 {
1014 puts (s: "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
1025static int
1026do_test (void)
1027{
1028 struct passwd *pwd = getpwnam (name: "nobody");
1029 if (pwd == NULL)
1030 {
1031 puts (s: "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 (ruid: &prev_ruid, euid: &prev_euid, suid: &prev_suid) < 0)
1038 {
1039 printf (format: "getresuid failed: %m\n");
1040 exit (1);
1041 }
1042
1043 if (getresgid (rgid: &prev_rgid, egid: &prev_egid, sgid: &prev_sgid) < 0)
1044 {
1045 printf (format: "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 (s: "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 (s: "already running as group nobody, skipping tests");
1060 exit (0);
1061 }
1062
1063 if (pthread_barrier_init (barrier: &b3, NULL, count: 3) != 0)
1064 {
1065 puts (s: "barrier_init failed");
1066 exit (1);
1067 }
1068
1069 if (pthread_barrier_init (barrier: &b4, NULL, count: 4) != 0)
1070 {
1071 puts (s: "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"
1084

source code of glibc/nptl/tst-setuid1.c