1640235e2SEnji Cooper /* $NetBSD: t_mlock.c,v 1.6 2016/08/09 12:02:44 kre Exp $ */
257718be8SEnji Cooper
357718be8SEnji Cooper /*-
457718be8SEnji Cooper * Copyright (c) 2012 The NetBSD Foundation, Inc.
557718be8SEnji Cooper * All rights reserved.
657718be8SEnji Cooper *
757718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation
857718be8SEnji Cooper * by Jukka Ruohonen.
957718be8SEnji Cooper *
1057718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without
1157718be8SEnji Cooper * modification, are permitted provided that the following conditions
1257718be8SEnji Cooper * are met:
1357718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright
1457718be8SEnji Cooper * notice, this list of conditions and the following disclaimer.
1557718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
1657718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the
1757718be8SEnji Cooper * documentation and/or other materials provided with the distribution.
1857718be8SEnji Cooper *
1957718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2057718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2157718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2257718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2357718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2457718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2557718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2657718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2757718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2857718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2957718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE.
3057718be8SEnji Cooper */
3157718be8SEnji Cooper #include <sys/cdefs.h>
32640235e2SEnji Cooper __RCSID("$NetBSD: t_mlock.c,v 1.6 2016/08/09 12:02:44 kre Exp $");
3357718be8SEnji Cooper
3455fd0faaSEnji Cooper #ifdef __FreeBSD__
3539a3103bSEnji Cooper #include <sys/param.h> /* NetBSD requires sys/param.h for sysctl(3), unlike FreeBSD */
3655fd0faaSEnji Cooper #endif
3757718be8SEnji Cooper #include <sys/mman.h>
3857718be8SEnji Cooper #include <sys/resource.h>
3957718be8SEnji Cooper #include <sys/sysctl.h>
4057718be8SEnji Cooper #include <sys/wait.h>
4157718be8SEnji Cooper
4257718be8SEnji Cooper #include <errno.h>
4357718be8SEnji Cooper #include <atf-c.h>
4457718be8SEnji Cooper #include <stdint.h>
4557718be8SEnji Cooper #include <stdio.h>
4657718be8SEnji Cooper #include <stdlib.h>
4757718be8SEnji Cooper #include <unistd.h>
4857718be8SEnji Cooper
4955fd0faaSEnji Cooper #ifdef __FreeBSD__
508e62f841SEnji Cooper #include <limits.h>
5155fd0faaSEnji Cooper #define _KMEMUSER
5255fd0faaSEnji Cooper #include <machine/vmparam.h>
53710542dfSBryan Drewery
54*54a3a114SMark Johnston void set_vm_max_wired(u_long);
55710542dfSBryan Drewery void restore_vm_max_wired(void);
5655fd0faaSEnji Cooper #endif
5755fd0faaSEnji Cooper
5857718be8SEnji Cooper static long page = 0;
5957718be8SEnji Cooper
6057718be8SEnji Cooper ATF_TC(mlock_clip);
ATF_TC_HEAD(mlock_clip,tc)6157718be8SEnji Cooper ATF_TC_HEAD(mlock_clip, tc)
6257718be8SEnji Cooper {
6357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test with mlock(2) that UVM only "
6457718be8SEnji Cooper "clips if the clip address is within the entry (PR kern/44788)");
6557718be8SEnji Cooper }
6657718be8SEnji Cooper
ATF_TC_BODY(mlock_clip,tc)6757718be8SEnji Cooper ATF_TC_BODY(mlock_clip, tc)
6857718be8SEnji Cooper {
6957718be8SEnji Cooper void *buf;
7057718be8SEnji Cooper
7157718be8SEnji Cooper buf = malloc(page);
7257718be8SEnji Cooper ATF_REQUIRE(buf != NULL);
7357718be8SEnji Cooper
7457718be8SEnji Cooper if (page < 1024)
7557718be8SEnji Cooper atf_tc_skip("page size too small");
7657718be8SEnji Cooper
7757718be8SEnji Cooper for (size_t i = page; i >= 1; i = i - 1024) {
7857718be8SEnji Cooper (void)mlock(buf, page - i);
7957718be8SEnji Cooper (void)munlock(buf, page - i);
8057718be8SEnji Cooper }
8157718be8SEnji Cooper
8257718be8SEnji Cooper free(buf);
8357718be8SEnji Cooper }
8457718be8SEnji Cooper
858e62f841SEnji Cooper #ifdef __FreeBSD__
868e62f841SEnji Cooper ATF_TC_WITH_CLEANUP(mlock_err);
878e62f841SEnji Cooper #else
8857718be8SEnji Cooper ATF_TC(mlock_err);
898e62f841SEnji Cooper #endif
ATF_TC_HEAD(mlock_err,tc)9057718be8SEnji Cooper ATF_TC_HEAD(mlock_err, tc)
9157718be8SEnji Cooper {
9257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
9357718be8SEnji Cooper "Test error conditions in mlock(2) and munlock(2)");
948e62f841SEnji Cooper #ifdef __FreeBSD__
958e62f841SEnji Cooper atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
968e62f841SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root");
978e62f841SEnji Cooper #endif
9857718be8SEnji Cooper }
9957718be8SEnji Cooper
ATF_TC_BODY(mlock_err,tc)10057718be8SEnji Cooper ATF_TC_BODY(mlock_err, tc)
10157718be8SEnji Cooper {
10255fd0faaSEnji Cooper #ifdef __NetBSD__
10357718be8SEnji Cooper unsigned long vmin = 0;
10457718be8SEnji Cooper size_t len = sizeof(vmin);
10555fd0faaSEnji Cooper #endif
106ca20f8ecSRuslan Bukin #if !defined(__aarch64__) && !defined(__riscv)
10757718be8SEnji Cooper void *invalid_ptr;
10894098ab7SAndrew Turner #endif
109640235e2SEnji Cooper void *buf;
11057718be8SEnji Cooper
11155fd0faaSEnji Cooper #ifdef __FreeBSD__
1128e62f841SEnji Cooper /* Set max_wired really really high to avoid EAGAIN */
1138e62f841SEnji Cooper set_vm_max_wired(INT_MAX);
11455fd0faaSEnji Cooper #else
11557718be8SEnji Cooper if (sysctlbyname("vm.minaddress", &vmin, &len, NULL, 0) != 0)
11657718be8SEnji Cooper atf_tc_fail("failed to read vm.minaddress");
117640235e2SEnji Cooper /*
118640235e2SEnji Cooper * Any bad address must return ENOMEM (for lock & unlock)
119640235e2SEnji Cooper */
120640235e2SEnji Cooper errno = 0;
121640235e2SEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, mlock(NULL, page) == -1);
12255fd0faaSEnji Cooper #endif
12357718be8SEnji Cooper
12457718be8SEnji Cooper errno = 0;
125640235e2SEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, mlock((char *)0, page) == -1);
12657718be8SEnji Cooper
12757718be8SEnji Cooper errno = 0;
128640235e2SEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, munlock(NULL, page) == -1);
12957718be8SEnji Cooper
13057718be8SEnji Cooper errno = 0;
131640235e2SEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, munlock((char *)0, page) == -1);
13257718be8SEnji Cooper
13376f9d275SAlan Somers #ifdef __FreeBSD__
13476f9d275SAlan Somers /* Wrap around should return EINVAL */
13576f9d275SAlan Somers errno = 0;
13676f9d275SAlan Somers ATF_REQUIRE_ERRNO(EINVAL, mlock((char *)-1, page) == -1);
13776f9d275SAlan Somers errno = 0;
13876f9d275SAlan Somers ATF_REQUIRE_ERRNO(EINVAL, munlock((char *)-1, page) == -1);
13976f9d275SAlan Somers #else
14076f9d275SAlan Somers errno = 0;
14176f9d275SAlan Somers ATF_REQUIRE_ERRNO(ENOMEM, mlock((char *)-1, page) == -1);
14257718be8SEnji Cooper errno = 0;
143640235e2SEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, munlock((char *)-1, page) == -1);
14476f9d275SAlan Somers #endif
145640235e2SEnji Cooper
14676f9d275SAlan Somers buf = malloc(page); /* Get a valid address */
147640235e2SEnji Cooper ATF_REQUIRE(buf != NULL);
14876f9d275SAlan Somers #ifdef __FreeBSD__
14957718be8SEnji Cooper errno = 0;
15076f9d275SAlan Somers /* Wrap around should return EINVAL */
15176f9d275SAlan Somers ATF_REQUIRE_ERRNO(EINVAL, mlock(buf, -page) == -1);
15276f9d275SAlan Somers errno = 0;
15376f9d275SAlan Somers ATF_REQUIRE_ERRNO(EINVAL, munlock(buf, -page) == -1);
15476f9d275SAlan Somers #else
15576f9d275SAlan Somers errno = 0;
15676f9d275SAlan Somers ATF_REQUIRE_ERRNO(ENOMEM, mlock(buf, -page) == -1);
15776f9d275SAlan Somers errno = 0;
15876f9d275SAlan Somers ATF_REQUIRE_ERRNO(ENOMEM, munlock(buf, -page) == -1);
15976f9d275SAlan Somers #endif
16076f9d275SAlan Somers (void)free(buf);
16157718be8SEnji Cooper
162b7b46892SRuslan Bukin /* There is no sbrk on AArch64 and RISC-V */
163ca20f8ecSRuslan Bukin #if !defined(__aarch64__) && !defined(__riscv)
16457718be8SEnji Cooper /*
16557718be8SEnji Cooper * Try to create a pointer to an unmapped page - first after current
16657718be8SEnji Cooper * brk will likely do.
16757718be8SEnji Cooper */
16857718be8SEnji Cooper invalid_ptr = (void*)(((uintptr_t)sbrk(0)+page) & ~(page-1));
16957718be8SEnji Cooper printf("testing with (hopefully) invalid pointer %p\n", invalid_ptr);
17057718be8SEnji Cooper
17157718be8SEnji Cooper errno = 0;
17257718be8SEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, mlock(invalid_ptr, page) == -1);
17357718be8SEnji Cooper
17457718be8SEnji Cooper errno = 0;
17557718be8SEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, munlock(invalid_ptr, page) == -1);
17694098ab7SAndrew Turner #endif
17757718be8SEnji Cooper }
17857718be8SEnji Cooper
1798e62f841SEnji Cooper #ifdef __FreeBSD__
ATF_TC_CLEANUP(mlock_err,tc)1808e62f841SEnji Cooper ATF_TC_CLEANUP(mlock_err, tc)
1818e62f841SEnji Cooper {
1828e62f841SEnji Cooper
1838e62f841SEnji Cooper restore_vm_max_wired();
1848e62f841SEnji Cooper }
1858e62f841SEnji Cooper #endif
1868e62f841SEnji Cooper
18757718be8SEnji Cooper ATF_TC(mlock_limits);
ATF_TC_HEAD(mlock_limits,tc)18857718be8SEnji Cooper ATF_TC_HEAD(mlock_limits, tc)
18957718be8SEnji Cooper {
19057718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test system limits with mlock(2)");
19157718be8SEnji Cooper }
19257718be8SEnji Cooper
ATF_TC_BODY(mlock_limits,tc)19357718be8SEnji Cooper ATF_TC_BODY(mlock_limits, tc)
19457718be8SEnji Cooper {
19557718be8SEnji Cooper struct rlimit res;
19657718be8SEnji Cooper void *buf;
19757718be8SEnji Cooper pid_t pid;
19857718be8SEnji Cooper int sta;
19957718be8SEnji Cooper
20057718be8SEnji Cooper buf = malloc(page);
20157718be8SEnji Cooper ATF_REQUIRE(buf != NULL);
20257718be8SEnji Cooper
20357718be8SEnji Cooper pid = fork();
20457718be8SEnji Cooper ATF_REQUIRE(pid >= 0);
20557718be8SEnji Cooper
20657718be8SEnji Cooper if (pid == 0) {
20757718be8SEnji Cooper
20857718be8SEnji Cooper for (ssize_t i = page; i >= 2; i -= 100) {
20957718be8SEnji Cooper
21057718be8SEnji Cooper res.rlim_cur = i - 1;
21157718be8SEnji Cooper res.rlim_max = i - 1;
21257718be8SEnji Cooper
21357718be8SEnji Cooper (void)fprintf(stderr, "trying to lock %zd bytes "
21457718be8SEnji Cooper "with %zu byte limit\n", i, (size_t)res.rlim_cur);
21557718be8SEnji Cooper
21657718be8SEnji Cooper if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
21757718be8SEnji Cooper _exit(EXIT_FAILURE);
21857718be8SEnji Cooper
21957718be8SEnji Cooper errno = 0;
22057718be8SEnji Cooper
22155fd0faaSEnji Cooper #ifdef __FreeBSD__
22255fd0faaSEnji Cooper /*
22355fd0faaSEnji Cooper * NetBSD doesn't conform to POSIX with ENOMEM requirement;
22455fd0faaSEnji Cooper * FreeBSD does.
22555fd0faaSEnji Cooper *
22655fd0faaSEnji Cooper * See: NetBSD PR # kern/48962 for more details.
22755fd0faaSEnji Cooper */
22855fd0faaSEnji Cooper if (mlock(buf, i) != -1 || errno != ENOMEM) {
22955fd0faaSEnji Cooper #else
23057718be8SEnji Cooper if (mlock(buf, i) != -1 || errno != EAGAIN) {
23155fd0faaSEnji Cooper #endif
23257718be8SEnji Cooper (void)munlock(buf, i);
23357718be8SEnji Cooper _exit(EXIT_FAILURE);
23457718be8SEnji Cooper }
23557718be8SEnji Cooper }
23657718be8SEnji Cooper
23757718be8SEnji Cooper _exit(EXIT_SUCCESS);
23857718be8SEnji Cooper }
23957718be8SEnji Cooper
24057718be8SEnji Cooper (void)wait(&sta);
24157718be8SEnji Cooper
24257718be8SEnji Cooper if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
24357718be8SEnji Cooper atf_tc_fail("mlock(2) locked beyond system limits");
24457718be8SEnji Cooper
24557718be8SEnji Cooper free(buf);
24657718be8SEnji Cooper }
24757718be8SEnji Cooper
2488e62f841SEnji Cooper #ifdef __FreeBSD__
2498e62f841SEnji Cooper ATF_TC_WITH_CLEANUP(mlock_mmap);
2508e62f841SEnji Cooper #else
25157718be8SEnji Cooper ATF_TC(mlock_mmap);
2528e62f841SEnji Cooper #endif
25357718be8SEnji Cooper ATF_TC_HEAD(mlock_mmap, tc)
25457718be8SEnji Cooper {
25557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test mlock(2)-mmap(2) interaction");
2568e62f841SEnji Cooper #ifdef __FreeBSD__
2578e62f841SEnji Cooper atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
2588e62f841SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root");
2598e62f841SEnji Cooper #endif
26057718be8SEnji Cooper }
26157718be8SEnji Cooper
26257718be8SEnji Cooper ATF_TC_BODY(mlock_mmap, tc)
26357718be8SEnji Cooper {
26455fd0faaSEnji Cooper #ifdef __NetBSD__
26557718be8SEnji Cooper static const int flags = MAP_ANON | MAP_PRIVATE | MAP_WIRED;
26655fd0faaSEnji Cooper #else
26755fd0faaSEnji Cooper static const int flags = MAP_ANON | MAP_PRIVATE;
26855fd0faaSEnji Cooper #endif
26957718be8SEnji Cooper void *buf;
27057718be8SEnji Cooper
2718e62f841SEnji Cooper #ifdef __FreeBSD__
2728e62f841SEnji Cooper /* Set max_wired really really high to avoid EAGAIN */
2738e62f841SEnji Cooper set_vm_max_wired(INT_MAX);
2748e62f841SEnji Cooper #endif
2758e62f841SEnji Cooper
27657718be8SEnji Cooper /*
27757718be8SEnji Cooper * Make a wired RW mapping and check that mlock(2)
27857718be8SEnji Cooper * does not fail for the (already locked) mapping.
27957718be8SEnji Cooper */
28057718be8SEnji Cooper buf = mmap(NULL, page, PROT_READ | PROT_WRITE, flags, -1, 0);
28157718be8SEnji Cooper
28257718be8SEnji Cooper ATF_REQUIRE(buf != MAP_FAILED);
28355fd0faaSEnji Cooper #ifdef __FreeBSD__
28455fd0faaSEnji Cooper /*
28555fd0faaSEnji Cooper * The duplicate mlock call is added to ensure that the call works
28655fd0faaSEnji Cooper * as described above without MAP_WIRED support.
28755fd0faaSEnji Cooper */
28855fd0faaSEnji Cooper ATF_REQUIRE(mlock(buf, page) == 0);
28955fd0faaSEnji Cooper #endif
29057718be8SEnji Cooper ATF_REQUIRE(mlock(buf, page) == 0);
29157718be8SEnji Cooper ATF_REQUIRE(munlock(buf, page) == 0);
29257718be8SEnji Cooper ATF_REQUIRE(munmap(buf, page) == 0);
29357718be8SEnji Cooper ATF_REQUIRE(munlock(buf, page) != 0);
29457718be8SEnji Cooper
29557718be8SEnji Cooper /*
29657718be8SEnji Cooper * But it should be impossible to mlock(2) a PROT_NONE mapping.
29757718be8SEnji Cooper */
29857718be8SEnji Cooper buf = mmap(NULL, page, PROT_NONE, flags, -1, 0);
29957718be8SEnji Cooper
30057718be8SEnji Cooper ATF_REQUIRE(buf != MAP_FAILED);
30155fd0faaSEnji Cooper #ifdef __FreeBSD__
30255fd0faaSEnji Cooper ATF_REQUIRE_ERRNO(ENOMEM, mlock(buf, page) != 0);
30355fd0faaSEnji Cooper #else
30457718be8SEnji Cooper ATF_REQUIRE(mlock(buf, page) != 0);
30555fd0faaSEnji Cooper #endif
30657718be8SEnji Cooper ATF_REQUIRE(munmap(buf, page) == 0);
30757718be8SEnji Cooper }
30857718be8SEnji Cooper
3098e62f841SEnji Cooper #ifdef __FreeBSD__
3108e62f841SEnji Cooper ATF_TC_CLEANUP(mlock_mmap, tc)
3118e62f841SEnji Cooper {
3128e62f841SEnji Cooper
3138e62f841SEnji Cooper restore_vm_max_wired();
3148e62f841SEnji Cooper }
3158e62f841SEnji Cooper #endif
3168e62f841SEnji Cooper
3178e62f841SEnji Cooper #ifdef __FreeBSD__
3188e62f841SEnji Cooper ATF_TC_WITH_CLEANUP(mlock_nested);
3198e62f841SEnji Cooper #else
32057718be8SEnji Cooper ATF_TC(mlock_nested);
3218e62f841SEnji Cooper #endif
32257718be8SEnji Cooper ATF_TC_HEAD(mlock_nested, tc)
32357718be8SEnji Cooper {
32457718be8SEnji Cooper atf_tc_set_md_var(tc, "descr",
32557718be8SEnji Cooper "Test that consecutive mlock(2) calls succeed");
3268e62f841SEnji Cooper #ifdef __FreeBSD__
3278e62f841SEnji Cooper atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
3288e62f841SEnji Cooper atf_tc_set_md_var(tc, "require.user", "root");
3298e62f841SEnji Cooper #endif
33057718be8SEnji Cooper }
33157718be8SEnji Cooper
33257718be8SEnji Cooper ATF_TC_BODY(mlock_nested, tc)
33357718be8SEnji Cooper {
33457718be8SEnji Cooper const size_t maxiter = 100;
33557718be8SEnji Cooper void *buf;
33657718be8SEnji Cooper
3378e62f841SEnji Cooper #ifdef __FreeBSD__
3388e62f841SEnji Cooper /* Set max_wired really really high to avoid EAGAIN */
3398e62f841SEnji Cooper set_vm_max_wired(INT_MAX);
3408e62f841SEnji Cooper #endif
3418e62f841SEnji Cooper
34257718be8SEnji Cooper buf = malloc(page);
34357718be8SEnji Cooper ATF_REQUIRE(buf != NULL);
34457718be8SEnji Cooper
34557718be8SEnji Cooper for (size_t i = 0; i < maxiter; i++)
34657718be8SEnji Cooper ATF_REQUIRE(mlock(buf, page) == 0);
34757718be8SEnji Cooper
34857718be8SEnji Cooper ATF_REQUIRE(munlock(buf, page) == 0);
34957718be8SEnji Cooper free(buf);
35057718be8SEnji Cooper }
35157718be8SEnji Cooper
3528e62f841SEnji Cooper #ifdef __FreeBSD__
3538e62f841SEnji Cooper ATF_TC_CLEANUP(mlock_nested, tc)
3548e62f841SEnji Cooper {
3558e62f841SEnji Cooper
3568e62f841SEnji Cooper restore_vm_max_wired();
3578e62f841SEnji Cooper }
3588e62f841SEnji Cooper #endif
3598e62f841SEnji Cooper
36076f9d275SAlan Somers #ifdef __FreeBSD__
36176f9d275SAlan Somers ATF_TC_WITH_CLEANUP(mlock_unaligned);
36276f9d275SAlan Somers #else
36376f9d275SAlan Somers ATF_TC(mlock_unaligned);
36476f9d275SAlan Somers #endif
36576f9d275SAlan Somers ATF_TC_HEAD(mlock_unaligned, tc)
36676f9d275SAlan Somers {
36776f9d275SAlan Somers atf_tc_set_md_var(tc, "descr",
36876f9d275SAlan Somers "Test that mlock(2) can lock page-unaligned memory");
36976f9d275SAlan Somers #ifdef __FreeBSD__
37076f9d275SAlan Somers atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
37176f9d275SAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
37276f9d275SAlan Somers #endif
37376f9d275SAlan Somers }
37476f9d275SAlan Somers
37576f9d275SAlan Somers ATF_TC_BODY(mlock_unaligned, tc)
37676f9d275SAlan Somers {
37776f9d275SAlan Somers void *buf, *addr;
37876f9d275SAlan Somers
37976f9d275SAlan Somers #ifdef __FreeBSD__
38076f9d275SAlan Somers /* Set max_wired really really high to avoid EAGAIN */
38176f9d275SAlan Somers set_vm_max_wired(INT_MAX);
38276f9d275SAlan Somers #endif
38376f9d275SAlan Somers
38476f9d275SAlan Somers buf = malloc(page);
38576f9d275SAlan Somers ATF_REQUIRE(buf != NULL);
38676f9d275SAlan Somers
38776f9d275SAlan Somers if ((uintptr_t)buf & ((uintptr_t)page - 1))
38876f9d275SAlan Somers addr = buf;
38976f9d275SAlan Somers else
39076f9d275SAlan Somers addr = (void *)(((uintptr_t)buf) + page/3);
39176f9d275SAlan Somers
39276f9d275SAlan Somers ATF_REQUIRE_EQ(mlock(addr, page/5), 0);
39376f9d275SAlan Somers ATF_REQUIRE_EQ(munlock(addr, page/5), 0);
39476f9d275SAlan Somers
39576f9d275SAlan Somers (void)free(buf);
39676f9d275SAlan Somers }
39776f9d275SAlan Somers
39876f9d275SAlan Somers #ifdef __FreeBSD__
39976f9d275SAlan Somers ATF_TC_CLEANUP(mlock_unaligned, tc)
40076f9d275SAlan Somers {
40176f9d275SAlan Somers
40276f9d275SAlan Somers restore_vm_max_wired();
40376f9d275SAlan Somers }
40476f9d275SAlan Somers #endif
40576f9d275SAlan Somers
40676f9d275SAlan Somers ATF_TC(munlock_unlocked);
40776f9d275SAlan Somers ATF_TC_HEAD(munlock_unlocked, tc)
40876f9d275SAlan Somers {
40976f9d275SAlan Somers atf_tc_set_md_var(tc, "descr",
41076f9d275SAlan Somers #ifdef __FreeBSD__
41176f9d275SAlan Somers "munlock(2) accepts unlocked memory");
41276f9d275SAlan Somers #else
41376f9d275SAlan Somers "munlock(2) of unlocked memory is an error");
41476f9d275SAlan Somers #endif
41576f9d275SAlan Somers atf_tc_set_md_var(tc, "require.user", "root");
41676f9d275SAlan Somers }
41776f9d275SAlan Somers
41876f9d275SAlan Somers ATF_TC_BODY(munlock_unlocked, tc)
41976f9d275SAlan Somers {
42076f9d275SAlan Somers void *buf;
42176f9d275SAlan Somers
42276f9d275SAlan Somers buf = malloc(page);
42376f9d275SAlan Somers ATF_REQUIRE(buf != NULL);
42476f9d275SAlan Somers
42576f9d275SAlan Somers #ifdef __FreeBSD__
42676f9d275SAlan Somers ATF_REQUIRE_EQ(munlock(buf, page), 0);
42776f9d275SAlan Somers #else
42876f9d275SAlan Somers errno = 0;
42976f9d275SAlan Somers ATF_REQUIRE_ERRNO(ENOMEM, munlock(buf, page) == -1);
43076f9d275SAlan Somers #endif
43176f9d275SAlan Somers (void)free(buf);
43276f9d275SAlan Somers }
43376f9d275SAlan Somers
43457718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
43557718be8SEnji Cooper {
43657718be8SEnji Cooper
43757718be8SEnji Cooper page = sysconf(_SC_PAGESIZE);
43857718be8SEnji Cooper ATF_REQUIRE(page >= 0);
43957718be8SEnji Cooper
44057718be8SEnji Cooper ATF_TP_ADD_TC(tp, mlock_clip);
44157718be8SEnji Cooper ATF_TP_ADD_TC(tp, mlock_err);
44257718be8SEnji Cooper ATF_TP_ADD_TC(tp, mlock_limits);
44357718be8SEnji Cooper ATF_TP_ADD_TC(tp, mlock_mmap);
44457718be8SEnji Cooper ATF_TP_ADD_TC(tp, mlock_nested);
44576f9d275SAlan Somers ATF_TP_ADD_TC(tp, mlock_unaligned);
44676f9d275SAlan Somers ATF_TP_ADD_TC(tp, munlock_unlocked);
44757718be8SEnji Cooper
44857718be8SEnji Cooper return atf_no_error();
44957718be8SEnji Cooper }
450