t_lwproc.c revision 313498
1/* $NetBSD: t_lwproc.c,v 1.7 2015/01/21 15:19:01 pooka 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 33#include <rump/rump.h> 34#include <rump/rump_syscalls.h> 35 36#include <atf-c.h> 37#include <err.h> 38#include <errno.h> 39#include <fcntl.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43#include <unistd.h> 44#include <util.h> 45 46#include "../../h_macros.h" 47 48ATF_TC(makelwp); 49ATF_TC_HEAD(makelwp, tc) 50{ 51 52 atf_tc_set_md_var(tc, "descr", "tests that lwps can be attached to " 53 "processes"); 54} 55 56ATF_TC_BODY(makelwp, tc) 57{ 58 struct lwp *l; 59 pid_t pid; 60 61 rump_init(); 62 RZ(rump_pub_lwproc_newlwp(0)); 63 ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(37), ESRCH); 64 l = rump_pub_lwproc_curlwp(); 65 66 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 67 ATF_REQUIRE(rump_pub_lwproc_curlwp() != l); 68 l = rump_pub_lwproc_curlwp(); 69 70 RZ(rump_pub_lwproc_newlwp(rump_sys_getpid())); 71 ATF_REQUIRE(rump_pub_lwproc_curlwp() != l); 72 73 pid = rump_sys_getpid(); 74 ATF_REQUIRE(pid != -1 && pid != 0); 75} 76 77ATF_TC(proccreds); 78ATF_TC_HEAD(proccreds, tc) 79{ 80 81 atf_tc_set_md_var(tc, "descr", "check that procs have different creds"); 82} 83 84ATF_TC_BODY(proccreds, tc) 85{ 86 struct lwp *l1, *l2; 87 88 rump_init(); 89 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 90 l1 = rump_pub_lwproc_curlwp(); 91 RZ(rump_pub_lwproc_newlwp(rump_sys_getpid())); 92 93 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 94 l2 = rump_pub_lwproc_curlwp(); 95 96 RL(rump_sys_setuid(22)); 97 ATF_REQUIRE_EQ(rump_sys_getuid(), 22); 98 99 rump_pub_lwproc_switch(l1); 100 ATF_REQUIRE_EQ(rump_sys_getuid(), 0); /* from parent, proc0 */ 101 RL(rump_sys_setuid(11)); 102 ATF_REQUIRE_EQ(rump_sys_getuid(), 11); 103 104 rump_pub_lwproc_switch(l2); 105 ATF_REQUIRE_EQ(rump_sys_getuid(), 22); 106 rump_pub_lwproc_newlwp(rump_sys_getpid()); 107 ATF_REQUIRE_EQ(rump_sys_getuid(), 22); 108} 109 110 111ATF_TC(inherit); 112ATF_TC_HEAD(inherit, tc) 113{ 114 115 atf_tc_set_md_var(tc, "descr", "new processes inherit creds from " 116 "parents"); 117} 118 119ATF_TC_BODY(inherit, tc) 120{ 121 122 rump_init(); 123 124 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 125 RL(rump_sys_setuid(66)); 126 ATF_REQUIRE_EQ(rump_sys_getuid(), 66); 127 128 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 129 ATF_REQUIRE_EQ(rump_sys_getuid(), 66); 130 131 /* release lwp and proc */ 132 rump_pub_lwproc_releaselwp(); 133 ATF_REQUIRE_EQ(rump_sys_getuid(), 0); 134} 135 136ATF_TC(lwps); 137ATF_TC_HEAD(lwps, tc) 138{ 139 140 atf_tc_set_md_var(tc, "descr", "proc can hold many lwps and is " 141 "automatically g/c'd when the last one exits"); 142} 143 144#define LOOPS 128 145ATF_TC_BODY(lwps, tc) 146{ 147 struct lwp *l[LOOPS]; 148 pid_t mypid; 149 struct lwp *l_orig; 150 int i; 151 152 rump_init(); 153 154 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 155 mypid = rump_sys_getpid(); 156 RL(rump_sys_setuid(375)); 157 158 l_orig = rump_pub_lwproc_curlwp(); 159 for (i = 0; i < LOOPS; i++) { 160 mypid = rump_sys_getpid(); 161 ATF_REQUIRE(mypid != -1 && mypid != 0); 162 RZ(rump_pub_lwproc_newlwp(mypid)); 163 l[i] = rump_pub_lwproc_curlwp(); 164 ATF_REQUIRE_EQ(rump_sys_getuid(), 375); 165 } 166 167 rump_pub_lwproc_switch(l_orig); 168 rump_pub_lwproc_releaselwp(); 169 for (i = 0; i < LOOPS; i++) { 170 rump_pub_lwproc_switch(l[i]); 171 ATF_REQUIRE_EQ(rump_sys_getpid(), mypid); 172 ATF_REQUIRE_EQ(rump_sys_getuid(), 375); 173 rump_pub_lwproc_releaselwp(); 174 ATF_REQUIRE_EQ(rump_sys_getpid(), 1); 175 ATF_REQUIRE_EQ(rump_sys_getuid(), 0); 176 } 177 178 ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(mypid), ESRCH); 179} 180 181ATF_TC(nolwprelease); 182ATF_TC_HEAD(nolwprelease, tc) 183{ 184 185 atf_tc_set_md_var(tc, "descr", "check that lwp context is required " 186 "for lwproc_releaselwp()"); 187} 188 189ATF_TC_BODY(nolwprelease, tc) 190{ 191 int status; 192 193 switch (fork()) { 194 case 0: 195 rump_init(); 196 rump_pub_lwproc_releaselwp(); 197 atf_tc_fail("survived"); 198 break; 199 case -1: 200 atf_tc_fail_errno("fork"); 201 break; 202 default: 203 wait(&status); 204 ATF_REQUIRE(WIFSIGNALED(status)); 205 ATF_REQUIRE_EQ(WTERMSIG(status), SIGABRT); 206 207 } 208} 209 210ATF_TC(nolwp); 211ATF_TC_HEAD(nolwp, tc) 212{ 213 214 atf_tc_set_md_var(tc, "descr", "check that curlwp for an implicit " 215 "context is NULL"); 216} 217 218ATF_TC_BODY(nolwp, tc) 219{ 220 221 rump_init(); 222 ATF_REQUIRE_EQ(rump_pub_lwproc_curlwp(), NULL); 223} 224 225ATF_TC(nullswitch); 226ATF_TC_HEAD(nullswitch, tc) 227{ 228 229 atf_tc_set_md_var(tc, "descr", "check that switching to NULL marks " 230 "current lwp as not running"); 231} 232 233ATF_TC_BODY(nullswitch, tc) 234{ 235 struct lwp *l; 236 237 rump_init(); 238 RZ(rump_pub_lwproc_newlwp(0)); 239 l = rump_pub_lwproc_curlwp(); 240 rump_pub_lwproc_switch(NULL); 241 /* if remains LP_RUNNING, next call will panic */ 242 rump_pub_lwproc_switch(l); 243} 244 245ATF_TC(rfork); 246ATF_TC_HEAD(rfork, tc) 247{ 248 249 atf_tc_set_md_var(tc, "descr", "check that fork shares fd's"); 250} 251 252ATF_TC_BODY(rfork, tc) 253{ 254 struct stat sb; 255 struct lwp *l, *l2; 256 int fd; 257 258 RZ(rump_init()); 259 260 ATF_REQUIRE_EQ(rump_pub_lwproc_rfork(RUMP_RFFDG|RUMP_RFCFDG), EINVAL); 261 262 RZ(rump_pub_lwproc_rfork(0)); 263 l = rump_pub_lwproc_curlwp(); 264 265 RL(fd = rump_sys_open("/file", O_RDWR | O_CREAT, 0777)); 266 267 /* ok, first check rfork(RUMP_RFCFDG) does *not* preserve fd's */ 268 RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG)); 269 ATF_REQUIRE_ERRNO(EBADF, rump_sys_write(fd, &fd, sizeof(fd)) == -1); 270 271 /* then check that rfork(0) does */ 272 rump_pub_lwproc_switch(l); 273 RZ(rump_pub_lwproc_rfork(0)); 274 ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd)); 275 RL(rump_sys_fstat(fd, &sb)); 276 l2 = rump_pub_lwproc_curlwp(); 277 278 /* 279 * check that the shared fd table is really shared by 280 * closing fd in parent 281 */ 282 rump_pub_lwproc_switch(l); 283 RL(rump_sys_close(fd)); 284 rump_pub_lwproc_switch(l2); 285 ATF_REQUIRE_ERRNO(EBADF, rump_sys_fstat(fd, &sb) == -1); 286 287 /* redo, this time copying the fd table instead of sharing it */ 288 rump_pub_lwproc_releaselwp(); 289 rump_pub_lwproc_switch(l); 290 RL(fd = rump_sys_open("/file", O_RDWR, 0777)); 291 RZ(rump_pub_lwproc_rfork(RUMP_RFFDG)); 292 ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd)); 293 RL(rump_sys_fstat(fd, &sb)); 294 l2 = rump_pub_lwproc_curlwp(); 295 296 /* check that the fd table is copied */ 297 rump_pub_lwproc_switch(l); 298 RL(rump_sys_close(fd)); 299 rump_pub_lwproc_switch(l2); 300 RL(rump_sys_fstat(fd, &sb)); 301 ATF_REQUIRE_EQ(sb.st_size, sizeof(fd)); 302} 303 304ATF_TP_ADD_TCS(tp) 305{ 306 307 ATF_TP_ADD_TC(tp, makelwp); 308 ATF_TP_ADD_TC(tp, proccreds); 309 ATF_TP_ADD_TC(tp, inherit); 310 ATF_TP_ADD_TC(tp, lwps); 311 ATF_TP_ADD_TC(tp, nolwprelease); 312 ATF_TP_ADD_TC(tp, nolwp); 313 ATF_TP_ADD_TC(tp, nullswitch); 314 ATF_TP_ADD_TC(tp, rfork); 315 316 return atf_no_error(); 317} 318