1 /****************************************************************************
2 * Copyright (C) 2006-2010 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3 * jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu *
4 * *
5 * This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src). *
6 * *
7 * DMTCP:dmtcp/src is free software: you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public License as *
9 * published by the Free Software Foundation, either version 3 of the *
10 * License, or (at your option) any later version. *
11 * *
12 * DMTCP:dmtcp/src is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with DMTCP:dmtcp/src. If not, see *
19 * <http://www.gnu.org/licenses/>. *
20 ****************************************************************************/
21
22 #include "mtcpinterface.h"
23 #include <stdarg.h>
24 #include <vector>
25 #include <list>
26 #include <string>
27 #include "syscallwrappers.h"
28 #include "../jalib/jassert.h"
29 #include "uniquepid.h"
30 #include "dmtcpworker.h"
31 #include "sockettable.h"
32 #include "protectedfds.h"
33 #include "connectionmanager.h"
34 #include "connectionidentifier.h"
35 #include "syslogcheckpointer.h"
36 #include "../jalib/jconvert.h"
37 #include "constants.h"
38 #include <sys/ioctl.h>
39 #include <sys/syscall.h>
40 #include <thread_db.h>
41 #include <sys/procfs.h>
42
43 #ifdef PID_VIRTUALIZATION
44
45 static pid_t originalToCurrentPid( pid_t originalPid )
46 {
47 /* This code is called from MTCP while the checkpoint thread is holding
48 the JASSERT log lock. Therefore, don't call JTRACE/JASSERT/JINFO/etc. in
49 this function. */
50 pid_t currentPid = dmtcp::VirtualPidTable::instance().originalToCurrentPid( originalPid );
51
52 if (currentPid == -1)
53 currentPid = originalPid;
54
55 return currentPid;
56 }
57
58 static pid_t currentToOriginalPid( pid_t currentPid )
59 {
60 /* This code is called from MTCP while the checkpoint thread is holding
61 the JASSERT log lock. Therefore, don't call JTRACE/JASSERT/JINFO/etc. in
62 this function. */
63 pid_t originalPid = dmtcp::VirtualPidTable::instance().currentToOriginalPid( currentPid );
64
65 if (originalPid == -1)
66 originalPid = currentPid;
67
68 return originalPid;
69 }
70
71 pid_t gettid()
72 {
73 WRAPPER_EXECUTION_DISABLE_CKPT();
74 /*
75 * We might want to cache the tid of all threads to avoid redundant calls
76 * to _real_gettid() and currentToOriginalPid().
77 * To cache, we must make sure that this function is invoked by each thread
78 * at least once prior to checkpoint.
79 * __thread can be used along with static storage class to make this cached
80 * value specific to each thread
81 */
82 pid_t currentTid = _real_gettid();
83 pid_t origTid = currentToOriginalPid ( currentTid );
84
85 WRAPPER_EXECUTION_ENABLE_CKPT();
86
87 return origTid;
88 }
89
90
91
92 extern "C" pid_t getpid()
93 {
94 //pid_t pid = _real_getpid();//dmtcp::UniquePid::ThisProcess().pid();
95
96 //return currentToOriginalPid ( pid );
97 return dmtcp::VirtualPidTable::instance().pid();
98 }
99
100 extern "C" pid_t getppid()
101 {
102 WRAPPER_EXECUTION_DISABLE_CKPT();
103
104 pid_t ppid = _real_getppid();
105 if ( _real_getppid() == 1 )
106 {
107 dmtcp::VirtualPidTable::instance().setppid( 1 );
108 }
109
110 pid_t origPpid = dmtcp::VirtualPidTable::instance().ppid( );
111
112 WRAPPER_EXECUTION_ENABLE_CKPT();
113
114 return origPpid;
115 }
116
117 extern "C" int tcsetpgrp(int fd, pid_t pgrp)
118 {
119 WRAPPER_EXECUTION_DISABLE_CKPT();
120
121 pid_t currPgrp = originalToCurrentPid( pgrp );
122 // JTRACE( "Inside tcsetpgrp wrapper" ) (fd) (pgrp) (currPgrp);
123 int retVal = _real_tcsetpgrp(fd, currPgrp);
124
125 //JTRACE( "tcsetpgrp return value" ) (fd) (pgrp) (currPgrp) (retval);
126 WRAPPER_EXECUTION_ENABLE_CKPT();
127
128 return retVal;
129 }
130
131 extern "C" pid_t tcgetpgrp(int fd)
132 {
133 WRAPPER_EXECUTION_DISABLE_CKPT();
134
135 pid_t retval = currentToOriginalPid( _real_tcgetpgrp(fd) );
136
137 //JTRACE ( "tcgetpgrp return value" ) (fd) (retval);
138 WRAPPER_EXECUTION_ENABLE_CKPT();
139
140 return retval;
141 }
142
143 extern "C" pid_t getpgrp(void)
144 {
145 WRAPPER_EXECUTION_DISABLE_CKPT();
146
147 pid_t pgrp = _real_getpgrp();
148 pid_t origPgrp = currentToOriginalPid( pgrp );
149
150 WRAPPER_EXECUTION_ENABLE_CKPT();
151
152 return origPgrp;
153 }
154
155 extern "C" pid_t setpgrp(void)
156 {
157 WRAPPER_EXECUTION_DISABLE_CKPT();
158
159 pid_t pgrp = _real_setpgrp();
160 pid_t origPgrp = currentToOriginalPid( pgrp );
161
162 WRAPPER_EXECUTION_ENABLE_CKPT();
163
164 return origPgrp;
165 }
166
167 extern "C" pid_t getpgid(pid_t pid)
168 {
169 WRAPPER_EXECUTION_DISABLE_CKPT();
170
171 pid_t currentPid = originalToCurrentPid (pid);
172 pid_t res = _real_getpgid (currentPid);
173 pid_t origPgid = currentToOriginalPid (res);
174
175 WRAPPER_EXECUTION_ENABLE_CKPT();
176
177 return origPgid;
178 }
179
180 extern "C" int setpgid(pid_t pid, pid_t pgid)
181 {
182 WRAPPER_EXECUTION_DISABLE_CKPT();
183
184 pid_t currPid = originalToCurrentPid (pid);
185 pid_t currPgid = originalToCurrentPid (pgid);
186
187 int retVal = _real_setpgid (currPid, currPgid);
188
189 WRAPPER_EXECUTION_ENABLE_CKPT();
190
191 return retVal;
192 }
193
194 extern "C" pid_t getsid(pid_t pid)
195 {
196 WRAPPER_EXECUTION_DISABLE_CKPT();
197
198 pid_t currPid;
199
200 // If !pid then we ask SID of this process
201 if( pid )
202 currPid = originalToCurrentPid (pid);
203 else
204 currPid = _real_getpid();
205
206 pid_t res = _real_getsid (currPid);
207
208 pid_t origSid = currentToOriginalPid (res);
209
210 WRAPPER_EXECUTION_ENABLE_CKPT();
211
212 return origSid;
213 }
214
215 extern "C" pid_t setsid(void)
216 {
217 WRAPPER_EXECUTION_DISABLE_CKPT();
218
219 pid_t pid = _real_setsid();
220 pid_t origPid = currentToOriginalPid (pid);
221 dmtcp::VirtualPidTable::instance().setsid(origPid);
222
223 WRAPPER_EXECUTION_ENABLE_CKPT();
224
225 return origPid;
226 }
227
228 extern "C" int kill(pid_t pid, int sig)
229 {
230 WRAPPER_EXECUTION_DISABLE_CKPT();
231
232 pid_t currPid = originalToCurrentPid (pid);
233
234 int retVal = _real_kill (currPid, sig);
235
236 WRAPPER_EXECUTION_ENABLE_CKPT();
237
238 return retVal;
239 }
240
241 int tkill(int tid, int sig)
242 {
243 WRAPPER_EXECUTION_DISABLE_CKPT();
244
245 int currentTid = originalToCurrentPid ( tid );
246
247 int retVal = _real_tkill ( currentTid, sig );
248
249 WRAPPER_EXECUTION_ENABLE_CKPT();
250
251 return retVal;
252 }
253
254 int tgkill(int tgid, int tid, int sig)
255 {
256 WRAPPER_EXECUTION_DISABLE_CKPT();
257
258 int currentTgid = originalToCurrentPid ( tgid );
259 int currentTid = originalToCurrentPid ( tid );
260
261 int retVal = _real_tgkill ( currentTgid, currentTid, sig );
262
263 WRAPPER_EXECUTION_ENABLE_CKPT();
264
265 return retVal;
266 }
267
268
269 //long sys_tgkill (int tgid, int pid, int sig)
270
271 // long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data)
272
273 #ifdef PTRACE
274
275 #define TRUE 1
276 #define FALSE 0
277
278 extern "C" td_err_e _dmtcp_td_thr_get_info ( const td_thrhandle_t *th_p,
279 td_thrinfo_t *ti_p)
280 {
281 td_err_e td_err;
282
283 td_err = _real_td_thr_get_info ( th_p, ti_p);
284 ti_p->ti_lid = ( lwpid_t ) currentToOriginalPid ( ( int ) ti_p->ti_lid );
285 ti_p->ti_tid = ( thread_t ) currentToOriginalPid ( (int ) ti_p->ti_tid );
286 return td_err;
287 }
288
289 /* gdb calls dlsym on td_thr_get_info. We need to wrap td_thr_get_info for
290 tid virtualization. It should be safe to comment this out if you don't
291 need to checkpoint gdb.
292 */
293 extern "C" void *dlsym ( void *handle, const char *symbol)
294 {
295 if ( strcmp ( symbol, "td_thr_get_info" ) == 0 )
296 return (void *) &_dmtcp_td_thr_get_info;
297 else
298 return _real_dlsym ( handle, symbol );
299 }
300
301 typedef void ( *set_singlestep_waited_on_t ) ( pid_t superior, pid_t inferior, int
302 value );
303 extern "C" set_singlestep_waited_on_t set_singlestep_waited_on_ptr;
304
305 typedef int ( *get_is_waitpid_local_t ) ();
306 extern "C" get_is_waitpid_local_t get_is_waitpid_local_ptr;
307
308 typedef void ( *unset_is_waitpid_local_t ) ();
309 extern "C" unset_is_waitpid_local_t unset_is_waitpid_local_ptr;
310
311 typedef pid_t ( *get_saved_pid_t) ( );
312 extern "C" get_saved_pid_t get_saved_pid_ptr;
313
314 typedef int ( *get_saved_status_t) ( );
315 extern "C" get_saved_status_t get_saved_status_ptr;
316
317 typedef int ( *get_has_status_and_pid_t) ( );
318 extern "C" get_has_status_and_pid_t get_has_status_and_pid_ptr;
319
320 typedef void ( *reset_pid_status_t) ( );
321 extern "C" reset_pid_status_t reset_pid_status_ptr;
322
323 typedef int ( *fill_in_pthread_t) ();
324 extern "C" fill_in_pthread_t fill_in_pthread_ptr;
325
326 typedef int ( *delete_thread_on_pthread_join_t) ();
327 extern "C" delete_thread_on_pthread_join_t delete_thread_on_pthread_join_ptr;
328
329 extern "C" sigset_t signals_set;
330 #endif
331
332 /*
333 * TODO: Add the wrapper protection for wait() family of system calls.
334 * It wouldn't be a straight forward process, we need to take care of the
335 * _BLOCKING_ property of these system calls.
336 * --KAPIL
337 */
338
339 extern "C" pid_t wait (__WAIT_STATUS stat_loc)
340 //extern "C" pid_t wait(int *stat_loc)
341 {
342 pid_t retVal = _real_wait (stat_loc);
343
344 if (retVal > 0) {
345 pid_t pid = currentToOriginalPid (retVal);
346
347 if ( pid > 0 )
348 dmtcp::VirtualPidTable::instance().erase(pid);
349
350 return pid;
351 }
352 return retVal;
353 }
354
355 extern "C" pid_t waitpid(pid_t pid, int *stat_loc, int options)
356 {
357 int status;
358 #ifdef PTRACE
359 pid_t superior;
360 pid_t inferior;
361 pid_t retval;
362 static int i = 0;
|
Event var_decl: |
Declaring variable "originalPid" without initializer. |
| Also see events: |
[uninit_use] |
363 pid_t originalPid;
364 #endif
365
|
At conditional (1): "stat_loc == NULL": Taking true branch.
|
366 if ( stat_loc == NULL )
367 stat_loc = &status;
368
369 pid_t currPid = originalToCurrentPid (pid);
370
371 #ifdef PTRACE
372 superior = syscall (SYS_gettid);
373
374 inferior = pid;
375
|
At conditional (2): "!(*get_is_waitpid_local_ptr)()": Taking true branch.
|
376 if (!get_is_waitpid_local_ptr ()) {
|
At conditional (3): "(*get_has_status_and_pid_ptr)()": Taking true branch.
|
377 if (get_has_status_and_pid_ptr ()) {
378 *stat_loc = get_saved_status_ptr ();
379 retval = get_saved_pid_ptr ();
380 reset_pid_status_ptr ();
381 }
382 else {
383 if (_real_pthread_sigmask (SIG_BLOCK, &signals_set, NULL) != 0) {
384 perror ("waitpid wrapper");
385 exit(-1);
386 }
387 set_singlestep_waited_on_ptr (superior, inferior, TRUE);
388 retval = _real_waitpid (currPid, stat_loc, options);
389 originalPid = currentToOriginalPid (retval);
390 if (_real_pthread_sigmask (SIG_UNBLOCK, &signals_set, NULL) != 0) {
391 perror ("waitpid wrapper");
392 exit(-1);
393 }
394 }
395 }
396 else {
397 retval = _real_waitpid (currPid, stat_loc, options);
398 unset_is_waitpid_local_ptr ();
399 originalPid = currentToOriginalPid (retval);
400 }
401 #else
402 pid_t retval = _real_waitpid (currPid, stat_loc, options);
403
404 pid_t originalPid = currentToOriginalPid ( retval );
405 #endif
406
|
At conditional (4): "retval > 0": Taking true branch.
|
|
At conditional (5): "(*stat_loc & 0x7f) == 0": Taking true branch.
|
407 if ( retval > 0
408 && ( WIFEXITED ( *stat_loc ) || WIFSIGNALED ( *stat_loc ) ) )
409 dmtcp::VirtualPidTable::instance().erase(originalPid);
410
|
Event uninit_use: |
Using uninitialized value "originalPid". |
| Also see events: |
[var_decl] |
411 return originalPid;
412 }
413
414 extern "C" int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
415 {
416 siginfo_t status;
417
418 if ( infop == NULL )
419 infop = &status;
420
421 pid_t currPd = originalToCurrentPid (id);
422
423 int retval = _real_waitid (idtype, currPd, infop, options);
424
425 if (retval != -1) {
426 pid_t originalPid = currentToOriginalPid ( infop->si_pid );
427 infop->si_pid = originalPid;
428
429 if ( infop->si_code == CLD_EXITED || infop->si_code == CLD_KILLED )
430 dmtcp::VirtualPidTable::instance().erase ( originalPid );
431 }
432
433 return retval;
434 }
435
436 extern "C" pid_t wait3(__WAIT_STATUS status, int options, struct rusage *rusage)
437 {
438 pid_t retval = _real_wait3 (status, options, rusage);
439
440 pid_t originalPid = currentToOriginalPid ( retval );
441
442 if ( originalPid > 0 )
443 dmtcp::VirtualPidTable::instance().erase(originalPid);
444
445 return originalPid;
446 }
447
448 extern "C" pid_t wait4(pid_t pid, __WAIT_STATUS status, int options, struct rusage *rusage)
449 {
450 int stat;
451
452 if ( status == NULL )
453 status = (__WAIT_STATUS) &stat;
454
455 pid_t currPid = originalToCurrentPid (pid);
456
457 pid_t retval = _real_wait4 ( currPid, status, options, rusage );
458
459 pid_t originalPid = currentToOriginalPid ( retval );
460
461 if ( retval > 0
462 && ( WIFEXITED ( * (int*) status ) || WIFSIGNALED ( * (int*) status ) ) )
463 dmtcp::VirtualPidTable::instance().erase ( originalPid );
464
465 return originalPid;
466 }
467
468 // TODO: ioctl must use virtualized pids for request = TIOCGPGRP / TIOCSPGRP
469 // These are synonyms for POSIX standard tcgetpgrp / tcsetpgrp
470 extern "C" {
471 int send_sigwinch = 0;
472 }
473 extern "C" int ioctl(int d, unsigned long int request, ...)
474 { va_list ap;
475 int rc;
476
477 if (send_sigwinch && request == TIOCGWINSZ) {
478 send_sigwinch = 0;
479 va_list local_ap;
480 va_copy(local_ap, ap);
481 va_start(local_ap, request);
482 struct winsize * win = va_arg(local_ap, struct winsize *);
483 va_end(local_ap);
484 rc = _real_ioctl(d, request, win); // This fills in win
485 win->ws_col--; // Lie to application, and force it to resize window,
486 // reset any scroll regions, etc.
487 kill(getpid(), SIGWINCH); // Tell application to look up true winsize
488 // and resize again.
489 } else {
490 void * arg;
491 va_start(ap, request);
492 arg = va_arg(ap, void *);
493 va_end(ap);
494 rc = _real_ioctl(d, request, arg);
495 }
496
497 return rc;
498 }
499
500 /*
501 extern "C" int setgid(gid_t gid)
502 {
503 return _real_setgid(gid);
504 }
505
506 extern "C" int setuid(uid_t uid)
507 {
508 return _real_setuid(uid);
509 }
510 */
511 #endif
512
513 // long sys_set_tid_address(int __user *tidptr);
514 // extern "C" int sigqueue(pid_t pid, int signo, const union sigval value)
515
516
517 // long sys_getuid(void);
518 // long sys_geteuid(void);
519 // long sys_getgid(void);
520 // long sys_getegid(void);
521 // long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid);
522 // long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid);
523 // long sys_getpgrp(void);
524 // long sys_getgroups(int gidsetsize, gid_t __user *grouplist);
525 //
526 // long sys_setregid(gid_t rgid, gid_t egid);
527 // long sys_setgid(gid_t gid);
528 // long sys_setreuid(uid_t ruid, uid_t euid);
529 // long sys_setuid(uid_t uid);
530 // long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid);
531 // long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid);
532 // long sys_setfsuid(uid_t uid);
533 // long sys_setfsgid(gid_t gid);
534 // long sys_setsid(void);
535 // long sys_setgroups(int gidsetsize, gid_t __user *grouplist);
536 //
537 //
538 // long sys_sched_setscheduler(pid_t pid, int policy,
539 // struct sched_param __user *param);
540 // long sys_sched_setparam(pid_t pid,
541 // struct sched_param __user *param);
542 // long sys_sched_getscheduler(pid_t pid);
543 // long sys_sched_getparam(pid_t pid,
544 // struct sched_param __user *param);
545 // long sys_sched_setaffinity(pid_t pid, unsigned int len,
546 // unsigned long __user *user_mask_ptr);
547 // long sys_sched_getaffinity(pid_t pid, unsigned int len,
548 // unsigned long __user *user_mask_ptr);
549 // long sys_sched_yield(void);
550 // long sys_sched_rr_get_interval(pid_t pid,
551 //
552 //
553 // long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t __user *uinfo);
554 //
555 //
556 //
557 //
558 // long sys_chown(const char __user *filename,
559 // uid_t user, gid_t group);
560 // long sys_lchown(const char __user *filename,
561 // uid_t user, gid_t group);
562 // long sys_fchown(unsigned int fd, uid_t user, gid_t group);
563 // #ifdef CONFIG_UID16
564 // long sys_chown16(const char __user *filename,
565 // old_uid_t user, old_gid_t group);
566 // long sys_lchown16(const char __user *filename,
567 // old_uid_t user, old_gid_t group);
568 // long sys_fchown16(unsigned int fd, old_uid_t user, old_gid_t group);
569 // long sys_setregid16(old_gid_t rgid, old_gid_t egid);
570 // long sys_setgid16(old_gid_t gid);
571 // long sys_setreuid16(old_uid_t ruid, old_uid_t euid);
572 // long sys_setuid16(old_uid_t uid);
573 // long sys_setresuid16(old_uid_t ruid, old_uid_t euid, old_uid_t suid);
574 // long sys_getresuid16(old_uid_t __user *ruid,
575 // old_uid_t __user *euid, old_uid_t __user *suid);
576 // long sys_setresgid16(old_gid_t rgid, old_gid_t egid, old_gid_t sgid);
577 // long sys_getresgid16(old_gid_t __user *rgid,
578 // old_gid_t __user *egid, old_gid_t __user *sgid);
579 // long sys_setfsuid16(old_uid_t uid);
580 // long sys_setfsgid16(old_gid_t gid);
581 // long sys_getgroups16(int gidsetsize, old_gid_t __user *grouplist);
582 // long sys_setgroups16(int gidsetsize, old_gid_t __user *grouplist);
583 // long sys_getuid16(void);
584 // long sys_geteuid16(void);
585 // long sys_getgid16(void);
586 // long sys_getegid16(void);
587 //
588 //
589 //
590 //
591 // long sys_add_key(const char __user *_type,
592 // const char __user *_description,
593 // const void __user *_payload,
594 // size_t plen,
595 // key_serial_t destringid);
596 //
597 // long sys_request_key(const char __user *_type,
598 // const char __user *_description,
599 // const char __user *_callout_info,
600 // key_serial_t destringid);
601 //
602 //
603 // long sys_migrate_pages(pid_t pid, unsigned long maxnode,
604 // const unsigned long __user *from,
605 // const unsigned long __user *to);
606 // long sys_move_pages(pid_t pid, unsigned long nr_pages,
607 // const void __user * __user *pages,
608 // const int __user *nodes,
609 // int __user *status,
610 // int flags);
611 // long compat_sys_move_pages(pid_t pid, unsigned long nr_page,
612 // __u32 __user *pages,
613 // const int __user *nodes,
614 // int __user *status,
615 // int flags);
616 //
617 // long sys_fchownat(int dfd, const char __user *filename, uid_t user,
618 // gid_t group, int flag);
619 //
620 // long sys_get_robust_list(int pid,
621 // struct robust_list_head __user * __user *head_ptr,
622 // size_t __user *len_ptr);
623 //
624