1272343Sngie/* $NetBSD: t_lwproc.c,v 1.5 2011/01/02 12:58:17 pooka Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2010 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17272343Sngie * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18272343Sngie * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19272343Sngie * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20272343Sngie * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21272343Sngie * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23272343Sngie * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25272343Sngie * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26272343Sngie * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27272343Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28272343Sngie */ 29272343Sngie 30272343Sngie#include <sys/types.h> 31272343Sngie#include <sys/wait.h> 32272343Sngie 33272343Sngie#include <rump/rump.h> 34272343Sngie#include <rump/rump_syscalls.h> 35272343Sngie 36272343Sngie#include <atf-c.h> 37272343Sngie#include <err.h> 38272343Sngie#include <errno.h> 39272343Sngie#include <fcntl.h> 40272343Sngie#include <stdio.h> 41272343Sngie#include <stdlib.h> 42272343Sngie#include <string.h> 43272343Sngie#include <unistd.h> 44272343Sngie#include <util.h> 45272343Sngie 46272343Sngie#include "../../h_macros.h" 47272343Sngie 48272343SngieATF_TC(makelwp); 49272343SngieATF_TC_HEAD(makelwp, tc) 50272343Sngie{ 51272343Sngie 52272343Sngie atf_tc_set_md_var(tc, "descr", "tests that lwps can be attached to " 53272343Sngie "processes"); 54272343Sngie} 55272343Sngie 56272343SngieATF_TC_BODY(makelwp, tc) 57272343Sngie{ 58272343Sngie struct lwp *l; 59272343Sngie pid_t pid; 60272343Sngie 61272343Sngie rump_init(); 62272343Sngie RZ(rump_pub_lwproc_newlwp(0)); 63272343Sngie ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(37), ESRCH); 64272343Sngie l = rump_pub_lwproc_curlwp(); 65272343Sngie 66272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 67272343Sngie ATF_REQUIRE(rump_pub_lwproc_curlwp() != l); 68272343Sngie l = rump_pub_lwproc_curlwp(); 69272343Sngie 70272343Sngie RZ(rump_pub_lwproc_newlwp(rump_sys_getpid())); 71272343Sngie ATF_REQUIRE(rump_pub_lwproc_curlwp() != l); 72272343Sngie 73272343Sngie pid = rump_sys_getpid(); 74272343Sngie ATF_REQUIRE(pid != -1 && pid != 0); 75272343Sngie} 76272343Sngie 77272343SngieATF_TC(proccreds); 78272343SngieATF_TC_HEAD(proccreds, tc) 79272343Sngie{ 80272343Sngie 81272343Sngie atf_tc_set_md_var(tc, "descr", "check that procs have different creds"); 82272343Sngie} 83272343Sngie 84272343SngieATF_TC_BODY(proccreds, tc) 85272343Sngie{ 86272343Sngie struct lwp *l1, *l2; 87272343Sngie 88272343Sngie rump_init(); 89272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 90272343Sngie l1 = rump_pub_lwproc_curlwp(); 91272343Sngie 92272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 93272343Sngie l2 = rump_pub_lwproc_curlwp(); 94272343Sngie 95272343Sngie RL(rump_sys_setuid(22)); 96272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 22); 97272343Sngie 98272343Sngie rump_pub_lwproc_switch(l1); 99272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 0); /* from parent, proc0 */ 100272343Sngie RL(rump_sys_setuid(11)); 101272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 11); 102272343Sngie 103272343Sngie rump_pub_lwproc_switch(l2); 104272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 22); 105272343Sngie rump_pub_lwproc_newlwp(rump_sys_getpid()); 106272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 22); 107272343Sngie} 108272343Sngie 109272343Sngie 110272343SngieATF_TC(inherit); 111272343SngieATF_TC_HEAD(inherit, tc) 112272343Sngie{ 113272343Sngie 114272343Sngie atf_tc_set_md_var(tc, "descr", "new processes inherit creds from " 115272343Sngie "parents"); 116272343Sngie} 117272343Sngie 118272343SngieATF_TC_BODY(inherit, tc) 119272343Sngie{ 120272343Sngie 121272343Sngie rump_init(); 122272343Sngie 123272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 124272343Sngie RL(rump_sys_setuid(66)); 125272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 66); 126272343Sngie 127272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 128272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 66); 129272343Sngie 130272343Sngie /* release lwp and proc */ 131272343Sngie rump_pub_lwproc_releaselwp(); 132272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 0); 133272343Sngie} 134272343Sngie 135272343SngieATF_TC(lwps); 136272343SngieATF_TC_HEAD(lwps, tc) 137272343Sngie{ 138272343Sngie 139272343Sngie atf_tc_set_md_var(tc, "descr", "proc can hold many lwps and is " 140272343Sngie "automatically g/c'd when the last one exits"); 141272343Sngie} 142272343Sngie 143272343Sngie#define LOOPS 128 144272343SngieATF_TC_BODY(lwps, tc) 145272343Sngie{ 146272343Sngie struct lwp *l[LOOPS]; 147272343Sngie pid_t mypid; 148272343Sngie struct lwp *l_orig; 149272343Sngie int i; 150272343Sngie 151272343Sngie rump_init(); 152272343Sngie 153272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 154272343Sngie mypid = rump_sys_getpid(); 155272343Sngie RL(rump_sys_setuid(375)); 156272343Sngie 157272343Sngie l_orig = rump_pub_lwproc_curlwp(); 158272343Sngie for (i = 0; i < LOOPS; i++) { 159272343Sngie mypid = rump_sys_getpid(); 160272343Sngie ATF_REQUIRE(mypid != -1 && mypid != 0); 161272343Sngie RZ(rump_pub_lwproc_newlwp(mypid)); 162272343Sngie l[i] = rump_pub_lwproc_curlwp(); 163272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 375); 164272343Sngie } 165272343Sngie 166272343Sngie rump_pub_lwproc_switch(l_orig); 167272343Sngie rump_pub_lwproc_releaselwp(); 168272343Sngie for (i = 0; i < LOOPS; i++) { 169272343Sngie rump_pub_lwproc_switch(l[i]); 170272343Sngie ATF_REQUIRE_EQ(rump_sys_getpid(), mypid); 171272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 375); 172272343Sngie rump_pub_lwproc_releaselwp(); 173272343Sngie ATF_REQUIRE_EQ(rump_sys_getpid(), 1); 174272343Sngie ATF_REQUIRE_EQ(rump_sys_getuid(), 0); 175272343Sngie } 176272343Sngie 177272343Sngie ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(mypid), ESRCH); 178272343Sngie} 179272343Sngie 180272343SngieATF_TC(nolwprelease); 181272343SngieATF_TC_HEAD(nolwprelease, tc) 182272343Sngie{ 183272343Sngie 184272343Sngie atf_tc_set_md_var(tc, "descr", "check that lwp context is required " 185272343Sngie "for lwproc_releaselwp()"); 186272343Sngie} 187272343Sngie 188272343SngieATF_TC_BODY(nolwprelease, tc) 189272343Sngie{ 190272343Sngie int status; 191272343Sngie 192272343Sngie switch (fork()) { 193272343Sngie case 0: 194272343Sngie rump_init(); 195272343Sngie rump_pub_lwproc_releaselwp(); 196272343Sngie atf_tc_fail("survived"); 197272343Sngie break; 198272343Sngie case -1: 199272343Sngie atf_tc_fail_errno("fork"); 200272343Sngie break; 201272343Sngie default: 202272343Sngie wait(&status); 203272343Sngie ATF_REQUIRE(WIFSIGNALED(status)); 204272343Sngie ATF_REQUIRE_EQ(WTERMSIG(status), SIGABRT); 205272343Sngie 206272343Sngie } 207272343Sngie} 208272343Sngie 209272343SngieATF_TC(nolwp); 210272343SngieATF_TC_HEAD(nolwp, tc) 211272343Sngie{ 212272343Sngie 213272343Sngie atf_tc_set_md_var(tc, "descr", "check that curlwp for an implicit " 214272343Sngie "context is NULL"); 215272343Sngie} 216272343Sngie 217272343SngieATF_TC_BODY(nolwp, tc) 218272343Sngie{ 219272343Sngie 220272343Sngie rump_init(); 221272343Sngie ATF_REQUIRE_EQ(rump_pub_lwproc_curlwp(), NULL); 222272343Sngie} 223272343Sngie 224272343SngieATF_TC(nullswitch); 225272343SngieATF_TC_HEAD(nullswitch, tc) 226272343Sngie{ 227272343Sngie 228272343Sngie atf_tc_set_md_var(tc, "descr", "check that switching to NULL marks " 229272343Sngie "current lwp as not running"); 230272343Sngie} 231272343Sngie 232272343SngieATF_TC_BODY(nullswitch, tc) 233272343Sngie{ 234272343Sngie struct lwp *l; 235272343Sngie 236272343Sngie rump_init(); 237272343Sngie RZ(rump_pub_lwproc_newlwp(0)); 238272343Sngie l = rump_pub_lwproc_curlwp(); 239272343Sngie rump_pub_lwproc_switch(NULL); 240272343Sngie /* if remains LP_RUNNING, next call will panic */ 241272343Sngie rump_pub_lwproc_switch(l); 242272343Sngie} 243272343Sngie 244272343SngieATF_TC(rfork); 245272343SngieATF_TC_HEAD(rfork, tc) 246272343Sngie{ 247272343Sngie 248272343Sngie atf_tc_set_md_var(tc, "descr", "check that fork shares fd's"); 249272343Sngie} 250272343Sngie 251272343SngieATF_TC_BODY(rfork, tc) 252272343Sngie{ 253272343Sngie struct stat sb; 254272343Sngie struct lwp *l, *l2; 255272343Sngie int fd; 256272343Sngie 257272343Sngie RZ(rump_init()); 258272343Sngie 259272343Sngie ATF_REQUIRE_EQ(rump_pub_lwproc_rfork(RUMP_RFFDG|RUMP_RFCFDG), EINVAL); 260272343Sngie 261272343Sngie RZ(rump_pub_lwproc_rfork(0)); 262272343Sngie l = rump_pub_lwproc_curlwp(); 263272343Sngie 264272343Sngie RL(fd = rump_sys_open("/file", O_RDWR | O_CREAT, 0777)); 265272343Sngie 266272343Sngie /* ok, first check rfork(RUMP_RFCFDG) does *not* preserve fd's */ 267272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 268272343Sngie ATF_REQUIRE_ERRNO(EBADF, rump_sys_write(fd, &fd, sizeof(fd)) == -1); 269272343Sngie 270272343Sngie /* then check that rfork(0) does */ 271272343Sngie rump_pub_lwproc_switch(l); 272272343Sngie RZ(rump_pub_lwproc_rfork(0)); 273272343Sngie ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd)); 274272343Sngie RL(rump_sys_fstat(fd, &sb)); 275272343Sngie l2 = rump_pub_lwproc_curlwp(); 276272343Sngie 277272343Sngie /* 278272343Sngie * check that the shared fd table is really shared by 279272343Sngie * closing fd in parent 280272343Sngie */ 281272343Sngie rump_pub_lwproc_switch(l); 282272343Sngie RL(rump_sys_close(fd)); 283272343Sngie rump_pub_lwproc_switch(l2); 284272343Sngie ATF_REQUIRE_ERRNO(EBADF, rump_sys_fstat(fd, &sb) == -1); 285272343Sngie 286272343Sngie /* redo, this time copying the fd table instead of sharing it */ 287272343Sngie rump_pub_lwproc_releaselwp(); 288272343Sngie rump_pub_lwproc_switch(l); 289272343Sngie RL(fd = rump_sys_open("/file", O_RDWR, 0777)); 290272343Sngie RZ(rump_pub_lwproc_rfork(RUMP_RFFDG)); 291272343Sngie ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd)); 292272343Sngie RL(rump_sys_fstat(fd, &sb)); 293272343Sngie l2 = rump_pub_lwproc_curlwp(); 294272343Sngie 295272343Sngie /* check that the fd table is copied */ 296272343Sngie rump_pub_lwproc_switch(l); 297272343Sngie RL(rump_sys_close(fd)); 298272343Sngie rump_pub_lwproc_switch(l2); 299272343Sngie RL(rump_sys_fstat(fd, &sb)); 300272343Sngie ATF_REQUIRE_EQ(sb.st_size, sizeof(fd)); 301272343Sngie} 302272343Sngie 303272343SngieATF_TP_ADD_TCS(tp) 304272343Sngie{ 305272343Sngie 306272343Sngie ATF_TP_ADD_TC(tp, makelwp); 307272343Sngie ATF_TP_ADD_TC(tp, proccreds); 308272343Sngie ATF_TP_ADD_TC(tp, inherit); 309272343Sngie ATF_TP_ADD_TC(tp, lwps); 310272343Sngie ATF_TP_ADD_TC(tp, nolwprelease); 311272343Sngie ATF_TP_ADD_TC(tp, nolwp); 312272343Sngie ATF_TP_ADD_TC(tp, nullswitch); 313272343Sngie ATF_TP_ADD_TC(tp, rfork); 314272343Sngie 315272343Sngie return atf_no_error(); 316272343Sngie} 317