Exemple #1
0
void cpu_print_filter(pid_t pid) {
	EUID_ASSERT();
	
	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();	// grsecurity
	char *comm = pid_proc_comm(pid);
	EUID_USER();	// grsecurity
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission denied.\n");
			exit(1);
		}
	}

	print_cpu(pid);
	exit(0);
}
Exemple #2
0
pid_t switch_to_child(pid_t pid) {
	EUID_ROOT();
	errno = 0;
	char *comm = pid_proc_comm(pid);
	if (!comm) {
		if (errno == ENOENT) {
			fprintf(stderr, "Error: cannot find process with pid %d\n", pid);
			exit(1);
		}
		else {
			fprintf(stderr, "Error: cannot read /proc file\n");
			exit(1);
		}
	}
	EUID_USER();
	if (strcmp(comm, "firejail") == 0) {
		pid_t child;
		if (find_child(pid, &child) == 1) {
			fprintf(stderr, "Error: no valid sandbox\n");
			exit(1);
		}
		fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) child);
		pid = child;
	}
	free(comm);
	return pid;
}
Exemple #3
0
// return 1 if firejail --x11 on command line
int pid_proc_cmdline_x11(const pid_t pid) {
	// if comm is not firejail return 0
	char *comm = pid_proc_comm(pid);
	if (strcmp(comm, "firejail") != 0) {
		free(comm);
		return 0;
	}
	free(comm);

	// open /proc/pid/cmdline file
	char *fname;
	int fd;
	if (asprintf(&fname, "/proc/%d/cmdline", pid) == -1)
		return 0;
	if ((fd = open(fname, O_RDONLY)) < 0) {
		free(fname);
		return 0;
	}
	free(fname);

	// read file
	unsigned char buffer[BUFLEN];
	ssize_t len;
	if ((len = read(fd, buffer, sizeof(buffer) - 1)) <= 0) {
		close(fd);
		return 0;
	}
	buffer[len] = '\0';
	close(fd);

	// skip the first argument
	int i;
	for (i = 0; buffer[i] != '\0'; i++);

	// parse remaining command line options
	while (1) {
		// extract argument
		i++;
		if (i >= len)
			break;
		char *arg = (char *)buffer + i;

		// detect the last command line option
		if (strcmp(arg, "--") == 0)
			break;
		if (strncmp(arg, "--", 2) != 0)
			break;
			
		// check x11
		if (strncmp(arg, "--x11", 5) == 0)
			return 1;
		i += strlen(arg);
	}
	return 0;
}
Exemple #4
0
// --protocol.print
void protocol_print_filter(pid_t pid) {
	EUID_ASSERT();
	
	(void) pid;
#ifdef SYS_socket
	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission denied.\n");
			exit(1);
		}
	}

	// find the seccomp filter
	EUID_ROOT();
	char *fname;
	if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_PROTOCOL_CFG) == -1)
		errExit("asprintf");

	struct stat s;
	if (stat(fname, &s) == -1) {
		printf("Cannot access seccomp filter.\n");
		exit(1);
	}

	// read and print the filter
	protocol_filter_load(fname);
	free(fname);
	if (cfg.protocol)
		printf("%s\n", cfg.protocol);
	exit(0);
#else
        fprintf(stderr, "Warning: --protocol not supported on this platform\n");
        return;
#endif  
}
Exemple #5
0
void seccomp_print_filter(pid_t pid) {
	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		struct stat s;
		char *dir;
		if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
			errExit("asprintf");
		if (stat(dir, &s) < 0)
			errExit("stat");
		if (s.st_uid != uid) {
			printf("Error: permission denied.\n");
			exit(1);
		}
	}


	// find the seccomp filter
	char *fname;
	if (asprintf(&fname, "/proc/%d/root/tmp/firejail/mnt/seccomp", pid) == -1)
		errExit("asprintf");

	struct stat s;
	if (stat(fname, &s) == -1) {
		printf("Cannot access seccomp filter.\n");
		exit(1);
	}

	// read and print the filter
	read_seccomp_file(fname);
	drop_privs(1);
	filter_debug();

	exit(0);
}
Exemple #6
0
void seccomp_print_filter(pid_t pid) {
	EUID_ASSERT();
	
	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission denied.\n");
			exit(1);
		}
	}


	// find the seccomp filter
	EUID_ROOT();
	char *fname;
	if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_CFG) == -1)
		errExit("asprintf");

	struct stat s;
	if (stat(fname, &s) == -1) {
		printf("Cannot access seccomp filter.\n");
		exit(1);
	}

	// read and print the filter
	read_seccomp_file(fname);
	drop_privs(1);
	filter_debug();
	free(fname);

	exit(0);
}
Exemple #7
0
void seccomp_print_filter(pid_t pid) {
	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: permission denied to print seccomp filters (sandbox belongs to a different user).\n");
			exit(1);
		}
	}

	// find the seccomp filter
	char *fname;
	if (asprintf(&fname, "/proc/%d/root/tmp/firejail/mnt/seccomp", pid) == -1)
		errExit("asprintf");

	struct stat s;
	if (stat(fname, &s) == -1) {
		exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: Cannot access seccomp filter.\n");
		exit(1);
	}

	// read and print the filter
	read_seccomp_file(fname);
	drop_privs(1);
	filter_debug();

	exit(0);
}
Exemple #8
0
void seccomp_print_filter(pid_t pid) {
	EUID_ASSERT();

	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission denied.\n");
			exit(1);
		}
	}

	// find the seccomp filter
	EUID_ROOT();
	char *fname;
	if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_SECCOMP_CFG) == -1)
		errExit("asprintf");

	struct stat s;
	if (stat(fname, &s) == -1) {
		printf("Cannot access seccomp filter.\n");
		exit(1);
	}

	// read and print the filter - run this as root, the user doesn't have access
	sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3, PATH_FSECCOMP, "print", fname);
	free(fname);

	exit(0);
}
Exemple #9
0
void caps_print_filter(pid_t pid) {
    // if the pid is that of a firejail  process, use the pid of the first child process
    char *comm = pid_proc_comm(pid);
    if (comm) {
        // remove \n
        char *ptr = strchr(comm, '\n');
        if (ptr)
            *ptr = '\0';
        if (strcmp(comm, "firejail") == 0) {
            pid_t child;
            if (find_child(pid, &child) == 0) {
                pid = child;
            }
        }
        free(comm);
    }

    // check privileges for non-root users
    uid_t uid = getuid();
    if (uid != 0) {
        struct stat s;
        char *dir;
        if (asprintf(&dir, "/proc/%u/ns", pid) == -1)
            errExit("asprintf");
        if (stat(dir, &s) < 0)
            errExit("stat");
        if (s.st_uid != uid) {
            printf("Error: permission denied.\n");
            exit(1);
        }
    }

    uint64_t caps = extract_caps(pid);
    drop_privs(1);

    int i;
    uint64_t mask;
    int elems = sizeof(capslist) / sizeof(capslist[0]);
    for (i = 0, mask = 1; i < elems; i++, mask <<= 1) {
        printf("%-18.18s  - %s\n", capslist[i].name, (mask & caps)? "enabled": "disabled");
    }

    exit(0);
}
Exemple #10
0
void caps_print_filter(pid_t pid) {
	EUID_ASSERT();
	
	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission denied.\n");
			exit(1);
		}
	}

	uint64_t caps = extract_caps(pid);
	drop_privs(1);

	int i;
	uint64_t mask;
	int elems = sizeof(capslist) / sizeof(capslist[0]);
	for (i = 0, mask = 1; i < elems; i++, mask <<= 1) {
		printf("%-18.18s  - %s\n", capslist[i].name, (mask & caps)? "enabled": "disabled");
	}

	exit(0);
}
Exemple #11
0
void net_dns_print(pid_t pid) {
	// drop privileges - will not be able to read /etc/resolv.conf for --noroot option
//	drop_privs(1);

	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
			}
		}
		free(comm);
	}
	
	char *fname;
	if (asprintf(&fname, "/proc/%d/root/etc/resolv.conf", pid) == -1)
		errExit("asprintf");

	// access /etc/resolv.conf
	FILE *fp = fopen(fname, "r");
	if (!fp) {
		fprintf(stderr, "Error: cannot access /etc/resolv.conf\n");
		exit(1);
	}
	
	char buf[MAXBUF];
	while (fgets(buf, MAXBUF, fp))
		printf("%s", buf);
	printf("\n");
	fclose(fp);
	free(fname);
	exit(0);
}
Exemple #12
0
void join(pid_t pid, int argc, char **argv, int index) {
	EUID_ASSERT();
	char *homedir = cfg.homedir;
	
	extract_command(argc, argv, index);
	signal (SIGTERM, signal_handler);

	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	EUID_ROOT();
	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)	// not available for uid 0
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (arg_join_network) {
		if (join_namespace(pid, "net"))
			exit(1);
	}
	else if (arg_join_filesystem) {
		if (join_namespace(pid, "mnt"))
			exit(1);
	}
	else {
		if (join_namespace(pid, "ipc") ||
		    join_namespace(pid, "net") ||
		    join_namespace(pid, "pid") ||
		    join_namespace(pid, "uts") ||
		    join_namespace(pid, "mnt"))
			exit(1);
	}

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv;
		if (!arg_join_network) {
			rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
			if (rv == 0)
				printf("changing root to %s\n", rootdir);
		}
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)	// not available for uid 0
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)	// not available for uid 0
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// read cfg.protocol from file
		if (getuid() != 0)
			protocol_filter_load(RUN_PROTOCOL_CFG);
		if (cfg.protocol) {	// not available for uid 0
			seccomp_load(RUN_SECCOMP_PROTOCOL);	// install filter	
		}
				
		// set seccomp filter
		if (apply_seccomp == 1)	// not available for uid 0
			seccomp_load(RUN_SECCOMP_CFG);
#endif

		// mount user namespace or drop privileges
		if (arg_noroot) {	// not available for uid 0
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);

			// user namespace resets capabilities
			// set caps filter
			if (apply_caps == 1)	// not available for uid 0
				caps_set(caps);
		}
		else 
			drop_privs(arg_nogroups);	// nogroups not available for uid 0


		// set nice
		if (arg_nice) {
			errno = 0;
			int rv = nice(cfg.nice);
			(void) rv;
			if (errno) {
				fprintf(stderr, "Warning: cannot set nice value\n");
				errno = 0;
			}
		}

		env_defaults();
		if (cfg.command_line == NULL) {
			assert(cfg.shell);
			cfg.command_line = cfg.shell;
			cfg.window_title = cfg.shell;
		}

		int cwd = 0;
		if (cfg.cwd) {
			if (chdir(cfg.cwd) == 0)
				cwd = 1;
		}

		if (!cwd) {
			if (chdir("/") < 0)
				errExit("chdir");
			if (cfg.homedir) {
				struct stat s;
				if (stat(cfg.homedir, &s) == 0) {
					/* coverity[toctou] */
					if (chdir(cfg.homedir) < 0)
						errExit("chdir");
				}
			}
		}

		start_application();

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	flush_stdin();
	exit(0);
}
Exemple #13
0
void join(pid_t pid, int argc, char **argv, int index) {
	EUID_ASSERT();
	char *homedir = cfg.homedir;
	
	extract_command(argc, argv, index);
	signal (SIGTERM, signal_handler);

	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	EUID_ROOT();
	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)	// not available for uid 0
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (arg_join_network) {
		if (join_namespace(pid, "net"))
			exit(1);
	}
	else if (arg_join_filesystem) {
		if (join_namespace(pid, "mnt"))
			exit(1);
	}
	else {
		if (join_namespace(pid, "ipc"))
			exit(1);
		if (join_namespace(pid, "net"))
			exit(1);
		if (join_namespace(pid, "pid"))
			exit(1);
		if (join_namespace(pid, "uts"))
			exit(1);
		if (join_namespace(pid, "mnt"))
			exit(1);
	}

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv;
		if (!arg_join_network) {
			rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
			if (rv == 0)
				printf("changing root to %s\n", rootdir);
		}
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)	// not available for uid 0
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)	// not available for uid 0
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// set protocol filter
		if (getuid() != 0)
			protocol_filter_load(RUN_PROTOCOL_CFG);
		if (cfg.protocol) {	// not available for uid 0
			protocol_filter();
		}
				
		// set seccomp filter
		if (apply_seccomp == 1)	// not available for uid 0
			seccomp_set();
#endif

		// fix qt 4.8
		if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
			errExit("setenv");
		if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
			errExit("setenv");

		// mount user namespace or drop privileges
		if (arg_noroot) {	// not available for uid 0
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);

			// user namespace resets capabilities
			// set caps filter
			if (apply_caps == 1)	// not available for uid 0
				caps_set(caps);
		}
		else 
			drop_privs(arg_nogroups);	// nogroups not available for uid 0


		// set prompt color to green
		char *prompt = getenv("FIREJAIL_PROMPT");
		if (prompt && strcmp(prompt, "yes") == 0) {
			//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
			if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
				errExit("setenv");
		}
		
		// set nice
		if (arg_nice) {
			errno = 0;
			int rv = nice(cfg.nice);
			(void) rv;
			if (errno) {
				fprintf(stderr, "Warning: cannot set nice value\n");
				errno = 0;
			}
		}

		// run cmdline trough shell
		if (cfg.command_line == NULL) {
			// if the sandbox was started with --shell=none, it is possible we don't have a shell
			// inside the sandbox
			if (cfg.shell == NULL) {
				cfg.shell = guess_shell();
				if (!cfg.shell) {
					fprintf(stderr, "Error: no POSIX shell found, please use --shell command line option\n");
					exit(1);
				}
			}
				
			struct stat s;
			if (stat(cfg.shell, &s) == -1)  {
				fprintf(stderr, "Error: %s shell not found inside the sandbox\n", cfg.shell);
				exit(1);
			}

			cfg.command_line = cfg.shell;
			cfg.window_title = cfg.shell;
		}

		int cwd = 0;
		if (cfg.cwd) {
			if (chdir(cfg.cwd) == 0)
				cwd = 1;
		}

		if (!cwd) {
			if (chdir("/") < 0)
				errExit("chdir");
			if (cfg.homedir) {
				struct stat s;
				if (stat(cfg.homedir, &s) == 0) {
					/* coverity[toctou] */
					if (chdir(cfg.homedir) < 0)
						errExit("chdir");
				}
			}
		}

		start_application();

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	flush_stdin();
	exit(0);
}
Exemple #14
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;
}
Exemple #15
0
// return 1 if error
// this function requires root access - todo: fix it!
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) {
			if (strcmp(comm, "firejail")) {
				free(comm);
				continue;
			}
			free(comm);
		}
		
		// look for the sandbox name in /run/firejail/name/<PID>
		// todo: use RUN_FIREJAIL_NAME_DIR define from src/firejail/firejail.h
		char *fname;
		if (asprintf(&fname, "/run/firejail/name/%d", newpid) == -1)
			errExit("asprintf");
		FILE *fp = fopen(fname, "r");
		if (fp) {
			char buf[BUFLEN];
			if (fgets(buf, BUFLEN, fp)) {
				// remove \n
				char *ptr = strchr(buf, '\n');
				if (ptr) {
					*ptr = '\0';
					if (strcmp(buf, name) == 0) {
						// we found it!
						fclose(fp);
						free(fname);
						*pid = newpid;
						closedir(dir);
						return 0;
					}
				}
				else
					fprintf(stderr, "Error: invalid %s\n", fname);
			}
			fclose(fp);
		}
		free(fname);
	}
	closedir(dir);
	return 1;
}
Exemple #16
0
void join(pid_t pid, const char *homedir, int argc, char **argv, int index) {
	extract_command(argc, argv, index);

	// if the pid is that of a firejail  process, use the pid of the first child process
	char *comm = pid_proc_comm(pid);
	if (comm) {
		// remove \n
		char *ptr = strchr(comm, '\n');
		if (ptr)
			*ptr = '\0';
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			exechelp_logerrv("firejail", FIREJAIL_ERROR, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (join_namespace(pid, "ipc"))
		exit(1);
	if (join_namespace(pid, "net"))
		exit(1);
	if (join_namespace(pid, "pid"))
		exit(1);
	if (join_namespace(pid, "uts"))
		exit(1);
	if (join_namespace(pid, "mnt"))
		exit(1);

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
		if (rv == 0)
			printf("changing root to %s\n", rootdir);
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// set seccomp filter
		if (apply_seccomp == 1)
			seccomp_set();
#endif


    /* We then load the variables that the original Firejail instance applied
     * to the original Firejail client whose namespace we're joining. */
    load_domain_env_from_chroot_proc();

		// mount user namespace or drop privileges
		if (arg_noroot) {
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);
		}
		else 
			drop_privs(arg_nogroups);

		// set prompt color to green
		//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
		if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
			errExit("setenv");

		// run icmdline trough /bin/bash
		if (cfg.command_line == NULL)
			// replace the process with a regular bash session
			execlp("/bin/bash", "/bin/bash", NULL);
		else {
			// run the command supplied by the user
			int cwd = 0;
			if (cfg.cwd) {
				if (chdir(cfg.cwd) == 0)
					cwd = 1;
			}
			
			if (!cwd) {
				if (chdir("/") < 0)
					errExit("chdir");
				if (cfg.homedir) {
					struct stat s;
					if (stat(cfg.homedir, &s) == 0) {
						if (chdir(cfg.homedir) < 0)
							errExit("chdir");
					}
				}
			}

			char *arg[5];
			arg[0] = "/bin/bash";
			arg[1] = "-c";
			if (arg_debug)
				printf("Starting %s\n", cfg.command_line);
      exechelp_logv("firejail", "Starting %s in sandbox %d\n", cfg.command_line, pid);
			if (!arg_doubledash) {
				arg[2] = cfg.command_line;
				arg[3] = NULL;
			}
			else {
				arg[2] = "--";
				arg[3] = cfg.command_line;
				arg[4] = NULL;
			}
			execvp("/bin/bash", arg);
		}

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	exit(0);
}
Exemple #17
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);		
}
Exemple #18
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;
}
Exemple #19
0
void join(pid_t pid, int argc, char **argv, int index) {
	EUID_ASSERT();
	char *homedir = cfg.homedir;
	
	extract_command(argc, argv, index);

	// if the pid is that of a firejail  process, use the pid of the first child process
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") == 0) {
			pid_t child;
			if (find_child(pid, &child) == 0) {
				pid = child;
				printf("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) pid);
			}
		}
		free(comm);
	}

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n");
			exit(1);
		}
	}

	EUID_ROOT();
	// in user mode set caps seccomp, cpu, cgroup, etc
	if (getuid() != 0) {
		extract_caps_seccomp(pid);
		extract_cpu(pid);
		extract_cgroup(pid);
		extract_nogroups(pid);
		extract_user_namespace(pid);
	}
	
	// set cgroup
	if (cfg.cgroup)	// not available for uid 0
		set_cgroup(cfg.cgroup);
		
	// join namespaces
	if (arg_join_network) {
		if (join_namespace(pid, "net"))
			exit(1);
	}
	else if (arg_join_filesystem) {
		if (join_namespace(pid, "mnt"))
			exit(1);
	}
	else {
		if (join_namespace(pid, "ipc"))
			exit(1);
		if (join_namespace(pid, "net"))
			exit(1);
		if (join_namespace(pid, "pid"))
			exit(1);
		if (join_namespace(pid, "uts"))
			exit(1);
		if (join_namespace(pid, "mnt"))
			exit(1);
	}

	pid_t child = fork();
	if (child < 0)
		errExit("fork");
	if (child == 0) {
		// chroot into /proc/PID/root directory
		char *rootdir;
		if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
			errExit("asprintf");
			
		int rv;
		if (!arg_join_network) {
			rv = chroot(rootdir); // this will fail for processes in sandboxes not started with --chroot option
			if (rv == 0)
				printf("changing root to %s\n", rootdir);
		}
		
		prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
		if (chdir("/") < 0)
			errExit("chdir");
		if (homedir) {
			struct stat s;
			if (stat(homedir, &s) == 0) {
				/* coverity[toctou] */
				if (chdir(homedir) < 0)
					errExit("chdir");
			}
		}
		
		// set cpu affinity
		if (cfg.cpus)	// not available for uid 0
			set_cpu_affinity();
					
		// set caps filter
		if (apply_caps == 1)	// not available for uid 0
			caps_set(caps);
#ifdef HAVE_SECCOMP
		// set protocol filter
		if (getuid() != 0)
			protocol_filter_load(RUN_PROTOCOL_CFG);
		if (cfg.protocol) {	// not available for uid 0
			protocol_filter();
		}
				
		// set seccomp filter
		if (apply_seccomp == 1)	// not available for uid 0
			seccomp_set();
		
#endif
		
		// fix qt 4.8
		if (setenv("QT_X11_NO_MITSHM", "1", 1) < 0)
			errExit("setenv");
		if (setenv("container", "firejail", 1) < 0) // LXC sets container=lxc,
			errExit("setenv");

		// mount user namespace or drop privileges
		if (arg_noroot) {	// not available for uid 0
			if (arg_debug)
				printf("Joining user namespace\n");
			if (join_namespace(1, "user"))
				exit(1);
		}
		else 
			drop_privs(arg_nogroups);	// nogroups not available for uid 0

		// set prompt color to green
		//export PS1='\[\e[1;32m\][\u@\h \W]\$\[\e[0m\] '
		if (setenv("PROMPT_COMMAND", "export PS1=\"\\[\\e[1;32m\\][\\u@\\h \\W]\\$\\[\\e[0m\\] \"", 1) < 0)
			errExit("setenv");

		// run cmdline trough /bin/bash
		if (cfg.command_line == NULL) {
			struct stat s;

			// replace the process with a shell
			if (stat("/bin/bash", &s) == 0)
				execlp("/bin/bash", "/bin/bash", NULL);
			else if (stat("/usr/bin/zsh", &s) == 0)
				execlp("/usr/bin/zsh", "/usr/bin/zsh", NULL);
			else if (stat("/bin/csh", &s) == 0)
				execlp("/bin/csh", "/bin/csh", NULL);
			else if (stat("/bin/sh", &s) == 0)
				execlp("/bin/sh", "/bin/sh", NULL);
			
			// no shell found, print an error and exit
			fprintf(stderr, "Error: no POSIX shell found\n");
			sleep(5);
			exit(1);
		}
		else {
			// run the command supplied by the user
			int cwd = 0;
			if (cfg.cwd) {
				if (chdir(cfg.cwd) == 0)
					cwd = 1;
			}
			
			if (!cwd) {
				if (chdir("/") < 0)
					errExit("chdir");
				if (cfg.homedir) {
					struct stat s;
					if (stat(cfg.homedir, &s) == 0) {
						if (chdir(cfg.homedir) < 0)
							errExit("chdir");
					}
				}
			}

			char *arg[5];
			arg[0] = "/bin/bash";
			arg[1] = "-c";
			if (arg_debug)
				printf("Starting %s\n", cfg.command_line);
			if (!arg_doubledash) {
				arg[2] = cfg.command_line;
				arg[3] = NULL;
			}
			else {
				arg[2] = "--";
				arg[3] = cfg.command_line;
				arg[4] = NULL;
			}
			execvp("/bin/bash", arg);
		}

		// it will never get here!!!
	}

	// wait for the child to finish
	waitpid(child, NULL, 0);
	exit(0);
}
Exemple #20
0
//***********************************
// command execution
//***********************************
void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up) {
	EUID_ASSERT();
	//************************
	// verify sandbox
	//************************
	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (!comm) {
		fprintf(stderr, "Error: cannot find sandbox\n");
		exit(1);
	}

	// check for firejail sandbox
	if (strcmp(comm, "firejail") != 0) {
		fprintf(stderr, "Error: cannot find sandbox\n");
		exit(1);
	}
	free(comm);
	
	// check network namespace
	char *name;
	if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1)
		errExit("asprintf");
	struct stat s;
	if (stat(name, &s) == -1) {
		fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n");
		exit(1);
	}

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

	EUID_ROOT();
	if (join_namespace(child, "net")) {
		fprintf(stderr, "Error: cannot join the network namespace\n");
		exit(1);
	}

	// set run file
	if (strcmp(command, "set") == 0)
		bandwidth_set(pid, dev, down, up);
	else if (strcmp(command, "clear") == 0)
		bandwidth_remove(pid, dev);

	//************************
	// build command
	//************************
	char *devname = NULL;
	if (dev) {
		// read network map file
		char *fname;
		if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1)
			errExit("asprintf");
		FILE *fp = fopen(fname, "r");
		if (!fp) {
			fprintf(stderr, "Error: cannot read network map file %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
	char *cmd = NULL;
	if (devname) {
		if (strcmp(command, "set") == 0) {
			if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s %d %d",
				LIBDIR, command, devname, down, up) == -1)
				errExit("asprintf");
		}
		else {
			if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s",
				LIBDIR, command, devname) == -1)
				errExit("asprintf");
		}
	}
	else {
		if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s", LIBDIR, 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/sh";
	arg[1] = "-c";
	arg[2] = cmd;
	arg[3] = NULL;
	clearenv();
	execvp(arg[0], arg);
	
	// it will never get here
	errExit("execvp");
}
Exemple #21
0
void shut(pid_t pid) {
	EUID_ASSERT();

	EUID_ROOT();
	char *comm = pid_proc_comm(pid);
	EUID_USER();
	if (comm) {
		if (strcmp(comm, "firejail") != 0) {
			fprintf(stderr, "Error: this is not a firejail sandbox\n");
			exit(1);
		}
		free(comm);
	}
	else
		errExit("/proc/PID/comm");

	// check privileges for non-root users
	uid_t uid = getuid();
	if (uid != 0) {
		uid_t sandbox_uid = pid_get_uid(pid);
		if (uid != sandbox_uid) {
			fprintf(stderr, "Error: permission is denied to shutdown a sandbox created by a different user.\n");
			exit(1);
		}
	}

	printf("Sending SIGTERM to %u\n", pid);
	kill(pid, SIGTERM);

	// wait for not more than 11 seconds
	int monsec = 11;
	char *monfile;
	if (asprintf(&monfile, "/proc/%d/cmdline", pid) == -1)
		errExit("asprintf");
	int killdone = 0;

	while (monsec) {
		sleep(1);
		monsec--;

		FILE *fp = fopen(monfile, "r");
		if (!fp) {
			killdone = 1;
			break;
		}

		char c;
		size_t count = fread(&c, 1, 1, fp);
		fclose(fp);
		if (count == 0) {
			// all done
			killdone = 1;
			break;
		}
	}
	free(monfile);


	// force SIGKILL
	if (!killdone) {
		// kill the process and its child
		pid_t child;
		if (find_child(pid, &child) == 0) {
			printf("Sending SIGKILL to %u\n", child);
			kill(child, SIGKILL);
		}
		printf("Sending SIGKILL to %u\n", pid);
		kill(pid, SIGKILL);
	}

	EUID_ROOT();
	delete_run_files(pid);
}
Exemple #22
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;
}
Exemple #23
0
static int monitor_application(pid_t app_pid) {
	monitored_pid = app_pid;
	signal (SIGTERM, sandbox_handler);
	EUID_USER();

	int status = 0;
	while (monitored_pid) {
		usleep(20000);
		char *msg;
		if (asprintf(&msg, "monitoring pid %d\n", monitored_pid) == -1)
			errExit("asprintf");
		logmsg(msg);
		if (arg_debug)
			printf("%s\n", msg);
		free(msg);

		pid_t rv;
		do {
			rv = waitpid(-1, &status, 0);
			if (rv == -1)
				break;
		}
		while(rv != monitored_pid);
		if (arg_debug)
			printf("Sandbox monitor: waitpid %u retval %d status %d\n", monitored_pid, rv, status);

		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;
		monitored_pid = 0;
		while ((entry = readdir(dir)) != NULL) {
			unsigned pid;
			if (sscanf(entry->d_name, "%u", &pid) != 1)
				continue;
			if (pid == 1)
				continue;
			
			// todo: make this generic
			// Dillo browser leaves a dpid process running, we need to shut it down
			if (strcmp(cfg.command_name, "dillo") == 0) {
				char *pidname = pid_proc_comm(pid);
				if (pidname && strcmp(pidname, "dpid") == 0)
					break;
				free(pidname);
			}

			monitored_pid = pid;
			break;
		}
		closedir(dir);

		if (monitored_pid != 0 && arg_debug)
			printf("Sandbox monitor: monitoring %u\n", monitored_pid);
	}

	// return the latest exit status.
	return status;

#if 0
// todo: find a way to shut down interfaces before closing the namespace
// the problem is we don't have enough privileges to shutdown interfaces in this moment
	// shut down bridge/macvlan interfaces
	if (any_bridge_configured()) {
		
		if (cfg.bridge0.configured) {
			printf("Shutting down %s\n", cfg.bridge0.devsandbox);
			net_if_down( cfg.bridge0.devsandbox);
		}
		if (cfg.bridge1.configured) {
			printf("Shutting down %s\n", cfg.bridge1.devsandbox);
			net_if_down( cfg.bridge1.devsandbox);
		}
		if (cfg.bridge2.configured) {
			printf("Shutting down %s\n", cfg.bridge2.devsandbox);
			net_if_down( cfg.bridge2.devsandbox);
		}
		if (cfg.bridge3.configured) {
			printf("Shutting down %s\n", cfg.bridge3.devsandbox);
			net_if_down( cfg.bridge3.devsandbox);
		}
		usleep(20000);	// 20 ms sleep
	}	
#endif	
}