diff options
| -rw-r--r-- | src/regress/lib/libc/explicit_bzero/explicit_bzero.c | 95 |
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 | ||
| 28 | static char altstack[SIGSTKSZ]; | 28 | /* 128 bits of random data. */ |
| 29 | static const char secret[16] = { | ||
| 30 | 0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c, | ||
| 31 | 0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96, | ||
| 32 | }; | ||
| 33 | |||
| 34 | enum { | ||
| 35 | SECRETCOUNT = 64, | ||
| 36 | SECRETBYTES = SECRETCOUNT * sizeof(secret) | ||
| 37 | }; | ||
| 38 | |||
| 39 | static char altstack[SIGSTKSZ + SECRETBYTES]; | ||
| 29 | 40 | ||
| 30 | static void | 41 | static void |
| 31 | setup_stack(void) | 42 | setup_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. */ | ||
| 89 | static const char secret[16] = { | ||
| 90 | 0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c, | ||
| 91 | 0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96, | ||
| 92 | }; | ||
| 93 | |||
| 94 | enum { | ||
| 95 | SECRETCOUNT = 16, | ||
| 96 | SECRETBYTES = SECRETCOUNT * sizeof(secret) | ||
| 97 | }; | ||
| 98 | |||
| 99 | static void | 99 | static void |
| 100 | populate_secret(char *buf, size_t len) | 100 | populate_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 | ||
| 113 | static void | 113 | static int |
| 114 | test_without_bzero(int signo) | 114 | count_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 | |||
| 126 | static char * | ||
| 127 | test_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 | ||
| 122 | static void | 137 | static char * |
| 123 | test_with_bzero(int signo) | 138 | test_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 | |||
| 149 | static void | ||
| 150 | do_test_without_bzero(int signo) | ||
| 151 | { | ||
| 152 | char *buf = test_without_bzero(); | ||
| 153 | ASSERT_GE(count_secrets(buf), 1); | ||
| 154 | } | ||
| 155 | |||
| 156 | static void | ||
| 157 | do_test_with_bzero(int signo) | ||
| 158 | { | ||
| 159 | char *buf = test_without_bzero(); | ||
| 160 | ASSERT_GE(count_secrets(buf), 0); | ||
| 130 | } | 161 | } |
| 131 | 162 | ||
| 132 | int | 163 | int |
| @@ -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 | } |
