xref: /aosp_15_r20/external/ltp/testcases/kernel/syscalls/brk/brk02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2021 Liam R. Howlett <[email protected]>
4  */
5 
6 /*\
7  * [Description]
8  *
9  * Expand brk() by at least 2 pages to ensure there is a newly created VMA
10  * and not expanding the original due to multiple anon pages.  mprotect() that
11  * new VMA then brk() back to the original address therefore causing a munmap of
12  * at least one full VMA.
13  */
14 
15 #include <unistd.h>
16 #include <sys/mman.h>
17 #include "tst_test.h"
18 #include "lapi/syscalls.h"
19 
brk_variants(void * addr)20 static void *brk_variants(void *addr)
21 {
22 	void *brk_addr;
23 
24 	if (tst_variant) {
25 		brk_addr = (void *)tst_syscall(__NR_brk, addr);
26 	} else {
27 		TST_EXP_PASS_SILENT(brk(addr), "brk()");
28 		brk_addr = (void *)sbrk(0);
29 	}
30 
31 	return brk_addr;
32 }
33 
brk_down_vmas(void)34 static void brk_down_vmas(void)
35 {
36 	void *brk_addr;
37 
38 	if (tst_variant) {
39 		tst_res(TINFO, "Testing syscall variant");
40 		brk_addr = (void *)tst_syscall(__NR_brk, 0);
41 	} else {
42 		tst_res(TINFO, "Testing libc variant");
43 		brk_addr = (void *)sbrk(0);
44 
45 		if (brk_addr == (void *)-1)
46 			tst_brk(TCONF, "sbrk() not implemented");
47 
48 		/*
49 		 * Check if brk itself is implemented: updating to the current break
50 		 * should be a no-op.
51 		 */
52 		if (brk(brk_addr) != 0)
53 			tst_brk(TCONF, "brk() not implemented");
54 	}
55 
56 	unsigned long page_size = getpagesize();
57 	void *addr = brk_addr + page_size;
58 
59 	if (brk_variants(addr) < addr) {
60 		tst_res(TFAIL | TERRNO, "Cannot expand brk() by page size");
61 		return;
62 	}
63 
64 	addr += page_size;
65 	if (brk_variants(addr) < addr) {
66 		tst_res(TFAIL | TERRNO, "Cannot expand brk() by 2x page size");
67 		return;
68 	}
69 
70 	if (mprotect(addr - page_size, page_size, PROT_READ)) {
71 		tst_res(TFAIL | TERRNO, "Cannot mprotect new VMA");
72 		return;
73 	}
74 
75 	addr += page_size;
76 	if (brk_variants(addr) < addr) {
77 		tst_res(TFAIL | TERRNO, "Cannot expand brk() after mprotect");
78 		return;
79 	}
80 
81 	if (brk_variants(brk_addr) != brk_addr) {
82 		tst_res(TFAIL | TERRNO, "Cannot restore brk() to start address");
83 		return;
84 	}
85 
86 	tst_res(TPASS, "munmap at least two VMAs of brk() passed");
87 }
88 
89 static struct tst_test test = {
90 	.test_all = brk_down_vmas,
91 	.test_variants = 2,
92 };
93