summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_mlock.c
diff options
context:
space:
mode:
authorbluhm <>2019-11-19 19:57:04 +0000
committerbluhm <>2019-11-19 19:57:04 +0000
commit9185f840eda265016178aeb0dcdba964f8f6f3e2 (patch)
treeda100b3712514c566fe948116f7926ad7f725401 /src/regress/lib/libc/sys/t_mlock.c
parent6a6fe688152b422f3d65c970dad56e7d9d28b1ee (diff)
downloadopenbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.gz
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.bz2
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.zip
Import NetBSD system call regression tests. They were written with
ATF (Automated Testing Framework), so we use a small wrapper to map it to our bsd.regress.mk framework. Only half of the 80 NetBSD tests have been taken, the others need more work to adapt. Of them 34 syscall tests pass. Moritz Buhl ported the tests to OpenBSD.
Diffstat (limited to 'src/regress/lib/libc/sys/t_mlock.c')
-rw-r--r--src/regress/lib/libc/sys/t_mlock.c325
1 files changed, 325 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_mlock.c b/src/regress/lib/libc/sys/t_mlock.c
new file mode 100644
index 0000000000..1fd986383d
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_mlock.c
@@ -0,0 +1,325 @@
1/* $OpenBSD: t_mlock.c,v 1.1.1.1 2019/11/19 19:57:04 bluhm Exp $ */
2/* $NetBSD: t_mlock.c,v 1.7 2019/03/13 08:50:12 kre Exp $ */
3
4/*-
5 * Copyright (c) 2012 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/cdefs.h>
36__RCSID("$NetBSD: t_mlock.c,v 1.7 2019/03/13 08:50:12 kre Exp $");
37
38#include <sys/mman.h>
39#include <sys/resource.h>
40#include <sys/sysctl.h>
41#include <sys/wait.h>
42
43#include <errno.h>
44#include "atf-c.h"
45#include <stdint.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50
51static long page = 0;
52
53ATF_TC(mlock_clip);
54ATF_TC_HEAD(mlock_clip, tc)
55{
56 atf_tc_set_md_var(tc, "descr", "Test with mlock(2) that UVM only "
57 "clips if the clip address is within the entry (PR kern/44788)");
58}
59
60ATF_TC_BODY(mlock_clip, tc)
61{
62 void *buf;
63 int err1, err2;
64
65 buf = malloc(page);
66 ATF_REQUIRE(buf != NULL);
67 fprintf(stderr, "mlock_clip: buf = %p (page=%ld)\n", buf, page);
68
69 if (page < 1024)
70 atf_tc_skip("page size too small");
71
72 for (size_t i = page; i >= 1; i = i - 1024) {
73 err1 = mlock(buf, page - i);
74 if (err1 != 0)
75 fprintf(stderr, "mlock_clip: page=%ld i=%zu,"
76 " mlock(%p, %ld): %s\n", page, i, buf, page - i,
77 strerror(errno));
78 err2 = munlock(buf, page - i);
79 if (err2 != 0)
80 fprintf(stderr, "mlock_clip: page=%ld i=%zu,"
81 " munlock(%p, %ld): %s (mlock %s)\n", page, i,
82 buf, page - i, strerror(errno), err1?"failed":"ok");
83 }
84
85 free(buf);
86}
87
88ATF_TC(mlock_err);
89ATF_TC_HEAD(mlock_err, tc)
90{
91 atf_tc_set_md_var(tc, "descr",
92 "Test error conditions in mlock(2) and munlock(2)");
93}
94
95ATF_TC_BODY(mlock_err, tc)
96{
97 void *invalid_ptr;
98 void *buf;
99 int mlock_err, munlock_err;
100
101 /*
102 * Any bad address must return ENOMEM (for lock & unlock)
103 */
104 errno = 0;
105 ATF_REQUIRE_ERRNO(ENOMEM, mlock(NULL, page) == -1);
106
107 errno = 0;
108 ATF_REQUIRE_ERRNO(ENOMEM, mlock((char *)0, page) == -1);
109
110 errno = 0;
111 /* Adjusted for OpenBSD, initially ENOMEM */
112 ATF_REQUIRE_ERRNO(EINVAL, mlock((char *)-1, page) == -1);
113
114 errno = 0;
115 ATF_REQUIRE_ERRNO(ENOMEM, munlock(NULL, page) == -1);
116
117 errno = 0;
118 ATF_REQUIRE_ERRNO(ENOMEM, munlock((char *)0, page) == -1);
119
120 errno = 0;
121 /* Adjusted for OpenBSD, initially ENOMEM */
122 ATF_REQUIRE_ERRNO(EINVAL, munlock((char *)-1, page) == -1);
123
124 buf = malloc(page);
125 ATF_REQUIRE(buf != NULL);
126 fprintf(stderr, "mlock_err: buf = %p (page=%ld)\n", buf, page);
127
128 /*
129 * unlocking memory that is not locked is an error...
130 */
131
132 /*
133 * Adjusted for OpenBSD
134 * errno = 0;
135 * ATF_REQUIRE_ERRNO(ENOMEM, munlock(buf, page) == -1);
136 */
137
138 /*
139 * These are permitted to fail (EINVAL) but do not on NetBSD
140 */
141 mlock_err = mlock((void *)(((uintptr_t)buf) + page/3), page/5);
142 if (mlock_err != 0)
143 fprintf(stderr, "mlock_err: mlock(%p, %ld): %d [%d] %s\n",
144 (void *)(((uintptr_t)buf) + page/3), page/5, mlock_err,
145 errno, strerror(errno));
146 ATF_REQUIRE(mlock_err == 0);
147 munlock_err= munlock((void *)(((uintptr_t)buf) + page/3), page/5);
148 if (munlock_err != 0)
149 fprintf(stderr, "mlock_err: munlock(%p, %ld): %d [%d] %s\n",
150 (void *)(((uintptr_t)buf) + page/3), page/5, munlock_err,
151 errno, strerror(errno));
152 ATF_REQUIRE(munlock_err == 0);
153
154 (void)free(buf);
155
156 /*
157 * Try to create a pointer to an unmapped page - first after current
158 * brk will likely do.
159 */
160 invalid_ptr = (void*)(((uintptr_t)sbrk(0)+page) & ~(page-1));
161 printf("testing with (hopefully) invalid pointer %p\n", invalid_ptr);
162
163 errno = 0;
164 ATF_REQUIRE_ERRNO(ENOMEM, mlock(invalid_ptr, page) == -1);
165
166 errno = 0;
167 ATF_REQUIRE_ERRNO(ENOMEM, munlock(invalid_ptr, page) == -1);
168}
169
170ATF_TC(mlock_limits);
171ATF_TC_HEAD(mlock_limits, tc)
172{
173 atf_tc_set_md_var(tc, "descr", "Test system limits with mlock(2)");
174}
175
176ATF_TC_BODY(mlock_limits, tc)
177{
178 struct rlimit res;
179 void *buf;
180 pid_t pid;
181 int sta;
182
183 buf = malloc(page);
184 ATF_REQUIRE(buf != NULL);
185 fprintf(stderr, "mlock_limits: buf = %p (page=%ld)\n", buf, page);
186
187 pid = fork();
188 ATF_REQUIRE(pid >= 0);
189
190 if (pid == 0) {
191
192 for (ssize_t i = page; i >= 2; i -= 100) {
193
194 res.rlim_cur = i - 1;
195 res.rlim_max = i - 1;
196
197 (void)fprintf(stderr, "trying to lock %zu bytes "
198 "with %zu byte limit\n", i, (size_t)res.rlim_cur);
199
200 if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
201 _exit(EXIT_FAILURE);
202
203 errno = 0;
204
205 if ((sta = mlock(buf, i)) != -1 || errno != EAGAIN) {
206 fprintf(stderr, "mlock(%p, %zu): %d [%d] %s\n",
207 buf, i, sta, errno, strerror(errno));
208 (void)munlock(buf, i);
209 _exit(EXIT_FAILURE);
210 }
211 }
212
213 _exit(EXIT_SUCCESS);
214 }
215
216 (void)wait(&sta);
217
218 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
219 atf_tc_fail("mlock(2) locked beyond system limits");
220
221 free(buf);
222}
223
224ATF_TC(mlock_mmap);
225ATF_TC_HEAD(mlock_mmap, tc)
226{
227 atf_tc_set_md_var(tc, "descr", "Test mlock(2)-mmap(2) interaction");
228}
229
230ATF_TC_BODY(mlock_mmap, tc)
231{
232 /* Adjusted for OpenBSD, initially ... | MAP_WIRED */
233 static const int flags = MAP_ANON | MAP_PRIVATE;
234 void *buf;
235
236 /*
237 * Make a wired RW mapping and check that mlock(2)
238 * does not fail for the (already locked) mapping.
239 */
240 buf = mmap(NULL, page, PROT_READ | PROT_WRITE, flags, -1, 0);
241
242 if (buf == MAP_FAILED)
243 fprintf(stderr,
244 "mlock_mmap: mmap(NULL, %ld, %#x, %#x, -1, 0): MAP_FAILED"
245 " [%d] %s\n", page, PROT_READ | PROT_WRITE, flags, errno,
246 strerror(errno));
247
248 ATF_REQUIRE(buf != MAP_FAILED);
249
250 fprintf(stderr, "mlock_mmap: buf=%p, page=%ld\n", buf, page);
251
252 ATF_REQUIRE(mlock(buf, page) == 0);
253 ATF_REQUIRE(munlock(buf, page) == 0);
254 ATF_REQUIRE(munmap(buf, page) == 0);
255 ATF_REQUIRE(munlock(buf, page) != 0);
256
257 fprintf(stderr, "mlock_mmap: first test succeeded\n");
258
259 /*
260 * But it should be impossible to mlock(2) a PROT_NONE mapping.
261 */
262 buf = mmap(NULL, page, PROT_NONE, flags, -1, 0);
263
264 if (buf == MAP_FAILED)
265 fprintf(stderr,
266 "mlock_mmap: mmap(NULL, %ld, %#x, %#x, -1, 0): MAP_FAILED"
267 " [%d] %s\n", page, PROT_NONE, flags, errno,
268 strerror(errno));
269
270 ATF_REQUIRE(buf != MAP_FAILED);
271 ATF_REQUIRE(mlock(buf, page) != 0);
272 ATF_REQUIRE(munmap(buf, page) == 0);
273
274 fprintf(stderr, "mlock_mmap: second test succeeded\n");
275}
276
277ATF_TC(mlock_nested);
278ATF_TC_HEAD(mlock_nested, tc)
279{
280 atf_tc_set_md_var(tc, "descr",
281 "Test that consecutive mlock(2) calls succeed");
282}
283
284ATF_TC_BODY(mlock_nested, tc)
285{
286 const size_t maxiter = 100;
287 void *buf;
288 int err;
289
290 buf = malloc(page);
291 ATF_REQUIRE(buf != NULL);
292 fprintf(stderr, "mlock_nested: buf = %p (page=%ld)\n", buf, page);
293
294 for (size_t i = 0; i < maxiter; i++) {
295 err = mlock(buf, page);
296 if (err != 0)
297 fprintf(stderr,
298 "mlock_nested: i=%zu (of %zu) mlock(%p, %ld): %d [%d] %s\n",
299 i, maxiter, buf, page, err, errno, strerror(errno));
300 ATF_REQUIRE(err == 0);
301 }
302
303 err = munlock(buf, page);
304 if (err != 0)
305 fprintf(stderr, "mlock_nested: munlock(%p, %ld): %d [%d] %s\n",
306 buf, page, err, errno, strerror(errno));
307 ATF_REQUIRE(err == 0);
308 free(buf);
309}
310
311ATF_TP_ADD_TCS(tp)
312{
313
314 page = sysconf(_SC_PAGESIZE);
315 fprintf(stderr, "t_mlock: pagesize %ld\n", page);
316 ATF_REQUIRE(page >= 0);
317
318 ATF_TP_ADD_TC(tp, mlock_clip);
319 ATF_TP_ADD_TC(tp, mlock_err);
320 ATF_TP_ADD_TC(tp, mlock_limits);
321 ATF_TP_ADD_TC(tp, mlock_mmap);
322 ATF_TP_ADD_TC(tp, mlock_nested);
323
324 return atf_no_error();
325}