summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-07-31 07:49:01 -0400
committerLibravatar GitHub <noreply@github.com>2016-07-31 07:49:01 -0400
commit8f4b7538f6a9ce94bb9868afc0269518387a591e (patch)
tree471d01530c313886a482d9728dc3b17d6a9535e8 /src
parentMerge pull request #664 from reinerh/recursive_mkdir (diff)
parentexit with error if length of quoted command line is longer than ARG_MAX (diff)
downloadfirejail-8f4b7538f6a9ce94bb9868afc0269518387a591e.tar.gz
firejail-8f4b7538f6a9ce94bb9868afc0269518387a591e.tar.zst
firejail-8f4b7538f6a9ce94bb9868afc0269518387a591e.zip
Merge pull request #661 from manevich/join-quoting
Fix command line quoting on joining, move quoting code to functions
Diffstat (limited to 'src')
-rw-r--r--src/firejail/cmdline.c151
-rw-r--r--src/firejail/join.c24
-rw-r--r--src/firejail/main.c104
3 files changed, 154 insertions, 125 deletions
diff --git a/src/firejail/cmdline.c b/src/firejail/cmdline.c
new file mode 100644
index 000000000..517124d9e
--- /dev/null
+++ b/src/firejail/cmdline.c
@@ -0,0 +1,151 @@
1/*
2 * Copyright (C) 2014-2016 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
21#include "firejail.h"
22#include <string.h>
23#include <stdbool.h>
24#include <stdio.h>
25#include <linux/limits.h>
26#include <assert.h>
27#include <errno.h>
28
29int cmdline_length(int argc, char **argv, int index) {
30 int i,j;
31 int len = 0;
32 int argcnt = argc - index;
33 bool in_quotes = false;
34
35 for (i = 0; i < argcnt; i++) {
36 in_quotes = false;
37 for (j = 0; j < strlen(argv[i + index]); j++) {
38 if (argv[i + index][j] == '\'') {
39 if (in_quotes)
40 len++;
41 if (j > 0 && argv[i + index][j-1] == '\'')
42 len++;
43 else
44 len += 3;
45 in_quotes = false;
46 } else {
47 if (!in_quotes)
48 len++;
49 len++;
50 in_quotes = true;
51 }
52 }
53 if (in_quotes) {
54 len++;
55 }
56 if (strlen(argv[i + index]) == 0) {
57 len += 2;
58 }
59 len++;
60 }
61
62 return len;
63}
64
65void quote_cmdline(char *command_line, char *window_title, int len, int argc, char **argv, int index) {
66 int i,j;
67 int argcnt = argc - index;
68 bool in_quotes = false;
69 char *ptr1 = command_line;
70 char *ptr2 = window_title;
71
72 for (i = 0; i < argcnt; i++) {
73
74 // enclose args by single quotes,
75 // and since single quote can't be represented in single quoted text
76 // each occurence of it should be enclosed by double quotes
77 in_quotes = false;
78 for (j = 0; j < strlen(argv[i + index]); j++) {
79 // single quote
80 if (argv[i + index][j] == '\'') {
81 if (in_quotes) {
82 // close quotes
83 ptr1[0] = '\'';
84 ptr1++;
85 }
86 // previous char was single quote too
87 if (j > 0 && argv[i + index][j-1] == '\'') {
88 ptr1--;
89 sprintf(ptr1, "\'\"");
90 }
91 // this first in series
92 else
93 {
94 sprintf(ptr1, "\"\'\"");
95 }
96 ptr1 += strlen(ptr1);
97 in_quotes = false;
98 }
99 // anything other
100 else
101 {
102 if (!in_quotes) {
103 // open quotes
104 ptr1[0] = '\'';
105 ptr1++;
106 }
107 ptr1[0] = argv[i + index][j];
108 ptr1++;
109 in_quotes = true;
110 }
111 }
112 // close quotes
113 if (in_quotes) {
114 ptr1[0] = '\'';
115 ptr1++;
116 }
117 // handle empty argument case
118 if (strlen(argv[i + index]) == 0) {
119 sprintf(ptr1, "\'\'");
120 ptr1 += strlen(ptr1);
121 }
122 // add space
123 sprintf(ptr1, " ");
124 ptr1 += strlen(ptr1);
125
126 sprintf(ptr2, "%s ", argv[i + index]);
127 ptr2 += strlen(ptr2);
128 }
129
130 assert(len == strlen(command_line));
131}
132
133void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index) {
134 int len = cmdline_length(argc, argv, index);
135 if (len > ARG_MAX) {
136 errno = E2BIG;
137 errExit("cmdline_length");
138 }
139
140 *command_line = malloc(len + 1);
141 if (!*command_line)
142 errExit("malloc");
143 *window_title = malloc(len + 1);
144 if (!*window_title)
145 errExit("malloc");
146
147 quote_cmdline(*command_line, *window_title, len, argc, argv, index);
148
149 assert(*command_line);
150 assert(*window_title);
151}
diff --git a/src/firejail/join.c b/src/firejail/join.c
index c14108986..0b5b6a34a 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -49,29 +49,9 @@ static void extract_command(int argc, char **argv, int index) {
49 exit(1); 49 exit(1);
50 } 50 }
51 51
52
53 int len = 0;
54 int i;
55 // calculate command length
56 for (i = index; i < argc; i++) {
57 len += strlen(argv[i]) + 3;
58 }
59 assert(len > 0);
60
61 // build command 52 // build command
62 cfg.command_line = malloc(len + 1); 53 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, index);
63 *cfg.command_line = '\0'; 54
64 for (i = index; i < argc; i++) {
65 if (strchr(argv[i], '&')) {
66 strcat(cfg.command_line, "\'");
67 strcat(cfg.command_line, argv[i]);
68 strcat(cfg.command_line, "\' ");
69 }
70 else {
71 strcat(cfg.command_line, argv[i]);
72 strcat(cfg.command_line, " ");
73 }
74 }
75 if (arg_debug) 55 if (arg_debug)
76 printf("Extracted command #%s#\n", cfg.command_line); 56 printf("Extracted command #%s#\n", cfg.command_line);
77} 57}
diff --git a/src/firejail/main.c b/src/firejail/main.c
index cbc3d57cf..e86d78ff1 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -2004,109 +2004,7 @@ int main(int argc, char **argv) {
2004 cfg.window_title = "appimage"; 2004 cfg.window_title = "appimage";
2005 } 2005 }
2006 else { 2006 else {
2007 // calculate the length of the command 2007 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
2008 int i;
2009 int len = 0;
2010 int argcnt = argc - prog_index;
2011 int j;
2012 bool in_quotes = false;
2013
2014 for (i = 0; i < argcnt; i++) {
2015 in_quotes = false;
2016 for (j = 0; j < strlen(argv[i + prog_index]); j++) {
2017 if (argv[i + prog_index][j] == '\'') {
2018 if (in_quotes)
2019 len++;
2020 if (j > 0 && argv[i + prog_index][j-1] == '\'')
2021 len++;
2022 else
2023 len += 3;
2024 in_quotes = false;
2025 } else {
2026 if (!in_quotes)
2027 len++;
2028 len++;
2029 in_quotes = true;
2030 }
2031 }
2032 if (in_quotes) {
2033 len++;
2034 }
2035 if (strlen(argv[i + prog_index]) == 0) {
2036 len += 2;
2037 }
2038 len++;
2039 }
2040
2041 // build the string
2042 cfg.command_line = malloc(len + 1); // + '\0'
2043 if (!cfg.command_line)
2044 errExit("malloc");
2045 cfg.window_title = malloc(len + 1); // + '\0'
2046 if (!cfg.window_title)
2047 errExit("malloc");
2048
2049 char *ptr1 = cfg.command_line;
2050 char *ptr2 = cfg.window_title;
2051 for (i = 0; i < argcnt; i++) {
2052
2053 // enclose args by single quotes,
2054 // and since single quote can't be represented in single quoted text
2055 // each occurence of it should be enclosed by double quotes
2056 in_quotes = false;
2057 for (j = 0; j < strlen(argv[i + prog_index]); j++) {
2058 // single quote
2059 if (argv[i + prog_index][j] == '\'') {
2060 if (in_quotes) {
2061 // close quotes
2062 ptr1[0] = '\'';
2063 ptr1++;
2064 }
2065 // previous char was single quote too
2066 if (j > 0 && argv[i + prog_index][j-1] == '\'') {
2067 ptr1--;
2068 sprintf(ptr1, "\'\"");
2069 }
2070 // this first in series
2071 else
2072 {
2073 sprintf(ptr1, "\"\'\"");
2074 }
2075 ptr1 += strlen(ptr1);
2076 in_quotes = false;
2077 }
2078 // anything other
2079 else
2080 {
2081 if (!in_quotes) {
2082 // open quotes
2083 ptr1[0] = '\'';
2084 ptr1++;
2085 }
2086 ptr1[0] = argv[i + prog_index][j];
2087 ptr1++;
2088 in_quotes = true;
2089 }
2090 }
2091 // close quotes
2092 if (in_quotes) {
2093 ptr1[0] = '\'';
2094 ptr1++;
2095 }
2096 // handle empty argument case
2097 if (strlen(argv[i + prog_index]) == 0) {
2098 sprintf(ptr1, "\'\'");
2099 ptr1 += strlen(ptr1);
2100 }
2101 // add space
2102 sprintf(ptr1, " ");
2103 ptr1 += strlen(ptr1);
2104
2105 sprintf(ptr2, "%s ", argv[i + prog_index]);
2106 ptr2 += strlen(ptr2);
2107 }
2108
2109 assert(len == strlen(cfg.command_line));
2110 } 2008 }
2111 2009
2112 assert(cfg.command_name); 2010 assert(cfg.command_name);