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 */ 93361515d9SRobert Watson /* privileged on privileged */ 948f6fee75SRobert Watson { &creds[0], &creds[0], 0, 0, 0, 0, 0, 0, "0. priv on priv"}, 958f6fee75SRobert Watson { &creds[0], &creds[1], 0, 0, 0, 0, 0, 0, "1. priv on priv"}, 968f6fee75SRobert Watson { &creds[1], &creds[0], 0, 0, 0, 0, 0, 0, "2. priv on priv"}, 978f6fee75SRobert Watson { &creds[1], &creds[1], 0, 0, 0, 0, 0, 0, "3. priv on priv"}, 98274f7445SRobert Watson /* privileged on unprivileged */ 998f6fee75SRobert Watson { &creds[0], &creds[2], 0, 0, 0, 0, 0, 0, "4. priv on unpriv1"}, 1008f6fee75SRobert Watson { &creds[0], &creds[3], 0, 0, 0, 0, 0, 0, "5. priv on unpriv1"}, 1018f6fee75SRobert Watson { &creds[1], &creds[2], 0, 0, 0, 0, 0, 0, "6. priv on unpriv1"}, 1028f6fee75SRobert Watson { &creds[1], &creds[3], 0, 0, 0, 0, 0, 0, "7. priv on unpriv1"}, 103274f7445SRobert Watson /* unprivileged on privileged */ 1048f6fee75SRobert Watson { &creds[2], &creds[0], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "8. unpriv1 on priv"}, 1058f6fee75SRobert Watson { &creds[2], &creds[1], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "9. unpriv1 on priv"}, 1068f6fee75SRobert Watson { &creds[3], &creds[0], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "10. unpriv1 on priv"}, 1078f6fee75SRobert Watson { &creds[3], &creds[1], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "11. unpriv1 on priv"}, 108274f7445SRobert Watson /* unprivileged on same unprivileged */ 1098f6fee75SRobert Watson { &creds[2], &creds[2], 0, 0, 0, 0, 0, 0, "12. unpriv1 on unpriv1"}, 1108f6fee75SRobert Watson { &creds[2], &creds[3], EPERM, EPERM, 0, EPERM, 0, 0, "13. unpriv1 on unpriv1"}, 1118f6fee75SRobert Watson { &creds[3], &creds[2], 0, 0, 0, 0, 0, 0, "14. unpriv1 on unpriv1"}, 1128f6fee75SRobert Watson { &creds[3], &creds[3], EPERM, EPERM, 0, EPERM, 0, 0, "15. unpriv1 on unpriv1"}, 113274f7445SRobert Watson /* unprivileged on different unprivileged */ 1148f6fee75SRobert Watson { &creds[2], &creds[4], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "16. unpriv1 on unpriv2"}, 1158f6fee75SRobert Watson { &creds[2], &creds[5], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "17. unpriv1 on unpriv2"}, 1168f6fee75SRobert Watson { &creds[3], &creds[4], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "18. unpriv1 on unpriv2"}, 1178f6fee75SRobert Watson { &creds[3], &creds[5], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "19. unpriv1 on unpriv2"}, 118274f7445SRobert Watson /* unprivileged on daemon, same */ 1198f6fee75SRobert Watson { &creds[2], &creds[6], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "20. unpriv1 on daemon1"}, 1208f6fee75SRobert Watson { &creds[2], &creds[7], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "21. unpriv1 on daemon1"}, 1218f6fee75SRobert Watson { &creds[3], &creds[6], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "22. unpriv1 on daemon1"}, 1228f6fee75SRobert Watson { &creds[3], &creds[7], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "23. unpriv1 on daemon1"}, 123274f7445SRobert Watson /* unprivileged on daemon, different */ 1248f6fee75SRobert Watson { &creds[2], &creds[8], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "24. unpriv1 on daemon2"}, 1258f6fee75SRobert Watson { &creds[2], &creds[9], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "25. unpriv1 on daemon2"}, 1268f6fee75SRobert Watson { &creds[3], &creds[8], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "26. unpriv1 on daemon2"}, 1278f6fee75SRobert Watson { &creds[3], &creds[9], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "27. unpriv1 on daemon2"}, 128274f7445SRobert Watson /* unprivileged on setuid, same */ 1298f6fee75SRobert Watson { &creds[2], &creds[10], EPERM, EPERM, 0, 0, 0, 0, "28. unpriv1 on setuid1"}, 1308f6fee75SRobert Watson { &creds[2], &creds[11], EPERM, EPERM, 0, EPERM, 0, 0, "29. unpriv1 on setuid1"}, 1318f6fee75SRobert Watson { &creds[3], &creds[10], EPERM, EPERM, 0, 0, 0, 0, "30. unpriv1 on setuid1"}, 1328f6fee75SRobert Watson { &creds[3], &creds[11], EPERM, EPERM, 0, EPERM, 0, 0, "31. unpriv1 on setuid1"}, 133274f7445SRobert Watson /* unprivileged on setuid, different */ 1348f6fee75SRobert Watson { &creds[2], &creds[12], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "32. unpriv1 on setuid2"}, 1358f6fee75SRobert Watson { &creds[2], &creds[13], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "33. unpriv1 on setuid2"}, 1368f6fee75SRobert Watson { &creds[3], &creds[12], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "34. unpriv1 on setuid2"}, 1378f6fee75SRobert Watson { &creds[3], &creds[13], EPERM, EPERM, EPERM, EPERM, 0, EPERM, "35. unpriv1 on setuid2"}, 138274f7445SRobert Watson }; 139274f7445SRobert Watson int scenarios_count = sizeof(scenarios) / sizeof(struct scenario); 140274f7445SRobert Watson 141274f7445SRobert Watson /* 142274f7445SRobert Watson * Convert an error number to a compact string representation. For now, 143274f7445SRobert Watson * implement only the error numbers we are likely to see. 144274f7445SRobert Watson */ 145274f7445SRobert Watson static char * 146274f7445SRobert Watson errno_to_string(int error) 147274f7445SRobert Watson { 148274f7445SRobert Watson 149274f7445SRobert Watson switch (error) { 150274f7445SRobert Watson case EPERM: 151274f7445SRobert Watson return ("EPERM"); 152274f7445SRobert Watson case EACCES: 153274f7445SRobert Watson return ("EACCES"); 154274f7445SRobert Watson case EINVAL: 155274f7445SRobert Watson return ("EINVAL"); 156274f7445SRobert Watson case ENOSYS: 157274f7445SRobert Watson return ("ENOSYS"); 158274f7445SRobert Watson case ESRCH: 159274f7445SRobert Watson return ("ESRCH"); 160bacff58cSRobert Watson case EOPNOTSUPP: 161bacff58cSRobert Watson return ("EOPNOTSUPP"); 162274f7445SRobert Watson case 0: 163274f7445SRobert Watson return ("0"); 164274f7445SRobert Watson default: 1658f6fee75SRobert Watson printf("%d\n", error); 166274f7445SRobert Watson return ("unknown"); 167274f7445SRobert Watson } 168274f7445SRobert Watson } 169274f7445SRobert Watson 170274f7445SRobert Watson /* 171274f7445SRobert Watson * Return a process credential describing the current process. 172274f7445SRobert Watson */ 173274f7445SRobert Watson static int 174274f7445SRobert Watson cred_get(struct cred *cred) 175274f7445SRobert Watson { 176274f7445SRobert Watson int error; 177274f7445SRobert Watson 178274f7445SRobert Watson error = getresuid(&cred->cr_ruid, &cred->cr_euid, &cred->cr_svuid); 179274f7445SRobert Watson if (error) 180274f7445SRobert Watson return (error); 181274f7445SRobert Watson 182274f7445SRobert Watson cred->cr_issetugid = issetugid(); 183274f7445SRobert Watson 184274f7445SRobert Watson return (0); 185274f7445SRobert Watson } 186274f7445SRobert Watson 187274f7445SRobert Watson /* 188274f7445SRobert Watson * Userland stub for __setsugid() to take into account possible presence 189274f7445SRobert Watson * in C library, kernel, et al. 190274f7445SRobert Watson */ 191274f7445SRobert Watson int 192274f7445SRobert Watson setugid(int flag) 193274f7445SRobert Watson { 194274f7445SRobert Watson 195274f7445SRobert Watson #ifdef SETSUGID_SUPPORTED 196274f7445SRobert Watson return (__setugid(flag)); 197274f7445SRobert Watson #else 198274f7445SRobert Watson #ifdef SETSUGID_SUPPORTED_BUT_NO_LIBC_STUB 199274f7445SRobert Watson return (syscall(374, flag)); 200274f7445SRobert Watson #else 201274f7445SRobert Watson return (ENOSYS); 202274f7445SRobert Watson #endif 203274f7445SRobert Watson #endif 204274f7445SRobert Watson } 205274f7445SRobert Watson 206274f7445SRobert Watson /* 207274f7445SRobert Watson * Set the current process's credentials to match the passed credential. 208274f7445SRobert Watson */ 209274f7445SRobert Watson static int 210274f7445SRobert Watson cred_set(struct cred *cred) 211274f7445SRobert Watson { 212274f7445SRobert Watson int error; 213274f7445SRobert Watson 214274f7445SRobert Watson error = setresuid(cred->cr_ruid, cred->cr_euid, cred->cr_svuid); 215274f7445SRobert Watson if (error) 216274f7445SRobert Watson return (error); 217274f7445SRobert Watson 218274f7445SRobert Watson error = setugid(cred->cr_issetugid); 219274f7445SRobert Watson if (error) { 220274f7445SRobert Watson perror("__setugid"); 221274f7445SRobert Watson return (error); 222274f7445SRobert Watson } 223274f7445SRobert Watson 224274f7445SRobert Watson #ifdef CHECK_CRED_SET 225274f7445SRobert Watson { 226274f7445SRobert Watson uid_t ruid, euid, svuid; 227274f7445SRobert Watson error = getresuid(&ruid, &euid, &svuid); 228274f7445SRobert Watson if (error) { 229274f7445SRobert Watson perror("getresuid"); 230274f7445SRobert Watson return (-1); 231274f7445SRobert Watson } 232274f7445SRobert Watson assert(ruid == cred->cr_ruid); 233274f7445SRobert Watson assert(euid == cred->cr_euid); 234274f7445SRobert Watson assert(svuid == cred->cr_svuid); 235274f7445SRobert Watson assert(cred->cr_issetugid == issetugid()); 236274f7445SRobert Watson } 237274f7445SRobert Watson #endif /* !CHECK_CRED_SET */ 238274f7445SRobert Watson 239274f7445SRobert Watson return (0); 240274f7445SRobert Watson } 241274f7445SRobert Watson 242274f7445SRobert Watson /* 243274f7445SRobert Watson * Print the passed process credential to the passed I/O stream. 244274f7445SRobert Watson */ 245274f7445SRobert Watson static void 246274f7445SRobert Watson cred_print(FILE *output, struct cred *cred) 247274f7445SRobert Watson { 248274f7445SRobert Watson 249274f7445SRobert Watson fprintf(output, "(e:%d r:%d s:%d P_SUGID:%d)", cred->cr_euid, 250274f7445SRobert Watson cred->cr_ruid, cred->cr_svuid, cred->cr_issetugid); 251274f7445SRobert Watson } 252274f7445SRobert Watson 253274f7445SRobert Watson #define LOOP_PTRACE 0 2548f6fee75SRobert Watson #define LOOP_KTRACE 1 2558f6fee75SRobert Watson #define LOOP_SIGHUP 2 2568f6fee75SRobert Watson #define LOOP_SIGSEGV 3 2578f6fee75SRobert Watson #define LOOP_SEE 4 2588f6fee75SRobert Watson #define LOOP_SCHED 5 259274f7445SRobert Watson #define LOOP_MAX LOOP_SCHED 260274f7445SRobert Watson 261274f7445SRobert Watson /* 262274f7445SRobert Watson * Enact a scenario by looping through the four test cases for the scenario, 263274f7445SRobert Watson * spawning off pairs of processes with the desired credentials, and 264274f7445SRobert Watson * reporting results to stdout. 265274f7445SRobert Watson */ 266274f7445SRobert Watson static int 267274f7445SRobert Watson enact_scenario(int scenario) 268274f7445SRobert Watson { 269274f7445SRobert Watson pid_t pid1, pid2; 2708f6fee75SRobert Watson char *name, *tracefile; 271274f7445SRobert Watson int error, desirederror, loop; 272274f7445SRobert Watson 273274f7445SRobert Watson for (loop = 0; loop < LOOP_MAX+1; loop++) { 274274f7445SRobert Watson /* 275274f7445SRobert Watson * Spawn the first child, target of the operation. 276274f7445SRobert Watson */ 277274f7445SRobert Watson pid1 = fork(); 278274f7445SRobert Watson switch (pid1) { 279274f7445SRobert Watson case -1: 280274f7445SRobert Watson return (-1); 281274f7445SRobert Watson case 0: 282274f7445SRobert Watson /* child */ 283274f7445SRobert Watson error = cred_set(scenarios[scenario].sc_cred2); 284274f7445SRobert Watson if (error) { 285274f7445SRobert Watson perror("cred_set"); 286274f7445SRobert Watson return (error); 287274f7445SRobert Watson } 288274f7445SRobert Watson /* 200 seconds should be plenty of time. */ 289274f7445SRobert Watson sleep(200); 290274f7445SRobert Watson exit(0); 291274f7445SRobert Watson default: 292274f7445SRobert Watson /* parent */ 2939e7ebef8SRobert Watson break; 294274f7445SRobert Watson } 295274f7445SRobert Watson 296274f7445SRobert Watson /* 297274f7445SRobert Watson * XXX 298274f7445SRobert Watson * This really isn't ideal -- give proc 1 a chance to set 299274f7445SRobert Watson * its credentials, or we may get spurious errors. Really, 300274f7445SRobert Watson * some for of IPC should be used to allow the parent to 301274f7445SRobert Watson * wait for the first child to be ready before spawning 302274f7445SRobert Watson * the second child. 303274f7445SRobert Watson */ 304274f7445SRobert Watson sleep(1); 305274f7445SRobert Watson 306274f7445SRobert Watson /* 307274f7445SRobert Watson * Spawn the second child, source of the operation. 308274f7445SRobert Watson */ 309274f7445SRobert Watson pid2 = fork(); 310274f7445SRobert Watson switch (pid2) { 311274f7445SRobert Watson case -1: 312274f7445SRobert Watson return (-1); 313274f7445SRobert Watson 314274f7445SRobert Watson case 0: 315274f7445SRobert Watson /* child */ 316274f7445SRobert Watson error = cred_set(scenarios[scenario].sc_cred1); 317274f7445SRobert Watson if (error) { 318274f7445SRobert Watson perror("cred_set"); 319274f7445SRobert Watson return (error); 320274f7445SRobert Watson } 321274f7445SRobert Watson 322274f7445SRobert Watson /* 323274f7445SRobert Watson * Initialize errno to zero so as to catch any 324274f7445SRobert Watson * generated errors. In each case, perform the 325274f7445SRobert Watson * operation. Preserve the error number for later 326274f7445SRobert Watson * use so it doesn't get stomped on by any I/O. 327274f7445SRobert Watson * Determine the desired error for the given case 328274f7445SRobert Watson * by extracting it from the scenario table. 329274f7445SRobert Watson * Initialize a function name string for output 330274f7445SRobert Watson * prettiness. 331274f7445SRobert Watson */ 332274f7445SRobert Watson errno = 0; 333274f7445SRobert Watson switch (loop) { 334274f7445SRobert Watson case LOOP_PTRACE: 335274f7445SRobert Watson error = ptrace(PT_ATTACH, pid1, NULL, 0); 336274f7445SRobert Watson error = errno; 337274f7445SRobert Watson name = "ptrace"; 338274f7445SRobert Watson desirederror = 33972919d5fSRobert Watson scenarios[scenario].sc_canptrace_errno; 340274f7445SRobert Watson break; 3418f6fee75SRobert Watson case LOOP_KTRACE: 3428f6fee75SRobert Watson tracefile = mktemp("/tmp/testuid_ktrace.XXXXXX"); 3438f6fee75SRobert Watson if (tracefile == NULL) { 3448f6fee75SRobert Watson error = errno; 3458f6fee75SRobert Watson perror("mktemp"); 3468f6fee75SRobert Watson break; 3478f6fee75SRobert Watson } 3488f6fee75SRobert Watson error = ktrace(tracefile, KTROP_SET, 3498f6fee75SRobert Watson KTRFAC_SYSCALL, pid1); 3508f6fee75SRobert Watson error = errno; 3518f6fee75SRobert Watson name = "ktrace"; 3528f6fee75SRobert Watson desirederror = 3538f6fee75SRobert Watson scenarios[scenario].sc_canktrace_errno; 3548f6fee75SRobert Watson unlink(tracefile); 3558f6fee75SRobert Watson break; 356bacff58cSRobert Watson case LOOP_SIGHUP: 357274f7445SRobert Watson error = kill(pid1, SIGHUP); 358274f7445SRobert Watson error = errno; 359bacff58cSRobert Watson name = "sighup"; 360274f7445SRobert Watson desirederror = 361bacff58cSRobert Watson scenarios[scenario].sc_cansighup_errno; 362bacff58cSRobert Watson break; 363bacff58cSRobert Watson case LOOP_SIGSEGV: 364bacff58cSRobert Watson error = kill(pid1, SIGSEGV); 365bacff58cSRobert Watson error = errno; 366bacff58cSRobert Watson name = "sigsegv"; 367bacff58cSRobert Watson desirederror = 368bacff58cSRobert Watson scenarios[scenario].sc_cansigsegv_errno; 369274f7445SRobert Watson break; 370274f7445SRobert Watson case LOOP_SEE: 371274f7445SRobert Watson getpriority(PRIO_PROCESS, pid1); 372274f7445SRobert Watson error = errno; 373274f7445SRobert Watson name = "see"; 374274f7445SRobert Watson desirederror = 375274f7445SRobert Watson scenarios[scenario].sc_cansee_errno; 376274f7445SRobert Watson break; 377274f7445SRobert Watson case LOOP_SCHED: 378274f7445SRobert Watson error = setpriority(PRIO_PROCESS, pid1, 379274f7445SRobert Watson 0); 380274f7445SRobert Watson error = errno; 381274f7445SRobert Watson name = "sched"; 382274f7445SRobert Watson desirederror = 383274f7445SRobert Watson scenarios[scenario].sc_cansched_errno; 384274f7445SRobert Watson break; 385274f7445SRobert Watson default: 386274f7445SRobert Watson name = "broken"; 387274f7445SRobert Watson } 388274f7445SRobert Watson 389274f7445SRobert Watson if (error != desirederror) { 390274f7445SRobert Watson fprintf(stdout, 391274f7445SRobert Watson "[%s].%s: expected %s, got %s\n ", 392274f7445SRobert Watson scenarios[scenario].sc_name, name, 393274f7445SRobert Watson errno_to_string(desirederror), 394274f7445SRobert Watson errno_to_string(error)); 395274f7445SRobert Watson cred_print(stdout, 396274f7445SRobert Watson scenarios[scenario].sc_cred1); 397274f7445SRobert Watson cred_print(stdout, 398274f7445SRobert Watson scenarios[scenario].sc_cred2); 399274f7445SRobert Watson fprintf(stdout, "\n"); 400274f7445SRobert Watson } 401274f7445SRobert Watson 402274f7445SRobert Watson exit(0); 403274f7445SRobert Watson 404274f7445SRobert Watson default: 405274f7445SRobert Watson /* parent */ 4069e7ebef8SRobert Watson break; 407274f7445SRobert Watson } 408274f7445SRobert Watson 409274f7445SRobert Watson error = waitpid(pid2, NULL, 0); 410274f7445SRobert Watson /* 411274f7445SRobert Watson * Once pid2 has died, it's safe to kill pid1, if it's still 412274f7445SRobert Watson * alive. Mask signal failure in case the test actually 413274f7445SRobert Watson * killed pid1 (not unlikely: can occur in both signal and 414274f7445SRobert Watson * ptrace cases). 415274f7445SRobert Watson */ 416274f7445SRobert Watson kill(pid1, SIGKILL); 417274f7445SRobert Watson error = waitpid(pid2, NULL, 0); 418274f7445SRobert Watson } 419274f7445SRobert Watson 420274f7445SRobert Watson return (0); 421274f7445SRobert Watson } 422274f7445SRobert Watson 423274f7445SRobert Watson void 424274f7445SRobert Watson enact_scenarios(void) 425274f7445SRobert Watson { 426274f7445SRobert Watson int i, error; 427274f7445SRobert Watson 428274f7445SRobert Watson for (i = 0; i < scenarios_count; i++) { 429274f7445SRobert Watson error = enact_scenario(i); 430274f7445SRobert Watson if (error) 431274f7445SRobert Watson perror("enact_scenario"); 432274f7445SRobert Watson } 433274f7445SRobert Watson } 434