summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/regress/lib/libc/Makefile4
-rw-r--r--src/regress/lib/libc/explicit_bzero/Makefile5
-rw-r--r--src/regress/lib/libc/explicit_bzero/explicit_bzero.c138
3 files changed, 145 insertions, 2 deletions
diff --git a/src/regress/lib/libc/Makefile b/src/regress/lib/libc/Makefile
index f138f16ffd..71eb6398a8 100644
--- a/src/regress/lib/libc/Makefile
+++ b/src/regress/lib/libc/Makefile
@@ -1,7 +1,7 @@
1# $OpenBSD: Makefile,v 1.39 2014/06/07 01:46:40 tobiasu Exp $ 1# $OpenBSD: Makefile,v 1.40 2014/06/12 22:01:55 matthew Exp $
2 2
3SUBDIR+= _setjmp alloca atexit basename cephes cxa-atexit db dirname env 3SUBDIR+= _setjmp alloca atexit basename cephes cxa-atexit db dirname env
4SUBDIR+= fmemopen fnmatch fpclassify getcap getopt_long glob 4SUBDIR+= explicit_bzero fmemopen fnmatch fpclassify getcap getopt_long glob
5SUBDIR+= hsearch longjmp locale malloc mkstemp modf netdb open_memstream 5SUBDIR+= hsearch longjmp locale malloc mkstemp modf netdb open_memstream
6SUBDIR+= orientation popen printf 6SUBDIR+= orientation popen printf
7SUBDIR+= regex setjmp setjmp-signal sigreturn sigsetjmp sprintf 7SUBDIR+= regex setjmp setjmp-signal sigreturn sigsetjmp sprintf
diff --git a/src/regress/lib/libc/explicit_bzero/Makefile b/src/regress/lib/libc/explicit_bzero/Makefile
new file mode 100644
index 0000000000..cd514a43a1
--- /dev/null
+++ b/src/regress/lib/libc/explicit_bzero/Makefile
@@ -0,0 +1,5 @@
1# $OpenBSD: Makefile,v 1.1 2014/06/12 22:01:55 matthew Exp $
2
3PROG= explicit_bzero
4
5.include <bsd.regress.mk>
diff --git a/src/regress/lib/libc/explicit_bzero/explicit_bzero.c b/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
new file mode 100644
index 0000000000..b4b6c9e559
--- /dev/null
+++ b/src/regress/lib/libc/explicit_bzero/explicit_bzero.c
@@ -0,0 +1,138 @@
1/* $OpenBSD: explicit_bzero.c,v 1.1 2014/06/12 22:01:55 matthew Exp $ */
2/*
3 * Copyright (c) 2014 Google Inc.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <assert.h>
19#include <errno.h>
20#include <signal.h>
21#include <string.h>
22#include <unistd.h>
23
24#define ASSERT_EQ(a, b) assert((a) == (b))
25#define ASSERT_NE(a, b) assert((a) != (b))
26#define ASSERT_GE(a, b) assert((a) >= (b))
27
28static void
29call_on_stack(void (*fn)(int), void *stack, size_t stacklen)
30{
31 /*
32 * This is a bit more complicated than strictly necessary, but
33 * it ensures we don't have any flaky test failures due to
34 * inherited signal masks/actions/etc.
35 *
36 * On systems where SA_ONSTACK is not supported, this could
37 * alternatively be implemented using makecontext() or
38 * pthread_attr_setstack().
39 */
40
41 const struct sigaction sigact = {
42 .sa_handler = fn,
43 .sa_flags = SA_ONSTACK,
44 };
45 const stack_t sigstk = {
46 .ss_sp = stack,
47 .ss_size = stacklen,
48 };
49 struct sigaction oldsigact;
50 stack_t oldsigstk;
51 sigset_t sigset, oldsigset;
52
53 /* First, block all signals. */
54 ASSERT_EQ(0, sigemptyset(&sigset));
55 ASSERT_EQ(0, sigfillset(&sigset));
56 ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigset, &oldsigset));
57
58 /* Next setup the signal stack and handler for SIGUSR1. */
59 ASSERT_EQ(0, sigaltstack(&sigstk, &oldsigstk));
60 ASSERT_EQ(0, sigaction(SIGUSR1, &sigact, &oldsigact));
61
62 /* Raise SIGUSR1 and momentarily unblock it to run the handler. */
63 ASSERT_EQ(0, raise(SIGUSR1));
64 ASSERT_EQ(0, sigdelset(&sigset, SIGUSR1));
65 ASSERT_EQ(-1, sigsuspend(&sigset));
66 ASSERT_EQ(EINTR, errno);
67
68 /* Restore the original signal action, stack, and mask. */
69 ASSERT_EQ(0, sigaction(SIGUSR1, &oldsigact, NULL));
70 ASSERT_EQ(0, sigaltstack(&oldsigstk, NULL));
71 ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &oldsigset, NULL));
72}
73
74/* 128 bits of random data. */
75static const char secret[16] = {
76 0xa0, 0x6c, 0x0c, 0x81, 0xba, 0xd8, 0x5b, 0x0c,
77 0xb0, 0xd6, 0xd4, 0xe3, 0xeb, 0x52, 0x5f, 0x96,
78};
79
80enum {
81 SECRETCOUNT = 16,
82 SECRETBYTES = SECRETCOUNT * sizeof(secret)
83};
84
85static void
86populate_secret(char *buf, size_t len)
87{
88 int i, fds[2];
89 ASSERT_EQ(0, pipe(fds));
90
91 for (i = 0; i < SECRETCOUNT; i++)
92 ASSERT_EQ(sizeof(secret), write(fds[1], secret, sizeof(secret)));
93 ASSERT_EQ(0, close(fds[1]));
94
95 ASSERT_EQ(len, read(fds[0], buf, len));
96 ASSERT_EQ(0, close(fds[0]));
97}
98
99static void
100test_without_bzero(int signo)
101{
102 char buf[SECRETBYTES];
103 populate_secret(buf, sizeof(buf));
104}
105
106static void
107test_with_bzero(int signo)
108{
109 char buf[SECRETBYTES];
110 populate_secret(buf, sizeof(buf));
111 explicit_bzero(buf, sizeof(buf));
112}
113
114static char altstack[SIGSTKSZ];
115
116int
117main()
118{
119 /*
120 * First, test that if we *don't* call explicit_bzero, that we
121 * *are* able to find the secret data on the stack. This
122 * sanity checks that call_on_stack() and populare_secret()
123 * work as intended.
124 */
125 memset(altstack, 0, sizeof(altstack));
126 call_on_stack(test_without_bzero, altstack, sizeof(altstack));
127 ASSERT_NE(NULL, memmem(altstack, sizeof(altstack), secret, sizeof(secret)));
128
129 /*
130 * Now test with a call to explicit_bzero() and check that we
131 * *don't* find the secret data.
132 */
133 memset(altstack, 0, sizeof(altstack));
134 call_on_stack(test_with_bzero, altstack, sizeof(altstack));
135 ASSERT_EQ(NULL, memmem(altstack, sizeof(altstack), secret, sizeof(secret)));
136
137 return (0);
138}