/***** kill or nice a process */ static void hurt_proc(int tty, int uid, int pid, char *cmd){ int failed; int saved_errno; char dn_buf[1000]; dev_to_tty(dn_buf, 999, tty, pid, ABBREV_DEV); if(i_flag){ char buf[8]; fprintf(stderr, "%-8.8s %-8.8s %5d %-16.16s ? ", (char*)dn_buf,user_from_uid(uid),pid,cmd ); if(!fgets(buf,7,stdin)){ printf("\n"); exit(0); } if(*buf!='y' && *buf!='Y') return; } /* do the actual work */ if(program==PROG_SKILL) failed=kill(pid,sig_or_pri); else failed=setpriority(PRIO_PROCESS,pid,sig_or_pri); saved_errno = errno; if(w_flag && failed){ fprintf(stderr, "%-8.8s %-8.8s %5d %-16.16s ", (char*)dn_buf,user_from_uid(uid),pid,cmd ); errno = saved_errno; perror(""); return; } if(i_flag) return; if(v_flag){ printf("%-8.8s %-8.8s %5d %-16.16s\n", (char*)dn_buf,user_from_uid(uid),pid,cmd ); return; } if(n_flag){ printf("%d\n",pid); return; } }
/* * Displays infos for a single task */ void show_task_info(proc_t *task, int pmem) { int i,j; unsigned int t; char *cmdptr; char tmp[2048], tmp2[2048] = "", tmp3[2048] = "", *p; for (i = 0; i < Numfields; i++) { tmp[0] = 0; switch (pflags[i]) { case P_PID: sprintf(tmp, "%5d ", task->pid); break; case P_PPID: sprintf(tmp, "%5d ", task->ppid); break; case P_EUID: sprintf(tmp, "%4d ", task->euid); break; case P_EUSER: sprintf(tmp, "%-8.8s ", task->euser); break; case P_PCPU: sprintf(tmp, "%4.1f ", (float)task->pcpu / 10); break; case P_LCPU: sprintf(tmp, "%2d ", task->lproc); break; case P_PMEM: sprintf(tmp, "%4.1f ", (float)pmem / 10); break; case P_TTY: { char outbuf[9]; dev_to_tty(outbuf, 8, task->tty, task->pid, ABBREV_DEV); sprintf(tmp, "%-8.8s ", outbuf); } break; case P_PRI: sprintf(tmp, "%3.3s ", scale_k(task->priority, 3, 0)); break; case P_NICE: sprintf(tmp, "%3.3s ", scale_k(task->nice, 3, 0)); break; case P_PAGEIN: sprintf(tmp, "%6.6s ", scale_k(task->maj_flt, 6, 0)); break; case P_TSIZ: sprintf(tmp, "%5.5s ", scale_k(((task->end_code - task->start_code) / 1024), 5, 1)); break; case P_DSIZ: sprintf(tmp, "%5.5s ", scale_k(((task->vsize - task->end_code) / 1024), 5, 1)); break; case P_SIZE: sprintf(tmp, "%5.5s ", scale_k((task->size << CL_pg_shift), 5, 1)); break; case P_TRS: sprintf(tmp, "%4.4s ", scale_k((task->trs << CL_pg_shift), 4, 1)); break; case P_SWAP: sprintf(tmp, "%4.4s ", scale_k(((task->size - task->resident) << CL_pg_shift), 4, 1)); break; case P_SHARE: sprintf(tmp, "%5.5s ", scale_k((task->share << CL_pg_shift), 5, 1)); break; case P_A: sprintf(tmp, "%3.3s ", "NYI"); break; case P_WP: sprintf(tmp, "%3.3s ", "NYI"); break; case P_DT: sprintf(tmp, "%3.3s ", scale_k(task->dt, 3, 0)); break; case P_RSS: /* resident not rss, it seems to be more correct. */ sprintf(tmp, "%4.4s ", scale_k((task->resident << CL_pg_shift), 4, 1)); break; case P_WCHAN: if (!CL_wchan_nout) sprintf(tmp, "%-9.9s ", wchan(task->wchan)); else sprintf(tmp, "%-9lx", task->wchan); break; case P_STAT: sprintf(tmp, "%-4.4s ", status(task)); break; case P_TIME: t = (task->utime + task->stime) / Hertz; if (Cumulative) t += (task->cutime + task->cstime) / Hertz; sprintf(tmp, "%6.6s ", scale_time(t,6)); break; case P_COMMAND: if (!show_cmd && task->cmdline && *(task->cmdline)) { j=0; while(((task->cmdline)[j] != NULL) && (strlen(tmp3)<1020)){ /* #if 0 */ /* This is useless? FIXME */ if (j > 0) strcat(tmp3, " "); /* #endif */ strncat(tmp3, (task->cmdline)[j], 1000); j++; } cmdptr = tmp3; } else { cmdptr = task->cmd; } if (strlen(cmdptr) > Maxcmd) cmdptr[Maxcmd - 1] = 0; sprintf(tmp, "%s", cmdptr); tmp3[0]=0; break; case P_FLAGS: sprintf(tmp, "%8lx ", task->flags); break; } strcat(tmp2, tmp); } if (strlen(tmp2) > Cols - 1) tmp2[Cols - 1] = 0; /* take care of cases like: perl -e 'foo bar foo bar foo # end of perl script' */ for (p=tmp2;*p;++p) if (!isgraph(*p)) *p=' '; printf("\n%s", tmp2); PUTP(top_clrtoeol); }
static int read_process(SEXP_t *cmd_ent, probe_ctx *ctx) { int err = 1; DIR *d; struct dirent *ent; d = opendir("/proc"); if (d == NULL) return err; // Get the time tick hertz ticks = (unsigned long)sysconf(_SC_CLK_TCK); get_boot_time(); // Scan the directories while (( ent = readdir(d) )) { int fd, len; char buf[256]; char *tmp, cmd[16], state, tty_dev[128]; int pid, ppid, pgrp, session, tty_nr, tpgid; unsigned flags, sched_policy; unsigned long minflt, cminflt, majflt, cmajflt, uutime, ustime; long cutime, cstime, priority, cnice, nthreads, itrealvalue; unsigned long long start; SEXP_t *cmd_sexp; // Skip non-process dir entries if(*ent->d_name<'0' || *ent->d_name>'9') continue; errno = 0; pid = strtol(ent->d_name, NULL, 10); if (errno || pid == 2) // skip err & kthreads continue; // Parse up the stat file for the proc snprintf(buf, 32, "/proc/%d/stat", pid); fd = open(buf, O_RDONLY, 0); if (fd < 0) continue; len = read(fd, buf, sizeof buf - 1); close(fd); if (len < 40) continue; buf[len] = 0; tmp = strrchr(buf, ')'); if (tmp) *tmp = 0; else continue; memset(cmd, 0, sizeof(cmd)); sscanf(buf, "%d (%15c", &ppid, cmd); sscanf(tmp+2, "%c %d %d %d %d %d " "%u %lu %lu %lu %lu " "%lu %lu %lu %ld %ld " "%ld %ld %ld %llu", &state, &ppid, &pgrp, &session, &tty_nr, &tpgid, &flags, &minflt, &cminflt, &majflt, &cmajflt, &uutime, &ustime, &cutime, &cstime, &priority, &cnice, &nthreads, &itrealvalue, &start ); // Skip kthreads if (ppid == 2) continue; err = 0; // If we get this far, no permission problems dI("Have command: %s\n", cmd); cmd_sexp = SEXP_string_newf("%s", cmd); if (probe_entobj_cmp(cmd_ent, cmd_sexp) == OVAL_RESULT_TRUE) { struct result_info r; unsigned long t = uutime/ticks + ustime/ticks; char tbuf[32], sbuf[32]; int tday,tyear; time_t s_time; struct tm *proc, *now; const char *fmt; // Now get scheduler policy sched_policy = sched_getscheduler(pid); switch (sched_policy) { case SCHED_OTHER: r.scheduling_class = "TS"; break; case SCHED_BATCH: r.scheduling_class = "B"; break; #ifdef SCHED_IDLE case SCHED_IDLE: r.scheduling_class = "#5"; break; #endif case SCHED_FIFO: r.scheduling_class = "FF"; break; case SCHED_RR: r.scheduling_class = "RR"; break; default: r.scheduling_class = "?"; break; } // Calculate the start time s_time = time(NULL); now = localtime(&s_time); tyear = now->tm_year; tday = now->tm_yday; s_time = boot + (start / ticks); proc = localtime(&s_time); // Select format based on how long we've been running // // FROM THE SPEC: // "This is the time of day the process started formatted in HH:MM:SS if // the same day the process started or formatted as MMM_DD (Ex.: Feb_5) // if process started the previous day or further in the past." // if (tday != proc->tm_yday || tyear != proc->tm_year) fmt = "%b_%d"; else fmt = "%H:%M:%S"; strftime(sbuf, sizeof(sbuf), fmt, proc); r.command = cmd; r.exec_time = convert_time(t, tbuf, sizeof(tbuf)); r.pid = pid; r.ppid = ppid; r.priority = priority; r.start_time = sbuf; dev_to_tty(tty_dev, sizeof(tty_dev), (dev_t) tty_nr, pid, ABBREV_DEV); r.tty = tty_dev; get_uids(pid, &r); report_finding(&r, ctx); } SEXP_free(cmd_sexp); } closedir(d); return err; }
static int read_process(SEXP_t *cmd_ent, SEXP_t *pid_ent, probe_ctx *ctx) { int err = 1, max_cap_id; DIR *d; struct dirent *ent; oval_version_t oval_version; d = opendir("/proc"); if (d == NULL) return err; // Get the time tick hertz ticks = (unsigned long)sysconf(_SC_CLK_TCK); get_boot_time(); oval_version = probe_obj_get_schema_version(probe_ctx_getobject(ctx)); if (oval_version_cmp(oval_version, OVAL_VERSION(5.11)) < 0) { max_cap_id = OVAL_5_8_MAX_CAP_ID; } else { max_cap_id = OVAL_5_11_MAX_CAP_ID; } struct oscap_buffer *cmdline_buffer = oscap_buffer_new(); char cmd_buffer[1 + 15 + 11 + 1]; // Format:" [ cmd:15 ] <defunc>" cmd_buffer[0] = '['; // Scan the directories while (( ent = readdir(d) )) { int fd, len; char buf[256]; char *tmp, state, tty_dev[128]; int pid, ppid, pgrp, session, tty_nr, tpgid; unsigned flags, sched_policy; unsigned long minflt, cminflt, majflt, cmajflt, uutime, ustime; long cutime, cstime, priority, cnice, nthreads, itrealvalue; unsigned long long start; SEXP_t *cmd_sexp = NULL, *pid_sexp = NULL; // Skip non-process58 dir entries if(*ent->d_name<'0' || *ent->d_name>'9') continue; errno = 0; pid = strtol(ent->d_name, NULL, 10); if (errno || pid == 2) // skip err & kthreads continue; // Parse up the stat file for the proc snprintf(buf, 32, "/proc/%d/stat", pid); fd = open(buf, O_RDONLY, 0); if (fd < 0) continue; len = read(fd, buf, sizeof buf - 1); close(fd); if (len < 40) continue; buf[len] = 0; tmp = strrchr(buf, ')'); if (tmp) *tmp = 0; else continue; memset(cmd_buffer + 1, 0, sizeof(cmd_buffer)-1); // clear cmd after starting '[' sscanf(buf, "%d (%15c", &ppid, cmd_buffer + 1); sscanf(tmp+2, "%c %d %d %d %d %d " "%u %lu %lu %lu %lu " "%lu %lu %lu %ld %ld " "%ld %ld %ld %llu", &state, &ppid, &pgrp, &session, &tty_nr, &tpgid, &flags, &minflt, &cminflt, &majflt, &cmajflt, &uutime, &ustime, &cutime, &cstime, &priority, &cnice, &nthreads, &itrealvalue, &start ); // Skip kthreads if (ppid == 2) continue; const char* cmd; if (state == 'Z') { // zombie cmd = make_defunc_str(cmd_buffer); } else { snprintf(buf, 32, "/proc/%d/cmdline", pid); if (get_process_cmdline(buf, cmdline_buffer)) { cmd = oscap_buffer_get_raw(cmdline_buffer); // use full cmdline } else { cmd = cmd_buffer + 1; } } err = 0; // If we get this far, no permission problems dI("Have command: %s\n", cmd); cmd_sexp = SEXP_string_newf("%s", cmd); pid_sexp = SEXP_number_newu_32(pid); if ((cmd_sexp == NULL || probe_entobj_cmp(cmd_ent, cmd_sexp) == OVAL_RESULT_TRUE) && (pid_sexp == NULL || probe_entobj_cmp(pid_ent, pid_sexp) == OVAL_RESULT_TRUE) ) { struct result_info r; unsigned long t = uutime/ticks + ustime/ticks; char tbuf[32], sbuf[32], *selinux_domain_label, **posix_capabilities; int tday,tyear; time_t s_time; struct tm *proc, *now; const char *fmt; // Now get scheduler policy sched_policy = sched_getscheduler(pid); switch (sched_policy) { case SCHED_OTHER: r.scheduling_class = "TS"; break; case SCHED_BATCH: r.scheduling_class = "B"; break; #ifdef SCHED_IDLE case SCHED_IDLE: r.scheduling_class = "#5"; break; #endif case SCHED_FIFO: r.scheduling_class = "FF"; break; case SCHED_RR: r.scheduling_class = "RR"; break; default: r.scheduling_class = "?"; break; } // Calculate the start time s_time = time(NULL); now = localtime(&s_time); tyear = now->tm_year; tday = now->tm_yday; s_time = boot + (start / ticks); proc = localtime(&s_time); // Select format based on how long we've been running // // FROM THE SPEC: // "This is the time of day the process started formatted in HH:MM:SS if // the same day the process started or formatted as MMM_DD (Ex.: Feb_5) // if process started the previous day or further in the past." // if (tday != proc->tm_yday || tyear != proc->tm_year) fmt = "%b_%d"; else fmt = "%H:%M:%S"; strftime(sbuf, sizeof(sbuf), fmt, proc); r.command_line = cmd; r.exec_time = convert_time(t, tbuf, sizeof(tbuf)); r.pid = pid; r.ppid = ppid; r.priority = priority; r.start_time = sbuf; dev_to_tty(tty_dev, sizeof(tty_dev), (dev_t) tty_nr, pid, ABBREV_DEV); r.tty = tty_dev; r.exec_shield = (get_exec_shield_status(pid) > 0); selinux_domain_label = get_selinux_label(pid); r.selinux_domain_label = selinux_domain_label; posix_capabilities = get_posix_capability(pid, max_cap_id); r.posix_capability = posix_capabilities; r.session_id = session; get_uids(pid, &r); report_finding(&r, ctx); if (selinux_domain_label != NULL) free(selinux_domain_label); if (posix_capabilities != NULL) { char **posix_capabilities_p = posix_capabilities; while (*posix_capabilities_p) free(*posix_capabilities_p++); free(posix_capabilities); } } SEXP_free(cmd_sexp); SEXP_free(pid_sexp); } closedir(d); oscap_buffer_free(cmdline_buffer); return err; }