1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2019 Cyril Hrubis <chrubis@suse.cz>
4 */
5
6 #include <sys/mman.h>
7 #include <stdlib.h>
8 #define TST_NO_DEFAULT_MAIN
9 #include "tst_test.h"
10
11 struct map {
12 void *addr;
13 size_t size;
14 size_t buf_shift;
15 struct map *next;
16 };
17
18 static struct map *maps;
19
setup_canary(struct map * map)20 static void setup_canary(struct map *map)
21 {
22 size_t i;
23 char *buf = map->addr;
24
25 for (i = 0; i < map->buf_shift/2; i++) {
26 char c = random();
27 buf[map->buf_shift - i - 1] = c;
28 buf[i] = c;
29 }
30 }
31
check_canary(struct map * map)32 static void check_canary(struct map *map)
33 {
34 size_t i;
35 char *buf = map->addr;
36
37 for (i = 0; i < map->buf_shift/2; i++) {
38 if (buf[map->buf_shift - i - 1] != buf[i]) {
39 tst_res(TWARN,
40 "pid %i: buffer modified address %p[%zi]",
41 getpid(), (char*)map->addr + map->buf_shift, -i-1);
42 }
43 }
44 }
45
tst_alloc(size_t size)46 void *tst_alloc(size_t size)
47 {
48 size_t page_size = getpagesize();
49 unsigned int pages = (size / page_size) + !!(size % page_size) + 1;
50 void *ret;
51 struct map *map = SAFE_MALLOC(sizeof(struct map));
52 static int print_msg = 1;
53
54 if (print_msg) {
55 tst_res(TINFO, "Test is using guarded buffers");
56 print_msg = 0;
57 }
58
59 ret = SAFE_MMAP(NULL, page_size * pages, PROT_READ | PROT_WRITE,
60 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
61
62 mprotect(ret + (pages-1) * page_size, page_size, PROT_NONE);
63
64 map->addr = ret;
65 map->size = pages * page_size;
66 map->next = maps;
67 maps = map;
68
69 if (size % page_size)
70 map->buf_shift = page_size - (size % page_size);
71 else
72 map->buf_shift = 0;
73
74 setup_canary(map);
75
76 return ret + map->buf_shift;
77 }
78
count_iovec(int * sizes)79 static int count_iovec(int *sizes)
80 {
81 int ret = 0;
82
83 while (sizes[ret++] != -1);
84
85 return ret - 1;
86 }
87
tst_iovec_alloc(int sizes[])88 struct iovec *tst_iovec_alloc(int sizes[])
89 {
90 int i, cnt = count_iovec(sizes);
91 struct iovec *iovec;
92
93 if (cnt <= 0)
94 return NULL;
95
96 iovec = tst_alloc(sizeof(struct iovec) * cnt);
97
98 for (i = 0; i < cnt; i++) {
99 if (sizes[i]) {
100 iovec[i].iov_base = tst_alloc(sizes[i]);
101 iovec[i].iov_len = sizes[i];
102 } else {
103 iovec[i].iov_base = NULL;
104 iovec[i].iov_base = 0;
105 }
106 }
107
108 return iovec;
109 }
110
tst_buffers_alloc(struct tst_buffers bufs[])111 void tst_buffers_alloc(struct tst_buffers bufs[])
112 {
113 unsigned int i;
114
115 for (i = 0; bufs[i].ptr; i++) {
116 if (bufs[i].size)
117 *((void**)bufs[i].ptr) = tst_alloc(bufs[i].size);
118 else
119 *((void**)bufs[i].ptr) = tst_iovec_alloc(bufs[i].iov_sizes);
120 }
121 }
122
tst_strdup(const char * str)123 char *tst_strdup(const char *str)
124 {
125 size_t len = strlen(str);
126 char *ret = tst_alloc(len + 1);
127 return strcpy(ret, str);
128 }
129
tst_free_all(void)130 void tst_free_all(void)
131 {
132 struct map *i = maps;
133
134 while (i) {
135 struct map *j = i;
136 check_canary(i);
137 SAFE_MUNMAP(i->addr, i->size);
138 i = i->next;
139 free(j);
140 }
141
142 maps = NULL;
143 }
144