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