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