diff --git a/kernel/include/process.h b/kernel/include/process.h index 512b0c03..f958a390 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -505,10 +505,12 @@ struct process { // PS_STOPPED -----+ // (PS_TRACED) - /* Store exit_status for a group of threads when stopped by SIGSTOP. - exit_status can't be used because values of exit_status of threads - might divert while the threads are exiting by group_exit(). */ - int group_exit_status; + /* Store exit_status for a group of threads when stopped by SIGSTOP. */ + /* exit_status can't be used because values of exit_status of threads */ + /* might divert while the threads are exiting by group_exit(). */ + /* The upper 4 bytes of group_exit_status is the confirmation flag of */ + /* exit status. The lower 4 bytes is the exit status. */ + unsigned long group_exit_status; /* Manage ptraced processes in the separate list to make it easy to restore the orginal parent child relationship when diff --git a/kernel/syscall.c b/kernel/syscall.c index da3ecbcc..3b395d81 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -448,34 +448,59 @@ static int wait_stopped(struct thread *thread, struct process *child, struct thr thread->proc->pid, child->pid, options); int ret; - /* Copy exit_status created in do_signal */ - int *exit_status; - if (c_thread) { - exit_status = &c_thread->exit_status; + /* Skip this process because exit_status has been reaped. */ + if (!c_thread->exit_status) { + ret = 0; + goto out; + } + + /* TODO: define 0x7f in kernel/include/process.h */ + if (status) { + *status = (c_thread->exit_status << 8) | 0x7f; + } + + /* Reap exit_status. signal_flags is reaped on receiving */ + /* signal in do_kill(). */ + if (!(options & WNOWAIT)) { + c_thread->exit_status = 0; + } } else if (child->status & (PS_STOPPED | PS_DELAY_STOPPED)) { - exit_status = &child->group_exit_status; + /* Skip this process because exit_status has been reaped. */ + if (!child->group_exit_status) { + ret = 0; + goto out; + } + + /* TODO: define 0x7f in kernel/include/process.h */ + if (status) { + *status = (child->group_exit_status << 8) | 0x7f; + } + + /* Reap exit_status. signal_flags is reaped on receiving */ + /* signal in do_kill(). */ + if (!(options & WNOWAIT)) { + child->group_exit_status = 0; + } } else { - exit_status = &child->main_thread->exit_status; - } + /* Skip this process because exit_status has been reaped. */ + if (!child->main_thread->exit_status) { + ret = 0; + goto out; + } - /* Skip this process because exit_status has been reaped. */ - if (!*exit_status) { - ret = 0; - goto out; - } + /* TODO: define 0x7f in kernel/include/process.h */ + if (status) { + *status = (child->main_thread->exit_status << 8) | 0x7f; + } - /* TODO: define 0x7f in kernel/include/process.h */ - if (status) { - *status = (*exit_status << 8) | 0x7f; - } - - /* Reap exit_status. signal_flags is reaped on receiving signal - in do_kill(). */ - if(!(options & WNOWAIT)) { - *exit_status = 0; + /* Reap exit_status. signal_flags is reaped on receiving */ + /* signal in do_kill(). */ + if (!(options & WNOWAIT)) { + child->main_thread->exit_status = 0; + } } dkprintf("wait_stopped,child->pid=%d,status=%08x\n", diff --git a/test/issues/1377/C1377.sh b/test/issues/1377/C1377.sh new file mode 100644 index 00000000..add3d592 --- /dev/null +++ b/test/issues/1377/C1377.sh @@ -0,0 +1,56 @@ +#!/bin/sh +USELTP=1 +USEOSTEST=0 + +. ../../common.sh + +################################################################################ +if [ ! -f "$LTPBIN/dirtyc0w" ]; then + echo BAD environment: LTP is too old >&2 + exit 1 +fi + +echo "*** C1377T01 start" +ng=0 +ok=0 +tp=dirtyc0w +for ((i=0; i<20; i++)); do + for ((j=0; j<50; j++)); do + sudo PATH=$PATH:$LTPBIN $MCEXEC $LTPBIN/$tp > $tp.txt 2>&1 + wok=`grep PASS $tp.txt | wc -l` + wng=`grep FAIL $tp.txt | wc -l` + if [ $wng != 0 ]; then + echo -n '*' + ng=`expr $ng + 1` + elif [ $wok == 0 ]; then + echo -n '?' + else + echo -n '.' + ok=`expr $ok + 1` + fi + done + echo +done + +if [ $ng != 0 ]; then + echo "*** C1377T01 FAILED ok: $ok, ng: $ng" +else + echo "*** C1377T01 PASS ok: $ok" +fi + + + +for i in wait02:02 wait401:03 waitpid01:04 waitpid02:05 waitpid04:06 \ + waitpid05:07 waitpid06:08 waitpid07:09 waitpid08:10 waitpid09:11 \ + waitpid10:12 waitpid11:13 waitpid12:14 waitpid13:15; do + tp=`echo $i|sed 's/:.*//'` + id=`echo $i|sed 's/.*://'` + sudo PATH=$PATH:$LTPBIN $MCEXEC $LTPBIN/$tp 2>&1 | tee $tp.txt + ok=`grep PASS $tp.txt | wc -l` + ng=`grep FAIL $tp.txt | wc -l` + if [ $ng = 0 ]; then + echo "*** C1377T$id: $tp PASS ($ok)" + else + echo "*** C1377T$id: $tp FAIL (ok=$ok ng=$ng)" + fi +done diff --git a/test/issues/1377/C1377_arm64.txt b/test/issues/1377/C1377_arm64.txt new file mode 100644 index 00000000..9e1daa39 --- /dev/null +++ b/test/issues/1377/C1377_arm64.txt @@ -0,0 +1,179 @@ +Script started on Tue 16 Jun 2020 02:42:48 PM JST +[shirasawa@apollo04 1377]$ make test +sh ./C1377.sh +mcstop+release.sh ... done +mcreboot.sh -c 2-31 -m 2G@0,2G@1 -O ... done +*** C1377T01 start +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +*** C1377T01 PASS ok: 1000 +wait02 1 TPASS : wait(&status) returned 78343 +*** C1377T02: wait02 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +wait401.c:55: PASS: waitpid() returned correct pid 78457 +wait401.c:64: PASS: WIFEXITED() is set in status +wait401.c:69: PASS: WEXITSTATUS() == 0 + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** C1377T03: wait401 PASS (3) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid01.c:51: PASS: waitpid() returned correct pid 78571 +waitpid01.c:60: PASS: WIFSIGNALED() set in status +waitpid01.c:68: PASS: WTERMSIG() == SIGALRM + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** C1377T04: waitpid01 PASS (3) +waitpid02 1 TPASS : received expected pid +waitpid02 2 TPASS : received expected signal +waitpid02 3 TPASS : received expected exit value +*** C1377T05: waitpid02 PASS (3) +waitpid04 1 TPASS : condition 1 test passed +waitpid04 2 TPASS : condition 2 test passed +waitpid04 3 TPASS : condition 3 test passed +*** C1377T06: waitpid04 PASS (3) +waitpid05 1 TPASS : received expected pid. +waitpid05 2 TPASS : received expected exit number. +waitpid05 3 TPASS : received expected pid. +waitpid05 4 TPASS : received expected exit number. +waitpid05 5 TPASS : received expected pid. +waitpid05 6 TPASS : received expected exit number. +waitpid05 7 TPASS : received expected pid. +waitpid05 8 TPASS : received expected exit number. +waitpid05 9 TPASS : received expected pid. +waitpid05 10 TPASS : received expected exit number. +waitpid05 11 TPASS : received expected pid. +waitpid05 12 TPASS : received expected exit number. +waitpid05 13 TPASS : received expected pid. +waitpid05 14 TPASS : received expected exit number. +waitpid05 15 TPASS : received expected pid. +waitpid05 16 TPASS : received expected exit number. +waitpid05 17 TPASS : received expected pid. +waitpid05 18 TPASS : received expected exit number. +waitpid05 19 TPASS : received expected pid. +waitpid05 20 TPASS : received expected exit number. +waitpid05 21 TPASS : received expected pid. +waitpid05 22 TPASS : received expected exit number. +waitpid05 23 TPASS : received expected pid. +waitpid05 24 TPASS : received expected exit number. +*** C1377T07: waitpid05 PASS (24) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid06.c:54: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T08: waitpid06 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid07.c:59: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T09: waitpid07 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid_common.h:142: INFO: Sending SIGCONT to 80073 +waitpid_common.h:142: INFO: Sending SIGCONT to 80105 +waitpid_common.h:142: INFO: Sending SIGCONT to 80137 +waitpid_common.h:142: INFO: Sending SIGCONT to 80169 +waitpid_common.h:142: INFO: Sending SIGCONT to 80201 +waitpid_common.h:142: INFO: Sending SIGCONT to 80233 +waitpid_common.h:142: INFO: Sending SIGCONT to 80266 +waitpid_common.h:142: INFO: Sending SIGCONT to 80298 +waitpid08.c:62: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T10: waitpid08 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid09.c:83: PASS: waitpid(pid, WNOHANG) = 0 for a running child +waitpid09.c:123: PASS: waitpid(pid, WNOHANG) = pid for an exited child +waitpid09.c:143: PASS: waitpid(-1, 0) = -1 with ECHILD if no children +waitpid09.c:162: PASS: waitpid(-1, WNOHANG) = -1 with ECHILD if no children + +Summary: +passed 4 +failed 0 +skipped 0 +warnings 0 +*** C1377T11: waitpid09 PASS (4) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid10.c:62: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T12: waitpid10 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid11.c:60: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T13: waitpid11 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid12.c:70: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T14: waitpid12 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid_common.h:142: INFO: Sending SIGCONT to 85038 +waitpid_common.h:142: INFO: Sending SIGCONT to 85070 +waitpid_common.h:142: INFO: Sending SIGCONT to 85102 +waitpid_common.h:142: INFO: Sending SIGCONT to 85134 +waitpid_common.h:142: INFO: Sending SIGCONT to 84910 +waitpid_common.h:142: INFO: Sending SIGCONT to 84942 +waitpid_common.h:142: INFO: Sending SIGCONT to 84974 +waitpid_common.h:142: INFO: Sending SIGCONT to 85006 +waitpid13.c:70: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T15: waitpid13 PASS (1) +[shirasawa@apollo04 1377]$ exit +exit + +Script done on Tue 16 Jun 2020 03:02:48 PM JST diff --git a/test/issues/1377/C1377_x86_64.txt b/test/issues/1377/C1377_x86_64.txt new file mode 100644 index 00000000..c79fec96 --- /dev/null +++ b/test/issues/1377/C1377_x86_64.txt @@ -0,0 +1,179 @@ +Script started on Tue Jun 16 15:36:06 2020 +bash-4.2$ make test +sh ./C1377.sh +mcstop+release.sh ... done +mcreboot.sh -c 1-7,9-15,17-23,25-31 -m 10G@0,10G@1 -r 1-7:0+9-15:8+17-23:16+25-31:24 ... done +*** C1377T01 start +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +.................................................. +*** C1377T01 PASS ok: 1000 +wait02 1 TPASS : wait(&status) returned 32240 +*** C1377T02: wait02 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +wait401.c:55: PASS: waitpid() returned correct pid 32347 +wait401.c:64: PASS: WIFEXITED() is set in status +wait401.c:69: PASS: WEXITSTATUS() == 0 + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** C1377T03: wait401 PASS (3) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid01.c:51: PASS: waitpid() returned correct pid 32454 +waitpid01.c:60: PASS: WIFSIGNALED() set in status +waitpid01.c:68: PASS: WTERMSIG() == SIGALRM + +Summary: +passed 3 +failed 0 +skipped 0 +warnings 0 +*** C1377T04: waitpid01 PASS (3) +waitpid02 1 TPASS : received expected pid +waitpid02 2 TPASS : received expected signal +waitpid02 3 TPASS : received expected exit value +*** C1377T05: waitpid02 PASS (3) +waitpid04 1 TPASS : condition 1 test passed +waitpid04 2 TPASS : condition 2 test passed +waitpid04 3 TPASS : condition 3 test passed +*** C1377T06: waitpid04 PASS (3) +waitpid05 1 TPASS : received expected pid. +waitpid05 2 TPASS : received expected exit number. +waitpid05 3 TPASS : received expected pid. +waitpid05 4 TPASS : received expected exit number. +waitpid05 5 TPASS : received expected pid. +waitpid05 6 TPASS : received expected exit number. +waitpid05 7 TPASS : received expected pid. +waitpid05 8 TPASS : received expected exit number. +waitpid05 9 TPASS : received expected pid. +waitpid05 10 TPASS : received expected exit number. +waitpid05 11 TPASS : received expected pid. +waitpid05 12 TPASS : received expected exit number. +waitpid05 13 TPASS : received expected pid. +waitpid05 14 TPASS : received expected exit number. +waitpid05 15 TPASS : received expected pid. +waitpid05 16 TPASS : received expected exit number. +waitpid05 17 TPASS : received expected pid. +waitpid05 18 TPASS : received expected exit number. +waitpid05 19 TPASS : received expected pid. +waitpid05 20 TPASS : received expected exit number. +waitpid05 21 TPASS : received expected pid. +waitpid05 22 TPASS : received expected exit number. +waitpid05 23 TPASS : received expected pid. +waitpid05 24 TPASS : received expected exit number. +*** C1377T07: waitpid05 PASS (24) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid06.c:54: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T08: waitpid06 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid07.c:59: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T09: waitpid07 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid_common.h:142: INFO: Sending SIGCONT to 1524 +waitpid_common.h:142: INFO: Sending SIGCONT to 1554 +waitpid_common.h:142: INFO: Sending SIGCONT to 1584 +waitpid_common.h:142: INFO: Sending SIGCONT to 1614 +waitpid_common.h:142: INFO: Sending SIGCONT to 1644 +waitpid_common.h:142: INFO: Sending SIGCONT to 1674 +waitpid_common.h:142: INFO: Sending SIGCONT to 1704 +waitpid_common.h:142: INFO: Sending SIGCONT to 1734 +waitpid08.c:62: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T10: waitpid08 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid09.c:83: PASS: waitpid(pid, WNOHANG) = 0 for a running child +waitpid09.c:123: PASS: waitpid(pid, WNOHANG) = pid for an exited child +waitpid09.c:143: PASS: waitpid(-1, 0) = -1 with ECHILD if no children +waitpid09.c:162: PASS: waitpid(-1, WNOHANG) = -1 with ECHILD if no children + +Summary: +passed 4 +failed 0 +skipped 0 +warnings 0 +*** C1377T11: waitpid09 PASS (4) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid10.c:62: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T12: waitpid10 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid11.c:60: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T13: waitpid11 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid12.c:70: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T14: waitpid12 PASS (1) +tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s +waitpid_common.h:142: INFO: Sending SIGCONT to 6219 +waitpid_common.h:142: INFO: Sending SIGCONT to 6249 +waitpid_common.h:142: INFO: Sending SIGCONT to 6279 +waitpid_common.h:142: INFO: Sending SIGCONT to 6309 +waitpid_common.h:142: INFO: Sending SIGCONT to 6099 +waitpid_common.h:142: INFO: Sending SIGCONT to 6129 +waitpid_common.h:142: INFO: Sending SIGCONT to 6159 +waitpid_common.h:142: INFO: Sending SIGCONT to 6189 +waitpid13.c:70: PASS: Test PASSED + +Summary: +passed 1 +failed 0 +skipped 0 +warnings 0 +*** C1377T15: waitpid13 PASS (1) +bash-4.2$ exit +exit + +Script done on Tue Jun 16 15:55:52 2020 diff --git a/test/issues/1377/Makefile b/test/issues/1377/Makefile new file mode 100644 index 00000000..ab4b9a25 --- /dev/null +++ b/test/issues/1377/Makefile @@ -0,0 +1,9 @@ +CC = gcc + +all:: + +test:: all + sh ./C1377.sh + +clean:: + rm -f $(TARGET) *.o diff --git a/test/issues/1377/README b/test/issues/1377/README new file mode 100644 index 00000000..ae4cf820 --- /dev/null +++ b/test/issues/1377/README @@ -0,0 +1,38 @@ +【Issue#1377 動作確認】 +□ テスト内容 +1. Issue 指摘事項の再現確認 + 現象はタイミングに依存し、ARM64環境でdirtyc0wを繰り返し実行した際に、 + 数回〜数十回に1回程度発生する。 + 問題の発生はタイミングに依存するため、dirtyc0wを十分な回数繰り返し + 実行し、問題が再発しないことを確認する。 + +C1377T01 dirtyc0wを1000回連続実行し、全てPASSすることを確認 + +2. LTP を用いて既存処理に影響しないことを確認 + プロセスの終了ステータスを変更したため、修正が既存処理に影響しないことを + wait系システムコールのLTPを用いて確認する。 +C1377T02 wait02: waitの基本機能の確認 +C1377T03 wait401: wait4の基本機能の確認 +C1377T04 waitpid01: waitpidの基本機能の確認 +C1377T05 waitpid02: waitpidの基本機能の確認 +C1377T06 waitpid04: waitpidの基本機能の確認 +C1377T07 waitpid05: waitpidの基本機能の確認 +C1377T08 waitpid06: waitpidの基本機能の確認 +C1377T09 waitpid07: waitpidの基本機能の確認 +C1377T10 waitpid08: waitpidの基本機能の確認 +C1377T11 waitpid09: waitpidの基本機能の確認 +C1377T12 waitpid10: waitpidの基本機能の確認 +C1377T13 waitpid11: waitpidの基本機能の確認 +C1377T14 waitpid12: waitpidの基本機能の確認 +C1377T15 waitpid13: waitpidの基本機能の確認 + +□ 実行手順 +$ make test + +McKernelのインストール先や LTP の配置場所は、$HOME/.mck_test_config を +参照する。.mck_test_config は、McKernel をビルドした際に生成される +mck_test_config.sample ファイルを $HOME にコピーし、適宜編集すること。 + +□ 実行結果 +C1377_x86_64.txt(x86_64実行結果)、C1377_arm64.txt(arm64実行結果)参照。 +全ての項目が PASS していることを確認。