aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/profile.c
diff options
context:
space:
mode:
authorLibravatar Glenn Washburn <development@efficientek.com>2018-10-10 04:16:49 -0500
committerLibravatar Glenn Washburn <development@efficientek.com>2018-10-16 03:24:54 -0500
commitdbf8d44df8ed36fd4345c65b10fadd22c5572cf9 (patch)
treeb288d83552221082557e08d6baddbfbe4fc109fd /src/firejail/profile.c
parentMerge branch 'improve-profile-handling' (diff)
downloadfirejail-dbf8d44df8ed36fd4345c65b10fadd22c5572cf9.tar.gz
firejail-dbf8d44df8ed36fd4345c65b10fadd22c5572cf9.tar.zst
firejail-dbf8d44df8ed36fd4345c65b10fadd22c5572cf9.zip
Add support for rudimentary conditionals in profiles, currently only the HAS_APPIMAGE conditional is supported.
Diffstat (limited to 'src/firejail/profile.c')
-rw-r--r--src/firejail/profile.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 4fc710f39..751347b29 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -132,12 +132,99 @@ void profile_add_ignore(const char *str) {
132} 132}
133 133
134 134
135int profile_check_conditional(char *ptr, int lineno, const char *fname) {
136 struct cond_t {
137 char *name; // conditional name
138 size_t len; // length of name
139 bool value; // true if set
140 } conditionals[] = {
141 {"HAS_APPIMAGE", strlen("HAS_APPIMAGE"), arg_appimage!=0},
142 NULL
143 }, *cond = conditionals;
144 char *tmp = ptr, *msg = NULL;
145
146 if (*ptr++ != '?')
147 return 1;
148
149 while (cond->name) {
150 // continue if not this conditional
151 if (strncmp(ptr, cond->name, cond->len) != 0) {
152 cond++;
153 continue;
154 }
155 ptr += cond->len;
156
157 if (*ptr == ' ')
158 ptr++;
159 if (*ptr++ != ':') {
160 msg = "invalid syntax: colon must come after conditional";
161 ptr = tmp;
162 goto error;
163 }
164 if (*ptr == '\0') {
165 msg = "invalid conditional line: no profile line after conditional";
166 ptr = tmp;
167 goto error;
168 }
169 if (*ptr == ' ')
170 ptr++;
171
172 // if set, continue processing statement in caller
173 if (cond->value) {
174 // move ptr to start of profile line
175 ptr = strdup(ptr);
176 if (!ptr)
177 errExit("strdup");
178
179 // check that the profile line does not contain either
180 // quiet or include directives
181 if ((strncmp(ptr, "quiet", 5) == 0) ||
182 (strncmp(ptr, "include", 7) == 0)) {
183 msg = "invalid profile line: quiet and include not allowed in conditionals";
184 ptr = tmp;
185 goto error;
186 }
187 free(tmp);
188
189 // verify syntax, exit in case of error
190 if (profile_check_line(ptr, lineno, fname))
191 profile_add(ptr);
192 }
193 // tell caller to ignore
194 return 0;
195 }
196
197 tmp = ptr;
198 // get the conditional used
199 while (*tmp != ':' && *tmp != '\0')
200 tmp++;
201 *tmp = '\0';
202
203 // this was a '?' prefix, but didn't match any of the conditionals
204 msg = "invalid/unsupported conditional";
205
206error:
207 fprintf(stderr, "Error: %s (\"%s\"", msg, ptr);
208 if (lineno == 0) ;
209 else if (fname != NULL)
210 fprintf(stderr, " on line %d in %s", lineno, fname);
211 else
212 fprintf(stderr, " on line %d in the custom profile", lineno);
213 fprintf(stderr, ")\n");
214 exit(1);
215}
216
217
135// check profile line; if line == 0, this was generated from a command line option 218// check profile line; if line == 0, this was generated from a command line option
136// return 1 if the command is to be added to the linked list of profile commands 219// return 1 if the command is to be added to the linked list of profile commands
137// return 0 if the command was already executed inside the function 220// return 0 if the command was already executed inside the function
138int profile_check_line(char *ptr, int lineno, const char *fname) { 221int profile_check_line(char *ptr, int lineno, const char *fname) {
139 EUID_ASSERT(); 222 EUID_ASSERT();
140 223
224 // check and process conditional profile lines
225 if (profile_check_conditional(ptr, lineno, fname) == 0)
226 return 0;
227
141 // check ignore list 228 // check ignore list
142 if (is_in_ignore_list(ptr)) 229 if (is_in_ignore_list(ptr))
143 return 0; 230 return 0;