From e83af0b1114499ccca03f6680a9e9b2c0e1e9493 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 26 Nov 2015 07:18:01 -0500 Subject: fixes --- src/firejail/fs_whitelist.c | 94 ++++++++++++++++++++++++++++++++++++++++++++- src/firejail/main.c | 2 +- src/firejail/util.c | 4 +- src/man/firejail.txt | 9 ++++- 4 files changed, 105 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index d018554d5..95238a956 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -27,11 +27,84 @@ #include #include +static char *dentry[] = { + "Downloads", + "Загрузки", + "Téléchargement", + NULL +}; + +#define MAXBUF 4098 +static char *resolve_downloads(void) { + char *fname; + struct stat s; + + // try a well known download directory name + int i = 0; + while (dentry[i] != NULL) { + if (asprintf(&fname, "%s/%s", cfg.homedir, dentry[i]) == -1) + errExit("asprintf"); + + if (stat(fname, &s) == 0) { + free(fname); + if (arg_debug) + printf("Downloads directory resolved as \"Downloads\"\n"); + + char *rv; + if (asprintf(&rv, "whitelist ~/%s", dentry[i]) == -1) + errExit("asprintf"); + return rv; + } + free(fname); + i++; + } + + // try a name form ~/.config/user-dirs.dirs + if (asprintf(&fname, "%s/.config/user-dirs.dirs", cfg.homedir) == -1) + errExit("asprintf"); + FILE *fp = fopen(fname, "r"); + if (!fp) { + free(fname); + return NULL; + } + free(fname); + + // extract downloads directory + char buf[MAXBUF]; + while (fgets(buf, MAXBUF, fp)) { + char *ptr = buf; + + // skip blanks + while (*ptr == ' ' || *ptr == '\t') + ptr++; + if (*ptr == '\0' || *ptr == '\n' || *ptr == '#') + continue; + + if (strncmp(ptr, "XDG_DOWNLOAD_DIR=\"$HOME/", 24) == 0) { + char *ptr1 = strchr(ptr + 24, '"'); + if (ptr1) { + *ptr1 = '\0'; + fclose(fp); + if (arg_debug) + printf("Downloads directory resolved as \"%s\"\n", ptr + 24); + + char *rv; + if (asprintf(&rv, "whitelist ~/%s", ptr + 24) == -1) + errExit("asprintf"); + return rv; + } + } + } + fclose(fp); + + return NULL; +} + static int mkpath(const char* path, mode_t mode) { assert(path && *path); mode |= 0111; - + // create directories with uid/gid as root or as current user if inside home directory uid_t uid = getuid(); gid_t gid = getgid(); @@ -211,6 +284,25 @@ void fs_whitelist(void) { continue; } + // resolve ${DOWNLOADS} + if (strcmp(entry->data + 10, "${DOWNLOADS}") == 0) { + char *tmp = resolve_downloads(); + if (tmp) + entry->data = tmp; + else { + *entry->data = '\0'; + fprintf(stderr, "***\n"); + fprintf(stderr, "*** Error: cannot whitelist Downloads directory\n"); + fprintf(stderr, "***\n"); + fprintf(stderr, "*** Any file saved in this directory will be lost when the sandbox is closed.\n"); + fprintf(stderr, "*** Please contact the developer. Workaround:\n"); + fprintf(stderr, "***\n"); + fprintf(stderr, "*** firejail --ignore=whitelist program-name\n"); + fprintf(stderr, "***\n"); + continue; + } + } + // replace ~/ or ${HOME} into /home/username new_name = expand_home(entry->data + 10, cfg.homedir); assert(new_name); diff --git a/src/firejail/main.c b/src/firejail/main.c index 02eab1a86..2981683aa 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -737,7 +737,7 @@ int main(int argc, char **argv) { } else if (strncmp(argv[i], "--ignore=", 9) == 0) { if (custom_profile) { - fprintf(stderr, "Error: please use --profile after --include\n"); + fprintf(stderr, "Error: please use --profile after --ignore\n"); exit(1); } diff --git a/src/firejail/util.c b/src/firejail/util.c index 0d9479a02..45f7ec364 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -574,13 +574,15 @@ void invalid_filename(const char *fname) { assert(fname); const char *ptr = fname; - if (arg_debug && arg_debug_check_filename) + if (arg_debug_check_filename) printf("Checking filename %s\n", fname); if (strncmp(ptr, "${HOME}", 7) == 0) ptr = fname + 7; else if (strncmp(ptr, "${PATH}", 7) == 0) ptr = fname + 7; + else if (strcmp(fname, "${DOWNLOADS}") == 0) + return; int len = strlen(ptr); // file globbing ('*') is allowed diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 39e0dbaf7..4f9f0cba9 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -155,8 +155,15 @@ Define a custom whitelist Linux capabilities filter. Example: .br $ sudo firejail \-\-caps.keep=chown,net_bind_service,setgid,\\ -setuid "/etc/init.d/nginx start && sleep inf" +setuid /etc/init.d/nginx start +.br +.br +A short note about mixing \-\-whitelist and \-\-read-only options. Whitelisted directories +should be made read-only independently. Making a parent directory read-only, will not +make the whitelist read-only. Example: +.br +$ firejail --whitelist=~/work --read-only=~/ --read-only=~/work .TP \fB\-\-caps.print=name Print the caps filter for the sandbox identified by name. -- cgit v1.2.3-54-g00ecf