//! Returns locale of a process char * get_proc_lang(pid_t pid) { pid_t pids[2]; pids[0] = pid; pids[1] = 0; proc_t proc; PROCTAB *ptp; int i = 0; char *lang = NULL; ptp = openproc(PROC_FILLENV | PROC_PID, pids); while(readproc(ptp, &proc)) { while (proc.environ[++i]) { if (strncmp(proc.environ[i - 1], "LANG", 4) == 0) { lang = strsub(proc.environ[i - 1], 5, 7); goto out; } } } out: closeproc(ptp); return lang; }
QueryData genProcesses(QueryContext& context) { QueryData results; proc_t* proc_info; PROCTAB* proc = openproc(PROC_SELECTS); // Populate proc struc for each process. while ((proc_info = readproc(proc, NULL))) { Row r; r["pid"] = INTEGER(proc_info->tid); r["uid"] = BIGINT((unsigned int)proc_info->ruid); r["gid"] = BIGINT((unsigned int)proc_info->rgid); r["euid"] = BIGINT((unsigned int)proc_info->euid); r["egid"] = BIGINT((unsigned int)proc_info->egid); r["name"] = proc_name(proc_info); r["cmdline"] = proc_cmdline(proc_info); r["path"] = proc_link(proc_info); r["on_disk"] = osquery::pathExists(r["path"]).toString(); r["resident_size"] = INTEGER(proc_info->vm_rss); r["phys_footprint"] = INTEGER(proc_info->vm_size); r["user_time"] = INTEGER(proc_info->utime); r["system_time"] = INTEGER(proc_info->stime); r["start_time"] = INTEGER(proc_info->start_time); r["parent"] = INTEGER(proc_info->ppid); results.push_back(r); standard_freeproc(proc_info); } closeproc(proc); return results; }
QueryData genProcessEnvs(QueryContext& context) { QueryData results; proc_t* proc_info; PROCTAB* proc = openproc(PROC_SELECTS); // Populate proc struc for each process. while ((proc_info = readproc(proc, NULL))) { auto env = proc_env(proc_info); for (auto itr = env.begin(); itr != env.end(); ++itr) { Row r; r["pid"] = INTEGER(proc_info->tid); r["name"] = proc_name(proc_info); r["path"] = proc_link(proc_info); r["key"] = itr->first; r["value"] = itr->second; results.push_back(r); } standard_freeproc(proc_info); } closeproc(proc); return results; }
QueryData genProcesses() { QueryData results; proc_t* proc_info; PROCTAB* proc = openproc(PROC_SELECTS); // Populate proc struc for each process. while ((proc_info = readproc(proc, NULL))) { Row r; r["pid"] = boost::lexical_cast<std::string>(proc_info->tid); r["name"] = proc_name(proc_info); r["cmdline"] = proc_cmdline(proc_info); r["path"] = proc_link(proc_info); r["on_disk"] = osquery::pathExists(r["path"]).toString(); r["resident_size"] = boost::lexical_cast<std::string>(proc_info->vm_rss); r["phys_footprint"] = boost::lexical_cast<std::string>(proc_info->vm_size); r["user_time"] = boost::lexical_cast<std::string>(proc_info->utime); r["system_time"] = boost::lexical_cast<std::string>(proc_info->stime); r["start_time"] = boost::lexical_cast<std::string>(proc_info->start_time); r["parent"] = boost::lexical_cast<std::string>(proc_info->ppid); results.push_back(r); standard_freeproc(proc_info); } closeproc(proc); return results; }
void ProcessManager::WarnExcess() { PROCTAB* proc = openproc(PROC_FILLARG | PROC_FILLSTAT | PROC_FILLMEM); proc_t * proc_info; Core::DebugLog("Looking for processes that exceed the hard or soft limit", 10); while (true) { proc_info = readproc(proc, NULL); if (proc_info == NULL) { break; } if (!Configuration::KillRoot && proc_info->euid == 0) { if (Configuration::Verbosity >= 6) { Core::DebugLog("Ignoring " + Core::int2String(proc_info->tid) + " owned by root", 6); } freeproc(proc_info); continue; } if (proc_info->tid == Configuration::pid && !Configuration::KillSelf) { Core::DebugLog("Ignoring " + Core::int2String(proc_info->tid) + " which is current instance of this daemon", 6); freeproc(proc_info); continue; } if (IgnoredId(proc_info->euid)) { Core::DebugLog("Ignoring " + Core::int2String(proc_info->tid) + " owned by ignored account: " + Core::int2String(proc_info->euid), 2); freeproc(proc_info); continue; } // check if this process is using most memory if ( proc_info->resident * 4 > ((long)Configuration::HardMemoryLimitMB * 1024 )) { Core::Log("WARNING: Exceeded hard limit - process " + Name(proc_info)); } else if ( proc_info->resident * 4 > ((long)Configuration::SoftMemoryLimitMB * 1024 )) { Core::Log("WARNING: Exceeded soft limit - process " + Name(proc_info)); } else { if (Configuration::Verbosity > 12) { Core::DebugLog("Not exceeded any limit " + Name(proc_info)); } } freeproc(proc_info); } closeproc(proc); return; }
/* The collector thread is responsible * for collecting data about running processes * and placing them in a structure that * The analyzer thread can read quickly */ void* collector_thread(void *a) { PROCTAB *proct; proc_t *proc_info; int hangup = 0; while (!hangup) { pthread_mutex_lock(&procsnap_mutex); proct = openproc(PROC_FILLARG | PROC_FILLSTAT | PROC_FILLSTATUS);//PROC_FILLMEM | PROC_FILLSTATUS | PROC_FILLSTAT | PROC_FILLARG); if (procsnap == NULL) { procsnap = (proc_statistics *) calloc(MAXPROCAVS, sizeof(proc_statistics)); if (procsnap == NULL) { printf("Can not allocate memory."); exit(-1); } } numprocsnap = 0; while((proc_info = readproc(proct,NULL))) { if (procsnap[numprocsnap]._command == NULL) { if ((procsnap[numprocsnap]._command = (char*)malloc(20*sizeof(char))) == NULL) { printf("malloc error, can not allocate memory.\n"); exit(-1); } if (procsnap[numprocsnap]._command == NULL) { printf("Can not allocate memory."); exit(-1); } } procsnap[numprocsnap]._pid = proc_info->tid; procsnap[numprocsnap]._uid = proc_info->ruid; strncpy(procsnap[numprocsnap]._command, proc_info->cmd, 20); procsnap[numprocsnap]._rssize = proc_info->rss; procsnap[numprocsnap]._size = proc_info->size; procsnap[numprocsnap]._perc = proc_info->pcpu; procsnap[numprocsnap]._age = 0; procsnap[numprocsnap]._read = 0; freep(proc_info); numprocsnap++; } closeproc(proct); pthread_mutex_unlock(&procsnap_mutex); pthread_mutex_lock(&hangup_mutex); if (m_hangup) hangup = 1; pthread_mutex_unlock(&hangup_mutex); if (!hangup) sleep(1); } return NULL; }
// all processes IoStatistics getAllProcessesIo() { IoStatistics info; info.read = 0; info.write = 0; #ifdef ANDROID _readSendTransmit(fopen(PROC_NET_DEV, "r"), &info); unsigned long read = 0; unsigned long write = 0; struct hd_driveid *id; int res, res2; FILE* fd = fopen(PROC_DISKSTATS, "r"); char dev[100]; char filename[BUFSIZ]; if (NULL != fd) { do { // # reads, #reads merged, #sect read, #ms reading, #writes, #sect written #ms writing #ios in progress #ms ios #weighted ios res = fscanf(fd, "%*u %*u %s %*u %*u %lu %*u %*u %lu %*u %*u %*u %*u %*u\n", dev, &read, &write); if (res > 0) { // prefer sda1 over sda res2 = sscanf(dev, "%*a[a-zA-z]%*u"); if (res2 > 0) { sprintf(filename, DEV_DEVID, dev); int devFd = open(filename, O_RDONLY|O_NONBLOCK); if (devFd >= 0) { if (ioctl(devFd, HDIO_GET_IDENTITY, id)) { info.read += read * id->sector_bytes; info.write += write * id->sector_bytes; } close(devFd); } } } } while (res > 0 && !feof(fd)); fclose(fd); } #else info.read = 0; info.write = 0; proc_t table; PROCTAB* PT = openproc(PROC_FILLMEM | PROC_FILLSTAT); if (NULL != PT) { info.read = 0; info.write = 0; while (NULL != readproc(PT, &table)) { IoStatistics procStat = _getProcessIo(table.tgid); info.read += procStat.read; info.write += procStat.write; } closeproc(PT); } #endif return info; }
extern int nummaps() { int nmaps, fd = openproc(); if (fd == ERROR) return ERROR; if (ERROR == ioctl(fd, PIOCNMAP, &nmaps)) { close(fd); perror("can't get number of memory maps\n"); exit(1); } close(fd); return nmaps; }
int process_list_processes(process_list_t **result) { proc_t proc_info; #ifdef COLLECT_STATS size_t proc_count = 0; extern stats_t stats; struct timeval tv1; gettimeofday(&tv1, NULL); #endif PROCTAB *proc = openproc(PROC_FILLMEM | PROC_FILLSTAT | PROC_FILLSTATUS | PROC_FILLCOM); memset(&proc_info, 0, sizeof(proc_info)); while (readproc(proc, &proc_info) != NULL) { process_t *to_add = calloc(1, sizeof(process_t)); to_add->tgid = proc_info.tgid; to_add->name = proc_info.cmd; if (proc_info.cmdline != NULL) { to_add->cmdline = strjoinv(" ", proc_info.cmdline); } to_add->vms = proc_info.vm_size; to_add->rss = proc_info.vm_rss; to_add->threads_num = proc_info.nlwp; to_add->utime = proc_info.utime; to_add->stime = proc_info.stime; to_add->user = proc_info.euid; #ifdef COLLECT_STATS proc_count++; #endif LL_APPEND((*result)->processes, to_add); // printf("%20s:\t%5ld\t%5lld\t%5lld\n", proc_info.cmd, proc_info.resident, // proc_info.utime, proc_info.stime); } closeproc(proc); struct timeval tv; gettimeofday(&tv, NULL); (*result)->timestamp = 1000000 * tv.tv_sec + tv.tv_usec; #ifdef COLLECT_STATS uint64_t t1 = 1000000 * tv1.tv_sec + tv1.tv_usec; stats.ps_dur = (*result)->timestamp - t1; stats.ps_times_count += 1; stats.ps_last_count = proc_count; #endif return 1; }
void process_processes(double cpup_limit, unsigned memory_limit, int maxNProc, char* name){ PROCTAB* proc = openproc(PROC_FILLMEM | PROC_FILLUSR | PROC_FILLSTAT | PROC_FILLSTATUS); userstats = NULL; proc_t proc_info; memset(&proc_info, 0, sizeof(proc_info)); while(readproc(proc, &proc_info) != NULL ) { if(strcmp(proc_info.suser,"root") != 0){ struct cur_process *cpp = find_process(proc_info.tid); if(cpp != NULL){ time_t prev_time = cpp->timestamp; time_t cur_time = getCurrentTime(); double diff_in_seconds = difftime(cur_time,prev_time); long unsigned int pid_diff = (proc_info.utime + proc_info.stime) - (cpp->utime + cpp->stime); double cpu_percentage = pid_diff / diff_in_seconds; unsigned memory = proc_info.vm_rss; if(cpup_limit > 0 && (strcmp(cpp->user,name) == 0 || isUserOfGroup(cpp->user,name))) checkCPUPLimit(cpup_limit, cpu_percentage, proc_info.suser, proc_info.cmd, proc_info.tid); if(memory_limit >0 && (strcmp(cpp->user,name) == 0 || isUserOfGroup(cpp->user, name))) checkMemoryLimit(memory_limit, memory, proc_info.suser, proc_info.cmd, proc_info.tid ); }else{ //printf("No Old process found \n"); } struct cur_process *cp = malloc(sizeof(struct cur_process)); cp->pid = proc_info.tid; cp->cutime = proc_info.cutime; cp->cstime = proc_info.cstime; cp->utime = proc_info.utime; cp->stime = proc_info.stime; cp->user = proc_info.suser; cp->command = proc_info.cmd; cp->vm_size = proc_info.vm_rss; cp->group = proc_info.rgroup; cp->timestamp = getCurrentTime(); add_process(cp); //printf("Group Name %s \n", proc_info.fgroup); if(maxNProc > 0 && (strcmp(cp->user,name) == 0 || isUserOfGroup(cp->user,name))) countAndValidateNProc(proc_info.suser, maxNProc); //printf("%5d\t%20s:\t%5lld\t%5lu\t%s\n",proc_info.tid, proc_info.cmd, proc_info.utime + proc_info.stime, proc_info.vm_size, proc_info.suser); } } closeproc(proc); }
extern int getmaps(int nmaps, struct MAP maps[nmaps]) { int i; prmap_t buf[nmaps+1]; int fd = openproc(); if (fd == ERROR) return ERROR; if (ERROR == ioctl(fd, PIOCMAP, buf)) { close(fd); return ERROR; } for (i=0; i<nmaps; i++) { maps[i].from = buf[i].pr_vaddr; maps[i].to = buf[i].pr_vaddr + buf[i].pr_size; maps[i].r = (buf[i].pr_mflags & MA_READ ) != 0; maps[i].w = (buf[i].pr_mflags & MA_WRITE) != 0; maps[i].x = (buf[i].pr_mflags & MA_EXEC ) != 0; maps[i].checksum = 0; maps[i].filename = NULL; } return close(fd); }
int main(int argc, char *argv[]){ FILE *file = fopen(argv[1],"r"); int i, len, sig,status; int numPrograms = 0; int runningProcess = 1; wordexp_t wordStruct; wordexp_t wordArray[MAXLEN]; char buffer[MAXLEN][MAXLEN]; char line[MAXLEN]; sigset_t sigSet; pid_t pid[numPrograms]; pid_t tempChild; pid_t procPID[numPrograms]; signal(SIGALRM,signalHandler); sigemptyset(&sigSet); sigaddset(&sigSet, SIGUSR1); sigprocmask(SIG_BLOCK,&sigSet,NULL); PROCTAB* proc; proc_t* procInfo; proc_t info; if( file != NULL){ /***PART 1***/ char* get; while((get = fgets(line, sizeof(line),file)) != NULL) { len = strlen(line); if(line[len-1] == '\n'){ line[len-1] = '\0'; } memset(&wordStruct, 0, sizeof(wordStruct)); strcpy(buffer[numPrograms], line); wordexp(buffer[numPrograms],&wordStruct,0); wordArray[numPrograms] = wordStruct; numPrograms++; } for(i = 0; i < numPrograms; ++i){ /***fork child process***/ tempChild = fork(); if(tempChild < 0){ perror("failed to fork\n"); exit(1); } if(tempChild ==0){ /***part 2***/ sigwait(&sigSet,&sig); if(execvp(wordArray[i].we_wordv[0], wordArray[i].we_wordv) == -1){ perror("Execution failed\n"); } } else if ( tempChild > 0) { pid[i] = tempChild; wordfree(&(wordArray[i])); } } /***Wake up child process***/ for(i = 0; i < numPrograms; ++i){ kill(pid[i],SIGUSR1); printf("Process %d signaled SIGUSR1\n",pid[i]); } /**Stop child process**/ for(i = 0; i < numPrograms; ++i){ kill(pid[i],SIGSTOP); printf("Process %d signaled SIGSTOP\n",pid[i]); } /*************************************** * * This while loop was used in part 2 of the mcp project * but removed. removed from part 2 * for(i = 0; i < numPrograms; ++i){ * kill(pid[i],SIGCONT); * printf("Child %d is continuing\n",i); * waitpid(-1,&pid[i],0); *} * *****************************************/ /************** * Got idea of this while loop from office hours * * * while flag{ * * flag = false; * for id in pids: * if running ID * flag == true * //ran process * * } * ***************/ /**flag **/ while(runningProcess == 1 ){ runningProcess = 0; for( i = 0; i < numPrograms; ++i){ if(waitpid(pid[i], &status, WNOHANG) == 0){ runningProcess = 1; printf("Process %d resumed\n",pid[i]); printf("----------------------\n"); kill(pid[i],SIGCONT); /**PART 4**/ proc = openproc(PROC_FILLMEM | PROC_FILLSTAT | PROC_FILLSTATUS| PROC_PID,pid); memset(&info, 0, sizeof(info)); printf("%20s:\t%s\t%5s\n", "COMMAND","PRIORITY","PPID(PID of parent)"); printf("%20s\t%s\t%5s\n", "--------","--------","----"); while((procInfo = readproc(proc,&info)) != NULL){ printf("%20s:\t%lu\t\t%5i\n", info.cmd, info.priority,info.ppid); } closeproc(proc); /**PART 3 alarm handler**/ alarm(1); /**Interupts the MCP**/ while(alarmHandler == 0){ ; } alarmHandler = 0; kill(pid[i],SIGSTOP); printf("----------------------\n"); printf("Stopping process %d \n",pid[i]); printf("----------------------\n"); } } } } printf("\nChild processes complete\nProgram Complete\n"); fclose(file); }
//! Kill process which is eating most void ProcessManager::KillHighest(bool hard) { PROCTAB* proc = openproc(PROC_FILLARG | PROC_FILLSTAT | PROC_FILLMEM); proc_t* proc_info; // zero out the allocated proc_info memory //memset(&proc_info, 0, sizeof(proc_info)); proc_t highest; long current_highest = 0; int current_score = -100; Core::DebugLog("Looking for a best candidate"); while (true) { proc_info = readproc(proc, NULL); if (proc_info == NULL) { break; } if (!Configuration::KillRoot && (int)proc_info->euid == 0) { if (Configuration::Verbosity >= 6) { Core::DebugLog("Ignoring " + Core::int2String(proc_info->tid) + " owned by root", 6); } freeproc(proc_info); continue; } if (IgnoredId(proc_info->euid)) { Core::DebugLog("Ignoring " + Core::int2String(proc_info->tid) + " owned by ignored account: " + Core::int2String(proc_info->euid), 2); freeproc(proc_info); continue; } if (proc_info->tid == Configuration::pid && !Configuration::KillSelf) { Core::DebugLog("Ignoring " + Core::int2String(proc_info->tid) + " which is current instance of this daemon", 6); freeproc(proc_info); continue; } int score = 0; // if it's a root process, decrease the score by 10 if (proc_info->euser == 0) { score -= 10; } score = score + (int)proc_info->nice; int badness_score = Core::GetOom(proc_info->tid); if (badness_score <= -17) { // ignore process freeproc(proc_info); continue; } if (badness_score != 0) { score = score + badness_score; } // check if this process is using most memory if ( proc_info->resident * 4 > current_highest ) { current_highest = proc_info->resident * 4; score += 10; } // if this process has highest score, we flag it for kill if ( score >= current_score ) { highest = *proc_info; current_score = score; } else { if (Configuration::Verbosity >= 12) { Core::DebugLog("Process " + Name(proc_info) + "is eating less than highest candidate", 12); } } freeproc(proc_info); } if (current_score == -100) { Core::ErrorLog("Unable to find any process to kill. System is running OOM and I can't do anything to fix it."); closeproc(proc); return; } Core::Log("Most preferred process has score " + Core::int2String(current_score) + " : " + Name(&highest) + " killing now"); if (KillExec(&highest) == 0) { KillProc((pid_t)highest.tid, hard); Exec(&highest); }else { Core::Log("Not killed " + Name(&highest) + " because the test command returned different value"); } closeproc(proc); return; }
int daemon_main(int argc, char *argv[]) { int opt; bool fork_flag = false; bool replace_flag = false; bool patch_sepolicy = true; enum { OPT_ALLOW_ROOT_CLIENT = 1000, OPT_NO_PATCH_SEPOLICY = 1001, OPT_SIGSTOP_WHEN_READY = 1002, OPT_LOG_TO_KMSG = 1003, OPT_LOG_TO_STDIO = 1004, OPT_NO_UNSHARE = 1005, }; static struct option long_options[] = { {"daemonize", no_argument, 0, 'd'}, {"replace", no_argument, 0, 'r'}, {"help", no_argument, 0, 'h'}, {"allow-root-client", no_argument, 0, OPT_ALLOW_ROOT_CLIENT}, {"no-patch-sepolicy", no_argument, 0, OPT_NO_PATCH_SEPOLICY}, {"sigstop-when-ready", no_argument, 0, OPT_SIGSTOP_WHEN_READY}, {"log-to-kmsg", no_argument, 0, OPT_LOG_TO_KMSG}, {"log-to-stdio", no_argument, 0, OPT_LOG_TO_STDIO}, {"no-unshare", no_argument, 0, OPT_NO_UNSHARE}, {0, 0, 0, 0} }; int long_index = 0; while ((opt = getopt_long(argc, argv, "drh", long_options, &long_index)) != -1) { switch (opt) { case 'd': fork_flag = true; break; case 'r': replace_flag = true; break; case 'h': daemon_usage(0); return EXIT_SUCCESS; case OPT_ALLOW_ROOT_CLIENT: allow_root_client = true; break; case OPT_NO_PATCH_SEPOLICY: patch_sepolicy = false; break; case OPT_SIGSTOP_WHEN_READY: sigstop_when_ready = true; break; case OPT_LOG_TO_KMSG: log_to_kmsg = true; break; case OPT_LOG_TO_STDIO: log_to_stdio = true; break; case OPT_NO_UNSHARE: no_unshare = true; break; default: daemon_usage(1); return EXIT_FAILURE; } } // There should be no other arguments if (argc - optind != 0) { daemon_usage(1); return EXIT_FAILURE; } if (!no_unshare && unshare(CLONE_NEWNS) < 0) { fprintf(stderr, "unshare() failed: %s\n", strerror(errno)); return EXIT_FAILURE; } if (patch_sepolicy) { patch_loaded_sepolicy(SELinuxPatch::MAIN); } if (!switch_context(MB_EXEC_CONTEXT)) { fprintf(stderr, "Failed to switch context; %s may not run properly", argv[0]); } if (replace_flag) { PROCTAB *proc = openproc(PROC_FILLCOM | PROC_FILLSTAT); if (proc) { pid_t curpid = getpid(); while (proc_t *info = readproc(proc, nullptr)) { // NOTE: Can't check 'strcmp(info->cmd, "mbtool") == 0' (which // is the basename of /proc/<pid>/cmd) because the binary is not // always called "mbtool". For example, when run via SignedExec, // it's just called "binary". // If we can read the cmdline and argc >= 2 if (info->cmdline && info->cmdline[0] && info->cmdline[1]) { const char *name = strrchr(info->cmdline[0], '/'); if (name) { ++name; } else { name = info->cmdline[0]; } if (strcmp(name, "mbtool") == 0 // This is mbtool && strstr(info->cmdline[1], "daemon") // And it's a daemon process && info->tid != curpid) { // And we're not killing ourself // Kill the daemon process LOGV("Killing PID %d", info->tid); kill(info->tid, SIGTERM); } } freeproc(info); } closeproc(proc); } // Give processes a chance to exit usleep(500000); } if (fork_flag) { run_daemon_fork(); } else { return (daemon_init() && run_daemon()) ? EXIT_SUCCESS : EXIT_FAILURE; } }
static void select_procs(void) { static size_t size = 0; PROCTAB* ptp; proc_t* task; size_t match; char* cmd_arg0; char* cmd_arg0_base; char* cmd_arg1; char* cmd_arg1_base; char* program_base; char* root_link; char* exe_link; char* exe_link_base; program_base = basename(program); /* get the input base name */ ptp = openproc(PROC_FILLCOM | PROC_FILLSTAT); while ((task = readproc(ptp, NULL))) { if (epidof_root) { /* get the /proc/<pid>/root symlink value */ root_link = pid_link(task->XXXID, "root"); match = !strcmp(epidof_root, root_link); xfree(root_link); if (!match) /* root check failed */ { freeproc(task); continue; } } if (!is_omitted(task->XXXID) && task->cmdline) { cmd_arg0 = task->cmdline[0]; /* processes starting with '-' are login shells */ if (*cmd_arg0 == '-') cmd_arg0++; cmd_arg0_base = basename(cmd_arg0); /* get the argv0 basename */ exe_link = pid_link(task->XXXID, "exe"); /* get the /proc/<pid>/exe symlink value */ exe_link_base = basename(exe_link); /* get the exe_link basename */ match = 0; #define __test(p, c) (!strcmp(p, c##_base) || !strcmp(p, c) || !strcmp(p##_base, c)) if (__test(program, cmd_arg0) || __test(program, exe_link)) match = 1; else if (opt_scripts_too && task->cmdline[1]) { cmd_arg1 = task->cmdline[1]; cmd_arg1_base = basename(cmd_arg1); /* if script, then task->cmd = argv1, otherwise task->cmd = argv0 */ if (task->cmd && !strncmp(task->cmd, cmd_arg1_base, strlen(task->cmd)) && __test(program, cmd_arg1)) match = 1; } #undef __test xfree(exe_link); if (match && environment_test(task->XXXID, *argv)) { if (proc_count == size) procs = xrealloc(procs, __grow(size) * sizeof(*procs)); procs[proc_count++] = task->XXXID; } } freeproc(task); } closeproc(ptp); }
int daemon_main(int argc, char *argv[]) { int opt; bool fork_flag = false; bool replace_flag = false; static struct option long_options[] = { {"daemonize", no_argument, 0, 'd'}, {"replace", no_argument, 0, 'r'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; int long_index = 0; while ((opt = getopt_long(argc, argv, "drh", long_options, &long_index)) != -1) { switch (opt) { case 'd': fork_flag = true; break; case 'r': replace_flag = true; break; case 'h': daemon_usage(0); return EXIT_SUCCESS; default: daemon_usage(1); return EXIT_FAILURE; } } // There should be no other arguments if (argc - optind != 0) { daemon_usage(1); return EXIT_FAILURE; } // Patch SELinux policy to make init permissive patch_loaded_sepolicy(); // Allow untrusted_app to connect to our daemon patch_sepolicy_daemon(); // Set version property if we're the system mbtool (i.e. launched by init) // Possible to override this with another program by double forking, letting // 2nd child reparent to init, and then calling execve("/mbtool", ...), but // meh ... if (getppid() == 1) { if (!util::set_property("ro.multiboot.version", get_mbtool_version())) { std::printf("Failed to set 'ro.multiboot.version' to '%s'\n", get_mbtool_version()); } } if (replace_flag) { PROCTAB *proc = openproc(PROC_FILLCOM | PROC_FILLSTAT); if (proc) { pid_t curpid = getpid(); while (proc_t *info = readproc(proc, nullptr)) { if (strcmp(info->cmd, "mbtool") == 0 // This is mbtool && info->cmdline // And we can see the command line && info->cmdline[1] // And argc > 1 && strstr(info->cmdline[1], "daemon") // And it's a daemon process && info->tid != curpid) { // And we're not killing ourself // Kill the daemon process std::printf("Killing PID %d\n", info->tid); kill(info->tid, SIGTERM); } freeproc(info); } closeproc(proc); } // Give processes a chance to exit usleep(500000); } // Set up logging if (!util::mkdir_parent(MULTIBOOT_LOG_DAEMON, 0775) && errno != EEXIST) { fprintf(stderr, "Failed to create parent directory of %s: %s\n", MULTIBOOT_LOG_DAEMON, strerror(errno)); return EXIT_FAILURE; } autoclose::file fp(autoclose::fopen(MULTIBOOT_LOG_DAEMON, "w")); if (!fp) { fprintf(stderr, "Failed to open log file %s: %s\n", MULTIBOOT_LOG_DAEMON, strerror(errno)); return EXIT_FAILURE; } fix_multiboot_permissions(); // mbtool logging log::log_set_logger(std::make_shared<log::StdioLogger>(fp.get(), true)); if (fork_flag) { run_daemon_fork(); } else { return run_daemon() ? EXIT_SUCCESS : EXIT_FAILURE; } }