1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <setjmp.h>
#include <cmocka.h>
#include "lib/replace/replace.h"
/*
* To check that a memset_explicit string is being memset when it
* appears unused, we meed to be sneaky in our check -- otherwise the
* check counts as a use.
*
* We are sneaky by using a function that seens to take an int
* argument which is really a pointer, and we hide that it is a
* pointer by masking it.
*
* For these tests we don't use talloc because the talloc magic gets
* in the way a little bit.
*/
#define MASK 0x12345678
__attribute__((noinline))
static void check_memset_explicit(intmax_t p, const char *expected, size_t len)
{
size_t i;
char *secret = (char *) (p ^ MASK);
for (i = 0; i < len; i++) {
assert_int_equal(secret[i], expected[i]);
}
}
__attribute__((noinline))
static char *get_secret(off_t offset)
{
char * secret = malloc(7 + offset);
memset(secret, 0, 7 + offset);
memcpy(secret + offset, "secret", 7);
/* avoiding *this* being elided */
print_message("secret is '%s'\n", secret);
asm("");
return secret;
}
static void test_memset_explicit(void ** state)
{
uintptr_t p;
char zeros[7] = {0};
char *secret = get_secret(0);
p = ((uintptr_t)secret) ^ MASK;
memset_explicit(secret, 'o', 3);
check_memset_explicit(p, "oooret", 7);
memset_explicit(secret, 0, 7);
check_memset_explicit(p, zeros, 7);
free(secret);
}
static void test_memset_explicit_double_alloc(void ** state)
{
size_t i, found;
uintptr_t p, q;
char *secret = get_secret(20);
p = (uintptr_t)secret ^ MASK;
memset_explicit(secret, 'x', 23);
free(secret);
/*
* Now we malloc the same size again, and hope we got the
* block we just freed.
*/
found = 0;
for (i = 0; i < 1000; i++) {
secret = malloc(27);
q = (uintptr_t)secret ^ MASK;
if (q == p) {
q = (uintptr_t)(secret + 20) ^ MASK;
check_memset_explicit(q, "xxxret", 7);
found ++;
}
free(secret);
}
print_message("found freed pointer %zu/1000 times \n",
found);
}
int main(void)
{
const struct CMUnitTest tests[] = {
cmocka_unit_test(test_memset_explicit),
cmocka_unit_test(test_memset_explicit_double_alloc),
};
if (! isatty(1)) {
cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
}
return cmocka_run_group_tests(tests, NULL, NULL);
}
|