xref: /illumos-gate/usr/src/test/os-tests/tests/getcontext_extd.c (revision b41e2fb6b2658a36accc73b3b86d99375e700dba)
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