Wed Jun 24 04:47:10 2020 UTC ()
Fix core_dump_procinfo tests for powerpc, for which child process was
stalled indefinitely in trap instruction even after PT_CONTINUE.

For powerpc, program counter is not automatically incremented by trap
instruction. We cannot increment PC in the trap handler, which breaks
applications depending on this behavior, e.g., GDB.

Therefore, we need to pass (PC + 4) instead of (void *)1 (== PC) to
PT_CONTINUE when child process traps itself.


(rin)
diff -r1.1 -r1.2 src/tests/lib/libc/sys/t_ptrace_core_wait.h

cvs diff -r1.1 -r1.2 src/tests/lib/libc/sys/t_ptrace_core_wait.h (switch to unified diff)

--- src/tests/lib/libc/sys/t_ptrace_core_wait.h 2020/05/05 01:24:29 1.1
+++ src/tests/lib/libc/sys/t_ptrace_core_wait.h 2020/06/24 04:47:10 1.2
@@ -1,222 +1,237 @@ @@ -1,222 +1,237 @@
1/* $NetBSD: t_ptrace_core_wait.h,v 1.1 2020/05/05 01:24:29 kamil Exp $ */ 1/* $NetBSD: t_ptrace_core_wait.h,v 1.2 2020/06/24 04:47:10 rin Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2016, 2017, 2018, 2019, 2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 2016, 2017, 2018, 2019, 2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 29
30/* 30/*
31 * Parse the core file and find the requested note. If the reading or parsing 31 * Parse the core file and find the requested note. If the reading or parsing
32 * fails, the test is failed. If the note is found, it is read onto buf, up to 32 * fails, the test is failed. If the note is found, it is read onto buf, up to
33 * buf_len. The actual length of the note is returned (which can be greater 33 * buf_len. The actual length of the note is returned (which can be greater
34 * than buf_len, indicating that it has been truncated). If the note is not 34 * than buf_len, indicating that it has been truncated). If the note is not
35 * found, -1 is returned. 35 * found, -1 is returned.
36 * 36 *
37 * If the note_name ends in '*', then we find the first note that matches 37 * If the note_name ends in '*', then we find the first note that matches
38 * the note_name prefix up to the '*' character, e.g.: 38 * the note_name prefix up to the '*' character, e.g.:
39 * 39 *
40 * NetBSD-CORE@* 40 * NetBSD-CORE@*
41 * 41 *
42 * finds the first note whose name prefix matches "NetBSD-CORE@". 42 * finds the first note whose name prefix matches "NetBSD-CORE@".
43 */ 43 */
44static ssize_t core_find_note(const char *core_path, 44static ssize_t core_find_note(const char *core_path,
45 const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 45 const char *note_name, uint64_t note_type, void *buf, size_t buf_len)
46{ 46{
47 int core_fd; 47 int core_fd;
48 Elf *core_elf; 48 Elf *core_elf;
49 size_t core_numhdr, i; 49 size_t core_numhdr, i;
50 ssize_t ret = -1; 50 ssize_t ret = -1;
51 size_t name_len = strlen(note_name); 51 size_t name_len = strlen(note_name);
52 bool prefix_match = false; 52 bool prefix_match = false;
53 53
54 if (note_name[name_len - 1] == '*') { 54 if (note_name[name_len - 1] == '*') {
55 prefix_match = true; 55 prefix_match = true;
56 name_len--; 56 name_len--;
57 } else { 57 } else {
58 /* note: we assume note name will be null-terminated */ 58 /* note: we assume note name will be null-terminated */
59 name_len++; 59 name_len++;
60 } 60 }
61 61
62 SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 62 SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1);
63 SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 63 SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE);
64 SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 64 SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL)));
65 65
66 SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 66 SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0);
67 for (i = 0; i < core_numhdr && ret == -1; i++) { 67 for (i = 0; i < core_numhdr && ret == -1; i++) {
68 GElf_Phdr core_hdr; 68 GElf_Phdr core_hdr;
69 size_t offset; 69 size_t offset;
70 SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 70 SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr));
71 if (core_hdr.p_type != PT_NOTE) 71 if (core_hdr.p_type != PT_NOTE)
72 continue; 72 continue;
73 73
74 for (offset = core_hdr.p_offset; 74 for (offset = core_hdr.p_offset;
75 offset < core_hdr.p_offset + core_hdr.p_filesz;) { 75 offset < core_hdr.p_offset + core_hdr.p_filesz;) {
76 Elf64_Nhdr note_hdr; 76 Elf64_Nhdr note_hdr;
77 char name_buf[64]; 77 char name_buf[64];
78 78
79 switch (gelf_getclass(core_elf)) { 79 switch (gelf_getclass(core_elf)) {
80 case ELFCLASS64: 80 case ELFCLASS64:
81 SYSCALL_REQUIRE(pread(core_fd, &note_hdr, 81 SYSCALL_REQUIRE(pread(core_fd, &note_hdr,
82 sizeof(note_hdr), offset) 82 sizeof(note_hdr), offset)
83 == sizeof(note_hdr)); 83 == sizeof(note_hdr));
84 offset += sizeof(note_hdr); 84 offset += sizeof(note_hdr);
85 break; 85 break;
86 case ELFCLASS32: 86 case ELFCLASS32:
87 { 87 {
88 Elf32_Nhdr tmp_hdr; 88 Elf32_Nhdr tmp_hdr;
89 SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 89 SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr,
90 sizeof(tmp_hdr), offset) 90 sizeof(tmp_hdr), offset)
91 == sizeof(tmp_hdr)); 91 == sizeof(tmp_hdr));
92 offset += sizeof(tmp_hdr); 92 offset += sizeof(tmp_hdr);
93 note_hdr.n_namesz = tmp_hdr.n_namesz; 93 note_hdr.n_namesz = tmp_hdr.n_namesz;
94 note_hdr.n_descsz = tmp_hdr.n_descsz; 94 note_hdr.n_descsz = tmp_hdr.n_descsz;
95 note_hdr.n_type = tmp_hdr.n_type; 95 note_hdr.n_type = tmp_hdr.n_type;
96 } 96 }
97 break; 97 break;
98 } 98 }
99 99
100 /* indicates end of notes */ 100 /* indicates end of notes */
101 if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 101 if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0)
102 break; 102 break;
103 if (((prefix_match && 103 if (((prefix_match &&
104 note_hdr.n_namesz > name_len) || 104 note_hdr.n_namesz > name_len) ||
105 (!prefix_match && 105 (!prefix_match &&
106 note_hdr.n_namesz == name_len)) && 106 note_hdr.n_namesz == name_len)) &&
107 note_hdr.n_namesz <= sizeof(name_buf)) { 107 note_hdr.n_namesz <= sizeof(name_buf)) {
108 SYSCALL_REQUIRE(pread(core_fd, name_buf, 108 SYSCALL_REQUIRE(pread(core_fd, name_buf,
109 note_hdr.n_namesz, offset) 109 note_hdr.n_namesz, offset)
110 == (ssize_t)(size_t)note_hdr.n_namesz); 110 == (ssize_t)(size_t)note_hdr.n_namesz);
111 111
112 if (!strncmp(note_name, name_buf, name_len) && 112 if (!strncmp(note_name, name_buf, name_len) &&
113 note_hdr.n_type == note_type) 113 note_hdr.n_type == note_type)
114 ret = note_hdr.n_descsz; 114 ret = note_hdr.n_descsz;
115 } 115 }
116 116
117 offset += note_hdr.n_namesz; 117 offset += note_hdr.n_namesz;
118 /* fix to alignment */ 118 /* fix to alignment */
119 offset = roundup(offset, core_hdr.p_align); 119 offset = roundup(offset, core_hdr.p_align);
120 120
121 /* if name & type matched above */ 121 /* if name & type matched above */
122 if (ret != -1) { 122 if (ret != -1) {
123 ssize_t read_len = MIN(buf_len, 123 ssize_t read_len = MIN(buf_len,
124 note_hdr.n_descsz); 124 note_hdr.n_descsz);
125 SYSCALL_REQUIRE(pread(core_fd, buf, 125 SYSCALL_REQUIRE(pread(core_fd, buf,
126 read_len, offset) == read_len); 126 read_len, offset) == read_len);
127 break; 127 break;
128 } 128 }
129 129
130 offset += note_hdr.n_descsz; 130 offset += note_hdr.n_descsz;
131 /* fix to alignment */ 131 /* fix to alignment */
132 offset = roundup(offset, core_hdr.p_align); 132 offset = roundup(offset, core_hdr.p_align);
133 } 133 }
134 } 134 }
135 135
136 elf_end(core_elf); 136 elf_end(core_elf);
137 close(core_fd); 137 close(core_fd);
138 138
139 return ret; 139 return ret;
140} 140}
141 141
142ATF_TC(core_dump_procinfo); 142ATF_TC(core_dump_procinfo);
143ATF_TC_HEAD(core_dump_procinfo, tc) 143ATF_TC_HEAD(core_dump_procinfo, tc)
144{ 144{
145 atf_tc_set_md_var(tc, "descr", 145 atf_tc_set_md_var(tc, "descr",
146 "Trigger a core dump and verify its contents."); 146 "Trigger a core dump and verify its contents.");
147} 147}
148 148
149ATF_TC_BODY(core_dump_procinfo, tc) 149ATF_TC_BODY(core_dump_procinfo, tc)
150{ 150{
151 const int exitval = 5; 151 const int exitval = 5;
152 pid_t child, wpid; 152 pid_t child, wpid;
153#if defined(TWAIT_HAVE_STATUS) 153#if defined(TWAIT_HAVE_STATUS)
154 const int sigval = SIGTRAP; 154 const int sigval = SIGTRAP;
155 int status; 155 int status;
156#endif 156#endif
157 char core_path[] = "/tmp/core.XXXXXX"; 157 char core_path[] = "/tmp/core.XXXXXX";
158 int core_fd; 158 int core_fd;
159 struct netbsd_elfcore_procinfo procinfo; 159 struct netbsd_elfcore_procinfo procinfo;
160 160
161 DPRINTF("Before forking process PID=%d\n", getpid()); 161 DPRINTF("Before forking process PID=%d\n", getpid());
162 SYSCALL_REQUIRE((child = fork()) != -1); 162 SYSCALL_REQUIRE((child = fork()) != -1);
163 if (child == 0) { 163 if (child == 0) {
164 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 164 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
165 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 165 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
166 166
167 DPRINTF("Before triggering SIGTRAP\n"); 167 DPRINTF("Before triggering SIGTRAP\n");
168 trigger_trap(); 168 trigger_trap();
169 169
170 DPRINTF("Before exiting of the child process\n"); 170 DPRINTF("Before exiting of the child process\n");
171 _exit(exitval); 171 _exit(exitval);
172 } 172 }
173 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 173 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
174 174
175 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 175 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
176 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 176 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
177 177
178 validate_status_stopped(status, sigval); 178 validate_status_stopped(status, sigval);
179 179
180 SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 180 SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1);
181 close(core_fd); 181 close(core_fd);
182 182
183 DPRINTF("Call DUMPCORE for the child process\n"); 183 DPRINTF("Call DUMPCORE for the child process\n");
184 SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 184 SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path))
185 != -1); 185 != -1);
186 186
187 DPRINTF("Read core file\n"); 187 DPRINTF("Read core file\n");
188 ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 188 ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE",
189 ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 189 ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)),
190 sizeof(procinfo)); 190 sizeof(procinfo));
191 191
192 ATF_CHECK_EQ(procinfo.cpi_version, 1); 192 ATF_CHECK_EQ(procinfo.cpi_version, 1);
193 ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 193 ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo));
194 ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 194 ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP);
195 ATF_CHECK_EQ(procinfo.cpi_pid, child); 195 ATF_CHECK_EQ(procinfo.cpi_pid, child);
196 ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 196 ATF_CHECK_EQ(procinfo.cpi_ppid, getpid());
197 ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 197 ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child));
198 ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 198 ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child));
199 ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 199 ATF_CHECK_EQ(procinfo.cpi_ruid, getuid());
200 ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 200 ATF_CHECK_EQ(procinfo.cpi_euid, geteuid());
201 ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 201 ATF_CHECK_EQ(procinfo.cpi_rgid, getgid());
202 ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 202 ATF_CHECK_EQ(procinfo.cpi_egid, getegid());
203 ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 203 ATF_CHECK_EQ(procinfo.cpi_nlwps, 1);
204 ATF_CHECK(procinfo.cpi_siglwp > 0); 204 ATF_CHECK(procinfo.cpi_siglwp > 0);
205 205
206 unlink(core_path); 206 unlink(core_path);
207 207
208 DPRINTF("Before resuming the child process where it left off and " 208 DPRINTF("Before resuming the child process where it left off and "
209 "without signal to be sent\n"); 209 "without signal to be sent\n");
 210#ifndef __powerpc__
210 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 211 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
 212#else
 213 /*
 214 * For powerpc, program counter is not automatically incremented by
 215 * a trap instruction. We cannot increment PC in the trap handler,
 216 * which breaks applications depending on this behavior, e.g., GDB.
 217 * Therefore, we need to pass (PC + 4) instead of (void *)1 (== PC)
 218 * to PT_CONTINUE here.
 219 */
 220 struct reg r;
 221
 222 SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
 223 SYSCALL_REQUIRE(
 224 ptrace(PT_CONTINUE, child, (void *)(r.pc + 4), 0) != -1);
 225#endif
211 226
212 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 227 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
213 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 228 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
214 229
215 validate_status_exited(status, exitval); 230 validate_status_exited(status, exitval);
216 231
217 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 232 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
218 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 233 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
219} 234}
220 235
221#define ATF_TP_ADD_TCS_PTRACE_WAIT_CORE() \ 236#define ATF_TP_ADD_TCS_PTRACE_WAIT_CORE() \
222 ATF_TP_ADD_TC(tp, core_dump_procinfo); 237 ATF_TP_ADD_TC(tp, core_dump_procinfo);