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 48 ATF_TC(makelwp); 49 ATF_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 56 ATF_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 77 ATF_TC(proccreds); 78 ATF_TC_HEAD(proccreds, tc) 79 { 80 81 atf_tc_set_md_var(tc, "descr", "check that procs have different creds"); 82 } 83 84 ATF_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 111 ATF_TC(inherit); 112 ATF_TC_HEAD(inherit, tc) 113 { 114 115 atf_tc_set_md_var(tc, "descr", "new processes inherit creds from " 116 "parents"); 117 } 118 119 ATF_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 136 ATF_TC(lwps); 137 ATF_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 145 ATF_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 181 ATF_TC(nolwprelease); 182 ATF_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 189 ATF_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 210 ATF_TC(nolwp); 211 ATF_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 218 ATF_TC_BODY(nolwp, tc) 219 { 220 221 rump_init(); 222 ATF_REQUIRE_EQ(rump_pub_lwproc_curlwp(), NULL); 223 } 224 225 ATF_TC(nullswitch); 226 ATF_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 233 ATF_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 245 ATF_TC(rfork); 246 ATF_TC_HEAD(rfork, tc) 247 { 248 249 atf_tc_set_md_var(tc, "descr", "check that fork shares fd's"); 250 } 251 252 ATF_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 304 ATF_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