int attach_process(int pid) { int status = 0; gettimeofday(&freeze_time, NULL); attached_pid = pid; if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) { perror("attach"); detach_process(pid); return -1; } if (!proc_stopped(pid)) { struct itimerval tm; if (opt_use_waitpid_timeout) { /* setup alarm to avoid long waiting on waitpid */ tm.it_interval.tv_sec = 0; tm.it_interval.tv_usec = 0; tm.it_value.tv_sec = 1; tm.it_value.tv_usec = stop_timeout % 1000000; setitimer(ITIMER_REAL, &tm, NULL); } if (waitpid(pid, &status, WUNTRACED) < 0) { if (errno == EINTR) { fprintf(stderr, "timeout on waitpid\n"); detach_process(pid); return -1; } fprintf(stderr, "waitpid %d: %s\n", pid, strerror(errno)); detach_process(pid); return -1; } if (opt_use_waitpid_timeout) { tm.it_value.tv_sec = 0; tm.it_value.tv_usec = 0; setitimer(ITIMER_REAL, &tm, NULL); } if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP) fprintf(stderr, "warning: waitpid(%d) WIFSTOPPED=%d WSTOPSIG=%d\n", pid, WIFSTOPPED(status), WSTOPSIG(status)); } if (kill(pid, SIGSTOP) < 0) { perror("send SIGSTOP"); return -1; } return 0; }
int backtrace_ptrace(int pid, int *tids, int *index, int nr_tids) { #if !defined (NO_LIBUNWIND_PTRACE) int i, count, rc = 0; int *threads = NULL; count = get_threads(pid, &threads); if (!count || threads == NULL) return -1; if (tids != NULL) { if (adjust_threads(threads, count, tids, index, nr_tids) < 0) return -1; free(threads); count = nr_tids; threads = tids; } if (attach_process(pid) < 0) return -1; for (i = 0; i < count; ++i) { void *upt_info; printf("-------------------- thread %d (%d) --------------------\n", (index != NULL ? index[i] : i+1), threads[i]); if (threads[i] != pid && attach_thread(threads[i]) < 0) { rc = -1; break; } upt_info = _UPT_create(threads[i]); if (backtrace_thread(&_UPT_accessors, upt_info) < 0) rc = -1; _UPT_destroy(upt_info); if (threads[i] != pid && detach_thread(threads[i])) rc = -1; if (rc < 0) break; } free(threads); if (detach_process(pid) < 0) return -1; return rc; #else return -1; #endif /* NO_LIBUNWIND_PTRACE */ }
void* process_traffic(void *arg) { PGW pgw; while(1){ pgw.read_data(); if(pgw.status == 0) continue; pgw.set_metadata(); if(pgw.type == 1){ attach_process(pgw); } else if(pgw.type == 2){ data_transfer(pgw); } else if(pgw.type == 3){ detach_process(pgw); } else{ cout << "Incorrect type - " << pgw.type << endl; } } return NULL; }
static int padzero(struct task_struct *tsk, unsigned long bss) { int ret = 0; unsigned long nbyte; struct mm_struct *mm = NULL; nbyte = ELF_PAGEOFFSET(bss); if (nbyte) { nbyte = ELF_MIN_ALIGN - nbyte; if (tsk == current) { if (clear_user((void __user *) bss, nbyte)) ret = -EFAULT; } else { struct eprocess *process = tsk->ethread->threads_process; mm = attach_process(&process->pcb); if (clear_user((void __user *) bss, nbyte)) ret = -EFAULT; detach_process(mm); } } return ret; }
/* Registers the call-back and configures the actions in case of a failure * with the Windows services manager. */ void service_start(int *argcp, char **argvp[]) { int argc = *argcp; char **argv = *argvp; int i; SERVICE_TABLE_ENTRY service_table[] = { {(LPTSTR)program_name, (LPSERVICE_MAIN_FUNCTION)main}, {NULL, NULL} }; /* If one of the command line option is "--detach", we create * a new process in case of parent, wait for child to start and exit. * In case of the child, we just return. We should not be creating a * service in either case. */ if (detach_process(argc, argv)) { return; } /* 'service_started' is 'false' when service_start() is called the first * time. It is 'true', when it is called the second time by the Windows * services manager. */ if (service_started) { init_service_status(); wevent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!wevent) { char *msg_buf = ovs_lasterror_to_string(); VLOG_FATAL("Failed to create a event (%s).", msg_buf); } poll_wevent_wait(wevent); /* Register the control handler. This function is called by the service * manager to stop the service. */ hstatus = RegisterServiceCtrlHandler(program_name, (LPHANDLER_FUNCTION)control_handler); if (!hstatus) { char *msg_buf = ovs_lasterror_to_string(); VLOG_FATAL("Failed to register the service control handler (%s).", msg_buf); } if (monitor) { set_config_failure_actions(); } /* When the service control manager does the call back, it does not * send the same arguments as sent to the main function during the * service start. So, use the arguments passed over during the first * time. */ *argcp = sargc; *argvp = *sargvp; /* XXX: Windows implementation cannot have a unixctl commands in the * traditional sense of unix domain sockets. If an implementation is * done that involves 'unixctl' vlog commands the following call is * needed to make sure that the unixctl commands for vlog get * registered in a daemon, even before the first log message. */ vlog_init(); return; } assert_single_threaded(); /* A reference to arguments passed to the main function the first time. * We need it after the call-back from service control manager. */ sargc = argc; sargvp = argvp; /* We are only interested in the '--service' and '--service-monitor' * options before the call-back from the service control manager. */ for (i = 0; i < argc; i ++) { if (!strcmp(argv[i], "--service")) { service_create = true; } else if (!strcmp(argv[i], "--service-monitor")) { monitor = true; } } /* If '--service' is not a command line option, run in foreground. */ if (!service_create) { return; } /* If we have been configured to run as a service, then that service * should already have been created either manually or through a start up * script. */ check_service(); service_started = true; /* StartServiceCtrlDispatcher blocks and returns after the service is * stopped. */ if (!StartServiceCtrlDispatcher(service_table)) { char *msg_buf = ovs_lasterror_to_string(); VLOG_FATAL("Failed at StartServiceCtrlDispatcher (%s)", msg_buf); } exit(0); }
/* * save process' memory maps, stack contents, thread identifiers and registers */ struct snapshot *get_snapshot(int pid, int *tids, int *index, int nr_tids) { struct snapshot *res; int attached_tid = 0; int i, n_frames; long page, label, rc; struct mem_data_chunk **stacks_cover = NULL; if ((page = sysconf(_SC_PAGESIZE)) < 0) { perror("get pagesize"); return NULL; } --page; res = calloc(1, sizeof(struct snapshot)); /* * create memory_map structure corresponding to process' maps */ res->map = create_maps(pid); if (res->map == NULL) goto get_snapshot_fail; /* * get process' threads */ res->num_threads = get_threads(pid, &res->tids); if (res->num_threads < 0 || res->tids == NULL) goto get_snapshot_fail; /* * user-provided list of threads */ if (tids != NULL) { if (adjust_threads(res->tids, res->num_threads, tids, index, nr_tids) < 0) goto get_snapshot_fail; free(res->tids); res->num_threads = nr_tids; res->tids = tids; } res->cur_thr = 0; res->regs = malloc(sizeof(res->regs[0])*res->num_threads); if (res->regs == NULL) { perror("malloc"); goto get_snapshot_fail; } /* FREEZE PROCESS */ if (attach_process(pid) < 0) goto get_snapshot_fail; for (i = 0; i < res->num_threads; ++i) { struct iovec iov; /* * we have already attached to main thread. call attach_thread() * for other ones */ attached_tid = res->tids[i]; if (res->tids[i] != pid && attach_thread(res->tids[i]) < 0) goto get_snapshot_fail_attached; /* * save thread's registers */ iov.iov_len = sizeof(res->regs[0]); iov.iov_base = &res->regs[i]; rc = ptrace(PTRACE_GETREGSET, res->tids[i], NT_PRSTATUS, &iov); if (rc < 0) { perror("PTRACE_GETREGSET"); goto get_snapshot_fail_attached; } /* * save label on memory region. it will indicate that memory contents * upper than this point (%rsp) will needed to unwind stacks */ label = SP_REG(&res->regs[i]) & ~page; rc = mem_map_add_label(res->map, (void *)label, res->num_threads); if (rc < 0) { fprintf(stderr, "failed to add label 0x%lx [rsp 0x%llx thread %d]\n", label, (long long unsigned int)SP_REG(&res->regs[i]), res->tids[i]); goto get_snapshot_fail_attached; } /* * detach from thread. it will still be frozen due to SIGSTOP */ if (res->tids[i] != pid && detach_thread(res->tids[i]) < 0) goto get_snapshot_fail_attached; } /* * arrange data chunks to copy memory contents. in most cases the chunks * will start from %rsp pointing somewhere in thread's stack * to the end of the stack region */ stacks_cover = malloc(sizeof(struct mem_data_chunk*) * res->num_threads); n_frames = mem_map_build_label_cover(res->map, stack_size, stacks_cover, page + 1); if (stacks_cover == NULL) { fprintf(stderr, "error: stacks cover == NULL, n_frames=%d\n", n_frames); goto get_snapshot_fail_attached; } /* * copy memory contents */ rc = copy_memory(pid, stacks_cover, n_frames); if (rc < 0) goto get_snapshot_fail_attached; /* UNFREEZE PROCESS */ if (detach_process(pid) < 0) goto get_snapshot_fail; if (opt_verbose) { for (i = 0; i < n_frames; ++i) { struct mem_data_chunk *chunk = stacks_cover[i]; printf("chunk #%d: 0x%lx-0x%lx length: %ldK\n", i, (size_t)chunk->start, (size_t)chunk->start + chunk->length, chunk->length >> 10); } } free(stacks_cover); return res; get_snapshot_fail_attached: if (attached_tid) detach_thread(attached_tid); detach_process(pid); get_snapshot_fail: if (opt_verbose) { fprintf(stderr, "maps of %d:\n", pid); print_proc_maps(pid); } free(stacks_cover); snapshot_destroy(res); return NULL; }
int backtrace_ptrace(int pid, int *tids, int *index, int nr_tids) { #if !defined (NO_LIBUNWIND_PTRACE) int i, count, rc = 0; int *threads = NULL; count = get_threads(pid, &threads); if (!count || threads == NULL) return -1; if (tids != NULL) { if (adjust_threads(threads, count, tids, index, nr_tids) < 0) return -1; free(threads); count = nr_tids; threads = tids; } if (attach_process(pid) < 0) return -1; for (i = 0; i < count; ++i) { void *upt_info; int x; char comm[16]; char end_pad[25] = "------------------------"; x = get_thread_comm(threads[i], comm, sizeof(comm)); if (x > 0 && x <= sizeof(end_pad)) { end_pad[sizeof(end_pad) - x] = '\0'; printf("-------------- thread %d (%d) (%s) %s\n", (index != NULL ? index[i] : i + 1), threads[i], comm, end_pad); } if (threads[i] != pid && attach_thread(threads[i]) < 0) { rc = -1; break; } upt_info = _UPT_create(threads[i]); if (backtrace_thread(&_UPT_accessors, upt_info) < 0) rc = -1; _UPT_destroy(upt_info); if (threads[i] != pid && detach_thread(threads[i])) rc = -1; if (rc < 0) break; } free(threads); if (detach_process(pid) < 0) return -1; return rc; #else return -1; #endif /* NO_LIBUNWIND_PTRACE */ }
/* * save process' memory maps, stack contents, thread identifiers and registers */ struct snapshot *get_snapshot(int pid, int *tids, int *index, int nr_tids) { struct snapshot *res; int i, attached_tid, n_frames; long page, label, rc; struct mem_data_chunk **stacks_cover = NULL; int v_major, v_minor; int use_process_vm_readv = 0; if ((page = sysconf(_SC_PAGESIZE)) < 0) { perror("get pagesize"); return NULL; } --page; res = calloc(1, sizeof(struct snapshot)); /* * create memory_map structure corresponding to process' maps */ res->map = create_maps(pid); if (res->map == NULL) goto get_snapshot_fail; /* * get process' threads */ res->num_threads = get_threads(pid, &res->tids); if (res->num_threads < 0 || res->tids == NULL) goto get_snapshot_fail; /* * user-provided list of threads */ if (tids != NULL) { if (adjust_threads(res->tids, res->num_threads, tids, index, nr_tids) < 0) goto get_snapshot_fail; free(res->tids); res->num_threads = nr_tids; res->tids = tids; } res->cur_thr = 0; res->regs = malloc(sizeof(struct user_regs_struct)*res->num_threads); if (res->regs == NULL) { perror("malloc"); goto get_snapshot_fail; } /* * decide how to copy memory contents of the process. on newer kernels * proc_vm_readv() is used by default. on older kernels or when the option * --proc-mem is specified read the file /proc/<pid>/mem */ if (!opt_proc_mem) { if (get_kernel_version(&v_major, &v_minor) < 0) goto get_snapshot_fail; if (((v_major << 16) | v_minor) >= 0x30002) use_process_vm_readv = 1; } else { use_process_vm_readv = 0; } /* FREEZE PROCESS */ if (attach_process(pid) < 0) goto get_snapshot_fail; for (i = 0; i < res->num_threads; ++i) { /* * we have already attached to main thread. call attach_thread() * for other ones */ attached_tid = res->tids[i]; if (res->tids[i] != pid && attach_thread(res->tids[i]) < 0) goto get_snapshot_fail_attached; /* * save thread's registers */ rc = ptrace(PTRACE_GETREGS, res->tids[i], NULL, &res->regs[i]); if (rc < 0) { perror("PTRACE_GETREGS"); goto get_snapshot_fail_attached; } /* * save label on memory region. it will indicate that memory contents * upper than this point (%rsp) will needed to unwind stacks */ label = res->regs[i].rsp & ~page; rc = mem_map_add_label(res->map, (void *)label, res->num_threads); if (rc < 0) { fprintf(stderr, "failed to add label 0x%lx [rsp 0x%lx thread %d]\n", label, res->regs[i].rsp, res->tids[i]); goto get_snapshot_fail_attached; } /* * detach from thread. it will still be frozen due to SIGSTOP */ if (res->tids[i] != pid && detach_thread(res->tids[i]) < 0) goto get_snapshot_fail_attached; } /* * arrange data chunks to copy memory contents. in most cases the chunks * will start from %rsp pointing somewhere in thread's stack * to the end of the stack region */ stacks_cover = malloc(sizeof(struct mem_data_chunk*) * res->num_threads); n_frames = mem_map_build_label_cover(res->map, stack_size, stacks_cover, page + 1); if (stacks_cover == NULL) { fprintf(stderr, "error: stacks cover == NULL, n_frames=%d\n", n_frames); goto get_snapshot_fail_attached; } /* * copy memory contents */ rc = use_process_vm_readv ? copy_memory_process_vm_readv(pid, stacks_cover, n_frames) : copy_memory_proc_mem(pid, stacks_cover, n_frames); if (rc < 0) goto get_snapshot_fail_attached; /* UNFREEZE PROCESS */ if (detach_process(pid) < 0) goto get_snapshot_fail; if (opt_verbose) { for (i = 0; i < n_frames; ++i) { struct mem_data_chunk *chunk = stacks_cover[i]; printf("chunk #%d: 0x%lx-0x%lx length: %ldK\n", i, (size_t)chunk->start, (size_t)chunk->start + chunk->length, chunk->length >> 10); } } free(stacks_cover); return res; get_snapshot_fail_attached: if (attached_tid) detach_thread(attached_tid); detach_process(pid); get_snapshot_fail: if (opt_verbose) { fprintf(stderr, "maps of %d:\n", pid); print_proc_maps(pid); } free(stacks_cover); snapshot_destroy(res); return NULL; }