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
successful_exit(uint32_t test)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
getcontext_stack(uint32_t test)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
main(void)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