• 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 #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