Home | History | Annotate | Line # | Download | only in rumpkern
      1 /*	$NetBSD: t_lwproc.c,v 1.10 2020/01/08 17:38:43 ad Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2010 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
     17  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
     25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include <sys/types.h>
     31 #include <sys/wait.h>
     32 #include <sys/stat.h>
     33 
     34 #include <rump/rump.h>
     35 #include <rump/rump_syscalls.h>
     36 
     37 #include <atf-c.h>
     38 #include <err.h>
     39 #include <errno.h>
     40 #include <fcntl.h>
     41 #include <stdio.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 #include <unistd.h>
     45 #include <util.h>
     46 
     47 #include "h_macros.h"
     48 
     49 ATF_TC(makelwp);
     50 ATF_TC_HEAD(makelwp, tc)
     51 {
     52 
     53 	atf_tc_set_md_var(tc, "descr", "tests that lwps can be attached to "
     54 	    "processes");
     55 }
     56 
     57 ATF_TC_BODY(makelwp, tc)
     58 {
     59 	struct lwp *l;
     60 	pid_t pid;
     61 
     62 	rump_init();
     63 	RZ(rump_pub_lwproc_newlwp(0));
     64 	ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(37), ESRCH);
     65 	l = rump_pub_lwproc_curlwp();
     66 
     67 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
     68 	ATF_REQUIRE(rump_pub_lwproc_curlwp() != l);
     69 	l = rump_pub_lwproc_curlwp();
     70 
     71 	RZ(rump_pub_lwproc_newlwp(rump_sys_getpid()));
     72 	ATF_REQUIRE(rump_pub_lwproc_curlwp() != l);
     73 
     74 	pid = rump_sys_getpid();
     75 	ATF_REQUIRE(pid != -1 && pid != 0);
     76 }
     77 
     78 ATF_TC(proccreds);
     79 ATF_TC_HEAD(proccreds, tc)
     80 {
     81 
     82 	atf_tc_set_md_var(tc, "descr", "check that procs have different creds");
     83 }
     84 
     85 ATF_TC_BODY(proccreds, tc)
     86 {
     87 	struct lwp *l1, *l2;
     88 
     89 	rump_init();
     90 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
     91 	l1 = rump_pub_lwproc_curlwp();
     92 	RZ(rump_pub_lwproc_newlwp(rump_sys_getpid()));
     93 
     94 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
     95 	l2 = rump_pub_lwproc_curlwp();
     96 
     97 	RL(rump_sys_setuid(22));
     98 	ATF_REQUIRE_EQ(rump_sys_getuid(), 22);
     99 
    100 	rump_pub_lwproc_switch(l1);
    101 	ATF_REQUIRE_EQ(rump_sys_getuid(), 0); /* from parent, proc0 */
    102 	RL(rump_sys_setuid(11));
    103 	ATF_REQUIRE_EQ(rump_sys_getuid(), 11);
    104 
    105 	rump_pub_lwproc_switch(l2);
    106 	ATF_REQUIRE_EQ(rump_sys_getuid(), 22);
    107 	rump_pub_lwproc_newlwp(rump_sys_getpid());
    108 	ATF_REQUIRE_EQ(rump_sys_getuid(), 22);
    109 }
    110 
    111 
    112 ATF_TC(inherit);
    113 ATF_TC_HEAD(inherit, tc)
    114 {
    115 
    116 	atf_tc_set_md_var(tc, "descr", "new processes inherit creds from "
    117 	    "parents");
    118 }
    119 
    120 ATF_TC_BODY(inherit, tc)
    121 {
    122 
    123 	rump_init();
    124 
    125 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
    126 	RL(rump_sys_setuid(66));
    127 	ATF_REQUIRE_EQ(rump_sys_getuid(), 66);
    128 
    129 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
    130 	ATF_REQUIRE_EQ(rump_sys_getuid(), 66);
    131 
    132 	/* release lwp and proc */
    133 	rump_pub_lwproc_releaselwp();
    134 	ATF_REQUIRE_EQ(rump_sys_getuid(), 0);
    135 }
    136 
    137 ATF_TC(lwps);
    138 ATF_TC_HEAD(lwps, tc)
    139 {
    140 
    141 	atf_tc_set_md_var(tc, "descr", "proc can hold many lwps and is "
    142 	    "automatically g/c'd when the last one exits");
    143 }
    144 
    145 #define LOOPS 128
    146 ATF_TC_BODY(lwps, tc)
    147 {
    148 	struct lwp *l[LOOPS];
    149 	pid_t mypid;
    150 	struct lwp *l_orig;
    151 	int i;
    152 
    153 	rump_init();
    154 
    155 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
    156 	mypid = rump_sys_getpid();
    157 	RL(rump_sys_setuid(375));
    158 
    159 	l_orig = rump_pub_lwproc_curlwp();
    160 	for (i = 0; i < LOOPS; i++) {
    161 		mypid = rump_sys_getpid();
    162 		ATF_REQUIRE(mypid != -1 && mypid != 0);
    163 		RZ(rump_pub_lwproc_newlwp(mypid));
    164 		l[i] = rump_pub_lwproc_curlwp();
    165 		ATF_REQUIRE_EQ(rump_sys_getuid(), 375);
    166 	}
    167 
    168 	rump_pub_lwproc_switch(l_orig);
    169 	rump_pub_lwproc_releaselwp();
    170 	for (i = 0; i < LOOPS; i++) {
    171 		rump_pub_lwproc_switch(l[i]);
    172 		ATF_REQUIRE_EQ(rump_sys_getpid(), mypid);
    173 		ATF_REQUIRE_EQ(rump_sys_getuid(), 375);
    174 		rump_pub_lwproc_releaselwp();
    175 		ATF_REQUIRE_EQ(rump_sys_getpid(), 1);
    176 		ATF_REQUIRE_EQ(rump_sys_getuid(), 0);
    177 	}
    178 
    179 	ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(mypid), ESRCH);
    180 }
    181 
    182 ATF_TC(nolwprelease);
    183 ATF_TC_HEAD(nolwprelease, tc)
    184 {
    185 
    186 	atf_tc_set_md_var(tc, "descr", "check that lwp context is required "
    187 	    "for lwproc_releaselwp()");
    188 }
    189 
    190 ATF_TC_BODY(nolwprelease, tc)
    191 {
    192 	int status;
    193 
    194 	switch (fork()) {
    195 	case 0:
    196 		rump_init();
    197 		rump_pub_lwproc_releaselwp();
    198 		atf_tc_fail("survived");
    199 		break;
    200 	case -1:
    201 		atf_tc_fail_errno("fork");
    202 		break;
    203 	default:
    204 		wait(&status);
    205 		ATF_REQUIRE(WIFSIGNALED(status));
    206 		ATF_REQUIRE_EQ(WTERMSIG(status), SIGABRT);
    207 
    208 	}
    209 }
    210 
    211 ATF_TC(nolwp);
    212 ATF_TC_HEAD(nolwp, tc)
    213 {
    214 
    215 	atf_tc_set_md_var(tc, "descr", "check that curlwp for an implicit "
    216 	    "context is NULL");
    217 }
    218 
    219 ATF_TC_BODY(nolwp, tc)
    220 {
    221 
    222 	rump_init();
    223 	ATF_REQUIRE_EQ(rump_pub_lwproc_curlwp(), NULL);
    224 }
    225 
    226 ATF_TC(nullswitch);
    227 ATF_TC_HEAD(nullswitch, tc)
    228 {
    229 
    230 	atf_tc_set_md_var(tc, "descr", "check that switching to NULL marks "
    231 	    "current lwp as not running");
    232 }
    233 
    234 ATF_TC_BODY(nullswitch, tc)
    235 {
    236 	struct lwp *l;
    237 
    238 	rump_init();
    239 	RZ(rump_pub_lwproc_newlwp(0));
    240 	l = rump_pub_lwproc_curlwp();
    241 	rump_pub_lwproc_switch(NULL);
    242 	/* if remains LW_RUNNING, next call will panic */
    243 	rump_pub_lwproc_switch(l);
    244 }
    245 
    246 ATF_TC(rfork);
    247 ATF_TC_HEAD(rfork, tc)
    248 {
    249 
    250 	atf_tc_set_md_var(tc, "descr", "check that fork shares fd's");
    251 }
    252 
    253 ATF_TC_BODY(rfork, tc)
    254 {
    255 	struct stat sb;
    256 	struct lwp *l, *l2;
    257 	int fd;
    258 
    259 	RZ(rump_init());
    260 
    261 	ATF_REQUIRE_EQ(rump_pub_lwproc_rfork(RUMP_RFFDG|RUMP_RFCFDG), EINVAL);
    262 
    263 	RZ(rump_pub_lwproc_rfork(0));
    264 	l = rump_pub_lwproc_curlwp();
    265 
    266 	RL(fd = rump_sys_open("/file", O_RDWR | O_CREAT, 0777));
    267 
    268 	/* ok, first check rfork(RUMP_RFCFDG) does *not* preserve fd's */
    269 	RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
    270 	ATF_REQUIRE_ERRNO(EBADF, rump_sys_write(fd, &fd, sizeof(fd)) == -1);
    271 
    272 	/* then check that rfork(0) does */
    273 	rump_pub_lwproc_switch(l);
    274 	RZ(rump_pub_lwproc_rfork(0));
    275 	ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd));
    276 	RL(rump_sys_fstat(fd, &sb));
    277 	l2 = rump_pub_lwproc_curlwp();
    278 
    279 	/*
    280 	 * check that the shared fd table is really shared by
    281 	 * closing fd in parent
    282 	 */
    283 	rump_pub_lwproc_switch(l);
    284 	RL(rump_sys_close(fd));
    285 	rump_pub_lwproc_switch(l2);
    286 	ATF_REQUIRE_ERRNO(EBADF, rump_sys_fstat(fd, &sb) == -1);
    287 
    288 	/* redo, this time copying the fd table instead of sharing it */
    289 	rump_pub_lwproc_releaselwp();
    290 	rump_pub_lwproc_switch(l);
    291 	RL(fd = rump_sys_open("/file", O_RDWR, 0777));
    292 	RZ(rump_pub_lwproc_rfork(RUMP_RFFDG));
    293 	ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd));
    294 	RL(rump_sys_fstat(fd, &sb));
    295 	l2 = rump_pub_lwproc_curlwp();
    296 
    297 	/* check that the fd table is copied */
    298 	rump_pub_lwproc_switch(l);
    299 	RL(rump_sys_close(fd));
    300 	rump_pub_lwproc_switch(l2);
    301 	RL(rump_sys_fstat(fd, &sb));
    302 	ATF_REQUIRE_EQ(sb.st_size, sizeof(fd));
    303 }
    304 
    305 ATF_TP_ADD_TCS(tp)
    306 {
    307 
    308 	ATF_TP_ADD_TC(tp, makelwp);
    309 	ATF_TP_ADD_TC(tp, proccreds);
    310 	ATF_TP_ADD_TC(tp, inherit);
    311 	ATF_TP_ADD_TC(tp, lwps);
    312 	ATF_TP_ADD_TC(tp, nolwprelease);
    313 	ATF_TP_ADD_TC(tp, nolwp);
    314 	ATF_TP_ADD_TC(tp, nullswitch);
    315 	ATF_TP_ADD_TC(tp, rfork);
    316 
    317 	return atf_no_error();
    318 }
    319