/* This sees if the current process has any signals set, and handles them. */ void chksigs(void) { uint8_t j; uint32_t pending = udata.u_ptab->p_pending & ~udata.u_ptab->p_held; int (**svec)(int) = &udata.u_sigvec[0]; uint32_t m; /* Fast path - no signals pending means no work Also don't do signal processing if we are in P_STOPPED. This isn't quite right but will paper over the holes for the moment FIXME */ if (!pending || udata.u_ptab->p_status == P_STOPPED) return; /* Dispatch the lowest numbered signal */ for (j = 1; j < NSIGS; ++j) { svec++; m = sigmask(j); if (!(m & pending)) continue; /* SIGSTOP can't be ignored and puts the process into P_STOPPED state when it is ready to handle the signal. Annoyingly right now we have to context switch to the task in order to stop it in the right place. That would be nice to fix */ if (j == SIGSTOP || j == SIGTTIN || j == SIGTTOU) { udata.u_ptab->p_status = P_STOPPED; udata.u_ptab->p_event = j; psleep(NULL); } /* This is more complex than in V7 - we have multiple behaviours (plus the unimplemented as yet core dump) */ if (*svec == SIG_DFL) { /* SIGCONT is subtle - we woke the process to handle the signal so ignoring here works fine */ if (j == SIGCHLD || j == SIGURG || j == SIGSTOP || j == SIGTTIN || j == SIGTTOU || j == SIGIO || j == SIGCONT || udata.u_ptab->p_pid == 1) { udata.u_ptab->p_pending &= ~m; // unset the bit continue; } /* FIXME: core dump on some signals */ #ifdef DEBUG kprintf("process terminated by signal %d\n", j); #endif doexit(dump_core(j)); } else if (*svec != SIG_IGN) { /* Arrange to call the user routine at return */ udata.u_ptab->p_pending &= ~m; // unset the bit #ifdef DEBUG kprintf("about to process signal %d\n", j); #endif udata.u_cursig = j; break; } } }
void signal_frame(uint8_t *trapframe, uint32_t d0, uint32_t d1, uint32_t a0, uint32_t a1) { extern void *udata_shadow; uint8_t *usp = get_usp(); udata_ptr = udata_shadow; uint16_t ccr = *(uint16_t *)trapframe; uint32_t addr = *(uint32_t *)(trapframe + 2); int err = 0; /* Build the user stack frame */ /* FIXME: eventually we should put the trap frame details and trap info into the frame */ usp -= 4; err |= uputl(addr, usp); usp -= 4; err |= uputw(ccr, usp); usp -= 2; err |=uputl(a1, usp); usp -= 4; err |= uputl(a0, usp); usp -= 4; err |= uputl(d1, usp); usp -= 4; err |= uputl(d0, usp); usp -= 4; err |= uputl(udata.u_codebase + 4, usp); set_usp(usp); if (err) { kprintf("%d: stack fault\n", udata.u_ptab->p_pid); doexit(dump_core(SIGKILL)); } /* Now patch up the kernel frame */ *(uint16_t *)trapframe = 0; *(uint32_t *)(trapframe + 2) = (uint32_t)udata.u_sigvec[udata.u_cursig]; udata.u_sigvec[udata.u_cursig] = SIG_DFL; udata.u_cursig = 0; }
/**************************************************************************** ** possibly continue after a fault **************************************************************************** */ static void fault_continue(void) { #if DUMP_CORE dump_core(); #endif } /* fault_continue */
static void fault_continue(void) { dump_core(); }
static void tracer_dump(pid_t pid) { /* Read arguments from tracee */ handle_events_until_dump_trap(-1); register_t ret = get_arg_from_regs(pid); assert(ret == TRAP_START_ARGS); debug_print("receive string from tracee %d\n", pid); ptrace_getdata(pid, (long) tracer_buff->str_tmp, loop_name, SIZE_LOOP); ptrace_syscall(pid); invocation = (int)receive_from_tracee(pid); ptrace_syscall(pid); int arg_count = (int)receive_from_tracee(pid); ptrace_syscall(pid); printf("DUMP( %s %d count = %d) \n", loop_name, invocation, arg_count); /* Ensure that the dump directory exists */ snprintf(dump_path, sizeof(dump_path), "%s/%s/%s", dump_prefix, dump_root, loop_name); mkdir(dump_path, 0777); snprintf(dump_path, sizeof(dump_path), "%s/%s/%s/%d", dump_prefix, dump_root, loop_name, invocation); if (mkdir(dump_path, 0777) != 0) errx(EXIT_FAILURE, "dump %s already exists, stop\n", dump_path); int i; void *addresses[arg_count]; for (i = 0; i < arg_count; i++) { addresses[i] = (void *)receive_from_tracee(pid); ptrace_syscall(pid); } /* Wait for end of arguments sigtrap */ handle_events_until_dump_trap(pid); ret = get_arg_from_regs(pid); assert(ret == TRAP_END_ARGS); /* Dump hotpages to disk */ flush_hot_pages_trace_to_disk(pid); char lel_bin_path[1024]; /* Link to the original binary */ snprintf(lel_bin_path, sizeof(lel_bin_path), "%s/lel_bin", dump_path); int res = linkat(AT_FDCWD, "lel_bin", AT_FDCWD, lel_bin_path, AT_SYMLINK_FOLLOW); if (res == -1) errx(EXIT_FAILURE, "Error copying the dump binary\n"); for (i = 0; i < arg_count; i++) { void *start_of_page = round_to_page(addresses[i]); if (start_of_page != NULL) { unprotect_i(pid, start_of_page, PAGESIZE); dump_page(pid, start_of_page); } } if (firsttouch_active) { dump_firsttouch(); } dump_core(arg_count, addresses); dump_unprotected_pages(pid); }
static void fault_quit(void) { #if DUMP_CORE dump_core(); #endif }
static void fault_quit(void) { dump_core(); }
uint8_t chksigs(void) { uint8_t j; uint32_t pending = udata.u_ptab->p_pending & ~udata.u_ptab->p_held; int (**svec)(int) = &udata.u_sigvec[0]; uint32_t m; /* Fast path - no signals pending means no work. Cursig being set means we've already worked out what to do. */ rescan: if (udata.u_cursig || !pending || udata.u_ptab->p_status == P_STOPPED) return udata.u_cursig; /* Dispatch the lowest numbered signal */ for (j = 1; j < NSIGS; ++j) { svec++; m = sigmask(j); if (!(m & pending)) continue; /* This is more complex than in V7 - we have multiple behaviours plus core dump */ if (*svec == SIG_DFL) { /* SIGSTOP can't be ignored and puts the process into P_STOPPED state when it is ready to handle the signal. Annoyingly right now we have to context switch to the task in order to stop it in the right place. That would be nice to fix */ if (m & stopper) { /* Don't allow us to race SIGCONT */ irqflags_t irq = di(); /* FIXME: can we ever end up here not in READY/RUNNING ? */ nready--; udata.u_ptab->p_status = P_STOPPED; udata.u_ptab->p_event = j; udata.u_ptab->p_pending &= ~m; // unset the bit irqrestore(irq); switchout(); /* Other things may have happened */ goto rescan; } /* The signal is being handled, so clear it even if we are exiting (otherwise we'll loop in chksigs) */ udata.u_ptab->p_pending &= ~m; if ((m & clear) || udata.u_ptab->p_pid == 1) { /* SIGCONT is subtle - we woke the process to handle the signal so ignoring here works fine */ continue; } #ifdef DEBUG kprintf("process terminated by signal %d\n", j); #endif /* We may have marked ourselves as asleep and then been caught by the chksigs when we tried to task switch into bed. In that case we need to put the process back in running state */ if (udata.u_ptab->p_status == P_SLEEP) { udata.u_ptab->p_status = P_RUNNING; nready++; } doexit(dump_core(j)); } else if (*svec != SIG_IGN) { /* Arrange to call the user routine at return */ udata.u_ptab->p_pending &= ~m; // unset the bit #ifdef DEBUG kprintf("about to process signal %d\n", j); #endif udata.u_cursig = j; break; } } return udata.u_cursig; }
int exception(struct trapdata *framedata) { ptptr proc; unsigned int frame, fsize; uint8_t trap = framedata->trap; unsigned int sig = 0; uint16_t m; uint16_t *sp = (uint16_t *)framedata; uint16_t *usp = get_usp(); uint16_t *unwind, *context; uint8_t err = 0; int i; /* We translate debug to SIGIOT and A and F line to SIGILL We will need to fix up 68000 v 68010 move to/from SR */ static const uint8_t trap_to_sig[] = { 0, 0, SIGSEGV, SIGBUS, SIGILL, SIGFPE, SIGABRT/*CHK*/, SIGTRAP/*TRAPV */, SIGILL, SIGIOT, SIGILL, SIGFPE }; proc = udata.u_ptab; if (sysinfo.cpu[0] == 10) { /* Long or short frame: the CPU tells us the frame format */ if (framedata->exception[3] & 0x8000) { fsize = 29; frame = FRAME_C; } else { fsize = 4; frame = FRAME_D; } } else { frame = FRAME_B; fsize = 3; } if (trap == 0) { sig = udata.u_cursig; udata.u_cursig = 0; } else if (trap < 12) { if (trap < 4) { /* On a 68010 this frame is 29 words and the event is restartable (although not always usefully). We need to decide whether to set the restart flag case by case */ if (sysinfo.cpu[0] == 0) { frame = FRAME_A; fsize = 7; } } sig = trap_to_sig[trap]; } else if (trap >= 32 && trap < 48) sig = SIGTRAP; /* This processing only applies to synchronous hardware exceptions */ if (trap) { /* Went boom in kernel space or without a user recovery */ if (kernel_flag || sig == 0) { explode(framedata, frame); panic("trap"); } /* Cheating here .. all our exceptions are low 16 signal */ m = 1 << sig; /* * The caller is ignoring our signal. In some cases this is fine * but in others it's less clear (eg division by zero) and we * may need to take different action. */ if (proc->p_sig[0].s_ignored & m) return 0; /* Weird case - we took a sync signal and the caller wants us to report it later. */ if (proc->p_sig[0].s_held & m) { /* TODO: if it's not meaningfully restartable we should probably treat this as a kill */ ssig(proc, sig); return 0; } recalc_cursig(); /* Put any async signal back */ } if (udata.u_sigvec[sig] == SIG_DFL) { /* Default action for our signal ? */ doexit(dump_core(sig)); /* This will never return. We will go schedule new work */ panic("exret"); } /* build signal frame Our unwinder code does move.l 8(sp),sp movem.l a0-a1/d0-d1,(sp)+ move.w (sp)+,ccr rts */ /* Now update the user stack */ /* - Push the recovery PC */ /* - Patch the kernel exception frame */ if (sysinfo.cpu[0]) { /* FIXME */ err |= pushw(&usp, sp[34]); err |= pushw(&usp, sp[33]); *(uint32_t *)(&sp[33]) = (uint32_t)udata.u_sigvec[sig]; } else { err |= pushw(&usp, sp[31 + fsize]); err |= pushw(&usp, sp[30 + fsize]); *(uint32_t *)(&sp[30 + fsize]) = (uint32_t)udata.u_sigvec[sig]; } /* FIXME: when we do ptrace we will need to support adding the T flag back here as the exception cleared it */ err |= pushw(&usp, framedata->sr); /* Push A1 A0 D1 D0 to match MOVEM.L */ err |= pushl(&usp, framedata->a[1]); err |= pushl(&usp, framedata->a[0]); err |= pushl(&usp, framedata->d[1]); err |= pushl(&usp, framedata->d[0]); /* Remember the target for undoing the frame */ unwind = usp; /* Copy in the signal context itself. 30 words of registers, 2 of trap code and then the hardware exception */ for (i = 0; i < 30 + 2 + fsize; i++) err |= pushw(&usp, *sp++); context = usp; err |= pushl(&usp, (uint32_t)unwind); /* Signal context is a secret extra non portable argument */ err |= pushl(&usp, (uint32_t)context); /* We end it with the call frame as seen from the signal handler, a single argument and a return address */ err |= pushl(&usp, sig); err |= pushl(&usp, udata.u_codebase + 0x04); set_usp(usp); if (err) { doexit(dump_core(SIGSTKFLT)); panic("exret2"); } /* Once built clear the restart state */ udata.u_sigvec[sig] = SIG_DFL; /* Return, RTE and end up on the signal frame */ return 1; }
static void exit_server_common(enum server_exit_reason how, const char *const reason) { struct smbd_server_connection *sconn = smbd_server_conn; if (!exit_firsttime) exit(0); exit_firsttime = false; change_to_root_user(); if (sconn && sconn->smb1.negprot.auth_context) { TALLOC_FREE(sconn->smb1.negprot.auth_context); } if (sconn) { if (lp_log_writeable_files_on_exit()) { bool found = false; files_forall(sconn, log_writeable_file_fn, &found); } (void)conn_close_all(sconn); invalidate_all_vuids(sconn); } /* 3 second timeout. */ print_notify_send_messages(sconn->msg_ctx, 3); /* delete our entry in the serverid database. */ if (am_parent) { /* * For children the parent takes care of cleaning up */ serverid_deregister(sconn_server_id(sconn)); } #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); } #endif #ifdef USE_DMAPI /* Destroy Samba DMAPI session only if we are master smbd process */ if (am_parent) { if (!dmapi_destroy_session()) { DEBUG(0,("Unable to close Samba DMAPI session\n")); } } #endif if (am_parent) { rpc_wkssvc_shutdown(); #ifdef ACTIVE_DIRECTORY rpc_dssetup_shutdown(); #endif #ifdef DEVELOPER rpc_rpcecho_shutdown(); #endif #ifdef DFS_SUPPORT rpc_netdfs_shutdown(); #endif rpc_initshutdown_shutdown(); #ifdef EXTRA_SERVICES rpc_eventlog_shutdown(); rpc_svcctl_shutdown(); rpc_ntsvcs_shutdown(); #endif #ifdef PRINTER_SUPPORT rpc_spoolss_shutdown(); #endif rpc_srvsvc_shutdown(); #ifdef WINREG_SUPPORT rpc_winreg_shutdown(); #endif #ifdef NETLOGON_SUPPORT rpc_netlogon_shutdown(); #endif #ifdef SAMR_SUPPORT rpc_samr_shutdown(); #endif #ifdef LSA_SUPPORT rpc_lsarpc_shutdown(); #endif } /* * we need to force the order of freeing the following, * because smbd_msg_ctx is not a talloc child of smbd_server_conn. */ sconn = NULL; TALLOC_FREE(smbd_server_conn); server_messaging_context_free(); server_event_context_free(); TALLOC_FREE(smbd_memcache_ctx); locking_end(); printing_end(); if (how != SERVER_EXIT_NORMAL) { DEBUGSEP(0); DEBUG(0,("Abnormal server exit: %s\n", reason ? reason : "no explanation provided")); DEBUGSEP(0); log_stack_trace(); dump_core(); /* Notreached. */ exit(1); } else { DEBUG(3,("Server exit (%s)\n", (reason ? reason : "normal exit"))); if (am_parent) { pidfile_unlink(); } gencache_stabilize(); } exit(0); }
static void exit_server_common(enum server_exit_reason how, const char *const reason) { static int firsttime=1; if (!firsttime) { #ifndef _XBOX exit(0); #endif } firsttime = 0; change_to_root_user(); if (negprot_global_auth_context) { (negprot_global_auth_context->free)(&negprot_global_auth_context); } conn_close_all(); invalidate_all_vuids(); #ifndef _XBOX print_notify_send_messages(3); /* 3 second timeout. */ #endif /* delete our entry in the connections database. */ yield_connection(NULL,""); respond_to_all_remaining_local_messages(); decrement_smbd_process_count(); #ifdef WITH_DFS if (dcelogin_atmost_once) { dfs_unlogin(); } #endif #ifndef _XBOX locking_end(); printing_end(); #endif if (how != SERVER_EXIT_NORMAL) { int oldlevel = DEBUGLEVEL; char *last_inbuf = get_InBuffer(); DEBUGLEVEL = 10; DEBUGSEP(0); DEBUG(0,("Abnormal server exit: %s\n", reason ? reason : "no explanation provided")); DEBUGSEP(0); #ifndef _XBOX log_stack_trace(); #endif if (last_inbuf) { DEBUG(0,("Last message was %s\n", LAST_MESSAGE())); show_msg(last_inbuf); } DEBUGLEVEL = oldlevel; #if DUMP_CORE dump_core(); #endif } else { DEBUG(3,("Server exit (%s)\n", (reason ? reason : "normal exit"))); } #ifndef _XBOX exit(0); #endif }