Ejemplo n.º 1
0
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);
	
}
Ejemplo n.º 2
0
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);
	
}
Ejemplo n.º 3
0
Archivo: pid.c Proyecto: maces/firejail
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);
}
Ejemplo n.º 4
0
Archivo: top.c Proyecto: spnow/firejail
// 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;
}
Ejemplo n.º 5
0
// return 1 if error
int name2pid(const char *name, pid_t *pid) {
    pid_t parent = getpid();

    DIR *dir;
    if (!(dir = opendir("/proc"))) {
        // sleep 2 seconds and try again
        sleep(2);
        if (!(dir = opendir("/proc"))) {
            fprintf(stderr, "Error: cannot open /proc directory\n");
            exit(1);
        }
    }

    struct dirent *entry;
    char *end;
    while ((entry = readdir(dir))) {
        pid_t newpid = strtol(entry->d_name, &end, 10);
        if (end == entry->d_name || *end)
            continue;
        if (newpid == parent)
            continue;

        // check if this is a firejail executable
        char *comm = pid_proc_comm(newpid);
        if (comm) {
            // remove \n
            char *ptr = strchr(comm, '\n');
            if (ptr)
                *ptr = '\0';
            if (strcmp(comm, "firejail")) {
                free(comm);
                continue;
            }
            free(comm);
        }

        char *cmd = pid_proc_cmdline(newpid);
        if (cmd) {
            // mark the end of the name
            char *ptr = strstr(cmd, "--name=");
            char *start = ptr;
            if (!ptr) {
                free(cmd);

                // extract name for /run/mnt/firejail/fslogger file
                char *fname;
                if (asprintf(&fname, "/proc/%d/root/run/firejail/mnt/fslogger", newpid) == -1)
                    errExit("asprintf");

                struct stat s;
                if (stat(fname, &s) == 0) {
                    FILE *fp = fopen(fname, "r");
                    if (fp) {
                        char buf[BUFLEN];
                        if (fgets(buf, BUFLEN, fp)) {
                            if (strncmp(buf, "sandbox name: ", 14) == 0) {
                                char *ptr2 = buf + 14;
                                if (strncmp(name, ptr2, strlen(name)) == 0) {
                                    fclose(fp);
                                    *pid = newpid;
                                    closedir(dir);
                                    return 0;
                                }
                            }
                        }
                        fclose(fp);
                    }
                }

                continue;
            }
            while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
                ptr++;
            *ptr = '\0';
            int rv = strcmp(start + 7, name);
            if (rv == 0) {
                free(cmd);
                *pid = newpid;
                closedir(dir);
                return 0;
            }
            free(cmd);
        }
    }
    closedir(dir);
    return 1;
}
Ejemplo n.º 6
0
void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up) {
	//************************
	// verify sandbox
	//************************
	char *comm = pid_proc_comm(pid);
	if (!comm) {
		fprintf(stderr, "Error: cannot find sandbox\n");
		exit(1);
	}

	// remove \n and check for firejail sandbox
	char *ptr = strchr(comm, '\n');
	if (ptr)
		*ptr = '\0';
	if (strcmp(comm, "firejail") != 0) {
		fprintf(stderr, "Error: cannot find sandbox\n");
		exit(1);
	}
	free(comm);
	
	// check network namespace
	char *cmd = pid_proc_cmdline(pid);
	if (!cmd || strstr(cmd, "--net") == NULL) {
		fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n");
		exit(1);
	}
	free(cmd);


	//************************
	// join the network namespace
	//************************
	pid_t child;
	if (find_child(pid, &child) == -1) {
		fprintf(stderr, "Error: cannot join the network namespace\n");
		exit(1);
	}
	if (join_namespace(child, "net")) {
		fprintf(stderr, "Error: cannot join the network namespace\n");
		exit(1);
	}

	// set shm file
	if (strcmp(command, "set") == 0)
		bandwidth_shm_set(pid, dev, down, up);
	else if (strcmp(command, "clear") == 0)
		bandwidth_shm_remove(pid, dev);

	//************************
	// build command
	//************************
	char *devname = NULL;
	if (dev) {
		// read shm network map file
		char *fname;
		if (asprintf(&fname, "/dev/shm/firejail/%d-netmap", (int) pid) == -1)
			errExit("asprintf");
		FILE *fp = fopen(fname, "r");
		if (!fp) {
			fprintf(stderr, "Error: cannot read netowk map filel %s\n", fname);
			exit(1);
		}
		
		char buf[1024];
		int len = strlen(dev);
		while (fgets(buf, 1024, fp)) {
			// remove '\n'
			char *ptr = strchr(buf, '\n');
			if (ptr)
				*ptr = '\0';
			if (*buf == '\0')
				break;

			if (strncmp(buf, dev, len) == 0  && buf[len] == ':') {
				devname = strdup(buf + len + 1);
				if (!devname)
					errExit("strdup");
				// check device in namespace
				if (if_nametoindex(devname) == 0) {
					fprintf(stderr, "Error: cannot find network device %s\n", devname);
					exit(1);
				}
				break;
			}
		}
		free(fname);
		fclose(fp);
	}
	
	// build fshaper.sh command
	cmd = NULL;
	if (devname) {
		if (strcmp(command, "set") == 0) {
			if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s %s %d %d",
				PREFIX, command, devname, down, up) == -1)
				errExit("asprintf");
		}
		else {
			if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s %s", 
				PREFIX, command, devname) == -1)
				errExit("asprintf");
		}
	}
	else {
		if (asprintf(&cmd, "%s/lib/firejail/fshaper.sh --%s", PREFIX, command) == -1)
			errExit("asprintf");
	}
	assert(cmd);

	// wipe out environment variables
	environ = NULL;

	//************************
	// build command
	//************************
	// elevate privileges
	if (setreuid(0, 0))
		errExit("setreuid");
	if (setregid(0, 0))
		errExit("setregid");

	char *arg[4];
	arg[0] = "/bin/bash";
	arg[1] = "-c";
	arg[2] = cmd;
	arg[3] = NULL;
	execvp("/bin/bash", arg);
	
	// it will never get here
	exit(0);		
}
Ejemplo n.º 7
0
// return 1 if error
int name2pid(const char *name, pid_t *pid) {
	pid_t parent = getpid();
	
	DIR *dir;
	if (!(dir = opendir("/proc"))) {
		// sleep 2 seconds and try again
		sleep(2);
		if (!(dir = opendir("/proc"))) {
			exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: cannot open /proc directory\n");
			exit(1);
		}
	}
	
	struct dirent *entry;
	char *end;
	while ((entry = readdir(dir))) {
		pid_t newpid = strtol(entry->d_name, &end, 10);
		if (end == entry->d_name || *end)
			continue;
		if (newpid == parent)
			continue;

		// check if this is a firejail executable
		char *comm = pid_proc_comm(newpid);
		if (comm) {
			// remove \n
			char *ptr = strchr(comm, '\n');
			if (ptr)
				*ptr = '\0';
			if (strcmp(comm, "firejail")) {
				free(comm);
				continue;
			}
			free(comm);
		}
		
		char *cmd = pid_proc_cmdline(newpid);
		if (cmd) {
			// mark the end of the name
			char *ptr = strstr(cmd, "--name=");
			char *start = ptr;
			if (!ptr) {
				free(cmd);
				continue;
			}
			// set a NULL pointer on the next identified argument
			char *next_for_sure = strstr(ptr, " --");
			if (next_for_sure)
		    *next_for_sure = '\0';
			// else we can't allow spaces in the --name argument
			else {
			  while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
				  ptr++;
			  *ptr = '\0';
			}
			int rv = strcmp(start + 7, name);
			if (rv == 0) {
				free(cmd);
				*pid = newpid;
				closedir(dir);
				return 0;
			}
			free(cmd);
		}
	}
	closedir(dir);
	return 1;
}
Ejemplo n.º 8
0
// return 1 if error
int name2pid(const char *name, pid_t *pid) {
	pid_t parent = getpid();
	
	DIR *dir;
	if (!(dir = opendir("/proc"))) {
		// sleep 2 seconds and try again
		sleep(2);
		if (!(dir = opendir("/proc"))) {
			fprintf(stderr, "Error: cannot open /proc directory\n");
			exit(1);
		}
	}
	
	struct dirent *entry;
	char *end;
	while ((entry = readdir(dir))) {
		pid_t newpid = strtol(entry->d_name, &end, 10);
		if (end == entry->d_name || *end)
			continue;
		if (newpid == parent)
			continue;

		// check if this is a firejail executable
		char *comm = pid_proc_comm(newpid);
		if (comm) {
			// remove \n
			char *ptr = strchr(comm, '\n');
			if (ptr)
				*ptr = '\0';
			if (strcmp(comm, "firejail")) {
				free(comm);
				continue;
			}
			free(comm);
		}
		
		char *cmd = pid_proc_cmdline(newpid);
		if (cmd) {
			// mark the end of the name
			char *ptr = strstr(cmd, "--name=");
			char *start = ptr;
			if (!ptr) {
				free(cmd);
				continue;
			}
			while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
				ptr++;
			*ptr = '\0';
			int rv = strcmp(start + 7, name);
			if (rv == 0) {
				free(cmd);
				*pid = newpid;
				closedir(dir);
				return 0;
			}
			free(cmd);
		}
	}
	closedir(dir);
	return 1;
}
Ejemplo n.º 9
0
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;
}