aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2022-03-10 14:43:17 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2022-03-10 14:43:17 +0100
commit4d3d3270883140535cc6ea5a190aebdf6f3dc120 (patch)
tree7bae03cfce71b7f13bba30fe907354d97d40df74
parentRELNOTES: add warning about allow-tray (diff)
downloadfirejail-4d3d3270883140535cc6ea5a190aebdf6f3dc120.tar.gz
firejail-4d3d3270883140535cc6ea5a190aebdf6f3dc120.tar.zst
firejail-4d3d3270883140535cc6ea5a190aebdf6f3dc120.zip
refactor meta character filtering
-rw-r--r--src/fcopy/main.c10
-rw-r--r--src/firejail/fs_lib.c6
-rw-r--r--src/firejail/macros.c43
-rw-r--r--src/fnetfilter/main.c5
-rw-r--r--src/include/common.h5
-rw-r--r--src/lib/common.c60
6 files changed, 73 insertions, 56 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c
index c64d20127..e56d853c8 100644
--- a/src/fcopy/main.c
+++ b/src/fcopy/main.c
@@ -472,18 +472,12 @@ int main(int argc, char **argv) {
472 size_t len = strlen(src); 472 size_t len = strlen(src);
473 while (len > 1 && src[len - 1] == '/') 473 while (len > 1 && src[len - 1] == '/')
474 src[--len] = '\0'; 474 src[--len] = '\0';
475 if (strcspn(src, "\\*&!?\"'<>%^(){}[];,") != len) { 475 reject_meta_chars(src, 0);
476 fprintf(stderr, "Error fcopy: invalid source file name %s\n", src);
477 exit(1);
478 }
479 476
480 len = strlen(dest); 477 len = strlen(dest);
481 while (len > 1 && dest[len - 1] == '/') 478 while (len > 1 && dest[len - 1] == '/')
482 dest[--len] = '\0'; 479 dest[--len] = '\0';
483 if (strcspn(dest, "\\*&!?\"'<>%^(){}[];,~") != len) { 480 reject_meta_chars(dest, 0);
484 fprintf(stderr, "Error fcopy: invalid dest file name %s\n", dest);
485 exit(1);
486 }
487 481
488 // the destination should be a directory; 482 // the destination should be a directory;
489 struct stat s; 483 struct stat s;
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c
index 194a980f4..848691a56 100644
--- a/src/firejail/fs_lib.c
+++ b/src/firejail/fs_lib.c
@@ -276,9 +276,9 @@ static void install_list_entry(const char *lib) {
276 assert(lib); 276 assert(lib);
277 277
278 // filename check 278 // filename check
279 int len = strlen(lib); 279 reject_meta_chars(lib, 1);
280 if (strcspn(lib, "\\&!?\"'<>%^(){}[];,") != (size_t)len || 280
281 strstr(lib, "..")) { 281 if (strstr(lib, "..")) {
282 fprintf(stderr, "Error: \"%s\" is an invalid library\n", lib); 282 fprintf(stderr, "Error: \"%s\" is an invalid library\n", lib);
283 exit(1); 283 exit(1);
284 } 284 }
diff --git a/src/firejail/macros.c b/src/firejail/macros.c
index 74d529504..3f9460041 100644
--- a/src/firejail/macros.c
+++ b/src/firejail/macros.c
@@ -265,28 +265,6 @@ char *expand_macros(const char *path) {
265 return rv; 265 return rv;
266} 266}
267 267
268// replace control characters with a '?'
269static char *fix_control_chars(const char *fname) {
270 assert(fname);
271
272 size_t len = strlen(fname);
273 char *rv = malloc(len + 1);
274 if (!rv)
275 errExit("malloc");
276
277 size_t i = 0;
278 while (fname[i] != '\0') {
279 if (iscntrl((unsigned char) fname[i]))
280 rv[i] = '?';
281 else
282 rv[i] = fname[i];
283 i++;
284 }
285 rv[i] = '\0';
286
287 return rv;
288}
289
290void invalid_filename(const char *fname, int globbing) { 268void invalid_filename(const char *fname, int globbing) {
291// EUID_ASSERT(); 269// EUID_ASSERT();
292 assert(fname); 270 assert(fname);
@@ -304,24 +282,5 @@ void invalid_filename(const char *fname, int globbing) {
304 return; 282 return;
305 } 283 }
306 284
307 size_t i = 0; 285 reject_meta_chars(ptr, globbing);
308 while (ptr[i] != '\0') {
309 if (iscntrl((unsigned char) ptr[i])) {
310 char *new = fix_control_chars(fname);
311 fprintf(stderr, "Error: \"%s\" is an invalid filename: no control characters allowed\n", new);
312 exit(1);
313 }
314 i++;
315 }
316
317 char *reject;
318 if (globbing)
319 reject = "\\&!\"<>%^{};,"; // file globbing ('*?[]') is allowed
320 else
321 reject = "\\&!?\"<>%^{};,*[]";
322 char *c = strpbrk(ptr, reject);
323 if (c) {
324 fprintf(stderr, "Error: \"%s\" is an invalid filename: rejected character: \"%c\"\n", fname, *c);
325 exit(1);
326 }
327} 286}
diff --git a/src/fnetfilter/main.c b/src/fnetfilter/main.c
index 081408ab3..a89e12933 100644
--- a/src/fnetfilter/main.c
+++ b/src/fnetfilter/main.c
@@ -187,10 +187,9 @@ printf("\n");
187 char *command = (argc == 3)? argv[1]: NULL; 187 char *command = (argc == 3)? argv[1]: NULL;
188//printf("command %s\n", command); 188//printf("command %s\n", command);
189//printf("destfile %s\n", destfile); 189//printf("destfile %s\n", destfile);
190
190 // destfile is a real filename 191 // destfile is a real filename
191 int len = strlen(destfile); 192 reject_meta_chars(destfile, 0);
192 if (strcspn(destfile, "\\&!?\"'<>%^(){};,*[]") != (size_t)len)
193 err_exit_cannot_open_file(destfile);
194 193
195 // handle default config (command = NULL, destfile) 194 // handle default config (command = NULL, destfile)
196 if (command == NULL) { 195 if (command == NULL) {
diff --git a/src/include/common.h b/src/include/common.h
index f72ec9738..c9640435a 100644
--- a/src/include/common.h
+++ b/src/include/common.h
@@ -140,6 +140,11 @@ char *pid_proc_comm(const pid_t pid);
140char *pid_proc_cmdline(const pid_t pid); 140char *pid_proc_cmdline(const pid_t pid);
141int pid_proc_cmdline_x11_xpra_xephyr(const pid_t pid); 141int pid_proc_cmdline_x11_xpra_xephyr(const pid_t pid);
142int pid_hidepid(void); 142int pid_hidepid(void);
143char *do_replace_cntrl_chars(char *str, char c);
144char *replace_cntrl_chars(const char *str, char c);
145int has_cntrl_chars(const char *str);
146void reject_cntrl_chars(const char *fname);
147void reject_meta_chars(const char *fname, int globbing);
143void warn_dumpable(void); 148void warn_dumpable(void);
144const char *gnu_basename(const char *path); 149const char *gnu_basename(const char *path);
145int *str_to_int_array(const char *str, size_t *sz); 150int *str_to_int_array(const char *str, size_t *sz);
diff --git a/src/lib/common.c b/src/lib/common.c
index 91d5125b1..8e84fab26 100644
--- a/src/lib/common.c
+++ b/src/lib/common.c
@@ -321,6 +321,66 @@ const char *gnu_basename(const char *path) {
321 return last_slash+1; 321 return last_slash+1;
322} 322}
323 323
324char *do_replace_cntrl_chars(char *str, char c) {
325 if (str) {
326 size_t i;
327 for (i = 0; str[i]; i++) {
328 if (iscntrl((unsigned char) str[i]))
329 str[i] = c;
330 }
331 }
332 return str;
333}
334
335char *replace_cntrl_chars(const char *str, char c) {
336 assert(str);
337
338 char *rv = strdup(str);
339 if (!rv)
340 errExit("strdup");
341
342 do_replace_cntrl_chars(rv, c);
343 return rv;
344}
345
346int has_cntrl_chars(const char *str) {
347 assert(str);
348
349 size_t i;
350 for (i = 0; str[i]; i++) {
351 if (iscntrl((unsigned char) str[i]))
352 return 1;
353 }
354 return 0;
355}
356
357void reject_cntrl_chars(const char *fname) {
358 assert(fname);
359
360 if (has_cntrl_chars(fname)) {
361 char *fname_print = replace_cntrl_chars(fname, '?');
362
363 fprintf(stderr, "Error: \"%s\" is an invalid filename: no control characters are allowed\n", fname_print);
364 exit(1);
365 }
366}
367
368void reject_meta_chars(const char *fname, int globbing) {
369 assert(fname);
370
371 reject_cntrl_chars(fname);
372
373 const char *reject = "\\&!?\"<>%^{};,*[]";
374 if (globbing)
375 reject = "\\&!\"<>%^{};,"; // file globbing ('*?[]') is allowed
376
377 const char *c = strpbrk(fname, reject);
378 if (c) {
379 fprintf(stderr, "Error: \"%s\" is an invalid filename: rejected character: \"%c\"\n", fname, *c);
380 exit(1);
381 }
382}
383
324// takes string with comma separated int values, returns int array 384// takes string with comma separated int values, returns int array
325int *str_to_int_array(const char *str, size_t *sz) { 385int *str_to_int_array(const char *str, size_t *sz) {
326 assert(str && sz); 386 assert(str && sz);