xref: /freebsd/lib/libc/tests/sys/brk_test.c (revision 9f9c9b22ecfd9e87cbe9e1becf946faeb5fbcac6)
1*9f9c9b22SMark Johnston /*-
2*9f9c9b22SMark Johnston  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*9f9c9b22SMark Johnston  *
4*9f9c9b22SMark Johnston  * Copyright (c) 2018 Mark Johnston <markj@FreeBSD.org>
5*9f9c9b22SMark Johnston  *
6*9f9c9b22SMark Johnston  * Redistribution and use in source and binary forms, with or without
7*9f9c9b22SMark Johnston  * modification, are permitted provided that the following conditions
8*9f9c9b22SMark Johnston  * are met:
9*9f9c9b22SMark Johnston  * 1. Redistributions of source code must retain the above copyright
10*9f9c9b22SMark Johnston  *    notice, this list of conditions and the following disclaimer.
11*9f9c9b22SMark Johnston  * 2. Redistributions in binary form must reproduce the above copyright
12*9f9c9b22SMark Johnston  *    notice, this list of conditions and the following disclaimer in the
13*9f9c9b22SMark Johnston  *    documentation and/or other materials provided with the distribution.
14*9f9c9b22SMark Johnston  *
15*9f9c9b22SMark Johnston  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*9f9c9b22SMark Johnston  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*9f9c9b22SMark Johnston  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*9f9c9b22SMark Johnston  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*9f9c9b22SMark Johnston  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*9f9c9b22SMark Johnston  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*9f9c9b22SMark Johnston  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*9f9c9b22SMark Johnston  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*9f9c9b22SMark Johnston  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*9f9c9b22SMark Johnston  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*9f9c9b22SMark Johnston  * SUCH DAMAGE.
26*9f9c9b22SMark Johnston  */
27*9f9c9b22SMark Johnston 
28*9f9c9b22SMark Johnston #include <sys/cdefs.h>
29*9f9c9b22SMark Johnston __FBSDID("$FreeBSD$");
30*9f9c9b22SMark Johnston 
31*9f9c9b22SMark Johnston #include <sys/param.h>
32*9f9c9b22SMark Johnston #include <sys/mman.h>
33*9f9c9b22SMark Johnston 
34*9f9c9b22SMark Johnston #include <errno.h>
35*9f9c9b22SMark Johnston #include <stdint.h>
36*9f9c9b22SMark Johnston #include <string.h>
37*9f9c9b22SMark Johnston #include <unistd.h>
38*9f9c9b22SMark Johnston 
39*9f9c9b22SMark Johnston #include <atf-c.h>
40*9f9c9b22SMark Johnston 
41*9f9c9b22SMark Johnston ATF_TC(brk_basic);
42*9f9c9b22SMark Johnston ATF_TC_HEAD(brk_basic, tc)
43*9f9c9b22SMark Johnston {
44*9f9c9b22SMark Johnston 	atf_tc_set_md_var(tc, "descr", "Verify basic brk() functionality");
45*9f9c9b22SMark Johnston }
46*9f9c9b22SMark Johnston ATF_TC_BODY(brk_basic, tc)
47*9f9c9b22SMark Johnston {
48*9f9c9b22SMark Johnston 	void *oldbrk, *newbrk;
49*9f9c9b22SMark Johnston 	int error;
50*9f9c9b22SMark Johnston 
51*9f9c9b22SMark Johnston 	/* Reset the break. */
52*9f9c9b22SMark Johnston 	error = brk(0);
53*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno));
54*9f9c9b22SMark Johnston 
55*9f9c9b22SMark Johnston 	oldbrk = sbrk(0);
56*9f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk != (void *)-1);
57*9f9c9b22SMark Johnston 
58*9f9c9b22SMark Johnston 	/* Try to allocate a page. */
59*9f9c9b22SMark Johnston 	error = brk((void *)((intptr_t)oldbrk + PAGE_SIZE * 2));
60*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno));
61*9f9c9b22SMark Johnston 
62*9f9c9b22SMark Johnston 	/*
63*9f9c9b22SMark Johnston 	 * Attempt to set the break below minbrk.  This should have no effect.
64*9f9c9b22SMark Johnston 	 */
65*9f9c9b22SMark Johnston 	error = brk((void *)((intptr_t)oldbrk - 1));
66*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno));
67*9f9c9b22SMark Johnston 	newbrk = sbrk(0);
68*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno));
69*9f9c9b22SMark Johnston 	ATF_REQUIRE(newbrk == oldbrk);
70*9f9c9b22SMark Johnston }
71*9f9c9b22SMark Johnston 
72*9f9c9b22SMark Johnston ATF_TC(sbrk_basic);
73*9f9c9b22SMark Johnston ATF_TC_HEAD(sbrk_basic, tc)
74*9f9c9b22SMark Johnston {
75*9f9c9b22SMark Johnston 	atf_tc_set_md_var(tc, "descr", "Verify basic sbrk() functionality");
76*9f9c9b22SMark Johnston }
77*9f9c9b22SMark Johnston ATF_TC_BODY(sbrk_basic, tc)
78*9f9c9b22SMark Johnston {
79*9f9c9b22SMark Johnston 	void *newbrk, *oldbrk;
80*9f9c9b22SMark Johnston 	int *p;
81*9f9c9b22SMark Johnston 
82*9f9c9b22SMark Johnston 	oldbrk = sbrk(0);
83*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(oldbrk != (void *)-1, "sbrk: %s", strerror(errno));
84*9f9c9b22SMark Johnston 	p = sbrk(sizeof(*p));
85*9f9c9b22SMark Johnston 	*p = 0;
86*9f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk == p);
87*9f9c9b22SMark Johnston 
88*9f9c9b22SMark Johnston 	newbrk = sbrk(-sizeof(*p));
89*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno));
90*9f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk == sbrk(0));
91*9f9c9b22SMark Johnston 
92*9f9c9b22SMark Johnston 	oldbrk = sbrk(PAGE_SIZE * 2 + 1);
93*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(oldbrk != (void *)-1, "sbrk: %s", strerror(errno));
94*9f9c9b22SMark Johnston 	memset(oldbrk, 0, PAGE_SIZE * 2 + 1);
95*9f9c9b22SMark Johnston 	newbrk = sbrk(-(PAGE_SIZE * 2 + 1));
96*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno));
97*9f9c9b22SMark Johnston 	ATF_REQUIRE(sbrk(0) == oldbrk);
98*9f9c9b22SMark Johnston }
99*9f9c9b22SMark Johnston 
100*9f9c9b22SMark Johnston ATF_TC(mlockfuture);
101*9f9c9b22SMark Johnston ATF_TC_HEAD(mlockfuture, tc)
102*9f9c9b22SMark Johnston {
103*9f9c9b22SMark Johnston 	atf_tc_set_md_var(tc, "descr",
104*9f9c9b22SMark Johnston 	    "Verify that mlockall(MCL_FUTURE) applies to the data segment");
105*9f9c9b22SMark Johnston }
106*9f9c9b22SMark Johnston ATF_TC_BODY(mlockfuture, tc)
107*9f9c9b22SMark Johnston {
108*9f9c9b22SMark Johnston 	void *oldbrk, *n, *newbrk;
109*9f9c9b22SMark Johnston 	int error;
110*9f9c9b22SMark Johnston 	char v;
111*9f9c9b22SMark Johnston 
112*9f9c9b22SMark Johnston 	error = mlockall(MCL_FUTURE);
113*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0,
114*9f9c9b22SMark Johnston 	    "mlockall: %s", strerror(errno));
115*9f9c9b22SMark Johnston 
116*9f9c9b22SMark Johnston 	/*
117*9f9c9b22SMark Johnston 	 * Advance the break so that at least one page is added to the data
118*9f9c9b22SMark Johnston 	 * segment.  This page should be automatically faulted in to the address
119*9f9c9b22SMark Johnston 	 * space.
120*9f9c9b22SMark Johnston 	 */
121*9f9c9b22SMark Johnston 	oldbrk = sbrk(0);
122*9f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk != (void *)-1);
123*9f9c9b22SMark Johnston 	newbrk = sbrk(PAGE_SIZE * 2);
124*9f9c9b22SMark Johnston 	ATF_REQUIRE(newbrk != (void *)-1);
125*9f9c9b22SMark Johnston 
126*9f9c9b22SMark Johnston 	n = (void *)(((uintptr_t)oldbrk + PAGE_SIZE) & ~PAGE_SIZE);
127*9f9c9b22SMark Johnston 	v = 0;
128*9f9c9b22SMark Johnston 	error = mincore(n, PAGE_SIZE, &v);
129*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0,
130*9f9c9b22SMark Johnston 	    "mincore: %s", strerror(errno));
131*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG((v & MINCORE_INCORE) != 0,
132*9f9c9b22SMark Johnston 	    "unexpected page flags %#x", v);
133*9f9c9b22SMark Johnston 
134*9f9c9b22SMark Johnston 	error = brk(oldbrk);
135*9f9c9b22SMark Johnston 	ATF_REQUIRE(error == 0);
136*9f9c9b22SMark Johnston 
137*9f9c9b22SMark Johnston 	error = munlockall();
138*9f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0,
139*9f9c9b22SMark Johnston 	    "munlockall: %s", strerror(errno));
140*9f9c9b22SMark Johnston }
141*9f9c9b22SMark Johnston 
142*9f9c9b22SMark Johnston ATF_TP_ADD_TCS(tp)
143*9f9c9b22SMark Johnston {
144*9f9c9b22SMark Johnston 	ATF_TP_ADD_TC(tp, brk_basic);
145*9f9c9b22SMark Johnston 	ATF_TP_ADD_TC(tp, sbrk_basic);
146*9f9c9b22SMark Johnston 	ATF_TP_ADD_TC(tp, mlockfuture);
147*9f9c9b22SMark Johnston 
148*9f9c9b22SMark Johnston 	return (atf_no_error());
149*9f9c9b22SMark Johnston }
150