Back to index

glibc  2.9
tst-setuid1.c
Go to the documentation of this file.
00001 /* Copyright (C) 2004 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Jakub Jelinek <jaku@redhat.com>, 2004.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <pthread.h>
00021 #include <pwd.h>
00022 #include <grp.h>
00023 #include <stdlib.h>
00024 #include <stdio.h>
00025 #include <sys/wait.h>
00026 #include <unistd.h>
00027 
00028 
00029 static pthread_barrier_t b3, b4;
00030 static uid_t prev_ruid, prev_euid, prev_suid, nobody_uid;
00031 static gid_t prev_rgid, prev_egid, prev_sgid, nobody_gid;
00032 enum ACTION { PREPARE, SET, CHECK_BEFORE, CHECK_AFTER };
00033 #define TESTNO(arg) ((long int) (arg) & 0xff)
00034 #define THREADNO(arg) ((long int) (arg) >> 8)
00035 
00036 
00037 static void
00038 check_prev_uid (int tno)
00039 {
00040   uid_t ruid, euid, suid;
00041   if (getresuid (&ruid, &euid, &suid) < 0)
00042     {
00043       printf ("getresuid failed: %d %m\n", tno);
00044       exit (1);
00045     }
00046 
00047   if (ruid != prev_ruid || euid != prev_euid || suid != prev_suid)
00048     {
00049       printf ("uids before in %d (%d %d %d) != (%d %d %d)\n", tno,
00050              ruid, euid, suid, prev_ruid, prev_euid, prev_suid);
00051       exit (1);
00052     }
00053 }
00054 
00055 
00056 static void
00057 check_prev_gid (int tno)
00058 {
00059   gid_t rgid, egid, sgid;
00060   if (getresgid (&rgid, &egid, &sgid) < 0)
00061     {
00062       printf ("getresgid failed: %d %m\n", tno);
00063       exit (1);
00064     }
00065 
00066   if (rgid != prev_rgid || egid != prev_egid || sgid != prev_sgid)
00067     {
00068       printf ("gids before in %d (%d %d %d) != (%d %d %d)\n", tno,
00069              rgid, egid, sgid, prev_rgid, prev_egid, prev_sgid);
00070       exit (1);
00071     }
00072 }
00073 
00074 
00075 static void
00076 test_setuid1 (enum ACTION action, int tno)
00077 {
00078   if (action == PREPARE)
00079     return;
00080 
00081   if (action != CHECK_AFTER)
00082     check_prev_uid (tno);
00083 
00084   if (action == SET && setuid (nobody_uid) < 0)
00085     {
00086        printf ("setuid failed: %m\n");
00087        exit (1);
00088     }
00089 
00090   if (action != CHECK_BEFORE)
00091     {
00092       uid_t ruid, euid, suid;
00093       if (getresuid (&ruid, &euid, &suid) < 0)
00094        {
00095          printf ("getresuid failed: %d %m\n", tno);
00096          exit (1);
00097        }
00098 
00099       if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
00100        {
00101          printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
00102                 ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
00103          exit (1);
00104        }
00105     }
00106 }
00107 
00108 
00109 static void
00110 test_setuid2 (enum ACTION action, int tno)
00111 {
00112   if (action == PREPARE)
00113     {
00114       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
00115        {
00116          printf ("setresuid failed: %m\n");
00117          exit (1);
00118        }
00119 
00120       prev_ruid = nobody_uid;
00121       prev_euid = nobody_uid;
00122       return;
00123     }
00124 
00125   if (action != CHECK_AFTER)
00126     check_prev_uid (tno);
00127 
00128   if (action == SET && setuid (prev_suid) < 0)
00129     {
00130       printf ("setuid failed: %m\n");
00131       exit (1);
00132     }
00133 
00134   if (action != CHECK_BEFORE)
00135     {
00136       uid_t ruid, euid, suid;
00137       if (getresuid (&ruid, &euid, &suid) < 0)
00138        {
00139          printf ("getresuid failed: %d %m\n", tno);
00140          exit (1);
00141        }
00142 
00143       if (ruid != nobody_uid || euid != prev_suid || suid != prev_suid)
00144        {
00145          printf ("after setuid %d (%d %d %d) != (%d %d %d)\n", tno,
00146                 ruid, euid, suid, nobody_uid, prev_suid, prev_suid);
00147          exit (1);
00148        }
00149     }
00150 }
00151 
00152 
00153 static void
00154 test_seteuid1 (enum ACTION action, int tno)
00155 {
00156   if (action == PREPARE)
00157     return;
00158 
00159   if (action != CHECK_AFTER)
00160     check_prev_uid (tno);
00161 
00162   if (action == SET && seteuid (nobody_uid) < 0)
00163     {
00164        printf ("seteuid failed: %m\n");
00165        exit (1);
00166     }
00167 
00168   if (action != CHECK_BEFORE)
00169     {
00170       uid_t ruid, euid, suid;
00171       if (getresuid (&ruid, &euid, &suid) < 0)
00172        {
00173          printf ("getresuid failed: %d %m\n", tno);
00174          exit (1);
00175        }
00176 
00177       if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
00178        {
00179          printf ("after seteuid %d (%d %d %d) != (%d %d %d)\n", tno,
00180                 ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
00181          exit (1);
00182        }
00183     }
00184 }
00185 
00186 
00187 static void
00188 test_seteuid2 (enum ACTION action, int tno)
00189 {
00190   if (action == PREPARE)
00191     {
00192       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
00193        {
00194          printf ("setresuid failed: %m\n");
00195          exit (1);
00196        }
00197 
00198       prev_ruid = nobody_uid;
00199       prev_euid = nobody_uid;
00200       nobody_uid = prev_suid;
00201       return;
00202     }
00203 
00204   test_seteuid1 (action, tno);
00205 }
00206 
00207 
00208 static void
00209 test_setreuid1 (enum ACTION action, int tno)
00210 {
00211   if (action == PREPARE)
00212     return;
00213 
00214   if (action != CHECK_AFTER)
00215     check_prev_uid (tno);
00216 
00217   if (action == SET && setreuid (-1, nobody_uid) < 0)
00218     {
00219        printf ("setreuid failed: %m\n");
00220        exit (1);
00221     }
00222 
00223   if (action != CHECK_BEFORE)
00224     {
00225       uid_t ruid, euid, suid, esuid;
00226       if (getresuid (&ruid, &euid, &suid) < 0)
00227        {
00228          printf ("getresuid failed: %d %m\n", tno);
00229          exit (1);
00230        }
00231 
00232       if (prev_ruid != nobody_uid)
00233        esuid = nobody_uid;
00234       else
00235        esuid = prev_suid;
00236 
00237       if (ruid != prev_ruid || euid != nobody_uid || suid != esuid)
00238        {
00239          printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
00240                 ruid, euid, suid, prev_ruid, nobody_uid, esuid);
00241          exit (1);
00242        }
00243     }
00244 }
00245 
00246 
00247 static void
00248 test_setreuid2 (enum ACTION action, int tno)
00249 {
00250   if (action == PREPARE)
00251     return;
00252 
00253   if (action != CHECK_AFTER)
00254     check_prev_uid (tno);
00255 
00256   if (action == SET && setreuid (nobody_uid, -1) < 0)
00257     {
00258        printf ("setreuid failed: %m\n");
00259        exit (1);
00260     }
00261 
00262   if (action != CHECK_BEFORE)
00263     {
00264       uid_t ruid, euid, suid;
00265       if (getresuid (&ruid, &euid, &suid) < 0)
00266        {
00267          printf ("getresuid failed: %d %m\n", tno);
00268          exit (1);
00269        }
00270 
00271       if (ruid != nobody_uid || euid != prev_euid || suid != prev_euid)
00272        {
00273          printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
00274                 ruid, euid, suid, nobody_uid, prev_euid, prev_euid);
00275          exit (1);
00276        }
00277     }
00278 }
00279 
00280 
00281 static void
00282 test_setreuid3 (enum ACTION action, int tno)
00283 {
00284   if (action == PREPARE)
00285     return;
00286 
00287   if (action != CHECK_AFTER)
00288     check_prev_uid (tno);
00289 
00290   if (action == SET && setreuid (nobody_uid, nobody_uid) < 0)
00291     {
00292        printf ("setreuid failed: %m\n");
00293        exit (1);
00294     }
00295 
00296   if (action != CHECK_BEFORE)
00297     {
00298       uid_t ruid, euid, suid;
00299       if (getresuid (&ruid, &euid, &suid) < 0)
00300        {
00301          printf ("getresuid failed: %d %m\n", tno);
00302          exit (1);
00303        }
00304 
00305       if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
00306        {
00307          printf ("after setreuid %d (%d %d %d) != (%d %d %d)\n", tno,
00308                 ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
00309          exit (1);
00310        }
00311     }
00312 }
00313 
00314 
00315 static void
00316 test_setreuid4 (enum ACTION action, int tno)
00317 {
00318   if (action == PREPARE)
00319     {
00320       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
00321        {
00322          printf ("setresuid failed: %m\n");
00323          exit (1);
00324        }
00325 
00326       prev_ruid = nobody_uid;
00327       prev_euid = nobody_uid;
00328       nobody_uid = prev_suid;
00329       return;
00330     }
00331 
00332   test_setreuid1 (action, tno);
00333 }
00334 
00335 
00336 static void
00337 test_setresuid1 (enum ACTION action, int tno)
00338 {
00339   if (action == PREPARE)
00340     return;
00341 
00342   if (action != CHECK_AFTER)
00343     check_prev_uid (tno);
00344 
00345   if (action == SET && setresuid (-1, nobody_uid, -1) < 0)
00346     {
00347        printf ("setresuid failed: %m\n");
00348        exit (1);
00349     }
00350 
00351   if (action != CHECK_BEFORE)
00352     {
00353       uid_t ruid, euid, suid;
00354       if (getresuid (&ruid, &euid, &suid) < 0)
00355        {
00356          printf ("getresuid failed: %d %m\n", tno);
00357          exit (1);
00358        }
00359 
00360       if (ruid != prev_ruid || euid != nobody_uid || suid != prev_suid)
00361        {
00362          printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
00363                 ruid, euid, suid, prev_ruid, nobody_uid, prev_suid);
00364          exit (1);
00365        }
00366     }
00367 }
00368 
00369 
00370 static void
00371 test_setresuid2 (enum ACTION action, int tno)
00372 {
00373   if (action == PREPARE)
00374     return;
00375 
00376   if (action != CHECK_AFTER)
00377     check_prev_uid (tno);
00378 
00379   if (action == SET && setresuid (prev_euid, nobody_uid, nobody_uid) < 0)
00380     {
00381        printf ("setresuid failed: %m\n");
00382        exit (1);
00383     }
00384 
00385   if (action != CHECK_BEFORE)
00386     {
00387       uid_t ruid, euid, suid;
00388       if (getresuid (&ruid, &euid, &suid) < 0)
00389        {
00390          printf ("getresuid failed: %d %m\n", tno);
00391          exit (1);
00392        }
00393 
00394       if (ruid != prev_euid || euid != nobody_uid || suid != nobody_uid)
00395        {
00396          printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
00397                 ruid, euid, suid, prev_euid, nobody_uid, nobody_uid);
00398          exit (1);
00399        }
00400     }
00401 }
00402 
00403 
00404 static void
00405 test_setresuid3 (enum ACTION action, int tno)
00406 {
00407   if (action == PREPARE)
00408     return;
00409 
00410   if (action != CHECK_AFTER)
00411     check_prev_uid (tno);
00412 
00413   if (action == SET && setresuid (nobody_uid, nobody_uid, nobody_uid) < 0)
00414     {
00415        printf ("setresuid failed: %m\n");
00416        exit (1);
00417     }
00418 
00419   if (action != CHECK_BEFORE)
00420     {
00421       uid_t ruid, euid, suid;
00422       if (getresuid (&ruid, &euid, &suid) < 0)
00423        {
00424          printf ("getresuid failed: %d %m\n", tno);
00425          exit (1);
00426        }
00427 
00428       if (ruid != nobody_uid || euid != nobody_uid || suid != nobody_uid)
00429        {
00430          printf ("after setresuid %d (%d %d %d) != (%d %d %d)\n", tno,
00431                 ruid, euid, suid, nobody_uid, nobody_uid, nobody_uid);
00432          exit (1);
00433        }
00434     }
00435 }
00436 
00437 
00438 static void
00439 test_setresuid4 (enum ACTION action, int tno)
00440 {
00441   if (action == PREPARE)
00442     {
00443       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
00444        {
00445          printf ("setresuid failed: %m\n");
00446          exit (1);
00447        }
00448 
00449       prev_ruid = nobody_uid;
00450       prev_euid = nobody_uid;
00451       nobody_uid = prev_suid;
00452       return;
00453     }
00454 
00455   test_setresuid1 (action, tno);
00456 }
00457 
00458 
00459 static void
00460 test_setgid1 (enum ACTION action, int tno)
00461 {
00462   if (action == PREPARE)
00463     return;
00464 
00465   if (action != CHECK_AFTER)
00466     check_prev_gid (tno);
00467 
00468   if (action == SET && setgid (nobody_gid) < 0)
00469     {
00470        printf ("setgid failed: %m\n");
00471        exit (1);
00472     }
00473 
00474   if (action != CHECK_BEFORE)
00475     {
00476       gid_t rgid, egid, sgid;
00477       if (getresgid (&rgid, &egid, &sgid) < 0)
00478        {
00479          printf ("getresgid failed: %d %m\n", tno);
00480          exit (1);
00481        }
00482 
00483       if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
00484        {
00485          printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
00486                 rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
00487          exit (1);
00488        }
00489     }
00490 }
00491 
00492 
00493 static void
00494 test_setgid2 (enum ACTION action, int tno)
00495 {
00496   if (action == PREPARE)
00497     {
00498       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
00499        {
00500          printf ("setresgid failed: %m\n");
00501          exit (1);
00502        }
00503 
00504       prev_rgid = nobody_gid;
00505       prev_egid = nobody_gid;
00506 
00507       if (setresuid (nobody_uid, nobody_uid, -1) < 0)
00508        {
00509          printf ("setresuid failed: %m\n");
00510          exit (1);
00511        }
00512 
00513       prev_ruid = nobody_uid;
00514       prev_euid = nobody_uid;
00515       return;
00516     }
00517 
00518   if (action != CHECK_AFTER)
00519     check_prev_gid (tno);
00520 
00521   if (action == SET && setgid (prev_sgid) < 0)
00522     {
00523       printf ("setgid failed: %m\n");
00524       exit (1);
00525     }
00526 
00527   if (action != CHECK_BEFORE)
00528     {
00529       gid_t rgid, egid, sgid;
00530       if (getresgid (&rgid, &egid, &sgid) < 0)
00531        {
00532          printf ("getresgid failed: %d %m\n", tno);
00533          exit (1);
00534        }
00535 
00536       if (rgid != nobody_gid || egid != prev_sgid || sgid != prev_sgid)
00537        {
00538          printf ("after setgid %d (%d %d %d) != (%d %d %d)\n", tno,
00539                 rgid, egid, sgid, nobody_gid, prev_sgid, prev_sgid);
00540          exit (1);
00541        }
00542     }
00543 }
00544 
00545 
00546 static void
00547 test_setegid1 (enum ACTION action, int tno)
00548 {
00549   if (action == PREPARE)
00550     return;
00551 
00552   if (action != CHECK_AFTER)
00553     check_prev_gid (tno);
00554 
00555   if (action == SET && setegid (nobody_gid) < 0)
00556     {
00557        printf ("setegid failed: %m\n");
00558        exit (1);
00559     }
00560 
00561   if (action != CHECK_BEFORE)
00562     {
00563       gid_t rgid, egid, sgid;
00564       if (getresgid (&rgid, &egid, &sgid) < 0)
00565        {
00566          printf ("getresgid failed: %d %m\n", tno);
00567          exit (1);
00568        }
00569 
00570       if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
00571        {
00572          printf ("after setegid %d (%d %d %d) != (%d %d %d)\n", tno,
00573                 rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
00574          exit (1);
00575        }
00576     }
00577 }
00578 
00579 
00580 static void
00581 test_setegid2 (enum ACTION action, int tno)
00582 {
00583   if (action == PREPARE)
00584     {
00585       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
00586        {
00587          printf ("setresgid failed: %m\n");
00588          exit (1);
00589        }
00590 
00591       prev_rgid = nobody_gid;
00592       prev_egid = nobody_gid;
00593       nobody_gid = prev_sgid;
00594       return;
00595     }
00596 
00597   test_setegid1 (action, tno);
00598 }
00599 
00600 
00601 static void
00602 test_setregid1 (enum ACTION action, int tno)
00603 {
00604   if (action == PREPARE)
00605     return;
00606 
00607   if (action != CHECK_AFTER)
00608     check_prev_gid (tno);
00609 
00610   if (action == SET && setregid (-1, nobody_gid) < 0)
00611     {
00612        printf ("setregid failed: %m\n");
00613        exit (1);
00614     }
00615 
00616   if (action != CHECK_BEFORE)
00617     {
00618       gid_t rgid, egid, sgid, esgid;
00619       if (getresgid (&rgid, &egid, &sgid) < 0)
00620        {
00621          printf ("getresgid failed: %d %m\n", tno);
00622          exit (1);
00623        }
00624 
00625       if (prev_rgid != nobody_gid)
00626        esgid = nobody_gid;
00627       else
00628        esgid = prev_sgid;
00629 
00630       if (rgid != prev_rgid || egid != nobody_gid || sgid != esgid)
00631        {
00632          printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
00633                 rgid, egid, sgid, prev_rgid, nobody_gid, esgid);
00634          exit (1);
00635        }
00636     }
00637 }
00638 
00639 
00640 static void
00641 test_setregid2 (enum ACTION action, int tno)
00642 {
00643   if (action == PREPARE)
00644     return;
00645 
00646   if (action != CHECK_AFTER)
00647     check_prev_gid (tno);
00648 
00649   if (action == SET && setregid (nobody_gid, -1) < 0)
00650     {
00651        printf ("setregid failed: %m\n");
00652        exit (1);
00653     }
00654 
00655   if (action != CHECK_BEFORE)
00656     {
00657       gid_t rgid, egid, sgid;
00658       if (getresgid (&rgid, &egid, &sgid) < 0)
00659        {
00660          printf ("getresgid failed: %d %m\n", tno);
00661          exit (1);
00662        }
00663 
00664       if (rgid != nobody_gid || egid != prev_egid || sgid != prev_egid)
00665        {
00666          printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
00667                 rgid, egid, sgid, nobody_gid, prev_egid, prev_egid);
00668          exit (1);
00669        }
00670     }
00671 }
00672 
00673 
00674 static void
00675 test_setregid3 (enum ACTION action, int tno)
00676 {
00677   if (action == PREPARE)
00678     return;
00679 
00680   if (action != CHECK_AFTER)
00681     check_prev_gid (tno);
00682 
00683   if (action == SET && setregid (nobody_gid, nobody_gid) < 0)
00684     {
00685        printf ("setregid failed: %m\n");
00686        exit (1);
00687     }
00688 
00689   if (action != CHECK_BEFORE)
00690     {
00691       gid_t rgid, egid, sgid;
00692       if (getresgid (&rgid, &egid, &sgid) < 0)
00693        {
00694          printf ("getresgid failed: %d %m\n", tno);
00695          exit (1);
00696        }
00697 
00698       if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
00699        {
00700          printf ("after setregid %d (%d %d %d) != (%d %d %d)\n", tno,
00701                 rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
00702          exit (1);
00703        }
00704     }
00705 }
00706 
00707 
00708 static void
00709 test_setregid4 (enum ACTION action, int tno)
00710 {
00711   if (action == PREPARE)
00712     {
00713       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
00714        {
00715          printf ("setresgid failed: %m\n");
00716          exit (1);
00717        }
00718 
00719       prev_rgid = nobody_gid;
00720       prev_egid = nobody_gid;
00721       nobody_gid = prev_sgid;
00722       return;
00723     }
00724 
00725   test_setregid1 (action, tno);
00726 }
00727 
00728 
00729 static void
00730 test_setresgid1 (enum ACTION action, int tno)
00731 {
00732   if (action == PREPARE)
00733     return;
00734 
00735   if (action != CHECK_AFTER)
00736     check_prev_gid (tno);
00737 
00738   if (action == SET && setresgid (-1, nobody_gid, -1) < 0)
00739     {
00740        printf ("setresgid failed: %m\n");
00741        exit (1);
00742     }
00743 
00744   if (action != CHECK_BEFORE)
00745     {
00746       gid_t rgid, egid, sgid;
00747       if (getresgid (&rgid, &egid, &sgid) < 0)
00748        {
00749          printf ("getresgid failed: %d %m\n", tno);
00750          exit (1);
00751        }
00752 
00753       if (rgid != prev_rgid || egid != nobody_gid || sgid != prev_sgid)
00754        {
00755          printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
00756                 rgid, egid, sgid, prev_rgid, nobody_gid, prev_sgid);
00757          exit (1);
00758        }
00759     }
00760 }
00761 
00762 
00763 static void
00764 test_setresgid2 (enum ACTION action, int tno)
00765 {
00766   if (action == PREPARE)
00767     return;
00768 
00769   if (action != CHECK_AFTER)
00770     check_prev_gid (tno);
00771 
00772   if (action == SET && setresgid (prev_egid, nobody_gid, nobody_gid) < 0)
00773     {
00774        printf ("setresgid failed: %m\n");
00775        exit (1);
00776     }
00777 
00778   if (action != CHECK_BEFORE)
00779     {
00780       gid_t rgid, egid, sgid;
00781       if (getresgid (&rgid, &egid, &sgid) < 0)
00782        {
00783          printf ("getresgid failed: %d %m\n", tno);
00784          exit (1);
00785        }
00786 
00787       if (rgid != prev_egid || egid != nobody_gid || sgid != nobody_gid)
00788        {
00789          printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
00790                 rgid, egid, sgid, prev_egid, nobody_gid, nobody_gid);
00791          exit (1);
00792        }
00793     }
00794 }
00795 
00796 
00797 static void
00798 test_setresgid3 (enum ACTION action, int tno)
00799 {
00800   if (action == PREPARE)
00801     return;
00802 
00803   if (action != CHECK_AFTER)
00804     check_prev_gid (tno);
00805 
00806   if (action == SET && setresgid (nobody_gid, nobody_gid, nobody_gid) < 0)
00807     {
00808        printf ("setresgid failed: %m\n");
00809        exit (1);
00810     }
00811 
00812   if (action != CHECK_BEFORE)
00813     {
00814       gid_t rgid, egid, sgid;
00815       if (getresgid (&rgid, &egid, &sgid) < 0)
00816        {
00817          printf ("getresgid failed: %d %m\n", tno);
00818          exit (1);
00819        }
00820 
00821       if (rgid != nobody_gid || egid != nobody_gid || sgid != nobody_gid)
00822        {
00823          printf ("after setresgid %d (%d %d %d) != (%d %d %d)\n", tno,
00824                 rgid, egid, sgid, nobody_gid, nobody_gid, nobody_gid);
00825          exit (1);
00826        }
00827     }
00828 }
00829 
00830 
00831 static void
00832 test_setresgid4 (enum ACTION action, int tno)
00833 {
00834   if (action == PREPARE)
00835     {
00836       if (setresgid (nobody_gid, nobody_gid, -1) < 0)
00837        {
00838          printf ("setresgid failed: %m\n");
00839          exit (1);
00840        }
00841 
00842       prev_rgid = nobody_gid;
00843       prev_egid = nobody_gid;
00844       nobody_gid = prev_sgid;
00845       return;
00846     }
00847 
00848   test_setresgid1 (action, tno);
00849 }
00850 
00851 
00852 static struct setuid_test
00853 {
00854   const char *name;
00855   void (*test) (enum ACTION, int tno);
00856 } setuid_tests[] =
00857 {
00858   { "setuid1", test_setuid1 },
00859   { "setuid2", test_setuid2 },
00860   { "seteuid1", test_seteuid1 },
00861   { "seteuid2", test_seteuid2 },
00862   { "setreuid1", test_setreuid1 },
00863   { "setreuid2", test_setreuid2 },
00864   { "setreuid3", test_setreuid3 },
00865   { "setreuid4", test_setreuid4 },
00866   { "setresuid1", test_setresuid1 },
00867   { "setresuid2", test_setresuid2 },
00868   { "setresuid3", test_setresuid3 },
00869   { "setresuid4", test_setresuid4 },
00870   { "setgid1", test_setgid1 },
00871   { "setgid2", test_setgid2 },
00872   { "setegid1", test_setegid1 },
00873   { "setegid2", test_setegid2 },
00874   { "setregid1", test_setregid1 },
00875   { "setregid2", test_setregid2 },
00876   { "setregid3", test_setregid3 },
00877   { "setregid4", test_setregid4 },
00878   { "setresgid1", test_setresgid1 },
00879   { "setresgid2", test_setresgid2 },
00880   { "setresgid3", test_setresgid3 },
00881   { "setresgid4", test_setresgid4 }
00882 };
00883 
00884 
00885 static void *
00886 tf2 (void *arg)
00887 {
00888   int e = pthread_barrier_wait (&b4);
00889   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00890     {
00891       puts ("barrier_wait failed");
00892       exit (1);
00893     }
00894 
00895   setuid_tests[TESTNO (arg)].test (CHECK_AFTER, THREADNO (arg));
00896   return NULL;
00897 }
00898 
00899 
00900 static void *
00901 tf (void *arg)
00902 {
00903   setuid_tests[TESTNO (arg)].test (CHECK_BEFORE, THREADNO (arg));
00904 
00905   int e = pthread_barrier_wait (&b3);
00906   if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00907     {
00908       puts ("barrier_wait failed");
00909       exit (1);
00910     }
00911 
00912   return tf2 (arg);
00913 }
00914 
00915 
00916 static int
00917 do_one_test (long int testno)
00918 {
00919   printf ("%s test\n", setuid_tests[testno].name);
00920 
00921   pid_t pid = fork ();
00922   if (pid == 0)
00923     {
00924       setuid_tests[testno].test (PREPARE, 0);
00925       setuid_tests[testno].test (SET, 0);
00926       exit (0);
00927     }
00928 
00929   if (pid < 0)
00930     {
00931       printf ("fork failed: %m\n");
00932       exit (1);
00933     }
00934 
00935   int status;
00936   if (waitpid (pid, &status, 0) < 0)
00937     {
00938       printf ("waitpid failed: %m\n");
00939       exit (1);
00940     }
00941 
00942   if (!WIFEXITED (status))
00943     {
00944       puts ("child did not exit");
00945       exit (1);
00946     }
00947 
00948   if (WEXITSTATUS (status))
00949     {
00950       printf ("skipping %s test\n", setuid_tests[testno].name);
00951       return 0;
00952     }
00953 
00954   pid = fork ();
00955   if (pid == 0)
00956     {
00957       setuid_tests[testno].test (PREPARE, 0);
00958 
00959       pthread_t th;
00960       int e = pthread_create (&th, NULL, tf, (void *) (testno | 0x100L));
00961       if (e != 0)
00962        {
00963          printf ("create failed: %m\n");
00964          exit (1);
00965        }
00966 
00967       pthread_t th2;
00968       e = pthread_create (&th2, NULL, tf, (void *) (testno | 0x200L));
00969       if (e != 0)
00970        {
00971          printf ("create failed: %m\n");
00972          exit (1);
00973        }
00974 
00975       e = pthread_barrier_wait (&b3);
00976       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00977        {
00978          puts ("barrier_wait failed");
00979          exit (1);
00980        }
00981 
00982       setuid_tests[testno].test (SET, 0);
00983 
00984       pthread_t th3;
00985       e = pthread_create (&th3, NULL, tf2, (void *) (testno | 0x300L));
00986       if (e != 0)
00987        {
00988          printf ("create failed: %m\n");
00989          exit (1);
00990        }
00991 
00992       e = pthread_barrier_wait (&b4);
00993       if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
00994        {
00995          puts ("barrier_wait failed");
00996          exit (1);
00997        }
00998 
00999       exit (0);
01000     }
01001 
01002   if (pid < 0)
01003     {
01004       printf ("fork failed: %m\n");
01005       exit (1);
01006     }
01007 
01008   if (waitpid (pid, &status, 0) < 0)
01009     {
01010       printf ("waitpid failed: %m\n");
01011       exit (1);
01012     }
01013 
01014   if (!WIFEXITED (status))
01015     {
01016       puts ("second child did not exit");
01017       exit (1);
01018     }
01019 
01020   if (WEXITSTATUS (status))
01021     exit (WEXITSTATUS (status));
01022 
01023   return 0;
01024 }
01025 
01026 
01027 static int
01028 do_test (void)
01029 {
01030   struct passwd *pwd = getpwnam ("nobody");
01031   if (pwd == NULL)
01032     {
01033       puts ("User nobody doesn't exist");
01034       return 0;
01035     }
01036   nobody_uid = pwd->pw_uid;
01037   nobody_gid = pwd->pw_gid;
01038 
01039   if (getresuid (&prev_ruid, &prev_euid, &prev_suid) < 0)
01040     {
01041       printf ("getresuid failed: %m\n");
01042       exit (1);
01043     }
01044 
01045   if (getresgid (&prev_rgid, &prev_egid, &prev_sgid) < 0)
01046     {
01047       printf ("getresgid failed: %m\n");
01048       exit (1);
01049     }
01050 
01051   if (prev_ruid == nobody_uid || prev_euid == nobody_uid
01052       || prev_suid == nobody_uid)
01053     {
01054       puts ("already running as user nobody, skipping tests");
01055       exit (0);
01056     }
01057 
01058   if (prev_rgid == nobody_gid || prev_egid == nobody_gid
01059       || prev_sgid == nobody_gid)
01060     {
01061       puts ("already running as group nobody, skipping tests");
01062       exit (0);
01063     }
01064 
01065   if (pthread_barrier_init (&b3, NULL, 3) != 0)
01066     {
01067       puts ("barrier_init failed");
01068       exit (1);
01069     }
01070 
01071   if (pthread_barrier_init (&b4, NULL, 4) != 0)
01072     {
01073       puts ("barrier_init failed");
01074       exit (1);
01075     }
01076 
01077   for (unsigned long int testno = 0;
01078        testno < sizeof (setuid_tests) / sizeof (setuid_tests[0]);
01079        ++testno)
01080     do_one_test (testno);
01081   return 0;
01082 }
01083 
01084 #define TEST_FUNCTION do_test ()
01085 #include "../test-skeleton.c"