1 /* $NetBSD: t_lwproc.c,v 1.9 2017/01/13 21:30:43 christos 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 LP_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