diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/fs_bin.c | 52 |
1 files changed, 50 insertions, 2 deletions
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index 9aa227caf..bf6a8ae91 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <sys/types.h> | 23 | #include <sys/types.h> |
24 | #include <sys/wait.h> | 24 | #include <sys/wait.h> |
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | #include <glob.h> | ||
26 | 27 | ||
27 | static char *paths[] = { | 28 | static char *paths[] = { |
28 | "/usr/local/bin", | 29 | "/usr/local/bin", |
@@ -146,6 +147,8 @@ errexit: | |||
146 | } | 147 | } |
147 | 148 | ||
148 | static void duplicate(char *fname, FILE *fplist) { | 149 | static void duplicate(char *fname, FILE *fplist) { |
150 | assert(fname); | ||
151 | |||
149 | if (*fname == '~' || strstr(fname, "..")) { | 152 | if (*fname == '~' || strstr(fname, "..")) { |
150 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); | 153 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
151 | exit(1); | 154 | exit(1); |
@@ -203,6 +206,51 @@ static void duplicate(char *fname, FILE *fplist) { | |||
203 | free(full_path); | 206 | free(full_path); |
204 | } | 207 | } |
205 | 208 | ||
209 | static void globbing(char *fname, FILE *fplist) { | ||
210 | assert(fname); | ||
211 | |||
212 | // go directly to duplicate() if no globbing char is present - see man 7 glob | ||
213 | if (strrchr(fname, '*') == NULL && | ||
214 | strrchr(fname, '[') == NULL && | ||
215 | strrchr(fname, '?') == NULL) | ||
216 | return duplicate(fname, fplist); | ||
217 | |||
218 | // loop through paths[] | ||
219 | int i = 0; | ||
220 | while (paths[i]) { | ||
221 | // private-bin-no-local can be disabled in /etc/firejail/firejail.config | ||
222 | if (checkcfg(CFG_PRIVATE_BIN_NO_LOCAL) && strstr(paths[i], "local/")) { | ||
223 | i++; | ||
224 | continue; | ||
225 | } | ||
226 | |||
227 | // check file | ||
228 | char *pattern; | ||
229 | if (asprintf(&pattern, "%s/%s", paths[i], fname) == -1) | ||
230 | errExit("asprintf"); | ||
231 | |||
232 | // globbing | ||
233 | glob_t globbuf; | ||
234 | int globerr = glob(pattern, GLOB_NOCHECK | GLOB_NOSORT | GLOB_PERIOD, NULL, &globbuf); | ||
235 | if (globerr) { | ||
236 | fprintf(stderr, "Error: failed to glob private-bin pattern %s\n", pattern); | ||
237 | exit(1); | ||
238 | } | ||
239 | |||
240 | size_t j; | ||
241 | for (j = 0; j < globbuf.gl_pathc; j++) { | ||
242 | assert(globbuf.gl_pathv[j]); | ||
243 | // testing for GLOB_NOCHECK - no pattern mached returns the origingal pattern | ||
244 | if (strcmp(globbuf.gl_pathv[j], pattern) == 0) | ||
245 | continue; | ||
246 | |||
247 | duplicate(globbuf.gl_pathv[j], fplist); | ||
248 | } | ||
249 | |||
250 | globfree(&globbuf); | ||
251 | i++; | ||
252 | } | ||
253 | } | ||
206 | 254 | ||
207 | void fs_private_bin_list(void) { | 255 | void fs_private_bin_list(void) { |
208 | char *private_list = cfg.bin_private_keep; | 256 | char *private_list = cfg.bin_private_keep; |
@@ -228,9 +276,9 @@ void fs_private_bin_list(void) { | |||
228 | } | 276 | } |
229 | 277 | ||
230 | char *ptr = strtok(dlist, ","); | 278 | char *ptr = strtok(dlist, ","); |
231 | duplicate(ptr, fplist); | 279 | globbing(ptr, fplist); |
232 | while ((ptr = strtok(NULL, ",")) != NULL) | 280 | while ((ptr = strtok(NULL, ",")) != NULL) |
233 | duplicate(ptr, fplist); | 281 | globbing(ptr, fplist); |
234 | free(dlist); | 282 | free(dlist); |
235 | fs_logger_print(); | 283 | fs_logger_print(); |
236 | if (fplist) | 284 | if (fplist) |