• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <stdio.h>
9 #define TST_NO_DEFAULT_MAIN
10 #include "tst_test.h"
11 
12 struct map {
13 	void *addr;
14 	size_t size;
15 	size_t buf_shift;
16 	struct map *next;
17 };
18 
19 static struct map *maps;
20 
setup_canary(struct map * map)21 static void setup_canary(struct map *map)
22 {
23 	size_t i;
24 	char *buf = map->addr;
25 
26 	for (i = 0; i < map->buf_shift/2; i++) {
27 		char c = random();
28 		buf[map->buf_shift - i - 1] = c;
29 		buf[i] = c;
30 	}
31 }
32 
check_canary(struct map * map)33 static void check_canary(struct map *map)
34 {
35 	size_t i;
36 	char *buf = map->addr;
37 
38 	for (i = 0; i < map->buf_shift/2; i++) {
39 		if (buf[map->buf_shift - i - 1] != buf[i]) {
40 			tst_res(TWARN,
41 				"pid %i: buffer modified address %p[%zi]",
42 				getpid(), (char*)map->addr + map->buf_shift, -i-1);
43 		}
44 	}
45 }
46 
tst_alloc(size_t size)47 void *tst_alloc(size_t size)
48 {
49 	size_t page_size = getpagesize();
50 	unsigned int pages = (size / page_size) + !!(size % page_size) + 1;
51 	void *ret;
52 	struct map *map = SAFE_MALLOC(sizeof(struct map));
53 	static int print_msg = 1;
54 
55 	if (print_msg) {
56 		tst_res(TINFO, "Test is using guarded buffers");
57 		print_msg = 0;
58 	}
59 
60 	ret = SAFE_MMAP(NULL, page_size * pages, PROT_READ | PROT_WRITE,
61 	                MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
62 
63 	mprotect(ret + (pages-1) * page_size, page_size, PROT_NONE);
64 
65 	map->addr = ret;
66 	map->size = pages * page_size;
67 	map->next = maps;
68 	maps = map;
69 
70 	if (size % page_size)
71 		map->buf_shift = page_size - (size % page_size);
72 	else
73 		map->buf_shift = 0;
74 
75 	setup_canary(map);
76 
77 	return ret + map->buf_shift;
78 }
79 
tst_aprintf(const char * fmt,...)80 char *tst_aprintf(const char *fmt, ...)
81 {
82 	va_list va;
83 	int len;
84 	char *ret;
85 
86         va_start(va, fmt);
87         len = vsnprintf(NULL, 0, fmt, va)+1;
88         va_end(va);
89 
90 	ret = tst_alloc(len);
91 
92 	va_start(va, fmt);
93         vsprintf(ret, fmt, va);
94         va_end(va);
95 
96 	return ret;
97 }
98 
count_iovec(int * sizes)99 static int count_iovec(int *sizes)
100 {
101 	int ret = 0;
102 
103 	while (sizes[ret++] != -1);
104 
105 	return ret - 1;
106 }
107 
tst_iovec_alloc(int sizes[])108 struct iovec *tst_iovec_alloc(int sizes[])
109 {
110 	int i, cnt = count_iovec(sizes);
111 	struct iovec *iovec;
112 
113 	if (cnt <= 0)
114 		return NULL;
115 
116 	iovec = tst_alloc(sizeof(struct iovec) * cnt);
117 
118 	for (i = 0; i < cnt; i++) {
119 		if (sizes[i]) {
120 			iovec[i].iov_base = tst_alloc(sizes[i]);
121 			iovec[i].iov_len = sizes[i];
122 		} else {
123 			iovec[i].iov_base = NULL;
124 			iovec[i].iov_base = 0;
125 		}
126 	}
127 
128 	return iovec;
129 }
130 
tst_buffers_alloc(struct tst_buffers bufs[])131 void tst_buffers_alloc(struct tst_buffers bufs[])
132 {
133 	unsigned int i;
134 
135 	for (i = 0; bufs[i].ptr; i++) {
136 		if (bufs[i].size)
137 			*((void**)bufs[i].ptr) = tst_alloc(bufs[i].size);
138 		else if (bufs[i].iov_sizes)
139 			*((void**)bufs[i].ptr) = tst_iovec_alloc(bufs[i].iov_sizes);
140 		else
141 			*((void**)bufs[i].ptr) = tst_strdup(bufs[i].str);
142 	}
143 }
144 
tst_strdup(const char * str)145 char *tst_strdup(const char *str)
146 {
147 	char *ret = tst_alloc(strlen(str) + 1);
148 
149 	return strcpy(ret, str);
150 }
151 
tst_free_all(void)152 void tst_free_all(void)
153 {
154 	struct map *i = maps;
155 
156 	while (i) {
157 		struct map *j = i;
158 		check_canary(i);
159 		SAFE_MUNMAP(i->addr, i->size);
160 		i = i->next;
161 		free(j);
162 	}
163 
164 	maps = NULL;
165 }
166