Beispiel #1
0
QueryData genProcessEnvs() {
  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"] = boost::lexical_cast<std::string>(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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
/* 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;
}
Beispiel #6
0
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);
}
Beispiel #8
0
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);
						
}
Beispiel #9
0
//! 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;
}
Beispiel #10
0
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;
    }
}
Beispiel #11
0
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);
}
Beispiel #12
0
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;
    }
}