xref: /freebsd/lib/libc/tests/sys/brk_test.c (revision 4d846d260e2b9a3d4d0a701462568268cbfe7a5b)
19f9c9b22SMark Johnston /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
39f9c9b22SMark Johnston  *
49f9c9b22SMark Johnston  * Copyright (c) 2018 Mark Johnston <markj@FreeBSD.org>
59f9c9b22SMark Johnston  *
69f9c9b22SMark Johnston  * Redistribution and use in source and binary forms, with or without
79f9c9b22SMark Johnston  * modification, are permitted provided that the following conditions
89f9c9b22SMark Johnston  * are met:
99f9c9b22SMark Johnston  * 1. Redistributions of source code must retain the above copyright
109f9c9b22SMark Johnston  *    notice, this list of conditions and the following disclaimer.
119f9c9b22SMark Johnston  * 2. Redistributions in binary form must reproduce the above copyright
129f9c9b22SMark Johnston  *    notice, this list of conditions and the following disclaimer in the
139f9c9b22SMark Johnston  *    documentation and/or other materials provided with the distribution.
149f9c9b22SMark Johnston  *
159f9c9b22SMark Johnston  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
169f9c9b22SMark Johnston  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
179f9c9b22SMark Johnston  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
189f9c9b22SMark Johnston  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
199f9c9b22SMark Johnston  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
209f9c9b22SMark Johnston  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
219f9c9b22SMark Johnston  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
229f9c9b22SMark Johnston  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
239f9c9b22SMark Johnston  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
249f9c9b22SMark Johnston  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
259f9c9b22SMark Johnston  * SUCH DAMAGE.
269f9c9b22SMark Johnston  */
279f9c9b22SMark Johnston 
289f9c9b22SMark Johnston #include <sys/cdefs.h>
299f9c9b22SMark Johnston __FBSDID("$FreeBSD$");
309f9c9b22SMark Johnston 
319f9c9b22SMark Johnston #include <sys/param.h>
329f9c9b22SMark Johnston #include <sys/mman.h>
339f9c9b22SMark Johnston 
349f9c9b22SMark Johnston #include <errno.h>
359f9c9b22SMark Johnston #include <stdint.h>
369f9c9b22SMark Johnston #include <string.h>
379f9c9b22SMark Johnston #include <unistd.h>
389f9c9b22SMark Johnston 
399f9c9b22SMark Johnston #include <atf-c.h>
409f9c9b22SMark Johnston 
419f9c9b22SMark Johnston ATF_TC(brk_basic);
429f9c9b22SMark Johnston ATF_TC_HEAD(brk_basic, tc)
439f9c9b22SMark Johnston {
449f9c9b22SMark Johnston 	atf_tc_set_md_var(tc, "descr", "Verify basic brk() functionality");
459f9c9b22SMark Johnston }
469f9c9b22SMark Johnston ATF_TC_BODY(brk_basic, tc)
479f9c9b22SMark Johnston {
489f9c9b22SMark Johnston 	void *oldbrk, *newbrk;
499f9c9b22SMark Johnston 	int error;
509f9c9b22SMark Johnston 
519f9c9b22SMark Johnston 	/* Reset the break. */
529f9c9b22SMark Johnston 	error = brk(0);
539f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno));
549f9c9b22SMark Johnston 
559f9c9b22SMark Johnston 	oldbrk = sbrk(0);
569f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk != (void *)-1);
579f9c9b22SMark Johnston 
589f9c9b22SMark Johnston 	/* Try to allocate a page. */
599f9c9b22SMark Johnston 	error = brk((void *)((intptr_t)oldbrk + PAGE_SIZE * 2));
609f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno));
619f9c9b22SMark Johnston 
629f9c9b22SMark Johnston 	/*
639f9c9b22SMark Johnston 	 * Attempt to set the break below minbrk.  This should have no effect.
649f9c9b22SMark Johnston 	 */
659f9c9b22SMark Johnston 	error = brk((void *)((intptr_t)oldbrk - 1));
669f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0, "brk: %s", strerror(errno));
679f9c9b22SMark Johnston 	newbrk = sbrk(0);
689f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno));
699f9c9b22SMark Johnston 	ATF_REQUIRE(newbrk == oldbrk);
709f9c9b22SMark Johnston }
719f9c9b22SMark Johnston 
729f9c9b22SMark Johnston ATF_TC(sbrk_basic);
739f9c9b22SMark Johnston ATF_TC_HEAD(sbrk_basic, tc)
749f9c9b22SMark Johnston {
759f9c9b22SMark Johnston 	atf_tc_set_md_var(tc, "descr", "Verify basic sbrk() functionality");
769f9c9b22SMark Johnston }
779f9c9b22SMark Johnston ATF_TC_BODY(sbrk_basic, tc)
789f9c9b22SMark Johnston {
799f9c9b22SMark Johnston 	void *newbrk, *oldbrk;
809f9c9b22SMark Johnston 	int *p;
819f9c9b22SMark Johnston 
829f9c9b22SMark Johnston 	oldbrk = sbrk(0);
839f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(oldbrk != (void *)-1, "sbrk: %s", strerror(errno));
849f9c9b22SMark Johnston 	p = sbrk(sizeof(*p));
859f9c9b22SMark Johnston 	*p = 0;
869f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk == p);
879f9c9b22SMark Johnston 
889f9c9b22SMark Johnston 	newbrk = sbrk(-sizeof(*p));
899f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno));
909f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk == sbrk(0));
919f9c9b22SMark Johnston 
929f9c9b22SMark Johnston 	oldbrk = sbrk(PAGE_SIZE * 2 + 1);
939f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(oldbrk != (void *)-1, "sbrk: %s", strerror(errno));
949f9c9b22SMark Johnston 	memset(oldbrk, 0, PAGE_SIZE * 2 + 1);
959f9c9b22SMark Johnston 	newbrk = sbrk(-(PAGE_SIZE * 2 + 1));
969f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(newbrk != (void *)-1, "sbrk: %s", strerror(errno));
979f9c9b22SMark Johnston 	ATF_REQUIRE(sbrk(0) == oldbrk);
989f9c9b22SMark Johnston }
999f9c9b22SMark Johnston 
1009f9c9b22SMark Johnston ATF_TC(mlockfuture);
1019f9c9b22SMark Johnston ATF_TC_HEAD(mlockfuture, tc)
1029f9c9b22SMark Johnston {
1039f9c9b22SMark Johnston 	atf_tc_set_md_var(tc, "descr",
1049f9c9b22SMark Johnston 	    "Verify that mlockall(MCL_FUTURE) applies to the data segment");
1059f9c9b22SMark Johnston }
1069f9c9b22SMark Johnston ATF_TC_BODY(mlockfuture, tc)
1079f9c9b22SMark Johnston {
1089f9c9b22SMark Johnston 	void *oldbrk, *n, *newbrk;
1099f9c9b22SMark Johnston 	int error;
1109f9c9b22SMark Johnston 	char v;
1119f9c9b22SMark Johnston 
1129f9c9b22SMark Johnston 	error = mlockall(MCL_FUTURE);
1139f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0,
1149f9c9b22SMark Johnston 	    "mlockall: %s", strerror(errno));
1159f9c9b22SMark Johnston 
1169f9c9b22SMark Johnston 	/*
1179f9c9b22SMark Johnston 	 * Advance the break so that at least one page is added to the data
1189f9c9b22SMark Johnston 	 * segment.  This page should be automatically faulted in to the address
1199f9c9b22SMark Johnston 	 * space.
1209f9c9b22SMark Johnston 	 */
1219f9c9b22SMark Johnston 	oldbrk = sbrk(0);
1229f9c9b22SMark Johnston 	ATF_REQUIRE(oldbrk != (void *)-1);
1239f9c9b22SMark Johnston 	newbrk = sbrk(PAGE_SIZE * 2);
1249f9c9b22SMark Johnston 	ATF_REQUIRE(newbrk != (void *)-1);
1259f9c9b22SMark Johnston 
1269f9c9b22SMark Johnston 	n = (void *)(((uintptr_t)oldbrk + PAGE_SIZE) & ~PAGE_SIZE);
1279f9c9b22SMark Johnston 	v = 0;
1289f9c9b22SMark Johnston 	error = mincore(n, PAGE_SIZE, &v);
1299f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0,
1309f9c9b22SMark Johnston 	    "mincore: %s", strerror(errno));
1319f9c9b22SMark Johnston 	ATF_REQUIRE_MSG((v & MINCORE_INCORE) != 0,
1329f9c9b22SMark Johnston 	    "unexpected page flags %#x", v);
1339f9c9b22SMark Johnston 
1349f9c9b22SMark Johnston 	error = brk(oldbrk);
1359f9c9b22SMark Johnston 	ATF_REQUIRE(error == 0);
1369f9c9b22SMark Johnston 
1379f9c9b22SMark Johnston 	error = munlockall();
1389f9c9b22SMark Johnston 	ATF_REQUIRE_MSG(error == 0,
1399f9c9b22SMark Johnston 	    "munlockall: %s", strerror(errno));
1409f9c9b22SMark Johnston }
1419f9c9b22SMark Johnston 
1429f9c9b22SMark Johnston ATF_TP_ADD_TCS(tp)
1439f9c9b22SMark Johnston {
1449f9c9b22SMark Johnston 	ATF_TP_ADD_TC(tp, brk_basic);
1459f9c9b22SMark Johnston 	ATF_TP_ADD_TC(tp, sbrk_basic);
1469f9c9b22SMark Johnston 	ATF_TP_ADD_TC(tp, mlockfuture);
1479f9c9b22SMark Johnston 
1489f9c9b22SMark Johnston 	return (atf_no_error());
1499f9c9b22SMark Johnston }
150