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