1 /*****************************************************************************
2 * Copyright (C) 2006-2009 by Michael Rieker, Jason Ansel, Kapil Arya, and *
3 * Gene Cooperman *
4 * mrieker@nii.net, jansel@csail.mit.edu, kapil@ccs.neu.edu, and *
5 * gene@ccs.neu.edu *
6 * *
7 * This file is part of the MTCP module of DMTCP (DMTCP:mtcp). *
8 * *
9 * DMTCP:mtcp is free software: you can redistribute it and/or *
10 * modify it under the terms of the GNU Lesser General Public License as *
11 * published by the Free Software Foundation, either version 3 of the *
12 * License, or (at your option) any later version. *
13 * *
14 * DMTCP:dmtcp/src is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU Lesser General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU Lesser General Public *
20 * License along with DMTCP:dmtcp/src. If not, see *
21 * <http://www.gnu.org/licenses/>. *
22 *****************************************************************************/
23
24 #include "mtcp_ptrace.h"
25 #include <pthread.h>
26 #include <semaphore.h>
27 #include <unistd.h>
28
29 #ifdef PTRACE
30
31 #include <stdio.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <sched.h>
38 #include <sys/user.h>
39 #include <sys/syscall.h>
40
41 #define GETTID() (int)syscall(SYS_gettid)
42
43 int only_once = 0;
44
45 const unsigned char DMTCP_SYS_sigreturn = 0x77;
46 const unsigned char DMTCP_SYS_rt_sigreturn = 0xad;
47
48 static const unsigned char linux_syscall[] = { 0xcd, 0x80 };
49
50 static __thread int is_waitpid_local = 0;
51 static __thread int is_ptrace_local = 0;
52 static __thread pid_t saved_pid = -1;
53 static __thread int saved_status = -1;
54 static __thread int has_status_and_pid = 0;
55
56 __thread pid_t setoptions_superior = -1;
57 __thread int is_ptrace_setoptions = FALSE;
58
59 static pthread_mutex_t ptrace_pairs_mutex = PTHREAD_MUTEX_INITIALIZER;
60
61 struct ckpt_thread {
62 pid_t pid;
63 pid_t tid;
64 };
65
66 sem_t ptrace_read_pairs_sem;
67 int init_ptrace_read_pairs_sem = 0;
68
69 sem_t __sem;
70 int init__sem = 0;
71
72 char ptrace_shared_file[MAXPATHLEN];
73 char ptrace_setoptions_file[MAXPATHLEN];
74 char checkpoint_threads_file[MAXPATHLEN];
75
76 int has_ptrace_file = 0;
77 pid_t delete_ptrace_leader = -1;
78 int has_setoptions_file = 0;
79 pid_t delete_setoptions_leader = -1;
80 int has_checkpoint_file = 0;
81 pid_t delete_checkpoint_leader = -1;
82
83 struct ptrace_tid_pairs ptrace_pairs[MAX_PTRACE_PAIRS_COUNT];
84 int ptrace_pairs_count = 0;
85 int init_ptrace_pairs = 0;
86
87 /***************************************************************************/
88 /* THIS CODE MUST BE CHANGED TO CHECK TO SEE IF THE USER CREATES EVEN MORE */
89 /* THREADS. */
90 /***************************************************************************/
91 #define MAX_CKPT_THREADS 100
92 static struct ckpt_thread ckpt_threads[MAX_CKPT_THREADS];
93 static int ckpt_threads_count = 0;
94
95 static void have_file(pid_t pid);
96
97 static int is_checkpoint_thread (pid_t tid);
98
99 static int ptrace_detach_ckpthread(pid_t tgid, pid_t tid, pid_t supid);
100
101 static void sort_ptrace_pairs ();
102
103 static void print_ptrace_pairs ();
104
105 static void reset_ptrace_pairs_entry ( int i );
106
107 void check_size_for_ptrace_file (const char *file) {
108 struct stat buf;
109 if (!stat (file, &buf)) {
110 mtcp_printf ("WARNING: %s has %d bytes.\n", file, buf.st_size);
111 } else {
112 if (errno != ENOENT) {
113 mtcp_printf ("WARNING: stat failed for %s with an error different than ENOENT.\n",
114 ptrace_shared_file);
115 }
116 }
117 }
118
119
120 void init_thread_local()
121 {
122 is_waitpid_local = 0; // no crash on pre-access
123 is_ptrace_local = 0; // no crash on pre-access
124 saved_pid = -1; // no crash on pre-access
125 saved_status = -1; // no crash on pre-access
126 has_status_and_pid = 0; // crash
127
128 setoptions_superior = -1;
129 is_ptrace_setoptions = FALSE;
130 }
131
132
133 /* FIXME: BAD FUNCTION NAME: readall(..., ..., count) would guarantee
134 * to read 'count' characters. This reads zero or more characters
135 * but does EAGAIN/EINTR processing so that the caller doesn't need to do it.
136 * Maybe a name like: read_no_error() ?
137 */
138 ssize_t readall(int fd, void *buf, size_t count)
139 {
140 int rc;
141 do
142 rc = read(fd, buf, count);
143 while (rc == -1 && (errno == EAGAIN || errno == EINTR));
144 if (rc == -1) { /* if not harmless error */
145 mtcp_printf("readall: Internal error\n");
146 mtcp_abort();
147 }
148 return rc; /* else rc >= 0; success */
149 }
150
151 void delete_file (int file, int delete_leader, int has_file)
152 {
153 if ((delete_leader == GETTID()) && has_file) {
154 switch (file) {
155 case 0: {
156 if (unlink(ptrace_shared_file) == -1 && errno != ENOENT) {
157 mtcp_printf("delete_file: unlink failed: %s\n",
158 strerror(errno));
159 mtcp_abort();
160 }
161 break;
162 }
163 case 1: {
164 if (unlink(ptrace_setoptions_file) == -1 && errno != ENOENT) {
165 mtcp_printf("delete_file: unlink failed: %s\n",
166 strerror(errno));
167 mtcp_abort();
168 }
169 break;
170 }
171 case 2: {
172 if (unlink(checkpoint_threads_file) == -1 && errno != ENOENT) {
173 mtcp_printf("delete_file: unlink failed: %s\n",
174 strerror(errno));
175 mtcp_abort();
176 }
177 break;
178 }
179 default: {
180 mtcp_printf ("delete_file: unknown option\n");
181 }
182 }
183 }
184 }
185
186 void ptrace_remove_notexisted()
187 {
188 int i;
189 struct ptrace_tid_pairs temp;
190
191 DPRINTF(("<<<<<<<<<<< start ptrace_remove_notexisted %d\n", GETTID()));
192
193 for (i = 0; i < ptrace_pairs_count; i++) {
194 int tid = ptrace_pairs[i].inferior;
195 char pstate = procfs_state(tid);
196 DPRINTF(("checking status of %d = %c\n",tid,pstate));
197 if( pstate == 0) {
198 // process not exist
199 if ( i != (ptrace_pairs_count - 1)) {
200 temp = ptrace_pairs[i];
201 ptrace_pairs[i] = ptrace_pairs[ptrace_pairs_count - 1];
202 ptrace_pairs[ptrace_pairs_count - 1] = temp;
203 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
204 i--;
205 ptrace_pairs_count--;
206 }
207 else {
208 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
209 ptrace_pairs_count --;
210 break;
211 }
212 }
213 }
214
215 print_ptrace_pairs ();
216 DPRINTF((">>>>>>>>>>> done ptrace_remove_notexisted %d\n", GETTID()));
217 }
218
219 void ptrace_attach_threads(int isRestart)
220 {
221 pid_t superior;
222 pid_t inferior;
223 int last_command;
224 int singlestep_waited_on;
225 struct user_regs_struct regs;
226 long peekdata;
227 long low, upp;
228 int status;
229 unsigned long addr;
230 unsigned long int eflags;
231 int i;
232
233 DPRINTF(("attach started %d\n", GETTID()));
234
235 /*
236 for (i = 0; i < ptrace_pairs_count; i++) {
237 mtcp_printf("tid = %d superior = %d inferior = %d last_command = %d\n", GETTID(), ptrace_pairs[i].superior, ptrace_pairs[i].inferior, ptrace_pairs[i].last_command);
238 }
239 */
240 for (i = 0; i < ptrace_pairs_count; i++) {
241
242 superior = ptrace_pairs[i].superior;
243 inferior = ptrace_pairs[i].inferior;
244 last_command = ptrace_pairs[i].last_command;
245 singlestep_waited_on = ptrace_pairs[i].singlestep_waited_on;
246
247 char inferior_st = ptrace_pairs[i].inferior_st;
248
249 // kill(inferior,0);
250 if (superior == GETTID()) {
251
252 DPRINTF (("(attach) tid = %d superior = %d inferior = %d\n",
253 GETTID(), (int)superior, (int)inferior));
254 // we must make sure the inferior process was created
255
256 sem_wait( &__sem);
257 if (only_once == 0) {
258 have_file (superior);
259 only_once = 1;
260 }
261 sem_post( &__sem);
262 if( is_checkpoint_thread(inferior)) {
263 have_file (inferior);
264 DPRINTF(("ptrace_attach_threads: attach to checkpoint thread: %d\n",inferior));
265 //sleep(5);
266 is_ptrace_local = 1;
267 if (ptrace(PTRACE_ATTACH, inferior, 0, 0) == -1) {
268 DPRINTF(("PTRACE_ATTACH failed for parent = %d child = %d\n", (int)superior, (int)inferior));
269 perror("ptrace_attach_threads: PTRACE_ATTACH for CKPT failed");
270 while(1);
271 mtcp_abort();
272 }
273 is_waitpid_local = 1;
274 if (waitpid(inferior, &status, __WCLONE) == -1) {
275 perror("ptrace_attach_threads: waitpid for ckpt failed\n");
276 mtcp_abort();
277 }
278 if (WIFEXITED(status)) {
279 DPRINTF(("The reason for ckpt child death was %d\n",WEXITSTATUS(status)));
280 }else if(WIFSIGNALED(status)) {
281 DPRINTF(("The reason for ckpt child death was signal %d\n",WTERMSIG(status)));
282 }
283
284 DPRINTF(("ptrace_attach_threads: preCheckpoint state = %c\n",inferior_st));
285 if( inferior_st != 'T' ){
286 is_ptrace_local = 1;
287 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
288 perror("ptrace_attach_threads: PTRACE_CONT failed");
289 mtcp_abort();
290 }
291 } continue;
292 }
293
294
295 is_ptrace_local = 1;
296 if (ptrace(PTRACE_ATTACH, inferior, 0, 0) == -1) {
297 mtcp_printf("PTRACE_ATTACH failed for parent = %d child = %d\n", (int)superior, (int)inferior);
298 perror("ptrace_attach_threads: PTRACE_ATTACH failed");
299 mtcp_abort();
300 }
301 create_file (inferior);
302 while(1) {
303 // mtcp_printf("new iter for sup=%d, inf=%d\n",superior,inferior);
304 is_waitpid_local = 1;
305 if( waitpid(inferior, &status, 0 ) == -1) {
306 is_waitpid_local = 1;
307 if( waitpid(inferior, &status, __WCLONE ) == -1) {
308 while(1);
309 perror("ptrace_attach_threads: waitpid failed\n");
310 mtcp_abort();
311 }
312 }
313 if (WIFEXITED(status)) {
314 DPRINTF(("The reason for childs death was %d\n",WEXITSTATUS(status)));
315 }else if(WIFSIGNALED(status)) {
316 DPRINTF(("The reason for child's death was signal %d\n",WTERMSIG(status)));
317 }
318
319 if (ptrace(PTRACE_GETREGS, inferior, 0, ®s) < 0) {
320 perror("ptrace_attach_threads: PTRACE_GETREGS failed");
321 mtcp_abort();
322 }
323 #ifdef __x86_64__
324 peekdata = ptrace(PTRACE_PEEKDATA, inferior, regs.rip, 0);
325 #else
326 peekdata = ptrace(PTRACE_PEEKDATA, inferior, regs.eip, 0);
327 #endif
328 low = peekdata & 0xff;
329 peekdata >>=8;
330 upp = peekdata & 0xff;
331
332 #ifdef __x86_64__
333 if ((low == 0xf) && (upp == 0x05) && (regs.rax == 0xf)) {
334 /* This code is yet to be written */
335 if ( isRestart ) {
336 if (last_command == PTRACE_SINGLESTEP_COMMAND ) {
337 if (regs.eax == DMTCP_SYS_sigreturn) {
338 addr = regs.esp;
339 }
340 else {
341 DPRINTF(("SYS_RT_SIGRETURN\n"));
342 //UNTESTED -> TODO; gdb very unclear
343 addr = regs.esp + 8;
344 addr = ptrace(PTRACE_PEEKDATA, inferior, addr, 0);
345 addr += 20;
346 }
347 addr += EFLAGS_OFFSET;
348 errno = 0;
349 if ((eflags = ptrace(PTRACE_PEEKDATA, inferior, (void *)addr, 0)) < 0) {
350 if (errno != 0) {
351 perror ("ptrace_attach_threads: PTRACE_PEEKDATA failed");
352 mtcp_abort ();
353 }
354 }
355 eflags |= 0x0100;
356 printf("inferior = %d addr = %ld eflags = %ld \n", inferior, addr, eflags);
357 if (ptrace(PTRACE_POKEDATA, inferior, addr, eflags) < 0) {
358 perror("ptrace_attach_threads: PTRACE_POKEDATA failed");
359 mtcp_abort();
360 }
361 }
362 else if (inferior_st != 'T' ) {
363 /*
364 TODO: remove in future as GROUP restore becames stable
365 - Artem
366 if (getsid(inferior) == getsid(superior)) {
367 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
368 {
369 perror("ptrace_attach_threads: tcsetpgrp failed");
370 mtcp_abort();
371 }
372 }
373 */
374 is_ptrace_local = 1;
375 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
376 perror("ptrace_attach_threads: PTRACE_CONT failed");
377 mtcp_abort();
378 }
379 }
380 } else {
381 if (inferior_st != 'T')
382 {
383 if (getsid(inferior) == getsid(superior)) {
384 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
385 {
386 perror("ptrace_attach_threads: tcsetpgrp failed");
387 mtcp_abort();
388 }
389 }
390 is_ptrace_local = 1;
391 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
392 perror("ptrace_attach_threads: PTRACE_CONT failed");
393 mtcp_abort();
394 }
395 }
396 }
397
398 if (inferior_st == 'T') {
399 /* this is needed because we are hitting the same breakpoint
400 twice if we were ckpt at a breakpoint
401 info breakpoint was giving incorrect values
402 */
403 is_ptrace_local = 1;
404 if (ptrace(PTRACE_SINGLESTEP, inferior, 0, 0) < 0) {
405 perror("ptrace_attach_threads: PTRACE_SINGLESTEP failed");
406 mtcp_abort();
407 }
408 is_waitpid_local = 1;
409 if( waitpid(inferior, &status, 0 ) == -1) {
410 is_waitpid_local = 1;
411 if( waitpid(inferior, &status, __WCLONE ) == -1) {
412 while(1);
413 perror("ptrace_attach_threads: waitpid failed\n");
414 mtcp_abort();
415 }
416 }
417 }
418 break;
419 }
420 #else
421 if (((low == 0xcd) && (upp == 0x80)) &&
422 ((regs.eax == DMTCP_SYS_sigreturn) ||
423 (regs.eax == DMTCP_SYS_rt_sigreturn))) {
424 if ( isRestart ) {
425 if (last_command == PTRACE_SINGLESTEP_COMMAND ) {
426 if (regs.eax == DMTCP_SYS_sigreturn) {
427 addr = regs.esp;
428 }
429 else {
430 DPRINTF(("SYS_RT_SIGRETURN\n"));
431 //UNTESTED -> TODO; gdb very unclear
432 addr = regs.esp + 8;
433 addr = ptrace(PTRACE_PEEKDATA, inferior, addr, 0);
434 addr += 20;
435 }
436 addr += EFLAGS_OFFSET;
437 errno = 0;
438 if ((eflags = ptrace(PTRACE_PEEKDATA, inferior, (void *)addr, 0)) < 0) {
439 if (errno != 0) {
440 perror ("ptrace_attach_threads: PTRACE_PEEKDATA failed");
441 mtcp_abort ();
442 }
443 }
444 eflags |= 0x0100;
445 if (ptrace(PTRACE_POKEDATA, inferior, (void *)addr, eflags) < 0) {
446 perror("ptrace_attach_threads: PTRACE_POKEDATA failed");
447 mtcp_abort();
448 }
449 } else if (inferior_st != 'T') {
450 if (getsid(inferior) == getsid(superior)) {
451 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
452 {
453 perror("ptrace_attach_threads: tcsetpgrp failed");
454 mtcp_abort();
455 }
456 }
457 is_ptrace_local = 1;
458 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
459 perror("ptrace_attach_threads: PTRACE_CONT failed");
460 mtcp_abort();
461 }
462 }
463 } else {
464 if (inferior_st != 'T') {
465 if (getsid(inferior) == getsid(superior)) {
466 if ( tcsetpgrp(STDIN_FILENO, inferior) == -1)
467 {
468 perror("ptrace_attach_threads: tcsetpgrp failed");
469 mtcp_abort();
470 }
471 }
472 is_ptrace_local = 1;
473 if (ptrace(PTRACE_CONT, inferior, 0, 0) < 0) {
474 perror("ptrace_attach_threads: PTRACE_CONT failed");
475 mtcp_abort();
476 }
477 }
478 }
479
480
481 if (inferior_st == 'T') {
482 /* this is needed because we are hitting the same breakpoint
483 twice if we were ckpt at a breakpoint
484 info breakpoint was giving incorrect values
485 */
486 is_ptrace_local = 1;
487 if (ptrace(PTRACE_SINGLESTEP, inferior, 0, 0) < 0) {
488 perror("ptrace_attach_threads: PTRACE_SINGLESTEP failed");
489 mtcp_abort();
490 }
491 is_waitpid_local = 1;
492 if( waitpid(inferior, &status, 0 ) == -1) {
493 is_waitpid_local = 1;
494 if( waitpid(inferior, &status, __WCLONE ) == -1) {
495 while(1);
496 perror("ptrace_attach_threads: waitpid failed\n");
497 mtcp_abort();
498 }
499 }
500 }
501 break;
502 }
503 #endif
504 is_ptrace_local = 1;
505 if (ptrace(PTRACE_SINGLESTEP, inferior, 0, 0) < 0) {
506 perror("ptrace_attach_threads: PTRACE_SINGLESTEP failed");
507 mtcp_abort();
508 }
509 }
510 }
511 else if (inferior == GETTID()) {
512
513 create_file (superior);
514 have_file (inferior);
515 }
516 }
517 DPRINTF(("ptrace_attach_threads: finished for %d\n", GETTID()));
518 }
519
520 void ptrace_detach_checkpoint_threads ()
521 {
522 int i,ret;
523 pid_t tgid;
524
525 // Release only checkpoint threads
526 for (i = 0; i < ptrace_pairs_count; i++) {
527 int tid = ptrace_pairs[i].inferior;
528 int sup = ptrace_pairs[i].superior;
529 tgid = is_checkpoint_thread (tid);
530 if ((sup == GETTID()) && tgid ) {
531 DPRINTF(("ptrace_detach_checkpoint_threads: ptrace_detach_ckpthread(%d,%d,%d)\n",
532 tgid,tid,sup));
533 if( ret = ptrace_detach_ckpthread(tgid,tid,sup) ){
534 if( ret == -ENOENT ){
535 DPRINTF(("%s: process not exist %d\n",__FUNCTION__,tid));
536 }
537 mtcp_abort();
538 }
539 }
540 }
541 DPRINTF((">>>>>>>>> done ptrace_detach_checkpoint_threads %d\n", GETTID()));
542 }
543
544 void ptrace_detach_user_threads ()
545 {
546 int i;
547 int status = 0;
548
549 for(i = 0; i < ptrace_pairs_count; i++) {
550 /*
551 mtcp_printf("tid = %d superior = %d inferior = %d last_command = %d\n", GETTID(), ptrace_pairs[i].superior,
552 ptrace_pairs[i].inferior, ptrace_pairs[i].last_command);
553 */
554 if( is_checkpoint_thread(ptrace_pairs[i].inferior) ){
555 DPRINTF(("ptrace_detach_user_threads: SKIP checkpoint thread %d\n",ptrace_pairs[i].inferior));
556 continue;
557 }
558
559 if( ptrace_pairs[i].superior == GETTID()) {
560 char pstate;
561 // required for all user threads to get SIGUSR2 from their checkpoint thread
562 // TODO: to be removed by waiting for the signal to have been delivered
563 // sleep(PTRACE_SLEEP_INTERVAL);
564 int tid = ptrace_pairs[i].inferior, tpid;
565 DPRINTF(("start waiting on %d\n",tid));
566
567 // Check if status of this thread already read by debugger
568 pstate = procfs_state(tid);
569 DPRINTF(("procfs_state(%d) = %c\n",tid,pstate));
570 if( pstate == 0){
571 // process not exist
572 mtcp_printf("%s: process not exist %d\n",__FUNCTION__,tid);
573 mtcp_abort();
574 } else if( pstate == 'T'){
575 // There can be posibility that GDB (or other) reads status of this
576 // thread before us. So we will block. We don't want that.
577 // Read anyway but without hang
578 DPRINTF(("!!!! Process already stopped !!!!\n"));
579
580 is_waitpid_local = 1;
581 tpid = waitpid (tid, &status, WNOHANG);
582 if(tpid == -1 && errno == ECHILD){
583 DPRINTF(("Check cloned process\n"));
584 // Try again with __WCLONE to check cloned processes.
585 is_waitpid_local = 1;
586 if( (tpid = waitpid (tid, &status, __WCLONE | WNOHANG ) ) == -1 ){
587 DPRINTF(("ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): : %s\n",
588 strerror(errno)));
589 }
590 }
591
592 DPRINTF(("tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,signal=%d\n",
593 tid,tpid,WIFSTOPPED(status),WSTOPSIG(status) == SIGSTOP,WSTOPSIG(status)));
594 }else{
595 // Process not in stopped state. We are in signal handler of GDB thread which waits for status change
596 // for this process. Now it is safe to call blocking waitpid.
597
598 DPRINTF(("!!!! Process is not stopped yet !!!!\n"));
599 is_waitpid_local = 1;
600 tpid = waitpid (tid, &status, 0);
601 if(tpid == -1 && errno == ECHILD){
602 DPRINTF(("Check cloned process\n"));
603 // Try again with __WCLONE to check cloned processes.
604 is_waitpid_local = 1;
605 if( (tpid = waitpid (tid, &status, __WCLONE ) ) == -1 ){
606 mtcp_printf("ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n",
607 strerror(errno));
608 }
609 }
610 DPRINTF(("tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,signal=%d\n",
611 tid,tpid,WIFSTOPPED(status),WSTOPSIG(status) == SIGSTOP,WSTOPSIG(status)));
612 if(WIFSTOPPED(status)) {
613 if (WSTOPSIG(status) == MTCP_DEFAULT_SIGNAL)
614 DPRINTF(("user thread %d was stopped by the delivery of MTCP_DEFAULT_SIGNAL\n",tid)); else{ //we should never get here
615 DPRINTF(("user thread %d was stopped by the delivery of %d\n", tid, WSTOPSIG(status))
616 );
617 }
618 }else //we should never end up here
619 DPRINTF(("user thread %d was NOT stopped by a signal\n", ptrace_pairs[i].inferior));
620 }
621
622 if (( ptrace_pairs[i].last_command == PTRACE_SINGLESTEP_COMMAND ) &&
623 ( ptrace_pairs[i].singlestep_waited_on == FALSE )) {
624 //is_waitpid_local = 1;
625 has_status_and_pid = 1;
626 saved_status = status;
627 DPRINTF(("+++++++++++++++++++++++++ptrace_detach_user_threads: AFTER WAITPID %d\n",
628 status));
629 ptrace_pairs[i].singlestep_waited_on = TRUE;
630 ptrace_pairs[i].last_command = PTRACE_UNSPECIFIED_COMMAND;
631 }
632
633 DPRINTF(("tid = %d detaching superior = %d from inferior = %d\n",
634 GETTID(), (int)ptrace_pairs[i].superior, (int)ptrace_pairs[i].inferior));
635 have_file (ptrace_pairs[i].inferior);
636 is_ptrace_local = 1;
637 if (ptrace(PTRACE_DETACH, ptrace_pairs[i].inferior, 0, MTCP_DEFAULT_SIGNAL) == -1) {
638 DPRINTF(("ptrace_detach_user_threads: parent = %d child = %d\n",
639 (int)ptrace_pairs[i].superior,
640 (int)ptrace_pairs[i].inferior));
641 DPRINTF(("ptrace_detach_user_threads: PTRACE_DETACH failed with error=%d",errno));
642 }
643 }
644 }
645 DPRINTF((">>>>>>>>> done ptrace_detach_user_threads %d\n", GETTID()));
646 }
647
648 void ptrace_lock_inferiors()
649 {
650 char file[SYNCHRONIZATIONPATHLEN];
651 snprintf(file,SYNCHRONIZATIONPATHLEN,"%s/dmtcp_ptrace_unlocked.%d",dir,GETTID());
652 unlink(file);
653 }
654
655 void ptrace_unlock_inferiors()
656 {
657 char file[SYNCHRONIZATIONPATHLEN];
658 int fd;
659 snprintf(file, SYNCHRONIZATIONPATHLEN, "%s/dmtcp_ptrace_unlocked.%d",dir,GETTID());
660 fd = creat(file,0644);
661 if( fd < 0 ){
662 mtcp_printf("init_lock: Error while creating lock file: %s\n",
663 strerror(errno));
664 mtcp_abort();
665 }
666 close(fd);
667 }
668
669 void create_file(pid_t pid)
670 {
671 char str[SYNCHRONIZATIONPATHLEN];
672 int fd;
673
674 memset(str, 0, SYNCHRONIZATIONPATHLEN);
|
Event secure_coding: |
[VERY RISKY]. Using "sprintf" can cause a buffer overflow when done incorrectly. Because sprintf() assumes an arbitrarily long string, callers must be careful not to overflow the actual space of the destination. Use snprintf() instead, or correct precision specifiers. |
675 sprintf(str, "%s/%d", dir, pid);
676
677 fd = open(str, O_CREAT|O_APPEND|O_WRONLY, 0644);
678 if (fd == -1) {
679 mtcp_printf("create_file: Error opening file %s\n: %s\n",
680 str, strerror(errno));
681 mtcp_abort();
682 }
683 if ( close(fd) != 0 ) {
684 mtcp_printf("create_file: Error closing file\n: %s\n",
685 strerror(errno));
686 mtcp_abort();
687 }
688 }
689
690 static void have_file(pid_t pid)
691 {
692 char str[SYNCHRONIZATIONPATHLEN];
693 int fd;
694
695 memset(str, 0, SYNCHRONIZATIONPATHLEN);
696 sprintf(str, "%s/%d", dir, pid);
697 while(1) {
698 fd = open(str, O_RDONLY);
699 if (fd != -1) {
700 if (close(fd) != 0) {
701 mtcp_printf("have_file: Error closing file: %s\n",
702 strerror(errno));
703 mtcp_abort();
704 }
705 if (unlink(str) == -1) {
706 mtcp_printf("have_file: unlink failed: %s\n",
707 strerror(errno));
708 mtcp_abort();
709 }
710 break;
711 }
712 usleep(100);
713 }
714 }
715
716 void ptrace_wait4(pid_t pid)
717 { char file[SYNCHRONIZATIONPATHLEN];
718 struct stat buf;
719 snprintf(file,SYNCHRONIZATIONPATHLEN,"%s/dmtcp_ptrace_unlocked.%d",dir,pid);
720
721 DPRINTF(("%d: Start waiting for superior\n",GETTID()));
722 while( stat(file,&buf) < 0 ){
723 struct timespec ts;
724 DPRINTF(("%d: Superior is not ready\n",GETTID()));
725 ts.tv_sec = 0;
726 ts.tv_nsec = 100000000;
727 if( errno != ENOENT ){
728 mtcp_printf("prtrace_wait4: Unexpected error in stat: %d\n",errno);
729 mtcp_abort();
730 }
731 nanosleep(&ts,NULL);
732 }
733 DPRINTF(("%d: Superior unlocked us\n",GETTID()));
734 }
735
736 /*************************************************************************/
737 /* Utilities for ptrace code */
738 /* IF ALL THESE FUNCTIONS MUST EXIST INSIDE mtcp.c AND NOT IN SEAPARATE */
739 /* FILE, THEN WE MUST RENAME THEM ALL WITH SOME PREFIX LIKE pt_ */
740 /* (DIFFERENT NAMESPACE FROM REST OF FILE). IF WE CAN MOVE THEM TO */
741 /* A DIFFERENT FILE, THAT WOULD BE EVEN BETTER. - Gene */
742 /*************************************************************************/
743 static void reset_ptrace_pairs_entry ( int i )
744 {
745 ptrace_pairs[i].last_command = PTRACE_UNSPECIFIED_COMMAND;
746 ptrace_pairs[i].singlestep_waited_on = FALSE;
747 ptrace_pairs[i].free = TRUE;
748 ptrace_pairs[i].inferior_st = 'u';
749 }
750
751 static void move_last_ptrace_pairs_entry_to_i ( int i )
752 {
753 ptrace_pairs[i].superior = ptrace_pairs[ptrace_pairs_count-1].superior;
754 ptrace_pairs[i].inferior = ptrace_pairs[ptrace_pairs_count-1].inferior;
755 ptrace_pairs[i].last_command = ptrace_pairs[ptrace_pairs_count-1].last_command;
756 ptrace_pairs[i].singlestep_waited_on = ptrace_pairs[ptrace_pairs_count-1].singlestep_waited_on;
757 ptrace_pairs[i].free = ptrace_pairs[ptrace_pairs_count-1].free;
758 ptrace_pairs[i].inferior_st = ptrace_pairs[ptrace_pairs_count-1].inferior_st;
759 }
760
761 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
762 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
763 * WE'RE A GUEST IN HIS PROCESS. - Gene
764 */
765 void remove_from_ptrace_pairs ( pid_t superior, pid_t inferior )
766 {
767 int i;
768 for (i = 0; i < ptrace_pairs_count; i++) {
769 if ((ptrace_pairs[i].superior == superior) && (ptrace_pairs[i].inferior == inferior)) {
770 break;
771 }
772 }
773 if (i == ptrace_pairs_count) return;
774 if (i != (ptrace_pairs_count-1)) {
775 pthread_mutex_lock(&ptrace_pairs_mutex);
776 move_last_ptrace_pairs_entry_to_i(i);
777 reset_ptrace_pairs_entry(ptrace_pairs_count-1);
778 ptrace_pairs_count--;
779 pthread_mutex_unlock(&ptrace_pairs_mutex);
780 }
781 else {
782 pthread_mutex_lock(&ptrace_pairs_mutex);
783 reset_ptrace_pairs_entry(i);
784 ptrace_pairs_count--;
785 pthread_mutex_unlock(&ptrace_pairs_mutex);
786 }
787 }
788
789 static int is_in_ptrace_pairs ( pid_t superior, pid_t inferior )
790 {
791 int i;
792 for (i = 0; i < ptrace_pairs_count; i++) {
793 if ((ptrace_pairs[i].superior == superior) && (ptrace_pairs[i].inferior == inferior)) return i;
794 }
795 return -1;
796 }
797
798 static void add_to_ptrace_pairs ( pid_t superior, pid_t inferior, int last_command, int singlestep_waited_on )
799 {
800 struct ptrace_tid_pairs new_pair;
801
802 new_pair.superior = superior;
803 new_pair.inferior = inferior;
804 new_pair.last_command = last_command;
805 new_pair.singlestep_waited_on = singlestep_waited_on;
806 new_pair.free = FALSE;
807 new_pair.inferior_st = 'u';
808 new_pair.eligible_for_deletion = TRUE;
809
810 pthread_mutex_lock(&ptrace_pairs_mutex);
811 ptrace_pairs[ptrace_pairs_count] = new_pair;
812 ptrace_pairs_count++;
813 pthread_mutex_unlock(&ptrace_pairs_mutex);
814 }
815
816 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
817 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
818 * WE'RE A GUEST IN HIS PROCESS. - Gene
819 */
820 void handle_command ( pid_t superior, pid_t inferior, int last_command )
821 {
822 int index = is_in_ptrace_pairs ( superior, inferior );
823 if ( index >= 0 ) {
824 ptrace_pairs[index].last_command = last_command;
825 if ( last_command == PTRACE_SINGLESTEP_COMMAND ) ptrace_pairs[index].singlestep_waited_on = FALSE;
826 }
827 else {
828 /* not in the ptrace pairs array; reason: inferior did an PTRACE_TRACEME and now the superior is issuing commands */
829 add_to_ptrace_pairs( superior, inferior, last_command, FALSE );
830 }
831 }
832
833 enum {
834 SORT_BY_SUPERIOR = 0,
835 SORT_BY_INFERIOR
836 };
837
838 static int find_slot (int seed) {
839 int i;
840 pid_t inferior;
841 for (i = seed; i >= 0; i--) {
842 inferior = ptrace_pairs[i].inferior;
843 if (!is_checkpoint_thread(inferior))
844 return i;
845 }
846 return -1;
847 }
848
849 /* This function moves all checkpoint threads at the end of ptrace_pairs array.
850 * It returns the index in ptrace_pairs array where ckpt threads are located. */
851 static int move_ckpt_threads_towards_end () {
852 int i;
853 struct ptrace_tid_pairs temp;
854 pid_t superior;
855 pid_t inferior;
856 int limit = ptrace_pairs_count;
857 int ckpt_threads = 0;
858
859 int slot = find_slot(ptrace_pairs_count - 1);
860 for (i = 0; i < limit; i++) {
861 inferior = ptrace_pairs[i].inferior;
862 if (is_checkpoint_thread(inferior)) {
863 ckpt_threads++;
864 if (slot > i) {
865 temp = ptrace_pairs[i];
866 ptrace_pairs[i] = ptrace_pairs[slot];
867 ptrace_pairs[slot] = temp;
868 limit = slot;
869 slot = find_slot(slot - 1);
870 }
871 }
872 }
873 return ckpt_threads;
874 }
875
876 static pid_t get_pid_by_key (int key, int index) {
877 if (key == SORT_BY_SUPERIOR)
878 return ptrace_pairs[index].superior;
879 else if (key == SORT_BY_INFERIOR)
880 return ptrace_pairs[index].inferior;
881 return -1;
882 }
883
884 static void sort_ptrace_pairs_by_key (int key, int begin, int end) {
885 int i, j;
886 pid_t upper_pid;
887 pid_t inner_pid;
888 pid_t temp_pid;
889 struct ptrace_tid_pairs temp;
890 for (i = begin; i < (end - 1); i++) {
891 upper_pid = get_pid_by_key (key, i);
892 for (j = i + 1; j < end; j++) {
893 inner_pid = get_pid_by_key (key, j);
894 if (upper_pid < inner_pid) {
895 temp = ptrace_pairs[i];
896 ptrace_pairs[i] = ptrace_pairs[j];
897 ptrace_pairs[j] = temp;
898 temp_pid = upper_pid;
899 upper_pid = inner_pid;
900 inner_pid = temp_pid;
901 }
902 }
903 }
904 }
905
906 static void sort_ptrace_pairs_within_limit (int begin, int end) {
907 sort_ptrace_pairs_by_key (SORT_BY_SUPERIOR, begin, end);
908 int ref_superior;
909 int superior;
910 int inferior;
911 int start = begin;
912 int i;
913 ref_superior = ptrace_pairs[0].superior;
914 for (i = (start + 1); i < end; i++) {
915 superior = ptrace_pairs[i].superior;
916 if (superior != ref_superior) {
917 sort_ptrace_pairs_by_key (SORT_BY_INFERIOR, start, i);
918 ref_superior = superior;
919 start = i;
920 }
921 }
922 sort_ptrace_pairs_by_key (SORT_BY_INFERIOR, start, end);
923 }
924
925 static void sort_ptrace_pairs () {
926 if (ptrace_pairs_count <= 1)
927 return;
928 int limit = ptrace_pairs_count - move_ckpt_threads_towards_end ();
929 /* sort all non-checkpoint threads*/
930 sort_ptrace_pairs_within_limit (0, limit);
931 /* sort all checkpoint threads */
932 sort_ptrace_pairs_within_limit (limit, ptrace_pairs_count);
933 }
934
935 static void print_ptrace_pairs ()
936 {
937 int i;
938 DPRINTF(("\n\n"));
939 for ( i = 0; i < ptrace_pairs_count; i++ )
940 DPRINTF(("tid = %d superior = %d inferior = %d \n",
941 GETTID(), (int)ptrace_pairs[i].superior, (int)ptrace_pairs[i].inferior));
942 DPRINTF(("tid = %d ptrace_pairs_count = %d \n", GETTID(), ptrace_pairs_count));
943 DPRINTF(("\n\n"));
944 }
945
946 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
947 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
948 * WE'RE A GUEST IN HIS PROCESS. - Gene
949 */
950
951
952 void write_info_to_file (int file, pid_t superior, pid_t inferior)
953 {
954 int fd;
955 struct flock lock;
956
957 switch (file) {
958 case 0: {
959 fd = open(ptrace_shared_file, O_CREAT|O_APPEND|O_WRONLY|O_FSYNC, 0644);
960 break;
961 }
962 case 1: {
963 fd = open(ptrace_setoptions_file, O_CREAT|O_APPEND|O_WRONLY|O_FSYNC, 0644);
964 break;
965 }
966 case 2: {
967 fd = open(checkpoint_threads_file, O_CREAT|O_APPEND|O_WRONLY|O_FSYNC, 0644);
968 break;
969 }
970 default: {
971 mtcp_printf ("write_info_to_file: unknown option\n");
972 return;
973 }
974 }
975
976 if (fd == -1) {
977 mtcp_printf("write_info_to_file: Error opening file\n: %s\n",
978 strerror(errno));
979 abort();
980 }
981
982 lock.l_type = F_WRLCK;
983 lock.l_whence = SEEK_CUR;
984 lock.l_start = 0;
985 lock.l_len = 0;
986 lock.l_pid = getpid();
987
988 if (fcntl(fd, F_GETLK, &lock ) == -1) {
989 mtcp_printf("write_info_to_file: Error acquiring lock: %s\n",
990 strerror(errno));
991 abort();
992 }
993
994 if (write(fd, &superior, sizeof(pid_t)) == -1) {
995 mtcp_printf("write_info_to_file: Error writing to file: %s\n",
996 strerror(errno));
997 abort();
998 }
999 if (write(fd, &inferior, sizeof(pid_t)) == -1) {
1000 mtcp_printf("write_info_to_file: Error writing to file: %s\n",
1001 strerror(errno));
1002 abort();
1003 }
1004
1005 lock.l_type = F_UNLCK;
1006 lock.l_whence = SEEK_CUR;
1007 lock.l_start = 0;
1008 lock.l_len = 0;
1009
1010 if (fcntl(fd, F_SETLK, &lock) == -1) {
1011 mtcp_printf("write_info_to_file: Error releasing lock: %s\n",
1012 strerror(errno));
1013 abort();
1014 }
1015 if (close(fd) != 0) {
1016 mtcp_printf("write_info_to_file: Error closing file: %s\n",
1017 strerror(errno));
1018 abort();
1019 }
1020 }
1021
1022 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1023 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1024 * WE'RE A GUEST IN HIS PROCESS. - Gene
1025 */
1026 void writeptraceinfo (pid_t superior, pid_t inferior)
1027 {
1028 int index = is_in_ptrace_pairs ( superior, inferior );
1029 if (index == -1 ) {
1030 write_info_to_file (0, superior, inferior);
1031 add_to_ptrace_pairs ( superior, inferior, PTRACE_UNSPECIFIED_COMMAND, FALSE );
1032 }
1033 }
1034
1035 /***********************************************************************
1036 * This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1037 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1038 * WE'RE A GUEST IN THE USER'S PROCESS. - Gene
1039 ***********************************************************************/
1040 void set_singlestep_waited_on ( pid_t superior, pid_t inferior,
1041 int value )
1042 {
1043 int index = is_in_ptrace_pairs ( superior, inferior );
1044 if (( index >= 0 ) && ( ptrace_pairs[index].last_command == PTRACE_SINGLESTEP_COMMAND ))
1045 ptrace_pairs[index].singlestep_waited_on = value;
1046 if (index >= 0)
1047 ptrace_pairs[index].last_command = PTRACE_UNSPECIFIED_COMMAND;
1048 }
1049
1050 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1051 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1052 * WE'RE A GUEST IN HIS PROCESS. - Gene
1053 */
1054 int get_is_waitpid_local ()
1055 {
1056 return is_waitpid_local;
1057 }
1058
1059 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1060 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1061 * WE'RE A GUEST IN HIS PROCESS. - Gene
1062 */
1063 int get_is_ptrace_local ()
1064 {
1065 return is_ptrace_local;
1066 }
1067
1068 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1069 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1070 * WE'RE A GUEST IN HIS PROCESS. - Gene
1071 */
1072 void unset_is_waitpid_local ()
1073 {
1074 is_waitpid_local = 0;
1075 }
1076
1077 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1078 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1079 * WE'RE A GUEST IN HIS PROCESS. - Gene
1080 */
1081 void unset_is_ptrace_local ()
1082 {
1083 is_ptrace_local = 0;
1084 }
1085
1086 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1087 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1088 * WE'RE A GUEST IN HIS PROCESS. - Gene
1089 */
1090 pid_t get_saved_pid ()
1091 {
1092 return saved_pid;
1093 }
1094
1095 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1096 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1097 * WE'RE A GUEST IN HIS PROCESS. - Gene
1098 */
1099 int get_saved_status ()
1100 {
1101 return saved_status;
1102 }
1103
1104 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1105 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1106 * WE'RE A GUEST IN HIS PROCESS. - Gene
1107 */
1108 int get_has_status_and_pid ()
1109 {
1110 return has_status_and_pid;
1111 }
1112
1113 /* This is called by DMTCP. BUT IT MUST THEN HAVE A PREFIX LIKE mtcp_
1114 * IN FRONT OF IT. WE DON'T WANT TO POLLUTE THE USER'S NAMESPACE.
1115 * WE'RE A GUEST IN HIS PROCESS. - Gene
1116 */
1117 void reset_pid_status ()
1118 {
1119 saved_pid = -1;
1120 saved_status = -1;
1121 has_status_and_pid = 0;
1122 }
1123
1124 static int is_alive (pid_t pid)
1125 {
1126 char str[20];
1127 int fd;
1128
1129 memset(str, 0, 20);
1130 sprintf(str, "/proc/%d/maps", pid);
1131
1132 fd = open(str, O_RDONLY);
1133 if (fd != -1) {
1134 if ( close(fd) != 0 ) {
1135 mtcp_printf("is_alive: Error closing file: %s\n",
1136 strerror(errno));
1137 mtcp_abort();
1138 }
1139 return 1;
1140 }
1141 return 0;
1142 }
1143
1144 static int is_in_ckpt_threads (pid_t pid)
1145 {
1146 int i;
1147 for (i = 0; i < ckpt_threads_count; i++) {
1148 if (ckpt_threads[i].pid == pid) return 1;
1149 }
1150 return 0;
1151 }
1152 static void print_ckpt_threads ()
1153 {
1154 int i;
1155 for (i = 0; i < ckpt_threads_count; i++)
1156 DPRINTF(("moa = %d pid = %d tid = %d \n",
1157 GETTID(), ckpt_threads[i].pid, ckpt_threads[i].tid));
1158 }
1159
1160 char procfs_state(int tid)
1161 {
1162 char name[64];
1163 char sbuf[256], *S, *tmp;
1164 char state;
1165 int num_read, fd;
1166
1167 sprintf(name,"/proc/%d/stat",tid);
1168 fd = open(name, O_RDONLY, 0);
1169 if( fd < 0 ){
1170 mtcp_printf("procfs_status: cannot open %s\n",name);
1171 return 0;
1172 }
1173 /* THIS CODE CAN'T WORK RELIABLY. SUPPOSE read() RETURNS 0,
1174 * OR -1 WITH EAGAIN OR EINTR? LOOK FOR EXAMPLES IN
1175 * mtcp_restart_nolibc.c:readfile() OR ELSEWHERE. - Gene
1176 */
1177 num_read = read(fd, sbuf, sizeof sbuf - 1);
1178 close(fd);
1179 if(num_read<=0) {
1180 return 0;
1181 }
1182 sbuf[num_read] = '\0';
1183
1184 S = strchr(sbuf, '(') + 1;
1185 tmp = strrchr(S, ')');
1186 S = tmp + 2; // skip ") "
1187
1188 /* YOU SEEM TO WANT S[0] HERE. WHY sscanf? ALSO WHY ARE WE USING
1189 * CAPS ("S") FOR VAR NAME? - Gene
1190 */
1191 sscanf(S, "%c", &state);
1192
1193 return state;
1194 }
1195
1196 void process_ptrace_info (pid_t *delete_ptrace_leader,
1197 int *has_ptrace_file,
1198 pid_t *delete_setoptions_leader, int *has_setoptions_file,
1199 pid_t *delete_checkpoint_leader, int *has_checkpoint_file)
1200 {
1201 int ptrace_fd = -1;
1202 siginfo_t infoop;
1203 int i;
1204 pid_t superior;
1205 pid_t inferior;
1206 int setoptions_fd = -1;
1207 struct ptrace_tid_pairs temp;
1208 int checkpoint_fd = -1;
1209 pid_t pid;
1210 pid_t tid;
1211 struct ckpt_thread ckpt_thread_temp;
1212
1213 DPRINTF((">>>>>>>>>>>>>>>>>>>>>>>>>>>>process_ptrace_info: thread = %d\n", GETTID()));
1214
1215 // TODO: consider that only checkpoint thread now runs this code
1216 // if (thread == motherofall) {
1217 // read the information from the ptrace file
1218 ptrace_fd = open(ptrace_shared_file, O_RDONLY);
1219 if (ptrace_fd != -1) {
1220 *has_ptrace_file = 1;
1221 while (readall(ptrace_fd, &superior, sizeof(pid_t)) > 0) {
1222 readall(ptrace_fd, &inferior, sizeof(pid_t));
1223 if ( is_in_ptrace_pairs(superior, inferior) == -1 ) {
1224 add_to_ptrace_pairs(superior, inferior, PTRACE_UNSPECIFIED_COMMAND, FALSE);
1225 }
1226 if (*delete_ptrace_leader < superior)
1227 *delete_ptrace_leader = superior;
1228 }
1229 if ( close(ptrace_fd) != 0 ) {
1230 mtcp_printf("process_ptrace_info: Error closing file. Error: %s\n", strerror(errno));
1231 mtcp_abort();
1232 }
1233
1234 /* delete all dead threads */
1235 for (i = 0; i < ptrace_pairs_count; i++) {
1236 if ((!is_alive(ptrace_pairs[i].superior) || !is_alive(ptrace_pairs[i].inferior))
1237 &&
1238 (ptrace_pairs[i].eligible_for_deletion == TRUE)) {
1239 if ( i != (ptrace_pairs_count - 1)) {
1240 temp = ptrace_pairs[i];
1241 ptrace_pairs[i] = ptrace_pairs[ptrace_pairs_count - 1];
1242 ptrace_pairs[ptrace_pairs_count - 1] = temp;
1243 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
1244 i--;
1245 ptrace_pairs_count --;
1246 }
1247 else {
1248 reset_ptrace_pairs_entry (ptrace_pairs_count - 1);
1249 ptrace_pairs_count --;
1250 break;
1251 }
1252 }
1253 }
1254
1255 /* none of the eligible for deletion entries can be deleted anymore */
1256 for (i = 0; i < ptrace_pairs_count; i++) {
1257 /* SHOULDN'T "=" BE REPLACED BY "==" IN IF CONDITION? - Gene */
1258 if (ptrace_pairs[i].eligible_for_deletion = TRUE)
1259 ptrace_pairs[i].eligible_for_deletion = FALSE;
1260 }
1261 }
1262 else mtcp_printf("process_ptrace_info: NO ptrace file\n");
1263
1264 // read the information from the setoptions file
1265 setoptions_fd = open(ptrace_setoptions_file, O_RDONLY);
1266 if (setoptions_fd != -1) {
1267 *has_setoptions_file = 1;
1268 while (readall(setoptions_fd, &superior, sizeof(pid_t)) > 0) {
1269 readall(setoptions_fd, &inferior, sizeof(pid_t));
1270 if (inferior == GETTID()) {
1271 setoptions_superior = superior;
1272 is_ptrace_setoptions = TRUE;
1273 }
1274 if (*delete_setoptions_leader < superior)
1275 *delete_setoptions_leader = superior;
1276 }
1277 if ( close(setoptions_fd) != 0 ) {
1278 mtcp_printf("process_ptrace_info: Error closing file: %s\n", strerror(errno));
1279 mtcp_abort();
1280 }
1281 }
1282 else mtcp_printf ("process_ptrace_info: NO setoptions file\n");
1283
1284 // read the information from the checkpoint threads file
1285 /* GDB specific code */
1286 checkpoint_fd = open(checkpoint_threads_file, O_RDONLY);
1287 if (checkpoint_fd != -1) {
1288 *has_checkpoint_file = 1;
1289 while (readall(checkpoint_fd, &pid, sizeof(pid_t)) > 0) {
1290 readall(checkpoint_fd, &tid, sizeof(pid_t));
1291 DPRINTF(("{%d} checkpoint threads: pid = %d tid = %d\n", GETTID(), pid, tid));
1292 if (is_alive(pid) && is_alive(tid)) {
1293 /* only the pid matters
1294 * for the first alive tid & pid, then tid is the ckpt of pid
1295 */
1296 if (!is_in_ckpt_threads(pid)) {
1297 ckpt_thread_temp.pid = pid;
1298 ckpt_thread_temp.tid = tid;
1299 ckpt_threads[ckpt_threads_count] = ckpt_thread_temp;
1300 ckpt_threads_count++;
1301 }
1302 if (*delete_checkpoint_leader < pid)
1303 *delete_checkpoint_leader = pid;
1304 }
1305 }
1306 if ( close(checkpoint_fd) != 0 ) {
1307 mtcp_printf("process_ptrace_info: Error closing file: %s\n", strerror(errno));
1308 mtcp_abort();
1309 }
1310 }
1311 else mtcp_printf("process_ptrace_info: NO checkpoint file\n");
1312
1313 sort_ptrace_pairs ();
1314
1315 print_ptrace_pairs ();
1316
1317 print_ckpt_threads ();
1318
1319 // We dont need sem_post anymore because this function is only called by checkpoint thread
1320 // TODO: remove semaphor-related stuff
1321
1322 /* allow all other threads to proceed
1323 * for all the threads excluding motherofall and checkpoint thread */
1324 /*
1325 for (loopthread = threads; loopthread != NULL && loopthread->next != NULL && loopthread->next->next != NULL;
1326 loopthread = loopthread->next) {
1327 sem_post(&ptrace_read_pairs_sem);
1328
1329 }
1330 }else
1331 // all threads with the exception of motherofall (checkpoint thread does NOT run this code) wait for motherofall to write
1332 // the info from the ptrace file to memory (shared among all threads of a process)
1333 sem_wait(&ptrace_read_pairs_sem);
1334 */
1335
1336 }
1337
1338 static int is_checkpoint_thread (pid_t tid)
1339 {
1340 int i;
1341 for (i = 0; i < ckpt_threads_count; i++) {
1342 if (ckpt_threads[i].tid == tid ) return ckpt_threads[i].pid;
1343 }
1344 return 0;
1345 }
1346
1347 static int ptrace_detach_ckpthread(pid_t tgid, pid_t tid, pid_t supid)
1348 {
1349 int status;
1350 char pstate;
1351 pid_t tpid;
1352
1353 DPRINTF(("detach_ckpthread: tid=%d, tgid = %d >>>>>>>>>>>>>>>>>>\n", tid, tgid));
1354
1355 pstate = procfs_state(tid);
1356 DPRINTF(("detach_ckpthread: CKPT Thread procfs_state(%d) = %c\n", tid, pstate));
1357 if( pstate == 0 ){
1358 // such process not exist
1359 return -ENOENT;
1360 }else if (pstate == 'T') {
1361 // There can be posibility that GDB (or other) reads status of this
1362 // thread before us. So we will block. We don't want that. // Read anyway but without hang
1363 DPRINTF(("detach_ckpthread: Checkpoint thread already stopped\n"));
1364
1365 is_waitpid_local = 1;
1366 tpid = waitpid(tid, &status, WNOHANG);
1367 if (tpid == -1 && errno == ECHILD) {
1368 DPRINTF(("detach_ckpthread: Check cloned process\n"));
1369 // Try again with __WCLONE to check cloned processes.
1370 is_waitpid_local = 1;
1371 if ((tpid = waitpid(tid, &status, __WCLONE | WNOHANG)) == -1) {
1372 DPRINTF(("detach_ckpthread: ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n"
1373 ,
1374 strerror(errno)));
1375 }
1376 }
1377 DPRINTF(("detach_ckpthread: tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,signal=%d\n",
1378 tid, tpid, WIFSTOPPED(status),
1379 WSTOPSIG(status) == SIGSTOP, WSTOPSIG(status)));
1380 }else{
1381 /*
1382 * and if inferior is a checkpoint thread
1383 */
1384 if (kill(tid, SIGSTOP) == -1) {
1385 mtcp_printf("detach_ckpthread: ptrace_detach_checkpoint_threads: kill: %s\n",
1386 strerror(errno));
1387 return -EAGAIN;
1388 }
1389 is_waitpid_local = 1;
1390 tpid = waitpid(tid, &status, 0);
1391 DPRINTF(("detach_ckpthread: tpid1=%d,errno=%d,ECHILD=%d\n", tpid, errno, ECHILD));
1392 if ((tpid) == -1 && errno == ECHILD) {
1393 DPRINTF(("detach_ckpthread: Check cloned process\n"));
1394 /*
1395 * Try again with __WCLONE to check cloned processes.
1396 */
1397 is_waitpid_local = 1;
1398 if ((tpid = waitpid(tid, &status, __WCLONE)) == -1) {
1399 mtcp_printf("detach_ckpthread: ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n",
1400 strerror(errno));
1401 return -EAGAIN;
1402 }
1403 }
1404 }
1405 DPRINTF(("detach_ckpthread: tgid = %d, tpid=%d,stopped=%d is_sigstop=%d,"
1406 "signal=%d,err=%s\n",
1407 tid, tpid, WIFSTOPPED(status),WSTOPSIG(status) == SIGSTOP,
1408 WSTOPSIG(status), strerror(errno)));
1409 if (WIFSTOPPED(status)) {
1410 if (WSTOPSIG(status) == SIGSTOP)
1411 DPRINTF(("detach_ckpthread: checkpoint thread %d was stopped by the delivery of SIGSTOP\n",tid));
1412 else { // we should never get here
1413 DPRINTF(("detach_ckpthread: checkpoint thread %d was stopped by the delivery of %d\n",
1414 tid,WSTOPSIG(status)));
1415 }
1416 } else // we should never end up here
1417 DPRINTF(("detach_ckpthread: checkpoint thread %d was NOT stopped by a signal\n", tid));
1418
1419 is_ptrace_local = 1;
1420 if (ptrace(PTRACE_DETACH, tid, 0, SIGCONT) == -1) {
1421 DPRINTF(("detach_ckpthread: ptrace_detach_checkpoint_threads: parent = %d child = %d\n",
1422 supid, tid));
1423 DPRINTF(("detach_ckpthread: ptrace_detach_checkpoint_threads: PTRACE_DETACH failed: %s\n",
1424 strerror(errno)));
1425 return -EAGAIN;
1426 }
1427
1428 DPRINTF(("detach_ckpthread: tid=%d, tgid = %d <<<<<<<<<<<<<<<<<<<<<<<<<<\n", tid, tgid));
1429 only_once = 0; /* no need for semaphore here - the UT execute this code */
1430 return 0;
1431 }
1432
1433 static int ptrace_control_ckpthread(pid_t tgid, pid_t tid)
1434 {
1435 int status;
1436 char pstate;
1437 pid_t tpid;
1438
1439 DPRINTF(("control_ckpthread: tid=%d, tgid = %d >>>>>>>>>>>>>>>>>>>>>>>\n", tid, tgid));
1440
1441 pstate = procfs_state(tid);
1442 DPRINTF(("control_ckpthread: CKPT Thread procfs_state(%d) = %c\n", tid, pstate));
1443
1444 if( pstate == 0 ){
1445 // process not exist
1446 return -ENOENT;
1447 }else if( pstate == 'T') {
1448 // There can be posibility that GDB (or other) reads status of this
1449 // thread before us. So we will block. We don't want that.
1450 // Read anyway but without hang
1451 DPRINTF(("control_ckpthread: Checkpoint thread stopped by controlled debugger\n"));
1452
1453 if( mtcp_sys_kernel_tkill(tid,SIGCONT) )
1454 return -EAGAIN;
1455
1456 DPRINTF(("control_ckpthread: Check cloned process\n"));
1457 // Try again with __WCLONE to check cloned processes.
1458 is_waitpid_local = 1;
1459 if ((tpid = waitpid(tid, &status, __WCLONE | WNOHANG)) == -1) {
1460 mtcp_printf("control_ckpthread: ptrace_detach_checkpoint_threads: waitpid(..,__WCLONE): %s\n",
1461 strerror(errno));
1462 return -EAGAIN;
1463 }
1464
1465 DPRINTF(("control_ckpthread: tgid = %d, tpid=%d,continued=%d,err=%s\n",
1466 tid, tpid, WIFCONTINUED(status), strerror(errno)));
1467
1468 if( WIFCONTINUED(status) ) {
1469 DPRINTF(("control_ckpthread: checkpoint thread %d was stopped by the delivery of SIGSTOP\n",tid));
1470 }else{ // we should never end up here
1471 DPRINTF(("control_ckpthread: checkpoint thread %d was NOT stopped by a signal\n", tid));
1472 }
1473 }
1474
1475 DPRINTF(("control_ckpthread: tid=%d, tgid = %d <<<<<<<<<<<<<<<<<<<<<<<<<<\n", tid, tgid));
1476 return 0;
1477 }
1478
1479 void ptrace_save_threads_state ()
1480 {
1481 int i;
1482
1483 DPRINTF((">>>>>>>>> start ptrace_save_threads_state %d\n", GETTID()));
1484
1485 for(i = 0; i < ptrace_pairs_count; i++) {
1486 /*
1487 if( is_checkpoint_thread(ptrace_pairs[i].inferior) ){
1488 mtcp_printf("ptrace_detach_user_threads: SKIP checkpoint thread %d\n",ptrace_pairs[i].inferior);
1489 continue;
1490 }
1491 */
1492 //if( ptrace_pairs[i].superior == GETTID()){
1493 char pstate;
1494 int tid = ptrace_pairs[i].inferior;
1495 pstate = procfs_state(tid);
1496 DPRINTF(("save state of thread %d = %c\n",tid,pstate));
1497 ptrace_pairs[i].inferior_st = pstate;
1498 //}
1499 }
1500 DPRINTF((">>>>>>>>> done ptrace_save_threads_state %d\n", GETTID()));
1501 }
1502
1503 #endif