t_minherit.c revision 272345
1259698Sdim/* $NetBSD: t_minherit.c,v 1.1 2014/07/18 12:34:52 christos Exp $ */
2259698Sdim
3259698Sdim/*-
4259698Sdim * Copyright (c) 2014 The NetBSD Foundation, Inc.
5259698Sdim * All rights reserved.
6259698Sdim *
7259698Sdim * This code is derived from software contributed to The NetBSD Foundation
8259698Sdim * by Christos Zoulas
9259698Sdim *
10259698Sdim * Redistribution and use in source and binary forms, with or without
11259698Sdim * modification, are permitted provided that the following conditions
12259698Sdim * are met:
13259698Sdim * 1. Redistributions of source code must retain the above copyright
14259698Sdim *    notice, this list of conditions and the following disclaimer.
15259698Sdim * 2. Redistributions in binary form must reproduce the above copyright
16259698Sdim *    notice, this list of conditions and the following disclaimer in the
17259698Sdim *    documentation and/or other materials provided with the distribution.
18259698Sdim *
19259698Sdim * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20259698Sdim * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21259698Sdim * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22259698Sdim * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23259698Sdim * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24259698Sdim * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25259698Sdim * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26259698Sdim * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27259698Sdim * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28259698Sdim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29259698Sdim * POSSIBILITY OF SUCH DAMAGE.
30259698Sdim */
31259698Sdim#include <sys/cdefs.h>
32259698Sdim__RCSID("$NetBSD: t_minherit.c,v 1.1 2014/07/18 12:34:52 christos Exp $");
33259698Sdim
34259698Sdim#include <sys/param.h>
35259698Sdim#include <sys/mman.h>
36259698Sdim#include <sys/sysctl.h>
37259698Sdim#include <sys/wait.h>
38259698Sdim
39259698Sdim#include <errno.h>
40259698Sdim#include <fcntl.h>
41259698Sdim#include <stdlib.h>
42259698Sdim#include <string.h>
43259698Sdim#include <unistd.h>
44259698Sdim
45259698Sdim#include <atf-c.h>
46259698Sdim
47259698Sdimstatic long page;
48259698Sdim
49259698Sdimstatic void *
50259698Sdimmakemap(int v, int f) {
51259698Sdim	void *map = mmap(NULL, page, PROT_READ|PROT_WRITE,
52259698Sdim	    MAP_SHARED|MAP_ANON, -1, 0);
53259698Sdim	ATF_REQUIRE(map != MAP_FAILED);
54259698Sdim	memset(map, v, page);
55259698Sdim	if (f != 666)
56259698Sdim		ATF_REQUIRE(minherit(map, page, f) == 0);
57259698Sdim	else
58259698Sdim		ATF_REQUIRE(minherit(map, page, f) == -1);
59259698Sdim	return map;
60259698Sdim}
61259698Sdim
62259698SdimATF_TC(minherit_copy);
63259698SdimATF_TC_HEAD(minherit_copy, tc)
64259698Sdim{
65259698Sdim	atf_tc_set_md_var(tc, "descr",
66259698Sdim	    "Test for MAP_INHERIT_COPY from minherit(2)");
67259698Sdim}
68259698Sdim
69259698SdimATF_TC_BODY(minherit_copy, tc)
70259698Sdim{
71259698Sdim	void *map1 = makemap(1, MAP_INHERIT_COPY);
72259698Sdim	void *map2 = makemap(1, MAP_INHERIT_COPY);
73259698Sdim	switch (fork()) {
74259698Sdim	default:
75259698Sdim		ATF_REQUIRE(wait(NULL) != -1);
76259698Sdim		ATF_REQUIRE(memcmp(map1, map2, page) == 0);
77259698Sdim		break;
78259698Sdim	case -1:
79259698Sdim		ATF_REQUIRE(0);
80259698Sdim		break;
81259698Sdim	case 0:
82259698Sdim		ATF_REQUIRE(memcmp(map1, map2, page) == 0);
83259698Sdim		memset(map1, 0, page);
84259698Sdim		exit(0);
85259698Sdim	}
86259698Sdim}
87259698Sdim
88259698SdimATF_TC(minherit_share);
89259698SdimATF_TC_HEAD(minherit_share, tc)
90259698Sdim{
91259698Sdim	atf_tc_set_md_var(tc, "descr",
92259698Sdim	    "Test for MAP_INHERIT_SHARE from minherit(2)");
93259698Sdim}
94259698Sdim
95259698SdimATF_TC_BODY(minherit_share, tc)
96259698Sdim{
97259698Sdim	void *map1 = makemap(1, MAP_INHERIT_SHARE);
98259698Sdim	void *map2 = makemap(1, MAP_INHERIT_SHARE);
99259698Sdim
100259698Sdim	switch (fork()) {
101259698Sdim	default:
102259698Sdim		ATF_REQUIRE(wait(NULL) != -1);
103259698Sdim		memset(map2, 0, page);
104259698Sdim		ATF_REQUIRE(memcmp(map1, map2, page) == 0);
105259698Sdim		break;
106259698Sdim	case -1:
107259698Sdim		ATF_REQUIRE(0);
108259698Sdim		break;
109259698Sdim	case 0:
110259698Sdim		ATF_REQUIRE(memcmp(map1, map2, page) == 0);
111259698Sdim		memset(map1, 0, page);
112259698Sdim		exit(0);
113259698Sdim	}
114259698Sdim}
115259698Sdim
116259698Sdimstatic void
117259698Sdimsegv(int n) {
118259698Sdim	_exit(n);
119259698Sdim}
120259698Sdim
121259698SdimATF_TC(minherit_none);
122259698SdimATF_TC_HEAD(minherit_none, tc)
123259698Sdim{
124259698Sdim	atf_tc_set_md_var(tc, "descr",
125259698Sdim	    "Test for MAP_INHERIT_NONE from minherit(2)");
126259698Sdim}
127259698Sdim
128259698SdimATF_TC_BODY(minherit_none, tc)
129259698Sdim{
130259698Sdim	void *map1 = makemap(0, MAP_INHERIT_NONE);
131259698Sdim	int status;
132259698Sdim
133259698Sdim	switch (fork()) {
134259698Sdim	default:
135259698Sdim		ATF_REQUIRE(wait(&status) != -1);
136259698Sdim		ATF_REQUIRE(WEXITSTATUS(status) == SIGSEGV);
137259698Sdim		break;
138259698Sdim	case -1:
139259698Sdim		ATF_REQUIRE(0);
140259698Sdim		break;
141259698Sdim	case 0:
142259698Sdim		ATF_REQUIRE(signal(SIGSEGV, segv) != SIG_ERR);
143259698Sdim		memset(map1, 0, page);
144259698Sdim		exit(0);
145259698Sdim	}
146259698Sdim}
147259698Sdim
148259698SdimATF_TC(minherit_zero);
149259698SdimATF_TC_HEAD(minherit_zero, tc)
150259698Sdim{
151259698Sdim	atf_tc_set_md_var(tc, "descr",
152259698Sdim	    "Test for MAP_INHERIT_ZERO from minherit(2)");
153259698Sdim}
154259698Sdim
155259698SdimATF_TC_BODY(minherit_zero, tc)
156259698Sdim{
157259698Sdim	void *map1 = makemap(1, MAP_INHERIT_ZERO);
158259698Sdim	void *map2 = makemap(0, MAP_INHERIT_SHARE);
159259698Sdim
160259698Sdim	switch (fork()) {
161259698Sdim	default:
162259698Sdim		ATF_REQUIRE(wait(NULL) != -1);
163259698Sdim		memset(map2, 1, page);
164259698Sdim		ATF_REQUIRE(memcmp(map1, map2, page) == 0);
165259698Sdim		break;
166259698Sdim	case -1:
167259698Sdim		ATF_REQUIRE(0);
168259698Sdim		break;
169259698Sdim	case 0:
170259698Sdim		ATF_REQUIRE(memcmp(map1, map2, page) == 0);
171259698Sdim		memset(map1, 2, page);
172259698Sdim		exit(0);
173259698Sdim	}
174259698Sdim}
175
176ATF_TC(minherit_bad);
177ATF_TC_HEAD(minherit_bad, tc)
178{
179	atf_tc_set_md_var(tc, "descr",
180	    "Test for bad minherit(2)");
181}
182
183ATF_TC_BODY(minherit_bad, tc)
184{
185	(void)makemap(0, 666);
186}
187
188ATF_TP_ADD_TCS(tp)
189{
190	page = sysconf(_SC_PAGESIZE);
191	ATF_REQUIRE(page >= 0);
192
193	ATF_TP_ADD_TC(tp, minherit_copy);
194	ATF_TP_ADD_TC(tp, minherit_share);
195	ATF_TP_ADD_TC(tp, minherit_none);
196	ATF_TP_ADD_TC(tp, minherit_zero);
197	ATF_TP_ADD_TC(tp, minherit_bad);
198
199	return atf_no_error();
200}
201