1*0a6a1f1dSLionel Sambuc /* $NetBSD: t_lwproc.c,v 1.7 2015/01/21 15:19:01 pooka Exp $ */
211be35a1SLionel Sambuc
311be35a1SLionel Sambuc /*
411be35a1SLionel Sambuc * Copyright (c) 2010 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc * All rights reserved.
611be35a1SLionel Sambuc *
711be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
811be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
911be35a1SLionel Sambuc * are met:
1011be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
1111be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1211be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
1311be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
1411be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
1511be35a1SLionel Sambuc *
1611be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
1711be35a1SLionel Sambuc * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
1811be35a1SLionel Sambuc * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1911be35a1SLionel Sambuc * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2011be35a1SLionel Sambuc * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
2111be35a1SLionel Sambuc * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2211be35a1SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2311be35a1SLionel Sambuc * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2411be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
2511be35a1SLionel Sambuc * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2611be35a1SLionel Sambuc * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
2711be35a1SLionel Sambuc * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2811be35a1SLionel Sambuc */
2911be35a1SLionel Sambuc
3011be35a1SLionel Sambuc #include <sys/types.h>
3111be35a1SLionel Sambuc #include <sys/wait.h>
3211be35a1SLionel Sambuc
3311be35a1SLionel Sambuc #include <rump/rump.h>
3411be35a1SLionel Sambuc #include <rump/rump_syscalls.h>
3511be35a1SLionel Sambuc
3611be35a1SLionel Sambuc #include <atf-c.h>
3711be35a1SLionel Sambuc #include <err.h>
3811be35a1SLionel Sambuc #include <errno.h>
3911be35a1SLionel Sambuc #include <fcntl.h>
4011be35a1SLionel Sambuc #include <stdio.h>
4111be35a1SLionel Sambuc #include <stdlib.h>
4211be35a1SLionel Sambuc #include <string.h>
4311be35a1SLionel Sambuc #include <unistd.h>
4411be35a1SLionel Sambuc #include <util.h>
4511be35a1SLionel Sambuc
4611be35a1SLionel Sambuc #include "../../h_macros.h"
4711be35a1SLionel Sambuc
4811be35a1SLionel Sambuc ATF_TC(makelwp);
ATF_TC_HEAD(makelwp,tc)4911be35a1SLionel Sambuc ATF_TC_HEAD(makelwp, tc)
5011be35a1SLionel Sambuc {
5111be35a1SLionel Sambuc
5211be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "tests that lwps can be attached to "
5311be35a1SLionel Sambuc "processes");
5411be35a1SLionel Sambuc }
5511be35a1SLionel Sambuc
ATF_TC_BODY(makelwp,tc)5611be35a1SLionel Sambuc ATF_TC_BODY(makelwp, tc)
5711be35a1SLionel Sambuc {
5811be35a1SLionel Sambuc struct lwp *l;
5911be35a1SLionel Sambuc pid_t pid;
6011be35a1SLionel Sambuc
6111be35a1SLionel Sambuc rump_init();
6211be35a1SLionel Sambuc RZ(rump_pub_lwproc_newlwp(0));
6311be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(37), ESRCH);
6411be35a1SLionel Sambuc l = rump_pub_lwproc_curlwp();
6511be35a1SLionel Sambuc
6611be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
6711be35a1SLionel Sambuc ATF_REQUIRE(rump_pub_lwproc_curlwp() != l);
6811be35a1SLionel Sambuc l = rump_pub_lwproc_curlwp();
6911be35a1SLionel Sambuc
7011be35a1SLionel Sambuc RZ(rump_pub_lwproc_newlwp(rump_sys_getpid()));
7111be35a1SLionel Sambuc ATF_REQUIRE(rump_pub_lwproc_curlwp() != l);
7211be35a1SLionel Sambuc
7311be35a1SLionel Sambuc pid = rump_sys_getpid();
7411be35a1SLionel Sambuc ATF_REQUIRE(pid != -1 && pid != 0);
7511be35a1SLionel Sambuc }
7611be35a1SLionel Sambuc
7711be35a1SLionel Sambuc ATF_TC(proccreds);
ATF_TC_HEAD(proccreds,tc)7811be35a1SLionel Sambuc ATF_TC_HEAD(proccreds, tc)
7911be35a1SLionel Sambuc {
8011be35a1SLionel Sambuc
8111be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "check that procs have different creds");
8211be35a1SLionel Sambuc }
8311be35a1SLionel Sambuc
ATF_TC_BODY(proccreds,tc)8411be35a1SLionel Sambuc ATF_TC_BODY(proccreds, tc)
8511be35a1SLionel Sambuc {
8611be35a1SLionel Sambuc struct lwp *l1, *l2;
8711be35a1SLionel Sambuc
8811be35a1SLionel Sambuc rump_init();
8911be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
9011be35a1SLionel Sambuc l1 = rump_pub_lwproc_curlwp();
91*0a6a1f1dSLionel Sambuc RZ(rump_pub_lwproc_newlwp(rump_sys_getpid()));
9211be35a1SLionel Sambuc
9311be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
9411be35a1SLionel Sambuc l2 = rump_pub_lwproc_curlwp();
9511be35a1SLionel Sambuc
9611be35a1SLionel Sambuc RL(rump_sys_setuid(22));
9711be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 22);
9811be35a1SLionel Sambuc
9911be35a1SLionel Sambuc rump_pub_lwproc_switch(l1);
10011be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 0); /* from parent, proc0 */
10111be35a1SLionel Sambuc RL(rump_sys_setuid(11));
10211be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 11);
10311be35a1SLionel Sambuc
10411be35a1SLionel Sambuc rump_pub_lwproc_switch(l2);
10511be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 22);
10611be35a1SLionel Sambuc rump_pub_lwproc_newlwp(rump_sys_getpid());
10711be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 22);
10811be35a1SLionel Sambuc }
10911be35a1SLionel Sambuc
11011be35a1SLionel Sambuc
11111be35a1SLionel Sambuc ATF_TC(inherit);
ATF_TC_HEAD(inherit,tc)11211be35a1SLionel Sambuc ATF_TC_HEAD(inherit, tc)
11311be35a1SLionel Sambuc {
11411be35a1SLionel Sambuc
11511be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "new processes inherit creds from "
11611be35a1SLionel Sambuc "parents");
11711be35a1SLionel Sambuc }
11811be35a1SLionel Sambuc
ATF_TC_BODY(inherit,tc)11911be35a1SLionel Sambuc ATF_TC_BODY(inherit, tc)
12011be35a1SLionel Sambuc {
12111be35a1SLionel Sambuc
12211be35a1SLionel Sambuc rump_init();
12311be35a1SLionel Sambuc
12411be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
12511be35a1SLionel Sambuc RL(rump_sys_setuid(66));
12611be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 66);
12711be35a1SLionel Sambuc
12811be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
12911be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 66);
13011be35a1SLionel Sambuc
13111be35a1SLionel Sambuc /* release lwp and proc */
13211be35a1SLionel Sambuc rump_pub_lwproc_releaselwp();
13311be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 0);
13411be35a1SLionel Sambuc }
13511be35a1SLionel Sambuc
13611be35a1SLionel Sambuc ATF_TC(lwps);
ATF_TC_HEAD(lwps,tc)13711be35a1SLionel Sambuc ATF_TC_HEAD(lwps, tc)
13811be35a1SLionel Sambuc {
13911be35a1SLionel Sambuc
14011be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "proc can hold many lwps and is "
14111be35a1SLionel Sambuc "automatically g/c'd when the last one exits");
14211be35a1SLionel Sambuc }
14311be35a1SLionel Sambuc
14411be35a1SLionel Sambuc #define LOOPS 128
ATF_TC_BODY(lwps,tc)14511be35a1SLionel Sambuc ATF_TC_BODY(lwps, tc)
14611be35a1SLionel Sambuc {
14711be35a1SLionel Sambuc struct lwp *l[LOOPS];
14811be35a1SLionel Sambuc pid_t mypid;
14911be35a1SLionel Sambuc struct lwp *l_orig;
15011be35a1SLionel Sambuc int i;
15111be35a1SLionel Sambuc
15211be35a1SLionel Sambuc rump_init();
15311be35a1SLionel Sambuc
15411be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
15511be35a1SLionel Sambuc mypid = rump_sys_getpid();
15611be35a1SLionel Sambuc RL(rump_sys_setuid(375));
15711be35a1SLionel Sambuc
15811be35a1SLionel Sambuc l_orig = rump_pub_lwproc_curlwp();
15911be35a1SLionel Sambuc for (i = 0; i < LOOPS; i++) {
16011be35a1SLionel Sambuc mypid = rump_sys_getpid();
16111be35a1SLionel Sambuc ATF_REQUIRE(mypid != -1 && mypid != 0);
16211be35a1SLionel Sambuc RZ(rump_pub_lwproc_newlwp(mypid));
16311be35a1SLionel Sambuc l[i] = rump_pub_lwproc_curlwp();
16411be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 375);
16511be35a1SLionel Sambuc }
16611be35a1SLionel Sambuc
16711be35a1SLionel Sambuc rump_pub_lwproc_switch(l_orig);
16811be35a1SLionel Sambuc rump_pub_lwproc_releaselwp();
16911be35a1SLionel Sambuc for (i = 0; i < LOOPS; i++) {
17011be35a1SLionel Sambuc rump_pub_lwproc_switch(l[i]);
17111be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getpid(), mypid);
17211be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 375);
17311be35a1SLionel Sambuc rump_pub_lwproc_releaselwp();
17411be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getpid(), 1);
17511be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_getuid(), 0);
17611be35a1SLionel Sambuc }
17711be35a1SLionel Sambuc
17811be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_pub_lwproc_newlwp(mypid), ESRCH);
17911be35a1SLionel Sambuc }
18011be35a1SLionel Sambuc
18111be35a1SLionel Sambuc ATF_TC(nolwprelease);
ATF_TC_HEAD(nolwprelease,tc)18211be35a1SLionel Sambuc ATF_TC_HEAD(nolwprelease, tc)
18311be35a1SLionel Sambuc {
18411be35a1SLionel Sambuc
18511be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "check that lwp context is required "
18611be35a1SLionel Sambuc "for lwproc_releaselwp()");
18711be35a1SLionel Sambuc }
18811be35a1SLionel Sambuc
ATF_TC_BODY(nolwprelease,tc)18911be35a1SLionel Sambuc ATF_TC_BODY(nolwprelease, tc)
19011be35a1SLionel Sambuc {
19111be35a1SLionel Sambuc int status;
19211be35a1SLionel Sambuc
19311be35a1SLionel Sambuc switch (fork()) {
19411be35a1SLionel Sambuc case 0:
19511be35a1SLionel Sambuc rump_init();
19611be35a1SLionel Sambuc rump_pub_lwproc_releaselwp();
19711be35a1SLionel Sambuc atf_tc_fail("survived");
19811be35a1SLionel Sambuc break;
19911be35a1SLionel Sambuc case -1:
20011be35a1SLionel Sambuc atf_tc_fail_errno("fork");
20111be35a1SLionel Sambuc break;
20211be35a1SLionel Sambuc default:
20311be35a1SLionel Sambuc wait(&status);
20411be35a1SLionel Sambuc ATF_REQUIRE(WIFSIGNALED(status));
20511be35a1SLionel Sambuc ATF_REQUIRE_EQ(WTERMSIG(status), SIGABRT);
20611be35a1SLionel Sambuc
20711be35a1SLionel Sambuc }
20811be35a1SLionel Sambuc }
20911be35a1SLionel Sambuc
21011be35a1SLionel Sambuc ATF_TC(nolwp);
ATF_TC_HEAD(nolwp,tc)21111be35a1SLionel Sambuc ATF_TC_HEAD(nolwp, tc)
21211be35a1SLionel Sambuc {
21311be35a1SLionel Sambuc
21411be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "check that curlwp for an implicit "
21511be35a1SLionel Sambuc "context is NULL");
21611be35a1SLionel Sambuc }
21711be35a1SLionel Sambuc
ATF_TC_BODY(nolwp,tc)21811be35a1SLionel Sambuc ATF_TC_BODY(nolwp, tc)
21911be35a1SLionel Sambuc {
22011be35a1SLionel Sambuc
22111be35a1SLionel Sambuc rump_init();
22211be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_pub_lwproc_curlwp(), NULL);
22311be35a1SLionel Sambuc }
22411be35a1SLionel Sambuc
22511be35a1SLionel Sambuc ATF_TC(nullswitch);
ATF_TC_HEAD(nullswitch,tc)22611be35a1SLionel Sambuc ATF_TC_HEAD(nullswitch, tc)
22711be35a1SLionel Sambuc {
22811be35a1SLionel Sambuc
22911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "check that switching to NULL marks "
23011be35a1SLionel Sambuc "current lwp as not running");
23111be35a1SLionel Sambuc }
23211be35a1SLionel Sambuc
ATF_TC_BODY(nullswitch,tc)23311be35a1SLionel Sambuc ATF_TC_BODY(nullswitch, tc)
23411be35a1SLionel Sambuc {
23511be35a1SLionel Sambuc struct lwp *l;
23611be35a1SLionel Sambuc
23711be35a1SLionel Sambuc rump_init();
23811be35a1SLionel Sambuc RZ(rump_pub_lwproc_newlwp(0));
23911be35a1SLionel Sambuc l = rump_pub_lwproc_curlwp();
24011be35a1SLionel Sambuc rump_pub_lwproc_switch(NULL);
24111be35a1SLionel Sambuc /* if remains LP_RUNNING, next call will panic */
24211be35a1SLionel Sambuc rump_pub_lwproc_switch(l);
24311be35a1SLionel Sambuc }
24411be35a1SLionel Sambuc
24511be35a1SLionel Sambuc ATF_TC(rfork);
ATF_TC_HEAD(rfork,tc)24611be35a1SLionel Sambuc ATF_TC_HEAD(rfork, tc)
24711be35a1SLionel Sambuc {
24811be35a1SLionel Sambuc
24911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "check that fork shares fd's");
25011be35a1SLionel Sambuc }
25111be35a1SLionel Sambuc
ATF_TC_BODY(rfork,tc)25211be35a1SLionel Sambuc ATF_TC_BODY(rfork, tc)
25311be35a1SLionel Sambuc {
25411be35a1SLionel Sambuc struct stat sb;
25511be35a1SLionel Sambuc struct lwp *l, *l2;
25611be35a1SLionel Sambuc int fd;
25711be35a1SLionel Sambuc
25811be35a1SLionel Sambuc RZ(rump_init());
25911be35a1SLionel Sambuc
26011be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_pub_lwproc_rfork(RUMP_RFFDG|RUMP_RFCFDG), EINVAL);
26111be35a1SLionel Sambuc
26211be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(0));
26311be35a1SLionel Sambuc l = rump_pub_lwproc_curlwp();
26411be35a1SLionel Sambuc
26511be35a1SLionel Sambuc RL(fd = rump_sys_open("/file", O_RDWR | O_CREAT, 0777));
26611be35a1SLionel Sambuc
26711be35a1SLionel Sambuc /* ok, first check rfork(RUMP_RFCFDG) does *not* preserve fd's */
26811be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFCFDG));
26911be35a1SLionel Sambuc ATF_REQUIRE_ERRNO(EBADF, rump_sys_write(fd, &fd, sizeof(fd)) == -1);
27011be35a1SLionel Sambuc
27111be35a1SLionel Sambuc /* then check that rfork(0) does */
27211be35a1SLionel Sambuc rump_pub_lwproc_switch(l);
27311be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(0));
27411be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd));
27511be35a1SLionel Sambuc RL(rump_sys_fstat(fd, &sb));
27611be35a1SLionel Sambuc l2 = rump_pub_lwproc_curlwp();
27711be35a1SLionel Sambuc
27811be35a1SLionel Sambuc /*
27911be35a1SLionel Sambuc * check that the shared fd table is really shared by
28011be35a1SLionel Sambuc * closing fd in parent
28111be35a1SLionel Sambuc */
28211be35a1SLionel Sambuc rump_pub_lwproc_switch(l);
28311be35a1SLionel Sambuc RL(rump_sys_close(fd));
28411be35a1SLionel Sambuc rump_pub_lwproc_switch(l2);
28511be35a1SLionel Sambuc ATF_REQUIRE_ERRNO(EBADF, rump_sys_fstat(fd, &sb) == -1);
28611be35a1SLionel Sambuc
28711be35a1SLionel Sambuc /* redo, this time copying the fd table instead of sharing it */
28811be35a1SLionel Sambuc rump_pub_lwproc_releaselwp();
28911be35a1SLionel Sambuc rump_pub_lwproc_switch(l);
29011be35a1SLionel Sambuc RL(fd = rump_sys_open("/file", O_RDWR, 0777));
29111be35a1SLionel Sambuc RZ(rump_pub_lwproc_rfork(RUMP_RFFDG));
29211be35a1SLionel Sambuc ATF_REQUIRE_EQ(rump_sys_write(fd, &fd, sizeof(fd)), sizeof(fd));
29311be35a1SLionel Sambuc RL(rump_sys_fstat(fd, &sb));
29411be35a1SLionel Sambuc l2 = rump_pub_lwproc_curlwp();
29511be35a1SLionel Sambuc
29611be35a1SLionel Sambuc /* check that the fd table is copied */
29711be35a1SLionel Sambuc rump_pub_lwproc_switch(l);
29811be35a1SLionel Sambuc RL(rump_sys_close(fd));
29911be35a1SLionel Sambuc rump_pub_lwproc_switch(l2);
30011be35a1SLionel Sambuc RL(rump_sys_fstat(fd, &sb));
30111be35a1SLionel Sambuc ATF_REQUIRE_EQ(sb.st_size, sizeof(fd));
30211be35a1SLionel Sambuc }
30311be35a1SLionel Sambuc
ATF_TP_ADD_TCS(tp)30411be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
30511be35a1SLionel Sambuc {
30611be35a1SLionel Sambuc
30711be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, makelwp);
30811be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, proccreds);
30911be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, inherit);
31011be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, lwps);
31111be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, nolwprelease);
31211be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, nolwp);
31311be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, nullswitch);
31411be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, rfork);
31511be35a1SLionel Sambuc
31611be35a1SLionel Sambuc return atf_no_error();
31711be35a1SLionel Sambuc }
318