summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatthew <>2014-07-11 00:38:17 +0000
committermatthew <>2014-07-11 00:38:17 +0000
commit0edafc21e5a0226078d996162aaab2e0b91b8a0e (patch)
treec4fa81a7f58e70f908e4dd71b7f7e0cb3a550533
parentc8e58b52150f7c13e3281d122ed2c3ff38b6a1d5 (diff)
downloadopenbsd-0edafc21e5a0226078d996162aaab2e0b91b8a0e.tar.gz
openbsd-0edafc21e5a0226078d996162aaab2e0b91b8a0e.tar.bz2
openbsd-0edafc21e5a0226078d996162aaab2e0b91b8a0e.zip
Fix explicit_bzero regress for Solaris and OS X compatibility
Solaris and OS X clobber the signal stack when returning to the main stack, which caused the original testing strategy (inspecting the signal stack once we're back on the main stack) to fail. To be compatible with this behavior, the regress test now inspects the signal stack space while we're still executing on it. This is a bit iffy because we might clobber it ourselves while inspecting it, but we as long as its not completely clobbered we should be okay. thx bcook for the Solaris test account
-rw-r--r--src/regress/lib/libc/explicit_bzero/explicit_bzero.c95
1 files changed, 68 insertions, 27 deletions
diff --git a/src/regress/lib/libc/explicit_bzero/explicit_bzero.c b/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
index d1e4d1494e..c2b677ca6a 100644
--- a/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
+++ b/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: explicit_bzero.c,v 1.4 2014/07/09 23:54:00 matthew Exp $ */ 1/* $OpenBSD: explicit_bzero.c,v 1.5 2014/07/11 00:38:17 matthew Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Google Inc. 3 * Copyright (c) 2014 Google Inc.
4 * 4 *
@@ -25,7 +25,18 @@
25#define ASSERT_NE(a, b) assert((a) != (b)) 25#define ASSERT_NE(a, b) assert((a) != (b))
26#define ASSERT_GE(a, b) assert((a) >= (b)) 26#define ASSERT_GE(a, b) assert((a) >= (b))
27 27
28static char altstack[SIGSTKSZ]; 28/* 128 bits of random data. */
29static const char secret[16] = {
30 0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c,
31 0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96,
32};
33
34enum {
35 SECRETCOUNT = 64,
36 SECRETBYTES = SECRETCOUNT * sizeof(secret)
37};
38
39static char altstack[SIGSTKSZ + SECRETBYTES];
29 40
30static void 41static void
31setup_stack(void) 42setup_stack(void)
@@ -85,17 +96,6 @@ call_on_stack(void (*fn)(int))
85 ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &oldsigset, NULL)); 96 ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &oldsigset, NULL));
86} 97}
87 98
88/* 128 bits of random data. */
89static const char secret[16] = {
90 0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c,
91 0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96,
92};
93
94enum {
95 SECRETCOUNT = 16,
96 SECRETBYTES = SECRETCOUNT * sizeof(secret)
97};
98
99static void 99static void
100populate_secret(char *buf, size_t len) 100populate_secret(char *buf, size_t len)
101{ 101{
@@ -110,23 +110,54 @@ populate_secret(char *buf, size_t len)
110 ASSERT_EQ(0, close(fds[0])); 110 ASSERT_EQ(0, close(fds[0]));
111} 111}
112 112
113static void 113static int
114test_without_bzero(int signo) 114count_secrets(const char *buf)
115{
116 int res = 0;
117 size_t i;
118 for (i = 0; i < SECRETCOUNT; i++) {
119 if (memcmp(buf + i * sizeof(secret), secret,
120 sizeof(secret)) == 0)
121 res += 1;
122 }
123 return (res);
124}
125
126static char *
127test_without_bzero()
115{ 128{
116 char buf[SECRETBYTES]; 129 char buf[SECRETBYTES];
117 assert_on_stack(); 130 assert_on_stack();
118 populate_secret(buf, sizeof(buf)); 131 populate_secret(buf, sizeof(buf));
119 ASSERT_NE(NULL, memmem(altstack, sizeof(altstack), buf, sizeof(buf))); 132 char *res = memmem(altstack, sizeof(altstack), buf, sizeof(buf));
133 ASSERT_NE(NULL, res);
134 return (res);
120} 135}
121 136
122static void 137static char *
123test_with_bzero(int signo) 138test_with_bzero()
124{ 139{
125 char buf[SECRETBYTES]; 140 char buf[SECRETBYTES];
126 assert_on_stack(); 141 assert_on_stack();
127 populate_secret(buf, sizeof(buf)); 142 populate_secret(buf, sizeof(buf));
128 ASSERT_NE(NULL, memmem(altstack, sizeof(altstack), buf, sizeof(buf))); 143 char *res = memmem(altstack, sizeof(altstack), buf, sizeof(buf));
144 ASSERT_NE(NULL, res);
129 explicit_bzero(buf, sizeof(buf)); 145 explicit_bzero(buf, sizeof(buf));
146 return (res);
147}
148
149static void
150do_test_without_bzero(int signo)
151{
152 char *buf = test_without_bzero();
153 ASSERT_GE(count_secrets(buf), 1);
154}
155
156static void
157do_test_with_bzero(int signo)
158{
159 char *buf = test_without_bzero();
160 ASSERT_GE(count_secrets(buf), 0);
130} 161}
131 162
132int 163int
@@ -135,22 +166,32 @@ main()
135 setup_stack(); 166 setup_stack();
136 167
137 /* 168 /*
169 * Solaris and OS X clobber the signal stack after returning to the
170 * normal stack, so we need to inspect altstack while we're still
171 * running on it. Unfortunately, this means we risk clobbering the
172 * buffer ourselves.
173 *
174 * To minimize this risk, test_with{,out}_bzero() are responsible for
175 * locating the offset of their buf variable within altstack, and
176 * and returning that address. Then we can simply memcmp() repeatedly
177 * to count how many instances of secret we found.
178 */
179
180 /*
138 * First, test that if we *don't* call explicit_bzero, that we 181 * First, test that if we *don't* call explicit_bzero, that we
139 * *are* able to find the secret data on the stack. This 182 * *are* able to find at least one instance of the secret data still
140 * sanity checks that call_on_stack() and populare_secret() 183 * on the stack. This sanity checks that call_on_stack() and
141 * work as intended. 184 * populate_secret() work as intended.
142 */ 185 */
143 memset(altstack, 0, sizeof(altstack)); 186 memset(altstack, 0, sizeof(altstack));
144 call_on_stack(test_without_bzero); 187 call_on_stack(do_test_without_bzero);
145 ASSERT_NE(NULL, memmem(altstack, sizeof(altstack), secret, sizeof(secret)));
146 188
147 /* 189 /*
148 * Now test with a call to explicit_bzero() and check that we 190 * Now test with a call to explicit_bzero() and check that we
149 * *don't* find the secret data. 191 * *don't* find any instances of the secret data.
150 */ 192 */
151 memset(altstack, 0, sizeof(altstack)); 193 memset(altstack, 0, sizeof(altstack));
152 call_on_stack(test_with_bzero); 194 call_on_stack(do_test_with_bzero);
153 ASSERT_EQ(NULL, memmem(altstack, sizeof(altstack), secret, sizeof(secret)));
154 195
155 return (0); 196 return (0);
156} 197}