aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-11-28 10:36:04 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2016-11-28 10:36:04 -0500
commitd0c1fcfa273d323a26aa8477130e176dc2435bf5 (patch)
tree5c0823ed12cabf602ace114a12b53fb3b2872b99 /src
parentcleanup (diff)
downloadfirejail-d0c1fcfa273d323a26aa8477130e176dc2435bf5.tar.gz
firejail-d0c1fcfa273d323a26aa8477130e176dc2435bf5.tar.zst
firejail-d0c1fcfa273d323a26aa8477130e176dc2435bf5.zip
netfilter rework
Diffstat (limited to 'src')
-rw-r--r--src/firejail/firejail.h5
-rw-r--r--src/firejail/netfilter.c233
-rw-r--r--src/firejail/sbox.c32
-rw-r--r--src/firejail/util.c42
-rw-r--r--src/firejail/x11.c1
5 files changed, 115 insertions, 198 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 4ae3cfd9f..61de17bf8 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -41,7 +41,6 @@
41#define RUN_CPU_CFG "/run/firejail/mnt/cpu" 41#define RUN_CPU_CFG "/run/firejail/mnt/cpu"
42#define RUN_GROUPS_CFG "/run/firejail/mnt/groups" 42#define RUN_GROUPS_CFG "/run/firejail/mnt/groups"
43#define RUN_PROTOCOL_CFG "/run/firejail/mnt/protocol" 43#define RUN_PROTOCOL_CFG "/run/firejail/mnt/protocol"
44#define RUN_CP_COMMAND "/run/firejail/mnt/cp"
45#define RUN_HOME_DIR "/run/firejail/mnt/home" 44#define RUN_HOME_DIR "/run/firejail/mnt/home"
46#define RUN_ETC_DIR "/run/firejail/mnt/etc" 45#define RUN_ETC_DIR "/run/firejail/mnt/etc"
47#define RUN_BIN_DIR "/run/firejail/mnt/bin" 46#define RUN_BIN_DIR "/run/firejail/mnt/bin"
@@ -463,6 +462,7 @@ void create_empty_dir_as_root(const char *dir, mode_t mode);
463void create_empty_file_as_root(const char *dir, mode_t mode); 462void create_empty_file_as_root(const char *dir, mode_t mode);
464int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode); 463int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode);
465void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid); 464void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid);
465char *read_text_file_or_exit(const char *fname);
466 466
467// fs_var.c 467// fs_var.c
468void fs_var_log(void); // mounting /var/log 468void fs_var_log(void); // mounting /var/log
@@ -679,6 +679,8 @@ void build_cmdline(char **command_line, char **window_title, int argc, char **ar
679#define PATH_FIREMON (PREFIX "/bin/firemon") 679#define PATH_FIREMON (PREFIX "/bin/firemon")
680#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp") 680#define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp")
681#define PATH_FCOPY (LIBDIR "/firejail/fcopy") 681#define PATH_FCOPY (LIBDIR "/firejail/fcopy")
682#define SBOX_STDIN_FILE "/run/firejail/mnt/sbox_stdin"
683
682// bitmapped filters for sbox_run 684// bitmapped filters for sbox_run
683#define SBOX_ROOT (1 << 0) // run the sandbox as root 685#define SBOX_ROOT (1 << 0) // run the sandbox as root
684#define SBOX_USER (1 << 1) // run the sandbox as a regular user 686#define SBOX_USER (1 << 1) // run the sandbox as a regular user
@@ -686,6 +688,7 @@ void build_cmdline(char **command_line, char **window_title, int argc, char **ar
686#define SBOX_CAPS_NONE (1 << 3) // drop all capabilities 688#define SBOX_CAPS_NONE (1 << 3) // drop all capabilities
687#define SBOX_CAPS_NETWORK (1 << 4) // caps filter for programs running network programs 689#define SBOX_CAPS_NETWORK (1 << 4) // caps filter for programs running network programs
688#define SBOX_ALLOW_STDIN (1 << 5) // don't close stdin 690#define SBOX_ALLOW_STDIN (1 << 5) // don't close stdin
691#define SBOX_STDIN_FROM_FILE (1 << 6) // open file and redirect it to stdin
689 692
690// run sbox 693// run sbox
691int sbox_run(unsigned filter, int num, ...); 694int sbox_run(unsigned filter, int num, ...);
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c
index 43f08e45b..ef4915f15 100644
--- a/src/firejail/netfilter.c
+++ b/src/firejail/netfilter.c
@@ -61,59 +61,6 @@ void check_netfilter_file(const char *fname) {
61 61
62 62
63void netfilter(const char *fname) { 63void netfilter(const char *fname) {
64 // default filter
65 char *filter = client_filter;
66
67 // custom filter
68 int allocated = 0;
69 if (netfilter_default)
70 fname = netfilter_default;
71 if (fname) {
72 assert(fname);
73
74 // open filter file
75 int fd = open(fname, O_RDONLY);
76 if (fd == -1)
77 goto errexit;
78 int size = lseek(fd, 0, SEEK_END);
79 if (size == -1)
80 goto errexit;
81 if (lseek(fd, 0 , SEEK_SET) == -1)
82 goto errexit;
83
84 // read filter
85 filter = malloc(size + 1); // + '\0'
86 if (filter == NULL)
87 goto errexit;
88 memset(filter, 0, size + 1);
89 int rd = 0;
90 while (rd < size) {
91 int rv = read(fd, (unsigned char *) filter + rd, size - rd);
92 if (rv == -1) {
93 close(fd);
94 goto errexit;
95 }
96 rd += rv;
97 }
98
99 // close file
100 close(fd);
101 allocated = 1;
102 }
103
104 // temporarily mount a tempfs on top of /tmp directory
105 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
106 errExit("mounting /tmp");
107
108 // create the filter file
109 FILE *fp = fopen("/tmp/netfilter", "w");
110 if (!fp) {
111 fprintf(stderr, "Error: cannot open /tmp/netfilter file\n");
112 exit(1);
113 }
114 fprintf(fp, "%s\n", filter);
115 fclose(fp);
116
117 // find iptables command 64 // find iptables command
118 struct stat s; 65 struct stat s;
119 char *iptables = NULL; 66 char *iptables = NULL;
@@ -127,113 +74,49 @@ void netfilter(const char *fname) {
127 iptables_restore = "/usr/sbin/iptables-restore"; 74 iptables_restore = "/usr/sbin/iptables-restore";
128 } 75 }
129 if (iptables == NULL || iptables_restore == NULL) { 76 if (iptables == NULL || iptables_restore == NULL) {
130 fprintf(stderr, "Error: iptables command not found\n"); 77 fprintf(stderr, "Error: iptables command not found, netfilter not configured\n");
131 goto doexit; 78 return;
132 } 79 }
133 80
134 // push filter 81 // read filter
135 pid_t child = fork(); 82 char *filter = client_filter;
136 if (child < 0) 83 int allocated = 0;
137 errExit("fork"); 84 if (netfilter_default)
138 if (child == 0) { 85 fname = netfilter_default;
139 if (arg_debug) 86 if (fname) {
140 printf("Installing network filter:\n%s\n", filter); 87 filter = read_text_file_or_exit(fname);
141 88 allocated = 1;
142 int fd;
143 if((fd = open("/tmp/netfilter", O_RDONLY)) == -1) {
144 fprintf(stderr,"Error: cannot open /tmp/netfilter\n");
145 exit(1);
146 }
147 dup2(fd,STDIN_FILENO);
148
149 // wipe out environment variables
150 clearenv();
151 execl(iptables_restore, iptables_restore, NULL);
152 perror("execl");
153 _exit(1);
154 } 89 }
155 // wait for the child to finish
156 waitpid(child, NULL, 0);
157 90
158 // debug 91 // create the filter file
159 if (arg_debug) { 92 FILE *fp = fopen(SBOX_STDIN_FILE, "w");
160 child = fork(); 93 if (!fp) {
161 if (child < 0) 94 fprintf(stderr, "Error: cannot open %s\n", SBOX_STDIN_FILE);
162 errExit("fork"); 95 exit(1);
163 if (child == 0) {
164 // elevate privileges in order to get grsecurity working
165 if (setreuid(0, 0))
166 errExit("setreuid");
167 if (setregid(0, 0))
168 errExit("setregid");
169 environ = NULL;
170 assert(getenv("LD_PRELOAD") == NULL);
171 execl(iptables, iptables, "-vL", NULL);
172 perror("execl");
173 _exit(1);
174 }
175 // wait for the child to finish
176 waitpid(child, NULL, 0);
177 } 96 }
97 fprintf(fp, "%s\n", filter);
98 fclose(fp);
99
178 100
179doexit: 101 // push filter
180 // unmount /tmp 102 if (arg_debug)
181 umount("/tmp"); 103 printf("Installing network filter:\n%s\n", filter);
104 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP | SBOX_STDIN_FROM_FILE, 1, iptables_restore);
105 unlink(SBOX_STDIN_FILE);
106
107 // debug
108 if (arg_debug)
109 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL");
182 110
183 if (allocated) 111 if (allocated)
184 free(filter); 112 free(filter);
185 return; 113 return;
186
187errexit:
188 fprintf(stderr, "Error: cannot read network filter %s\n", fname);
189 exit(1);
190} 114}
191 115
192void netfilter6(const char *fname) { 116void netfilter6(const char *fname) {
193 if (fname == NULL) 117 if (fname == NULL)
194 return; 118 return;
195 119
196 char *filter;
197
198 // open filter file
199 int fd = open(fname, O_RDONLY);
200 if (fd == -1)
201 goto errexit;
202 int size = lseek(fd, 0, SEEK_END);
203 if (size == -1)
204 goto errexit;
205 if (lseek(fd, 0 , SEEK_SET) == -1)
206 goto errexit;
207
208 // read filter
209 filter = malloc(size + 1); // + '\0'
210 if (filter == NULL)
211 goto errexit;
212 memset(filter, 0, size + 1);
213 int rd = 0;
214 while (rd < size) {
215 int rv = read(fd, (unsigned char *) filter + rd, size - rd);
216 if (rv == -1)
217 goto errexit;
218 rd += rv;
219 }
220
221 // close file
222 close(fd);
223
224 // temporarily mount a tempfs on top of /tmp directory
225 if (mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0)
226 errExit("mounting /tmp");
227
228 // create the filter file
229 FILE *fp = fopen("/tmp/netfilter6", "w");
230 if (!fp) {
231 fprintf(stderr, "Error: cannot open /tmp/netfilter6 file\n");
232 exit(1);
233 }
234 fprintf(fp, "%s\n", filter);
235 fclose(fp);
236
237 // find iptables command 120 // find iptables command
238 char *ip6tables = NULL; 121 char *ip6tables = NULL;
239 char *ip6tables_restore = NULL; 122 char *ip6tables_restore = NULL;
@@ -247,56 +130,30 @@ void netfilter6(const char *fname) {
247 ip6tables_restore = "/usr/sbin/ip6tables-restore"; 130 ip6tables_restore = "/usr/sbin/ip6tables-restore";
248 } 131 }
249 if (ip6tables == NULL || ip6tables_restore == NULL) { 132 if (ip6tables == NULL || ip6tables_restore == NULL) {
250 fprintf(stderr, "Error: ip6tables command not found\n"); 133 fprintf(stderr, "Error: ip6tables command not found, netfilter6 not configured\n");
251 goto doexit; 134 return;
252 } 135 }
253 136
254 // push filter 137 // create the filter file
255 pid_t child = fork(); 138 char *filter = read_text_file_or_exit(fname);
256 if (child < 0) 139 FILE *fp = fopen(SBOX_STDIN_FILE, "w");
257 errExit("fork"); 140 if (!fp) {
258 if (child == 0) { 141 fprintf(stderr, "Error: cannot open /tmp/netfilter6 file\n");
259 if (arg_debug) 142 exit(1);
260 printf("Installing network filter:\n%s\n", filter);
261
262 int fd;
263 if((fd = open("/tmp/netfilter6", O_RDONLY)) == -1) {
264 fprintf(stderr,"Error: cannot open /tmp/netfilter6\n");
265 exit(1);
266 }
267 dup2(fd,STDIN_FILENO);
268
269 // wipe out environment variables
270 clearenv();
271 execl(ip6tables_restore, ip6tables_restore, NULL);
272 perror("execl");
273 _exit(1);
274 } 143 }
275 // wait for the child to finish 144 fprintf(fp, "%s\n", filter);
276 waitpid(child, NULL, 0); 145 fclose(fp);
277 146
147 // push filter
148 if (arg_debug)
149 printf("Installing network filter:\n%s\n", filter);
150 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP | SBOX_STDIN_FROM_FILE, 1, ip6tables_restore);
151 unlink(SBOX_STDIN_FILE);
152
278 // debug 153 // debug
279 if (arg_debug) { 154 if (arg_debug)
280 child = fork(); 155 sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL");
281 if (child < 0)
282 errExit("fork");
283 if (child == 0) {
284 clearenv();
285 execl(ip6tables, ip6tables, "-vL", NULL);
286 perror("execl");
287 _exit(1);
288 }
289 // wait for the child to finish
290 waitpid(child, NULL, 0);
291 }
292 156
293doexit:
294 // unmount /tmp
295 umount("/tmp");
296 free(filter); 157 free(filter);
297 return; 158 return;
298
299errexit:
300 fprintf(stderr, "Error: cannot read network filter %s\n", fname);
301 exit(1);
302} 159}
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index 65c4e35e9..f28bbaf1a 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -138,18 +138,34 @@ int sbox_run(unsigned filter, int num, ...) {
138 if (child == 0) { 138 if (child == 0) {
139 // clean the new process 139 // clean the new process
140 clearenv(); 140 clearenv();
141 int max = 20; // getdtablesize() is overkill for a firejail process 141
142 for (i = 3; i < max; i++) 142 if (filter & SBOX_STDIN_FROM_FILE) {
143 close(i); // close open files 143 int fd;
144 if ((filter & SBOX_ALLOW_STDIN) == 0) { 144 if((fd = open(SBOX_STDIN_FILE, O_RDONLY)) == -1) {
145 int fd = open("/dev/null",O_RDWR, 0); 145 fprintf(stderr,"Error: cannot open /tmp/netfilter\n");
146 if (fd != -1) { 146 exit(1);
147 dup2 (fd, STDIN_FILENO);
148 close(fd);
149 } 147 }
148 dup2(fd,STDIN_FILENO);
149 }
150 else if ((filter & SBOX_ALLOW_STDIN) == 0) {
151 int fd = open("/dev/null",O_RDWR, 0);
152 if (fd != -1)
153 dup2(fd, STDIN_FILENO);
150 else // the user could run the sandbox without /dev/null 154 else // the user could run the sandbox without /dev/null
151 close(STDIN_FILENO); 155 close(STDIN_FILENO);
152 } 156 }
157
158 // close all other file descriptors
159 int max = 20; // getdtablesize() is overkill for a firejail process
160 for (i = 3; i < max; i++)
161 close(i); // close open files
162
163 if (arg_debug) {
164 printf("sbox file descriptors:\n");
165 int rv = system("ls -l /proc/self/fd");
166 (void) rv;
167 }
168
153 umask(027); 169 umask(027);
154 170
155 // apply filters 171 // apply filters
diff --git a/src/firejail/util.c b/src/firejail/util.c
index c3e00a110..75f2acdb9 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -777,3 +777,45 @@ void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) {
777 777
778 ASSERT_PERMS(fname, uid, gid, mode); 778 ASSERT_PERMS(fname, uid, gid, mode);
779} 779}
780
781char *read_text_file_or_exit(const char *fname) {
782 assert(fname);
783
784 // open file
785 int fd = open(fname, O_RDONLY);
786 if (fd == -1) {
787 fprintf(stderr, "Error: cannot read %s\n", fname);
788 exit(1);
789 }
790
791 int size = lseek(fd, 0, SEEK_END);
792 if (size == -1)
793 goto errexit;
794 if (lseek(fd, 0 , SEEK_SET) == -1)
795 goto errexit;
796
797 // allocate memory
798 char *data = malloc(size + 1); // + '\0'
799 if (data == NULL)
800 goto errexit;
801 memset(data, 0, size + 1);
802
803 // read file
804 int rd = 0;
805 while (rd < size) {
806 int rv = read(fd, (unsigned char *) data + rd, size - rd);
807 if (rv == -1) {
808 goto errexit;
809 }
810 rd += rv;
811 }
812
813 // close file
814 close(fd);
815 return data;
816
817errexit:
818 close(fd);
819 fprintf(stderr, "Error: cannot read %s\n", fname);
820 exit(1);
821} \ No newline at end of file
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index d9b3b23d1..e67260490 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -252,7 +252,6 @@ void x11_start_xephyr(int argc, char **argv) {
252 } 252 }
253 253
254 for (i = 0; i < (int) strlen(xephyr_extra_params)-1; i++) { 254 for (i = 0; i < (int) strlen(xephyr_extra_params)-1; i++) {
255//todo: if working , add a -2 also in 0.9.44-bugfix
256 if (pos >= (sizeof(server_argv)/sizeof(*server_argv)) - 2) { 255 if (pos >= (sizeof(server_argv)/sizeof(*server_argv)) - 2) {
257 fprintf(stderr, "Error: arg count limit exceeded while parsing xephyr_extra_params\n"); 256 fprintf(stderr, "Error: arg count limit exceeded while parsing xephyr_extra_params\n");
258 exit(1); 257 exit(1);