static void print_proc(int index, int itv, int col) { // command char *cmd = pid_proc_cmdline(index); char *ptrcmd; if (cmd == NULL) { if (pids[index].zombie) ptrcmd = "(zombie)"; else ptrcmd = ""; } else ptrcmd = cmd; // check network namespace char *name; if (asprintf(&name, "/run/firejail/network/%d-netmap", index) == -1) errExit("asprintf"); struct stat s; if (stat(name, &s) == -1) { // the sandbox doesn't have a --net= option, don't print if (cmd) free(cmd); return; } // pid char pidstr[10]; snprintf(pidstr, 10, "%u", index); // user char *user = pid_get_user_name(pids[index].uid); char *ptruser; if (user) ptruser = user; else ptruser = ""; float rx_kbps = ((float) pids[index].rx_delta / 1000) / itv; char ptrrx[15]; sprintf(ptrrx, "%.03f", rx_kbps); float tx_kbps = ((float) pids[index].tx_delta / 1000) / itv; char ptrtx[15]; sprintf(ptrtx, "%.03f", tx_kbps); char buf[1024 + 1]; snprintf(buf, 1024, "%-5.5s %-9.9s %-10.10s %-10.10s %s", pidstr, ptruser, ptrrx, ptrtx, ptrcmd); if (col < 1024) buf[col] = '\0'; printf("%s\n", buf); if (cmd) free(cmd); if (user) free(user); }
static void print_proc(int index, int itv, int col) { // command char *cmd = pid_proc_cmdline(index); char *ptrcmd; if (cmd == NULL) { if (pids[index].zombie) ptrcmd = "(zombie)"; else ptrcmd = ""; } else ptrcmd = cmd; // if the command doesn't have a --net= option, don't print if (strstr(ptrcmd, "--net=") == NULL) { if (cmd) free(cmd); return; } // pid char pidstr[10]; snprintf(pidstr, 10, "%u", index); // user char *user = pid_get_user_name(pids[index].uid); char *ptruser; if (user) ptruser = user; else ptruser = ""; float rx_kbps = ((float) pids[index].rx_delta / 1000) / itv; char ptrrx[15]; sprintf(ptrrx, "%.03f", rx_kbps); float tx_kbps = ((float) pids[index].tx_delta / 1000) / itv; char ptrtx[15]; sprintf(ptrtx, "%.03f", tx_kbps); char buf[1024 + 1]; snprintf(buf, 1024, "%-5.5s %-9.9s %-10.10s %-10.10s %s", pidstr, ptruser, ptrrx, ptrtx, ptrcmd); if (col < 1024) buf[col] = '\0'; printf("%s\n", buf); if (cmd) free(cmd); if (user) free(user); }
static void print_elem(unsigned index, int nowrap) { // get terminal size struct winsize sz; int col = 0; if (isatty(STDIN_FILENO)) { if (!ioctl(0, TIOCGWINSZ, &sz)) col = sz.ws_col; } // indent char indent[(pids[index].level - 1) * 2 + 1]; memset(indent, ' ', sizeof(indent)); indent[(pids[index].level - 1) * 2] = '\0'; // get data uid_t uid = pids[index].uid; char *cmd = pid_proc_cmdline(index); char *user = pid_get_user_name(uid); char *allocated = user; if (user ==NULL) user = ""; if (cmd) { if (col < 4 || nowrap) printf("%s%u:%s:%s\n", indent, index, user, cmd); else { char *out; if (asprintf(&out, "%s%u:%s:%s\n", indent, index, user, cmd) == -1) errExit("asprintf"); int len = strlen(out); if (len > col) { out[col] = '\0'; out[col - 1] = '\n'; } printf("%s", out); free(out); } free(cmd); } else { if (pids[index].zombie) printf("%s%u: (zombie)\n", indent, index); else printf("%s%u:\n", indent, index); } if (allocated) free(allocated); }
// recursivity!!! static char *print_top(unsigned index, unsigned parent, unsigned *utime, unsigned *stime, unsigned itv, float *cpu, int *cnt) { char *rv = NULL; char procdir[20]; snprintf(procdir, 20, "/proc/%u", index); struct stat s; if (stat(procdir, &s) == -1) return NULL; if (pids[index].level == 1) { pgs_rss = 0; pgs_shared = 0; *utime = 0; *stime = 0; *cnt = 0; } (*cnt)++; pid_getmem(index, &pgs_rss, &pgs_shared); unsigned utmp; unsigned stmp; pid_get_cpu_time(index, &utmp, &stmp); *utime += utmp; *stime += stmp; int i; for (i = index + 1; i < MAX_PIDS; i++) { if (pids[i].parent == index) print_top(i, index, utime, stime, itv, cpu, cnt); } if (pids[index].level == 1) { // pid char pidstr[10]; snprintf(pidstr, 10, "%u", index); // command char *cmd = pid_proc_cmdline(index); char *ptrcmd; if (cmd == NULL) { if (pids[index].zombie) ptrcmd = "(zombie)"; else ptrcmd = ""; } else ptrcmd = cmd; // user char *user = pid_get_user_name(pids[index].uid); char *ptruser; if (user) ptruser = user; else ptruser = ""; char entry[60]; snprintf(entry, 60, "%s:%s:%s", pidstr, ptruser, ptrcmd); // memory int pgsz = getpagesize(); char rss[10]; snprintf(rss, 10, "%u", pgs_rss * pgsz / 1024); char shared[10]; snprintf(shared, 10, "%u", pgs_shared * pgsz / 1024); // uptime unsigned long long uptime = pid_get_start_time(index); if (clocktick == 0) clocktick = sysconf(_SC_CLK_TCK); uptime /= clocktick; uptime = sysuptime - uptime; unsigned sec = uptime % 60; uptime -= sec; uptime /= 60; unsigned min = uptime % 60; uptime -= min; uptime /= 60; unsigned hour = uptime; char uptime_str[50]; snprintf(uptime_str, 50, "%02u:%02u:%02u", hour, min, sec); // cpu itv *= clocktick; float ud = (float) (*utime - pids[index].utime) / itv * 100; float sd = (float) (*stime - pids[index].stime) / itv * 100; float cd = ud + sd; // if (cd > 100) // cd = 99.9; *cpu = cd; char cpu_str[10]; snprintf(cpu_str, 10, "%2.1f", cd); // process count char prcs_str[10]; snprintf(prcs_str, 10, "%d", *cnt); if (asprintf(&rv, "%-5.5s %-9.9s %-8.8s %-8.8s %-5.5s %-4.4s %-9.9s %s", pidstr, ptruser, rss, shared, cpu_str, prcs_str, uptime_str, ptrcmd) == -1) errExit("asprintf"); if (cmd) free(cmd); if (user) free(user); } return rv; }
static int procevent_monitor(const int sock, pid_t mypid) { ssize_t len; struct nlmsghdr *nlmsghdr; while (1) { char __attribute__ ((aligned(NLMSG_ALIGNTO)))buf[4096]; if ((len = recv(sock, buf, sizeof(buf), 0)) == 0) { return 0; } if (len == -1) { if (errno == EINTR) { return 0; } else { fprintf(stderr,"recv: %s\n", strerror(errno)); return -1; } } for (nlmsghdr = (struct nlmsghdr *)buf; NLMSG_OK (nlmsghdr, len); nlmsghdr = NLMSG_NEXT (nlmsghdr, len)) { struct cn_msg *cn_msg; struct proc_event *proc_ev; struct tm tm; struct timeval tv; time_t now; if ((nlmsghdr->nlmsg_type == NLMSG_ERROR) || (nlmsghdr->nlmsg_type == NLMSG_NOOP)) continue; cn_msg = NLMSG_DATA(nlmsghdr); if ((cn_msg->id.idx != CN_IDX_PROC) || (cn_msg->id.val != CN_VAL_PROC)) continue; (void)time(&now); (void)localtime_r(&now, &tm); char line[PIDS_BUFLEN]; char *lineptr = line; sprintf(lineptr, "%2.2d:%2.2d:%2.2d", tm.tm_hour, tm.tm_min, tm.tm_sec); lineptr += strlen(lineptr); proc_ev = (struct proc_event *)cn_msg->data; pid_t pid = 0; pid_t child = 0; int remove_pid = 0; switch (proc_ev->what) { case PROC_EVENT_FORK: if (proc_ev->event_data.fork.child_pid != proc_ev->event_data.fork.child_tgid) continue; // this is a thread, not a process pid = proc_ev->event_data.fork.parent_tgid; if (pids[pid].level > 0) { child = proc_ev->event_data.fork.child_tgid; child %= MAX_PIDS; pids[child].level = pids[pid].level + 1; pids[child].uid = pid_get_uid(child); } sprintf(lineptr, " fork"); break; case PROC_EVENT_EXEC: pid = proc_ev->event_data.exec.process_tgid; sprintf(lineptr, " exec"); break; case PROC_EVENT_EXIT: if (proc_ev->event_data.exit.process_pid != proc_ev->event_data.exit.process_tgid) continue; // this is a thread, not a process pid = proc_ev->event_data.exit.process_tgid; remove_pid = 1; sprintf(lineptr, " exit"); break; case PROC_EVENT_UID: pid = proc_ev->event_data.id.process_tgid; sprintf(lineptr, " uid "); break; case PROC_EVENT_GID: pid = proc_ev->event_data.id.process_tgid; sprintf(lineptr, " gid "); break; case PROC_EVENT_SID: pid = proc_ev->event_data.sid.process_tgid; sprintf(lineptr, " sid "); break; default: sprintf(lineptr, "\n"); continue; } int add_new = 0; if (pids[pid].level < 0) // not a firejail process continue; else if (pids[pid].level == 0) { // new porcess, do we have track it? if (pid_is_firejail(pid) && mypid == 0) { pids[pid].level = 1; add_new = 1; } else { pids[pid].level = -1; continue; } } lineptr += strlen(lineptr); sprintf(lineptr, " %u", pid); lineptr += strlen(lineptr); char *user = pids[pid].user; if (!user) user = pid_get_user_name(pids[pid].uid); if (user) { pids[pid].user = user; sprintf(lineptr, " (%s)", user); lineptr += strlen(lineptr); } int sandbox_closed = 0; // exit sandbox flag char *cmd = pids[pid].cmd; if (add_new) { sprintf(lineptr, " NEW SANDBOX\n"); lineptr += strlen(lineptr); } else if (proc_ev->what == PROC_EVENT_EXIT && pids[pid].level == 1) { sprintf(lineptr, " EXIT SANDBOX\n"); lineptr += strlen(lineptr); if (mypid == pid) sandbox_closed = 1; } else { if (!cmd) { cmd = pid_proc_cmdline(pid); } if (cmd == NULL) sprintf(lineptr, "\n"); else { sprintf(lineptr, " %s\n", cmd); free(cmd); } lineptr += strlen(lineptr); } (void) lineptr; // print the event printf("%s", line); fflush(0); // unflag pid for exit events if (remove_pid) { if (pids[pid].user) free(pids[pid].user); if (pids[pid].cmd) free(pids[pid].cmd); memset(&pids[pid], 0, sizeof(Process)); } // print forked child if (child) { cmd = pid_proc_cmdline(child); if (cmd) { printf("\tchild %u %s\n", child, cmd); free(cmd); } else printf("\tchild %u\n", child); } // on uid events the uid is changing if (proc_ev->what == PROC_EVENT_UID) { if (pids[pid].user) free(pids[pid].user); pids[pid].user = 0; pids[pid].uid = pid_get_uid(pid); } if (sandbox_closed) exit(0); } } return 0; }