aboutsummaryrefslogtreecommitdiffstats
path: root/src/jailcheck/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jailcheck/main.c')
-rw-r--r--src/jailcheck/main.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/jailcheck/main.c b/src/jailcheck/main.c
new file mode 100644
index 000000000..4d642bf96
--- /dev/null
+++ b/src/jailcheck/main.c
@@ -0,0 +1,192 @@
1/*
2 * Copyright (C) 2014-2021 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "jailcheck.h"
21#include "../include/firejail_user.h"
22#include "../include/pid.h"
23#include <sys/wait.h>
24
25uid_t user_uid = 0;
26gid_t user_gid = 0;
27char *user_name = NULL;
28char *user_home_dir = NULL;
29char *user_run_dir = NULL;
30int arg_debug = 0;
31
32static char *usage_str =
33 "Usage: jailcheck [options] directory [directory]\n\n"
34 "Options:\n"
35 " --debug - print debug messages.\n"
36 " --help, -? - this help screen.\n"
37 " --version - print program version and exit.\n";
38
39
40static void usage(void) {
41 printf("firetest - version %s\n\n", VERSION);
42 puts(usage_str);
43}
44
45static void cleanup(void) {
46 // running only as root
47 if (getuid() == 0) {
48 if (arg_debug)
49 printf("cleaning up!\n");
50 access_destroy();
51 virtual_destroy();
52 }
53}
54
55int main(int argc, char **argv) {
56 int i;
57 int findex = 0;
58
59 for (i = 1; i < argc; i++) {
60 if (strcmp(argv[i], "-?") == 0 || strcmp(argv[i], "--help") == 0) {
61 usage();
62 return 0;
63 }
64 else if (strcmp(argv[i], "--version") == 0) {
65 printf("firetest version %s\n\n", VERSION);
66 return 0;
67 }
68 else if (strncmp(argv[i], "--hello=", 8) == 0) { // used by noexec test
69 printf(" Warning: I can run programs in %s\n", argv[i] + 8);
70 return 0;
71 }
72 else if (strcmp(argv[i], "--debug") == 0)
73 arg_debug = 1;
74 else if (strncmp(argv[i], "--", 2) == 0) {
75 fprintf(stderr, "Error: invalid option\n");
76 return 1;
77 }
78 else {
79 findex = i;
80 break;
81 }
82 }
83
84 // user setup
85 if (getuid() != 0) {
86 fprintf(stderr, "Error: you need to be root (via sudo) to run this program\n");
87 exit(1);
88 }
89 user_name = get_sudo_user();
90 assert(user_name);
91 user_home_dir = get_homedir(user_name, &user_uid, &user_gid);
92 if (user_uid == 0) {
93 fprintf(stderr, "Error: root user not supported\n");
94 exit(1);
95 }
96 if (asprintf(&user_run_dir, "/run/user/%d", user_uid) == -1)
97 errExit("asprintf");
98
99 // test setup
100 atexit(cleanup);
101 access_setup("~/.ssh");
102 access_setup("~/.gnupg");
103 if (findex > 0) {
104 for (i = findex; i < argc; i++)
105 access_setup(argv[i]);
106 }
107
108 noexec_setup();
109 virtual_setup(user_home_dir);
110 virtual_setup("/tmp");
111 virtual_setup("/var/tmp");
112 virtual_setup("/dev");
113 virtual_setup("/etc");
114 virtual_setup("/bin");
115 virtual_setup("/usr/share");
116 virtual_setup(user_run_dir);
117 // basic sysfiles
118 sysfiles_setup("/etc/shadow");
119 sysfiles_setup("/etc/gshadow");
120 sysfiles_setup("/usr/bin/mount");
121 sysfiles_setup("/usr/bin/su");
122 sysfiles_setup("/usr/bin/ksu");
123 sysfiles_setup("/usr/bin/sudo");
124 sysfiles_setup("/usr/bin/strace");
125 // X11
126 sysfiles_setup("/usr/bin/xev");
127 sysfiles_setup("/usr/bin/xinput");
128 // compilers
129 sysfiles_setup("/usr/bin/gcc");
130 sysfiles_setup("/usr/bin/clang");
131 // networking
132 sysfiles_setup("/usr/bin/dig");
133 sysfiles_setup("/usr/bin/nslookup");
134 sysfiles_setup("/usr/bin/resolvectl");
135 sysfiles_setup("/usr/bin/nc");
136 sysfiles_setup("/usr/bin/ncat");
137 sysfiles_setup("/usr/bin/nmap");
138 sysfiles_setup("/usr/sbin/tcpdump");
139 // terminals
140 sysfiles_setup("/usr/bin/gnome-terminal");
141 sysfiles_setup("/usr/bin/xfce4-terminal");
142 sysfiles_setup("/usr/bin/lxterminal");
143
144 // print processes
145 pid_read(0);
146 for (i = 0; i < max_pids; i++) {
147 if (pids[i].level == 1) {
148 uid_t uid = pid_get_uid(i);
149 if (uid != user_uid) // not interested in other user sandboxes
150 continue;
151
152 // in case the pid is that of a firejail process, use the pid of the first child process
153 uid_t pid = find_child(i);
154 printf("\n");
155 pid_print_list(i, 0); // no wrapping
156 apparmor_test(pid);
157 seccomp_test(pid);
158 fflush(0);
159
160 pid_t child = fork();
161 if (child == -1)
162 errExit("fork");
163 if (child == 0) {
164 int rv = join_namespace(pid, "mnt");
165 if (rv == 0) {
166 virtual_test();
167 noexec_test(user_home_dir);
168 noexec_test("/tmp");
169 noexec_test("/var/tmp");
170 noexec_test(user_run_dir);
171 access_test();
172 sysfiles_test();
173 }
174 else {
175 printf(" Error: I cannot join the process mount space\n");
176 exit(1);
177 }
178
179 // drop privileges in order not to trigger cleanup()
180 if (setgid(user_gid) != 0)
181 errExit("setgid");
182 if (setuid(user_uid) != 0)
183 errExit("setuid");
184 return 0;
185 }
186 int status;
187 wait(&status);
188 }
189 }
190
191 return 0;
192}