diff options
-rw-r--r-- | src/firejail/cmdline.c | 151 | ||||
-rw-r--r-- | src/firejail/join.c | 24 | ||||
-rw-r--r-- | src/firejail/main.c | 104 |
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 | |||
29 | int 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 | |||
65 | void 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 | |||
133 | void 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); |