1274f7445SRobert Watson /*- 2274f7445SRobert Watson * Copyright (c) 2001 Robert N. M. Watson 3274f7445SRobert Watson * All rights reserved. 4274f7445SRobert Watson * 5274f7445SRobert Watson * Redistribution and use in source and binary forms, with or without 6274f7445SRobert Watson * modification, are permitted provided that the following conditions 7274f7445SRobert Watson * are met: 8274f7445SRobert Watson * 1. Redistributions of source code must retain the above copyright 9274f7445SRobert Watson * notice, this list of conditions and the following disclaimer. 10274f7445SRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 11274f7445SRobert Watson * notice, this list of conditions and the following disclaimer in the 12274f7445SRobert Watson * documentation and/or other materials provided with the distribution. 13274f7445SRobert Watson * 14274f7445SRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15274f7445SRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16274f7445SRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17274f7445SRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18274f7445SRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19274f7445SRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20274f7445SRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21274f7445SRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22274f7445SRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23274f7445SRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24274f7445SRobert Watson * SUCH DAMAGE. 25274f7445SRobert Watson * 26274f7445SRobert Watson * $FreeBSD$ 27274f7445SRobert Watson */ 28274f7445SRobert Watson 298f6fee75SRobert Watson #include <sys/param.h> 308f6fee75SRobert Watson #include <sys/uio.h> 31274f7445SRobert Watson #include <sys/ptrace.h> 32274f7445SRobert Watson #include <sys/time.h> 33274f7445SRobert Watson #include <sys/resource.h> 34274f7445SRobert Watson #include <sys/syscall.h> 35274f7445SRobert Watson #include <sys/wait.h> 368f6fee75SRobert Watson #include <sys/ktrace.h> 37274f7445SRobert Watson 38274f7445SRobert Watson #include <assert.h> 39274f7445SRobert Watson #include <errno.h> 40274f7445SRobert Watson #include <signal.h> 41274f7445SRobert Watson #include <stdio.h> 42274f7445SRobert Watson #include <string.h> 43274f7445SRobert Watson #include <unistd.h> 44274f7445SRobert Watson 45274f7445SRobert Watson /* 46274f7445SRobert Watson * Relevant parts of a process credential. 47274f7445SRobert Watson */ 48274f7445SRobert Watson struct cred { 49274f7445SRobert Watson uid_t cr_euid, cr_ruid, cr_svuid; 50274f7445SRobert Watson int cr_issetugid; 51274f7445SRobert Watson }; 52274f7445SRobert Watson 53274f7445SRobert Watson /* 54274f7445SRobert Watson * Description of a scenario. 55274f7445SRobert Watson */ 56274f7445SRobert Watson struct scenario { 57274f7445SRobert Watson struct cred *sc_cred1, *sc_cred2; /* credentials of p1 and p2 */ 5872919d5fSRobert Watson int sc_canptrace_errno; /* desired ptrace failure */ 598f6fee75SRobert Watson int sc_canktrace_errno; /* desired ktrace failure */ 60bacff58cSRobert Watson int sc_cansighup_errno; /* desired SIGHUP failure */ 61bacff58cSRobert Watson int sc_cansigsegv_errno; /* desired SIGSEGV failure */ 62274f7445SRobert Watson int sc_cansee_errno; /* desired getprio failure */ 63274f7445SRobert Watson int sc_cansched_errno; /* desired setprio failure */ 64274f7445SRobert Watson char *sc_name; /* test name */ 65274f7445SRobert Watson }; 66274f7445SRobert Watson 67274f7445SRobert Watson /* 68274f7445SRobert Watson * Table of relevant credential combinations. 69274f7445SRobert Watson */ 70274f7445SRobert Watson static struct cred creds[] = { 71274f7445SRobert Watson /* euid ruid svuid issetugid */ 72274f7445SRobert Watson /* 0 */ { 0, 0, 0, 0 }, /* privileged */ 73274f7445SRobert Watson /* 1 */ { 0, 0, 0, 1 }, /* privileged + issetugid */ 74274f7445SRobert Watson /* 2 */ { 1000, 1000, 1000, 0 }, /* unprivileged1 */ 75274f7445SRobert Watson /* 3 */ { 1000, 1000, 1000, 1 }, /* unprivileged1 + issetugid */ 76274f7445SRobert Watson /* 4 */ { 1001, 1001, 1001, 0 }, /* unprivileged2 */ 77274f7445SRobert Watson /* 5 */ { 1001, 1001, 1001, 1 }, /* unprivileged2 + issetugid */ 78274f7445SRobert Watson /* 6 */ { 1000, 0, 0, 0 }, /* daemon1 */ 79274f7445SRobert Watson /* 7 */ { 1000, 0, 0, 1 }, /* daemon1 + issetugid */ 80274f7445SRobert Watson /* 8 */ { 1001, 0, 0, 0 }, /* daemon2 */ 81274f7445SRobert Watson /* 9 */ { 1001, 0, 0, 1 }, /* daemon2 + issetugid */ 82274f7445SRobert Watson /* 10 */{ 0, 1000, 1000, 0 }, /* setuid1 */ 83274f7445SRobert Watson /* 11 */{ 0, 1000, 1000, 1 }, /* setuid1 + issetugid */ 84274f7445SRobert Watson /* 12 */{ 0, 1001, 1001, 0 }, /* setuid2 */ 85274f7445SRobert Watson /* 13 */{ 0, 1001, 1001, 1 }, /* setuid2 + issetugid */ 86274f7445SRobert Watson }; 87274f7445SRobert Watson 88274f7445SRobert Watson /* 89274f7445SRobert Watson * Table of scenarios. 90274f7445SRobert Watson */ 91274f7445SRobert Watson static const struct scenario scenarios[] = { 928f6fee75SRobert Watson /* cred1 cred2 ptrace ktrace, sighup sigsegv see sched name */ 938f6fee75SRobert Watson { &creds[0], &creds[0], 0, 0, 0, 0, 0, 0, "0. priv on priv"}, 948f6fee75SRobert Watson { &creds[0], &creds[1], 0, 0, 0, 0, 0, 0, "1. priv on priv"}, 958f6fee75SRobert Watson { &creds[1], &creds[0], 0, 0, 0, 0, 0, 0, "2. priv on priv"}, 968f6fee75SRobert Watson { &creds[1], &creds[1], 0, 0, 0, 0, 0, 0, "3. priv on priv"}, 97274f7445SRobert Watson /* privileged on unprivileged */ 988f6fee75SRobert Watson { &creds[0], &creds[2], 0, 0, 0, 0, 0, 0, "4. priv on unpriv1"}, 998f6fee75SRobert Watson { &creds[0], &creds[3], 0, 0, 0, 0, 0, 0, "5. priv on unpriv1"}, 1008f6fee75SRobert Watson { &creds[1], &creds[2], 0, 0, 0, 0, 0, 0, "6. priv on unpriv1"}, 1018f6fee75SRobert Watson { &creds[1], &creds[3], 0, 0, 0, 0, 0, 0, "7. priv on unpriv1"}, 102274f7445SRobert Watson /* unprivileged on privileged */ 1038f6fee75SRobert Watson { &creds[2], &creds[0], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "8. unpriv1 on priv"}, 1048f6fee75SRobert Watson { &creds[2], &creds[1], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "9. unpriv1 on priv"}, 1058f6fee75SRobert Watson { &creds[3], &creds[0], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "10. unpriv1 on priv"}, 1068f6fee75SRobert Watson { &creds[3], &creds[1], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "11. unpriv1 on priv"}, 107274f7445SRobert Watson /* unprivileged on same unprivileged */ 1088f6fee75SRobert Watson { &creds[2], &creds[2], 0, 0, 0, 0, 0, 0, "12. unpriv1 on unpriv1"}, 1098f6fee75SRobert Watson { &creds[2], &creds[3], EPERM, EPERM, 0, EPERM, 0, 0, "13. unpriv1 on unpriv1"}, 1108f6fee75SRobert Watson { &creds[3], &creds[2], 0, 0, 0, 0, 0, 0, "14. unpriv1 on unpriv1"}, 1118f6fee75SRobert Watson { &creds[3], &creds[3], EPERM, EPERM, 0, EPERM, 0, 0, "15. unpriv1 on unpriv1"}, 112274f7445SRobert Watson /* unprivileged on different unprivileged */ 1138f6fee75SRobert Watson { &creds[2], &creds[4], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "16. unpriv1 on unpriv2"}, 1148f6fee75SRobert Watson { &creds[2], &creds[5], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "17. unpriv1 on unpriv2"}, 1158f6fee75SRobert Watson { &creds[3], &creds[4], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "18. unpriv1 on unpriv2"}, 1168f6fee75SRobert Watson { &creds[3], &creds[5], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "19. unpriv1 on unpriv2"}, 117274f7445SRobert Watson /* unprivileged on daemon, same */ 1188f6fee75SRobert Watson { &creds[2], &creds[6], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "20. unpriv1 on daemon1"}, 1198f6fee75SRobert Watson { &creds[2], &creds[7], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "21. unpriv1 on daemon1"}, 1208f6fee75SRobert Watson { &creds[3], &creds[6], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "22. unpriv1 on daemon1"}, 1218f6fee75SRobert Watson { &creds[3], &creds[7], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "23. unpriv1 on daemon1"}, 122274f7445SRobert Watson /* unprivileged on daemon, different */ 1238f6fee75SRobert Watson { &creds[2], &creds[8], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "24. unpriv1 on daemon2"}, 1248f6fee75SRobert Watson { &creds[2], &creds[9], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "25. unpriv1 on daemon2"}, 1258f6fee75SRobert Watson { &creds[3], &creds[8], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "26. unpriv1 on daemon2"}, 1268f6fee75SRobert Watson { &creds[3], &creds[9], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "27. unpriv1 on daemon2"}, 127274f7445SRobert Watson /* unprivileged on setuid, same */ 1288f6fee75SRobert Watson { &creds[2], &creds[10], EPERM, EPERM, 0, 0, 0, 0, "28. unpriv1 on setuid1"}, 1298f6fee75SRobert Watson { &creds[2], &creds[11], EPERM, EPERM, 0, EPERM, 0, 0, "29. unpriv1 on setuid1"}, 1308f6fee75SRobert Watson { &creds[3], &creds[10], EPERM, EPERM, 0, 0, 0, 0, "30. unpriv1 on setuid1"}, 1318f6fee75SRobert Watson { &creds[3], &creds[11], EPERM, EPERM, 0, EPERM, 0, 0, "31. unpriv1 on setuid1"}, 132274f7445SRobert Watson /* unprivileged on setuid, different */ 1338f6fee75SRobert Watson { &creds[2], &creds[12], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "32. unpriv1 on setuid2"}, 1348f6fee75SRobert Watson { &creds[2], &creds[13], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "33. unpriv1 on setuid2"}, 1358f6fee75SRobert Watson { &creds[3], &creds[12], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "34. unpriv1 on setuid2"}, 1368f6fee75SRobert Watson { &creds[3], &creds[13], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "35. unpriv1 on setuid2"}, 137274f7445SRobert Watson }; 138274f7445SRobert Watson int scenarios_count = sizeof(scenarios) / sizeof(struct scenario); 139274f7445SRobert Watson 140274f7445SRobert Watson /* 141274f7445SRobert Watson * Convert an error number to a compact string representation. For now, 142274f7445SRobert Watson * implement only the error numbers we are likely to see. 143274f7445SRobert Watson */ 144274f7445SRobert Watson static char * 145274f7445SRobert Watson errno_to_string(int error) 146274f7445SRobert Watson { 147274f7445SRobert Watson 148274f7445SRobert Watson switch (error) { 149274f7445SRobert Watson case EPERM: 150274f7445SRobert Watson return ("EPERM"); 151274f7445SRobert Watson case EACCES: 152274f7445SRobert Watson return ("EACCES"); 153274f7445SRobert Watson case EINVAL: 154274f7445SRobert Watson return ("EINVAL"); 155274f7445SRobert Watson case ENOSYS: 156274f7445SRobert Watson return ("ENOSYS"); 157274f7445SRobert Watson case ESRCH: 158274f7445SRobert Watson return ("ESRCH"); 159bacff58cSRobert Watson case EOPNOTSUPP: 160bacff58cSRobert Watson return ("EOPNOTSUPP"); 161274f7445SRobert Watson case 0: 162274f7445SRobert Watson return ("0"); 163274f7445SRobert Watson default: 1648f6fee75SRobert Watson printf("%d\n", error); 165274f7445SRobert Watson return ("unknown"); 166274f7445SRobert Watson } 167274f7445SRobert Watson } 168274f7445SRobert Watson 169274f7445SRobert Watson /* 170274f7445SRobert Watson * Return a process credential describing the current process. 171274f7445SRobert Watson */ 172274f7445SRobert Watson static int 173274f7445SRobert Watson cred_get(struct cred *cred) 174274f7445SRobert Watson { 175274f7445SRobert Watson int error; 176274f7445SRobert Watson 177274f7445SRobert Watson error = getresuid(&cred->cr_ruid, &cred->cr_euid, &cred->cr_svuid); 178274f7445SRobert Watson if (error) 179274f7445SRobert Watson return (error); 180274f7445SRobert Watson 181274f7445SRobert Watson cred->cr_issetugid = issetugid(); 182274f7445SRobert Watson 183274f7445SRobert Watson return (0); 184274f7445SRobert Watson } 185274f7445SRobert Watson 186274f7445SRobert Watson /* 187274f7445SRobert Watson * Userland stub for __setsugid() to take into account possible presence 188274f7445SRobert Watson * in C library, kernel, et al. 189274f7445SRobert Watson */ 190274f7445SRobert Watson int 191274f7445SRobert Watson setugid(int flag) 192274f7445SRobert Watson { 193274f7445SRobert Watson 194274f7445SRobert Watson #ifdef SETSUGID_SUPPORTED 195274f7445SRobert Watson return (__setugid(flag)); 196274f7445SRobert Watson #else 197274f7445SRobert Watson #ifdef SETSUGID_SUPPORTED_BUT_NO_LIBC_STUB 198274f7445SRobert Watson return (syscall(374, flag)); 199274f7445SRobert Watson #else 200274f7445SRobert Watson return (ENOSYS); 201274f7445SRobert Watson #endif 202274f7445SRobert Watson #endif 203274f7445SRobert Watson } 204274f7445SRobert Watson 205274f7445SRobert Watson /* 206274f7445SRobert Watson * Set the current process's credentials to match the passed credential. 207274f7445SRobert Watson */ 208274f7445SRobert Watson static int 209274f7445SRobert Watson cred_set(struct cred *cred) 210274f7445SRobert Watson { 211274f7445SRobert Watson int error; 212274f7445SRobert Watson 213274f7445SRobert Watson error = setresuid(cred->cr_ruid, cred->cr_euid, cred->cr_svuid); 214274f7445SRobert Watson if (error) 215274f7445SRobert Watson return (error); 216274f7445SRobert Watson 217274f7445SRobert Watson error = setugid(cred->cr_issetugid); 218274f7445SRobert Watson if (error) { 219274f7445SRobert Watson perror("__setugid"); 220274f7445SRobert Watson return (error); 221274f7445SRobert Watson } 222274f7445SRobert Watson 223274f7445SRobert Watson #ifdef CHECK_CRED_SET 224274f7445SRobert Watson { 225274f7445SRobert Watson uid_t ruid, euid, svuid; 226274f7445SRobert Watson error = getresuid(&ruid, &euid, &svuid); 227274f7445SRobert Watson if (error) { 228274f7445SRobert Watson perror("getresuid"); 229274f7445SRobert Watson return (-1); 230274f7445SRobert Watson } 231274f7445SRobert Watson assert(ruid == cred->cr_ruid); 232274f7445SRobert Watson assert(euid == cred->cr_euid); 233274f7445SRobert Watson assert(svuid == cred->cr_svuid); 234274f7445SRobert Watson assert(cred->cr_issetugid == issetugid()); 235274f7445SRobert Watson } 236274f7445SRobert Watson #endif /* !CHECK_CRED_SET */ 237274f7445SRobert Watson 238274f7445SRobert Watson return (0); 239274f7445SRobert Watson } 240274f7445SRobert Watson 241274f7445SRobert Watson /* 242274f7445SRobert Watson * Print the passed process credential to the passed I/O stream. 243274f7445SRobert Watson */ 244274f7445SRobert Watson static void 245274f7445SRobert Watson cred_print(FILE *output, struct cred *cred) 246274f7445SRobert Watson { 247274f7445SRobert Watson 248274f7445SRobert Watson fprintf(output, "(e:%d r:%d s:%d P_SUGID:%d)", cred->cr_euid, 249274f7445SRobert Watson cred->cr_ruid, cred->cr_svuid, cred->cr_issetugid); 250274f7445SRobert Watson } 251274f7445SRobert Watson 252274f7445SRobert Watson #define LOOP_PTRACE 0 2538f6fee75SRobert Watson #define LOOP_KTRACE 1 2548f6fee75SRobert Watson #define LOOP_SIGHUP 2 2558f6fee75SRobert Watson #define LOOP_SIGSEGV 3 2568f6fee75SRobert Watson #define LOOP_SEE 4 2578f6fee75SRobert Watson #define LOOP_SCHED 5 258274f7445SRobert Watson #define LOOP_MAX LOOP_SCHED 259274f7445SRobert Watson 260274f7445SRobert Watson /* 261274f7445SRobert Watson * Enact a scenario by looping through the four test cases for the scenario, 262274f7445SRobert Watson * spawning off pairs of processes with the desired credentials, and 263274f7445SRobert Watson * reporting results to stdout. 264274f7445SRobert Watson */ 265274f7445SRobert Watson static int 266274f7445SRobert Watson enact_scenario(int scenario) 267274f7445SRobert Watson { 268274f7445SRobert Watson pid_t pid1, pid2; 2698f6fee75SRobert Watson char *name, *tracefile; 270274f7445SRobert Watson int error, desirederror, loop; 271274f7445SRobert Watson 272274f7445SRobert Watson for (loop = 0; loop < LOOP_MAX+1; loop++) { 273274f7445SRobert Watson /* 274274f7445SRobert Watson * Spawn the first child, target of the operation. 275274f7445SRobert Watson */ 276274f7445SRobert Watson pid1 = fork(); 277274f7445SRobert Watson switch (pid1) { 278274f7445SRobert Watson case -1: 279274f7445SRobert Watson return (-1); 280274f7445SRobert Watson case 0: 281274f7445SRobert Watson /* child */ 282274f7445SRobert Watson error = cred_set(scenarios[scenario].sc_cred2); 283274f7445SRobert Watson if (error) { 284274f7445SRobert Watson perror("cred_set"); 285274f7445SRobert Watson return (error); 286274f7445SRobert Watson } 287274f7445SRobert Watson /* 200 seconds should be plenty of time. */ 288274f7445SRobert Watson sleep(200); 289274f7445SRobert Watson exit(0); 290274f7445SRobert Watson default: 291274f7445SRobert Watson /* parent */ 292274f7445SRobert Watson } 293274f7445SRobert Watson 294274f7445SRobert Watson /* 295274f7445SRobert Watson * XXX 296274f7445SRobert Watson * This really isn't ideal -- give proc 1 a chance to set 297274f7445SRobert Watson * its credentials, or we may get spurious errors. Really, 298274f7445SRobert Watson * some for of IPC should be used to allow the parent to 299274f7445SRobert Watson * wait for the first child to be ready before spawning 300274f7445SRobert Watson * the second child. 301274f7445SRobert Watson */ 302274f7445SRobert Watson sleep(1); 303274f7445SRobert Watson 304274f7445SRobert Watson /* 305274f7445SRobert Watson * Spawn the second child, source of the operation. 306274f7445SRobert Watson */ 307274f7445SRobert Watson pid2 = fork(); 308274f7445SRobert Watson switch (pid2) { 309274f7445SRobert Watson case -1: 310274f7445SRobert Watson return (-1); 311274f7445SRobert Watson 312274f7445SRobert Watson case 0: 313274f7445SRobert Watson /* child */ 314274f7445SRobert Watson error = cred_set(scenarios[scenario].sc_cred1); 315274f7445SRobert Watson if (error) { 316274f7445SRobert Watson perror("cred_set"); 317274f7445SRobert Watson return (error); 318274f7445SRobert Watson } 319274f7445SRobert Watson 320274f7445SRobert Watson /* 321274f7445SRobert Watson * Initialize errno to zero so as to catch any 322274f7445SRobert Watson * generated errors. In each case, perform the 323274f7445SRobert Watson * operation. Preserve the error number for later 324274f7445SRobert Watson * use so it doesn't get stomped on by any I/O. 325274f7445SRobert Watson * Determine the desired error for the given case 326274f7445SRobert Watson * by extracting it from the scenario table. 327274f7445SRobert Watson * Initialize a function name string for output 328274f7445SRobert Watson * prettiness. 329274f7445SRobert Watson */ 330274f7445SRobert Watson errno = 0; 331274f7445SRobert Watson switch (loop) { 332274f7445SRobert Watson case LOOP_PTRACE: 333274f7445SRobert Watson error = ptrace(PT_ATTACH, pid1, NULL, 0); 334274f7445SRobert Watson error = errno; 335274f7445SRobert Watson name = "ptrace"; 336274f7445SRobert Watson desirederror = 33772919d5fSRobert Watson scenarios[scenario].sc_canptrace_errno; 338274f7445SRobert Watson break; 3398f6fee75SRobert Watson case LOOP_KTRACE: 3408f6fee75SRobert Watson tracefile = mktemp("/tmp/testuid_ktrace.XXXXXX"); 3418f6fee75SRobert Watson if (tracefile == NULL) { 3428f6fee75SRobert Watson error = errno; 3438f6fee75SRobert Watson perror("mktemp"); 3448f6fee75SRobert Watson break; 3458f6fee75SRobert Watson } 3468f6fee75SRobert Watson error = ktrace(tracefile, KTROP_SET, 3478f6fee75SRobert Watson KTRFAC_SYSCALL, pid1); 3488f6fee75SRobert Watson error = errno; 3498f6fee75SRobert Watson name = "ktrace"; 3508f6fee75SRobert Watson desirederror = 3518f6fee75SRobert Watson scenarios[scenario].sc_canktrace_errno; 3528f6fee75SRobert Watson unlink(tracefile); 3538f6fee75SRobert Watson break; 354bacff58cSRobert Watson case LOOP_SIGHUP: 355274f7445SRobert Watson error = kill(pid1, SIGHUP); 356274f7445SRobert Watson error = errno; 357bacff58cSRobert Watson name = "sighup"; 358274f7445SRobert Watson desirederror = 359bacff58cSRobert Watson scenarios[scenario].sc_cansighup_errno; 360bacff58cSRobert Watson break; 361bacff58cSRobert Watson case LOOP_SIGSEGV: 362bacff58cSRobert Watson error = kill(pid1, SIGSEGV); 363bacff58cSRobert Watson error = errno; 364bacff58cSRobert Watson name = "sigsegv"; 365bacff58cSRobert Watson desirederror = 366bacff58cSRobert Watson scenarios[scenario].sc_cansigsegv_errno; 367274f7445SRobert Watson break; 368274f7445SRobert Watson case LOOP_SEE: 369274f7445SRobert Watson getpriority(PRIO_PROCESS, pid1); 370274f7445SRobert Watson error = errno; 371274f7445SRobert Watson name = "see"; 372274f7445SRobert Watson desirederror = 373274f7445SRobert Watson scenarios[scenario].sc_cansee_errno; 374274f7445SRobert Watson break; 375274f7445SRobert Watson case LOOP_SCHED: 376274f7445SRobert Watson error = setpriority(PRIO_PROCESS, pid1, 377274f7445SRobert Watson 0); 378274f7445SRobert Watson error = errno; 379274f7445SRobert Watson name = "sched"; 380274f7445SRobert Watson desirederror = 381274f7445SRobert Watson scenarios[scenario].sc_cansched_errno; 382274f7445SRobert Watson break; 383274f7445SRobert Watson default: 384274f7445SRobert Watson name = "broken"; 385274f7445SRobert Watson } 386274f7445SRobert Watson 387274f7445SRobert Watson if (error != desirederror) { 388274f7445SRobert Watson fprintf(stdout, 389274f7445SRobert Watson "[%s].%s: expected %s, got %s\n ", 390274f7445SRobert Watson scenarios[scenario].sc_name, name, 391274f7445SRobert Watson errno_to_string(desirederror), 392274f7445SRobert Watson errno_to_string(error)); 393274f7445SRobert Watson cred_print(stdout, 394274f7445SRobert Watson scenarios[scenario].sc_cred1); 395274f7445SRobert Watson cred_print(stdout, 396274f7445SRobert Watson scenarios[scenario].sc_cred2); 397274f7445SRobert Watson fprintf(stdout, "\n"); 398274f7445SRobert Watson } 399274f7445SRobert Watson 400274f7445SRobert Watson exit(0); 401274f7445SRobert Watson 402274f7445SRobert Watson default: 403274f7445SRobert Watson /* parent */ 404274f7445SRobert Watson } 405274f7445SRobert Watson 406274f7445SRobert Watson error = waitpid(pid2, NULL, 0); 407274f7445SRobert Watson /* 408274f7445SRobert Watson * Once pid2 has died, it's safe to kill pid1, if it's still 409274f7445SRobert Watson * alive. Mask signal failure in case the test actually 410274f7445SRobert Watson * killed pid1 (not unlikely: can occur in both signal and 411274f7445SRobert Watson * ptrace cases). 412274f7445SRobert Watson */ 413274f7445SRobert Watson kill(pid1, SIGKILL); 414274f7445SRobert Watson error = waitpid(pid2, NULL, 0); 415274f7445SRobert Watson } 416274f7445SRobert Watson 417274f7445SRobert Watson return (0); 418274f7445SRobert Watson } 419274f7445SRobert Watson 420274f7445SRobert Watson void 421274f7445SRobert Watson enact_scenarios(void) 422274f7445SRobert Watson { 423274f7445SRobert Watson int i, error; 424274f7445SRobert Watson 425274f7445SRobert Watson for (i = 0; i < scenarios_count; i++) { 426274f7445SRobert Watson error = enact_scenario(i); 427274f7445SRobert Watson if (error) 428274f7445SRobert Watson perror("enact_scenario"); 429274f7445SRobert Watson } 430274f7445SRobert Watson } 431