// Run the command specified by the argv array and kill it after timeout // seconds. static void SpawnCommand(char *const *argv, double timeout_secs) { CHECK_CALL(global_child_pid = fork()); if (global_child_pid == 0) { // In child. CHECK_CALL(setsid()); ClearSignalMask(); // Force umask to include read and execute for everyone, to make // output permissions predictable. umask(022); // Does not return unless something went wrong. execvp(argv[0], argv); err(EXIT_FAILURE, "execvp(\"%s\", ...)", argv[0]); } else { // In parent. // Set up a signal handler which kills all subprocesses when the given // signal is triggered. HandleSignal(SIGALRM, OnSignal); HandleSignal(SIGTERM, OnSignal); HandleSignal(SIGINT, OnSignal); SetTimeout(timeout_secs); int status = WaitChild(global_child_pid, argv[0]); // The child is done for, but may have grandchildren that we still have to // kill. kill(-global_child_pid, SIGKILL); if (global_signal > 0) { // Don't trust the exit code if we got a timeout or signal. UnHandle(global_signal); raise(global_signal); } else if (WIFEXITED(status)) { exit(WEXITSTATUS(status)); } else { int sig = WTERMSIG(status); UnHandle(sig); raise(sig); } } }
void UnHandle(int sig) { switch (sig) { case SIGSTOP: case SIGKILL: // These signals can't be handled, so they'll always have a valid default // handler. In fact, even trying to install SIG_DFL again will result in // EINVAL, so we'll just not do anything for these. return; default: HandleSignal(sig, SIG_DFL); } }
void DirPop(int goback,char * name,struct stat *sb) /* Exit dir and check for race exploits */ { if (goback && TRAVLINKS) { if (chdir(name) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } CheckLinkSecurity(sb,name); } else if (goback) { if (chdir("..") == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Error in backing out of recursive descent securely to %s",name); CfLog(cferror,OUTPUT,"chdir"); HandleSignal(SIGTERM); } } }
void CheckLinkSecurity(struct stat *sb,char *name) { struct stat security; Debug("Checking the inode and device to make sure we are where we think we are...\n"); if (stat(".",&security) == -1) { snprintf(OUTPUT,CF_BUFSIZE,"Could not stat directory %s after entering!",name); CfLog(cferror,OUTPUT,"stat"); return; } if ((sb->st_dev != security.st_dev) || (sb->st_ino != security.st_ino)) { snprintf(OUTPUT,CF_BUFSIZE,"SERIOUS SECURITY ALERT: path race exploited in recursion to/from %s. Not safe for agent to continue - aborting",name); CfLog(cferror,OUTPUT,""); HandleSignal(SIGTERM); /* Exits */ } }
// Set up various signal handlers. static void SetupSignals(void) { HandleSignal(SIGSEGV, RecoverFromError); HandleSignal(SIGBUS, RecoverFromError); HandleSignal(SIGFPE, RecoverFromError); HandleSignal(SIGTRAP, ConsumeTrap); HandleSignal(SIGILL, HandleUnsupportedInstruction); #ifdef SIGSTKFLT HandleSignal(SIGSTKFLT, RecoverFromError); #endif // SIGSTKFLT sigset_t set; sigemptyset(&set); sigprocmask(SIG_SETMASK, &set, nullptr); stack_t sig_stack; sig_stack.ss_sp = &gSigStack; sig_stack.ss_size = SIGSTKSZ; sig_stack.ss_flags = 0; sigaltstack(&sig_stack, nullptr); }
/** * @function GUI_DrawObjects * @brief handle all object (user event, refresh) * @param none * @return none */ void GUI_DrawObjects(void) { g_obj_st *ptr = NULL; coord_t newX, newY; /*reset signal & read touch screen; only once for all object*/ signal = 0; TouchScreenRead(&newX, &newY); /*small hysteresis to compensate touchscreen noise*/ #define TOUCH_THRES_HYS 2 if(newX < 0 || newY < 0) { x = y = -1; } else { if(x < 0 || y < 0) { x = newX; y = newY; } else if(P2D_Abs(newX - x) > TOUCH_THRES_HYS || P2D_Abs(newY - y) > TOUCH_THRES_HYS) { x = newX; y = newY; } } /*get the object list, according to the active layer*/ ptr = GetObjectList(); /*process notification blink*/ if(IsTimerElapsed(tmrBlink)) { bBlink = !bBlink; tmrBlink = GetPeriodicTimeout(500); while(ptr != NULL) { GUI_ObjSetBlink(ptr, bBlink); ptr = ptr->next; } } /*process each generic object of the current layer*/ while(ptr != NULL) { /*handle user interaction*/ HandleTouchEvent(x, y, ptr); /*handle object signals*/ HandleSignal(ptr); if(ptr->obj != NULL) { /*launch the object task, if any*/ if(ptr->task != NULL) ptr->task(ptr, ptr->obj); /*redraw the object, only if needed*/ if(GUI_ObjIsNeedRefresh(ptr) && ptr->draw != NULL) { P2D_SetClip(&(ptr->rec)); ptr->draw(ptr, ptr->obj); GUI_ObjSetNeedRefresh(ptr, false); } } /*next object*/ ptr = ptr->next; } /** * execute, if any, the top layer task * pInternalTask may close the top layer and return a signal; * when closing the top layer, pInternalTask becomes NULL * this signal will be given to the user at end of GUI_DrawObjects() */ if(pInternalTask != NULL) signal = pInternalTask(signal); /** * Save the last non null signal (for slave remote) */ if(signal != 0 && pInternalTask == NULL) { lastSignal = signal; } /** * execute the user task, if no internal task is running * DO NOT concate this condition with the previous one in a if/else statement ! */ if(pInternalTask == NULL) { if(pUserTask != NULL) pUserTask(signal); } }