1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2023 Oxide Computer Company 14 */ 15 16 /* 17 * Basic test for getcontext_extd() variant. We have two cases that we need to 18 * consider. A ucontext_t that is allocated and initialized from the stack and 19 * then one that comes from a ucontext_alloc(). We test both that setcontext() 20 * and makecontext() work with these. 21 */ 22 23 #include <ucontext.h> 24 #include <unistd.h> 25 #include <stdlib.h> 26 #include <err.h> 27 #include <string.h> 28 #include <errno.h> 29 #include <upanic.h> 30 31 #define STACK_MAGIC 42 32 #define EXIT_MAGIC 23 33 static volatile uint32_t count = 0; 34 static volatile uint32_t stack_count = 0; 35 36 static void 37 successful_exit(uint32_t test) 38 { 39 if (test != EXIT_MAGIC) { 40 errx(EXIT_FAILURE, "TEST FAILED: makecontext had wrong " 41 "argument, found 0x%x, expected 0x%x", test, EXIT_MAGIC); 42 } 43 44 printf("TEST PASSED: makecontext called with right argument\n"); 45 exit(0); 46 } 47 48 static void 49 getcontext_stack(uint32_t test) 50 { 51 ucontext_t ctx; 52 53 if (test != STACK_MAGIC) { 54 errx(EXIT_FAILURE, "TEST FAILED: makecontext had wrong " 55 "argument, found 0x%x, expected 0x%x", test, STACK_MAGIC); 56 } 57 58 (void) memset(&ctx, 0, sizeof (ctx)); 59 60 if (getcontext_extd(&ctx, 0) != 0) { 61 err(EXIT_FAILURE, "failed to get extended context from stack"); 62 } 63 64 count++; 65 if (count < 5) { 66 const char *msg = "stack setcontext returned, sorry"; 67 (void) setcontext(&ctx); 68 upanic(msg, strlen(msg) + 1); 69 } 70 71 (void) printf("TEST PASSED: stack ucontext_t / getcontext_extd() / " 72 "setcontext() combo worked\n"); 73 ctx.uc_stack.ss_sp = calloc(SIGSTKSZ, sizeof (uint8_t)); 74 if (ctx.uc_stack.ss_sp == NULL) { 75 err(EXIT_FAILURE, "failed to allocate second makecontext " 76 "stack"); 77 } 78 ctx.uc_stack.ss_size = SIGSTKSZ; 79 ctx.uc_stack.ss_flags = 0; 80 makecontext(&ctx, successful_exit, 1, EXIT_MAGIC); 81 (void) setcontext(&ctx); 82 83 err(EXIT_FAILURE, "TEST FAILED: stack ucontext_t / makecontext() " 84 "returned from setcontext()"); 85 } 86 87 int 88 main(void) 89 { 90 ucontext_t *ctx = ucontext_alloc(0); 91 if (ctx == NULL) { 92 err(EXIT_FAILURE, "failed to get allocate ucontext_t"); 93 } 94 95 if (getcontext_extd(ctx, 23) == 0) { 96 errx(EXIT_FAILURE, "TEST FAILED: getcontext_extd worked with " 97 "bad flags"); 98 } 99 100 if (errno != EINVAL) { 101 errx(EXIT_FAILURE, "TEST FAILED: getcontext_extd returned " 102 "wrong errno for bad flags: 0x%x", errno); 103 } 104 105 if (getcontext_extd(ctx, 0) != 0) { 106 err(EXIT_FAILURE, "failed to get extended context"); 107 } 108 109 count++; 110 if (count < 5) { 111 const char *msg = "setcontext returned, sorry"; 112 (void) setcontext(ctx); 113 upanic(msg, strlen(msg) + 1); 114 } 115 116 (void) printf("TEST PASSED: ucontext_alloc() / getcontext_extd() / " 117 "setcontext() combo worked\n"); 118 ctx->uc_stack.ss_sp = calloc(SIGSTKSZ, sizeof (uint8_t)); 119 if (ctx->uc_stack.ss_sp == NULL) { 120 err(EXIT_FAILURE, "failed to allocate first makecontext " 121 "stack"); 122 } 123 ctx->uc_stack.ss_size = SIGSTKSZ; 124 ctx->uc_stack.ss_flags = 0; 125 makecontext(ctx, getcontext_stack, 1, STACK_MAGIC); 126 (void) setcontext(ctx); 127 128 warn("TEST FAILED: failed to setcontext() to makecontext() from " 129 "ucontext_alloc() / getcontext_extd()"); 130 return (EXIT_FAILURE); 131 } 132