diff options
author | 2016-07-25 11:07:52 -0400 | |
---|---|---|
committer | 2016-07-25 11:07:52 -0400 | |
commit | 20b89731df5868f1fb66ab93dcb6b7ec4dc2864b (patch) | |
tree | ca8eebc09d3273ad60a5e4332bc52abc385242cb /src | |
parent | 0.9.42~rc2 development (diff) | |
parent | Fix problem with single quotes in args (diff) | |
download | firejail-20b89731df5868f1fb66ab93dcb6b7ec4dc2864b.tar.gz firejail-20b89731df5868f1fb66ab93dcb6b7ec4dc2864b.tar.zst firejail-20b89731df5868f1fb66ab93dcb6b7ec4dc2864b.zip |
Merge pull request #629 from manevich/patch-2
Additional fixes of command line quoting
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/main.c | 92 | ||||
-rw-r--r-- | src/firejail/run_symlink.c | 11 |
2 files changed, 82 insertions, 21 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c index 25063700c..cbc3d57cf 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -2008,8 +2008,35 @@ int main(int argc, char **argv) { | |||
2008 | int i; | 2008 | int i; |
2009 | int len = 0; | 2009 | int len = 0; |
2010 | int argcnt = argc - prog_index; | 2010 | int argcnt = argc - prog_index; |
2011 | for (i = 0; i < argcnt; i++) | 2011 | int j; |
2012 | len += strlen(argv[i + prog_index]) + 3; // + ' ' + 2 '"' | 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 | } | ||
2013 | 2040 | ||
2014 | // build the string | 2041 | // build the string |
2015 | cfg.command_line = malloc(len + 1); // + '\0' | 2042 | cfg.command_line = malloc(len + 1); // + '\0' |
@@ -2022,21 +2049,64 @@ int main(int argc, char **argv) { | |||
2022 | char *ptr1 = cfg.command_line; | 2049 | char *ptr1 = cfg.command_line; |
2023 | char *ptr2 = cfg.window_title; | 2050 | char *ptr2 = cfg.window_title; |
2024 | for (i = 0; i < argcnt; i++) { | 2051 | for (i = 0; i < argcnt; i++) { |
2025 | // detect bash commands | 2052 | |
2026 | if (strstr(argv[i + prog_index], "&&") || strstr(argv[i + prog_index], "||")) { | 2053 | // enclose args by single quotes, |
2027 | sprintf(ptr1, "%s ", argv[i + prog_index]); | 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 | } | ||
2028 | } | 2090 | } |
2029 | else if (arg_command){ | 2091 | // close quotes |
2030 | sprintf(ptr1, "%s ", argv[i + prog_index]); | 2092 | if (in_quotes) { |
2093 | ptr1[0] = '\''; | ||
2094 | ptr1++; | ||
2031 | } | 2095 | } |
2032 | else { | 2096 | // handle empty argument case |
2033 | sprintf(ptr1, "\'%s\' ", argv[i + prog_index]); | 2097 | if (strlen(argv[i + prog_index]) == 0) { |
2098 | sprintf(ptr1, "\'\'"); | ||
2099 | ptr1 += strlen(ptr1); | ||
2034 | } | 2100 | } |
2035 | sprintf(ptr2, "%s ", argv[i + prog_index]); | 2101 | // add space |
2036 | 2102 | sprintf(ptr1, " "); | |
2037 | ptr1 += strlen(ptr1); | 2103 | ptr1 += strlen(ptr1); |
2104 | |||
2105 | sprintf(ptr2, "%s ", argv[i + prog_index]); | ||
2038 | ptr2 += strlen(ptr2); | 2106 | ptr2 += strlen(ptr2); |
2039 | } | 2107 | } |
2108 | |||
2109 | assert(len == strlen(cfg.command_line)); | ||
2040 | } | 2110 | } |
2041 | 2111 | ||
2042 | assert(cfg.command_name); | 2112 | assert(cfg.command_name); |
diff --git a/src/firejail/run_symlink.c b/src/firejail/run_symlink.c index 26c6c5133..020e70b80 100644 --- a/src/firejail/run_symlink.c +++ b/src/firejail/run_symlink.c | |||
@@ -103,16 +103,7 @@ void run_symlink(int argc, char **argv) { | |||
103 | a[1] = program; | 103 | a[1] = program; |
104 | int i; | 104 | int i; |
105 | for (i = 0; i < (argc - 1); i++) { | 105 | for (i = 0; i < (argc - 1); i++) { |
106 | // look for & character | 106 | a[i + 2] = argv[i + 1]; |
107 | if (strchr(argv[i + 1], '&')) { | ||
108 | char *str = malloc(strlen(argv[i + 1])); | ||
109 | if (str == NULL) | ||
110 | errExit("malloc"); | ||
111 | sprintf(str, "\"%s\"", argv[i + 1]); | ||
112 | a[i + 2] = str; | ||
113 | } | ||
114 | else | ||
115 | a[i + 2] = argv[i + 1]; | ||
116 | } | 107 | } |
117 | a[i + 2] = NULL; | 108 | a[i + 2] = NULL; |
118 | execvp(a[0], a); | 109 | execvp(a[0], a); |