From 23a962a1af3894b6834ad08c12b3c3fd99775247 Mon Sep 17 00:00:00 2001 From: startx2017 Date: Tue, 14 Aug 2018 08:35:01 -0400 Subject: 0.9.56-rc1 merges --- src/firecfg/firecfg.config | 2 + src/firecfg/main.c | 2 +- src/firejail/appimage.c | 2 +- src/firejail/firejail.h | 12 +- src/firejail/fs_home.c | 2 + src/firejail/fs_whitelist.c | 509 +++++++++++++----------------------------- src/firejail/join.c | 4 +- src/firejail/ls.c | 5 + src/firejail/macros.c | 284 +++++++++++++++++++++++ src/firejail/main.c | 25 +-- src/firejail/profile.c | 46 ++-- src/firejail/run_symlink.c | 1 + src/firejail/sandbox.c | 4 +- src/firejail/usage.c | 2 +- src/firejail/util.c | 129 ++++------- src/firemon/arp.c | 2 +- src/firemon/route.c | 6 +- src/firemon/usage.c | 2 +- src/fnet/veth.c | 4 +- src/fnetfilter/main.c | 8 +- src/fsec-print/print.c | 2 +- src/include/libnetlink.h | 4 +- src/lib/libnetlink.c | 4 +- src/libtracelog/libtracelog.c | 15 +- 24 files changed, 562 insertions(+), 514 deletions(-) create mode 100644 src/firejail/macros.c (limited to 'src') diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index 2585d204a..a33aaeb49 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config @@ -46,6 +46,7 @@ baloo_file baloo_filemetadata_temp_extractor baobab basilisk +beaker bibletime bitlbee bleachbit @@ -108,6 +109,7 @@ dosbox dragon dropbox ebook-viewer +electrum elinks empathy enchant diff --git a/src/firecfg/main.c b/src/firecfg/main.c index b79053d3e..6fe220d35 100644 --- a/src/firecfg/main.c +++ b/src/firecfg/main.c @@ -53,7 +53,7 @@ static char *usage_str = " [...]\n" "\n" "License GPL version 2 or later\n" - "Homepage: http://firejail.wordpress.com\n\n"; + "Homepage: https://firejail.wordpress.com\n\n"; static void usage(void) { printf("firecfg - version %s\n\n", VERSION); diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index 631276c0b..e8db91958 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c @@ -17,7 +17,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -// http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=770fe30a46a12b6fb6b63fbe1737654d28e84844 +// https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=770fe30a46a12b6fb6b63fbe1737654d28e84844 // sudo mount -o loop krita-3.0-x86_64.appimage mnt #include "firejail.h" diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 0faf10340..f31d6a2bc 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -451,6 +451,7 @@ void fs_chroot(const char *rootdir); void fs_check_chroot_dir(const char *rootdir); void fs_private_tmp(void); void fs_private_cache(void); +void fs_mnt(void); // profile.c // find and read the profile specified by name from dir directory @@ -463,7 +464,7 @@ void profile_read(const char *fname); int profile_check_line(char *ptr, int lineno, const char *fname); // add a profile entry in cfg.profile list; use str to populate the list void profile_add(char *str); -void fs_mnt(void); +void profile_add_ignore(const char *str); // list.c void list(void); @@ -490,6 +491,13 @@ int arp_check(const char *dev, uint32_t destaddr); // assign an IP address using arp scanning uint32_t arp_assign(const char *dev, Bridge *br); +// macros.c +char *expand_home(const char *path, const char *homedir); +char *resolve_macro(const char *name); +void invalid_filename(const char *fname, int globbing); +int is_macro(const char *name); + + // util.c void errLogExit(char* fmt, ...); void fwarning(char* fmt, ...); @@ -515,10 +523,8 @@ void check_private_dir(void); void update_map(char *mapping, char *map_file); void wait_for_other(int fd); void notify_other(int fd); -char *expand_home(const char *path, const char* homedir); const char *gnu_basename(const char *path); uid_t pid_get_uid(pid_t pid); -void invalid_filename(const char *fname, int globbing); uid_t get_group_id(const char *group); int remove_overlay_directory(void); void flush_stdin(void); diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index f8e7e6e74..3a332f7ff 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -290,6 +290,8 @@ void fs_private(void) { if (u == 0 && arg_allusers) // allow --allusers when starting the sandbox as root ; else { + if (arg_allusers) + fwarning("--allusers disabled by --private or --whitelist\n"); if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) errExit("mounting home directory"); fs_logger("tmpfs /home"); diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index bf839b524..c3d34e259 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -29,207 +29,95 @@ // mountinfo functionality test; // 1. enable TEST_MOUNTINFO definition -// 2. set a symlink in /tmp: ln -s /etc /tmp/etc -// 3. run firejail --debug --whitelist=/tmp/etc +// 2. run firejail --whitelist=/any/directory //#define TEST_MOUNTINFO -static char *dentry[] = { - "Downloads", - "Загрузки", - "Téléchargement", - NULL -}; - -static char *mentry[] = { - "Music", - "Музыка", - "Musique", - NULL -}; - -static char *ventry[] = { - "Videos", - "Видео", - "Vidéos", - NULL -}; - -static char *pentry[] = { - "Pictures", - "Изображения", - "Photos", - NULL -}; - -static char *deentry[] = { - "Desktop", - "Рабочий стол", - "Bureau", - NULL -}; - -static char *doentry[] = { - "Documents", - "Документы", - "Documents", - NULL -}; - #define EMPTY_STRING ("") #define MAXBUF 4098 -static char *resolve_xdg(int nowhitelist_flag, const char *var, size_t length, const char *prnt) { - EUID_ASSERT(); - char *fname; - struct stat s; - - 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); - - 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, var, length) == 0) { - char *ptr1 = ptr + length; - char *ptr2 = strchr(ptr1, '"'); - if (ptr2) { - fclose(fp); - *ptr2 = '\0'; - if (arg_debug || arg_debug_whitelists) - printf("extracted %s from ~/.config/user-dirs.dirs\n", ptr1); - if (strlen(ptr1) != 0) { - if (arg_debug || arg_debug_whitelists) - printf("%s ",prnt); - printf("directory resolved as \"%s\"\n", ptr1); - - if (asprintf(&fname, "%s/%s", cfg.homedir, ptr1) == -1) - errExit("asprintf"); - - if (stat(fname, &s) == -1) { - free(fname); - goto errout; - } - - char *rv; - if (nowhitelist_flag) { - if (asprintf(&rv, "nowhitelist ~/%s", ptr + length) == -1) - errExit("asprintf"); - } - else { - if (asprintf(&rv, "whitelist ~/%s", ptr + length) == -1) - errExit("asprintf"); - } - return rv; - } - else - goto errout; - } - } - } - - fclose(fp); - return NULL; - - errout: - if (!arg_private) { - fprintf(stderr, "***\n"); - fprintf(stderr, "*** Error: %s directory was not found in user home.\n",prnt); - fprintf(stderr, "*** \tAny files saved by the program, will be lost when the sandbox is closed.\n"); - fprintf(stderr, "***\n"); +// returns mallocated memory +char *parse_nowhitelist(int nowhitelist_flag, char *ptr1) { + char *rv; + if (nowhitelist_flag) { + if (asprintf(&rv, "nowhitelist ~/%s", ptr1) == -1) + errExit("asprintf"); } - return NULL; -} - -static char *resolve_hardcoded(int nowhitelist_flag, char *entries[], const char *prnt) { - EUID_ASSERT(); - char *fname; - struct stat s; - - int i = 0; - while (entries[i] != NULL) { - if (asprintf(&fname, "%s/%s", cfg.homedir, entries[i]) == -1) + else { + if (asprintf(&rv, "whitelist ~/%s", ptr1) == -1) errExit("asprintf"); - - if (stat(fname, &s) == 0) { - if (arg_debug || arg_debug_whitelists) { - printf("%s ", prnt); - printf("directory resolved as \"%s\"\n", fname); - } - - char *rv; - if (nowhitelist_flag) { - if (asprintf(&rv, "nowhitelist ~/%s", entries[i]) == -1) - errExit("asprintf"); - } - else { - if (asprintf(&rv, "whitelist ~/%s", entries[i]) == -1) - errExit("asprintf"); - } - free(fname); - return rv; - } - free(fname); - i++; } - - return NULL; + return rv; } 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(); - if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) != 0) { - uid = 0; - gid = 0; + if (strncmp(path, cfg.homedir, strlen(cfg.homedir)) == 0) { + EUID_USER(); } // work on a copy of the path - char *file_path = strdup(path); - if (!file_path) + char *dup = strdup(path); + if (!dup) errExit("strdup"); - char* p; + // don't create the last path element + char *p = strrchr(dup, '/'); + assert(p); + *p = '\0'; + + int parentfd = open("/", O_PATH|O_DIRECTORY|O_CLOEXEC); + if (parentfd == -1) + errExit("open"); + + // traverse the path, return -1 if a symlink is encountered int done = 0; - for (p=strchr(file_path+1, '/'); p; p=strchr(p+1, '/')) { - *p='\0'; - if (mkdir(file_path, mode)==-1) { + int fd = -1; + char *tok = strtok(dup, "/"); + assert(tok); // path is no top level directory + while (tok) { + // skip all instances of "/./" + if (strcmp(tok, ".") == 0) { + tok = strtok(NULL, "/"); + continue; + } + // create the directory if necessary + if (mkdirat(parentfd, tok, mode) == -1) { if (errno != EEXIST) { - *p='/'; - free(file_path); + if (arg_debug || arg_debug_whitelists) + perror("mkdir"); + close(parentfd); + free(dup); + EUID_ROOT(); return -1; } } - else { - if (set_perms(file_path, uid, gid, mode)) - errExit("set_perms"); + else done = 1; + // open the directory + fd = openat(parentfd, tok, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); + if (fd == -1) { + if (arg_debug || arg_debug_whitelists) + perror("open"); + close(parentfd); + free(dup); + EUID_ROOT(); + return -1; } - - *p='/'; + // move on to next path segment + close(parentfd); + parentfd = fd; + tok = strtok(NULL, "/"); } + if (done) fs_logger2("mkpath", path); - free(file_path); - return 0; + free(dup); + EUID_ROOT(); + return fd; } static void whitelist_path(ProfileEntry *entry) { @@ -323,13 +211,17 @@ static void whitelist_path(ProfileEntry *entry) { } assert(wfile); - // check if the file exists, confirm again there is no symlink + if (arg_debug || arg_debug_whitelists) + printf("Whitelisting %s\n", path); + + // confirm again the mount source exists and there is no symlink struct stat wfilestat; -#ifndef TEST_MOUNTINFO EUID_USER(); int fd = safe_fd(wfile, O_PATH|O_NOFOLLOW|O_CLOEXEC); EUID_ROOT(); if (fd == -1) { + if (arg_debug || arg_debug_whitelists) + printf("Debug %d: skip whitelisting of %s\n", __LINE__, path); free(wfile); return; } @@ -337,57 +229,68 @@ static void whitelist_path(ProfileEntry *entry) { errExit("fstat"); close(fd); if (S_ISLNK(wfilestat.st_mode)) { + if (arg_debug || arg_debug_whitelists) + printf("Debug %d: skip whitelisting of %s\n", __LINE__, path); free(wfile); return; } + +#ifdef TEST_MOUNTINFO + printf("TEST_MOUNTINFO\n"); + path = "/etc/."; #endif - if (arg_debug || arg_debug_whitelists) - printf("Whitelisting %s\n", path); + // create path of the mount target if necessary + int fd2 = mkpath(path, 0755); + if (fd2 == -1) { + // something went wrong during path creation or a symlink was found; + // if there is a symlink somewhere in the path of the mount target, + // assume the file is whitelisted already + if (arg_debug || arg_debug_whitelists) + printf("Debug %d: skip whitelisting of %s\n", __LINE__, path); + free(wfile); + return; + } - // create the path if necessary - struct stat s; - if (stat(path, &s) == -1) { - mkpath(path, 0755); - if (S_ISDIR(wfilestat.st_mode)) { - int rv = mkdir(path, 0755); - if (rv) { - fprintf(stderr, "Error: cannot create directory %s\n", path); - exit(1); - } - } - else { - int fd2 = open(path, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR|S_IWUSR); - if (fd2 == -1) { - fprintf(stderr, "Error: cannot create empty file %s\n", path); - exit(1); + // get file name of the mount target + const char *file = gnu_basename(path); + + // create the mount target if necessary and open it, a symlink is rejected + int fd3 = -1; + if (S_ISDIR(wfilestat.st_mode)) { + // directory foo can exist already: + // firejail --whitelist=/foo/bar --whitelist=/foo + if (mkdirat(fd2, file, 0755) == -1 && errno != EEXIST) { + if (arg_debug || arg_debug_whitelists) { + perror("mkdir"); + printf("Debug %d: skip whitelisting of %s\n", __LINE__, path); } close(fd2); + free(wfile); + return; } + fd3 = openat(fd2, file, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); } else { - if (!S_ISDIR(s.st_mode)) { - free(wfile); - return; // the file is already present - } + // create an empty file, fails with EEXIST if it is whitelisted already: + // firejail --whitelist=/foo --whitelist=/foo/bar + fd3 = openat(fd2, file, O_RDONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR|S_IWUSR); } - fs_logger2("whitelist", path); - - // get a file descriptor for path; if path contains anything other than directories - // or a regular file, assume it is whitelisted already - int fd3 = safe_fd(path, O_PATH|O_NOFOLLOW|O_CLOEXEC); if (fd3 == -1) { + if (arg_debug || arg_debug_whitelists) { + if (errno != EEXIST) { + perror("open"); + printf("Debug %d: skip whitelisting of %s\n", __LINE__, path); + } + } + close(fd2); free(wfile); return; } - if (fstat(fd3, &s) == -1) - errExit("fstat"); - if (!(S_ISDIR(s.st_mode) || S_ISREG(s.st_mode))) { - free(wfile); - close(fd3); - return; - } + close(fd2); + + fs_logger2("whitelist", path); // mount via the link in /proc/self/fd char *proc; @@ -411,6 +314,7 @@ static void whitelist_path(ProfileEntry *entry) { int fd4 = safe_fd(path, O_PATH|O_NOFOLLOW|O_CLOEXEC); if (fd4 == -1) errExit("safe_fd"); + struct stat s; if (fstat(fd4, &s) == -1) errExit("fstat"); if (s.st_dev != wfilestat.st_dev || s.st_ino != wfilestat.st_ino) @@ -465,99 +369,21 @@ void fs_whitelist(void) { } char *dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - // resolve ${DOWNLOADS} - if (strcmp(dataptr, "${DOWNLOADS}") == 0) { - char *tmp = resolve_xdg(nowhitelist_flag, "XDG_DOWNLOAD_DIR=\"$HOME/", 24, "Downloads"); - char *tmp2 = resolve_hardcoded(nowhitelist_flag, dentry, "Downloads"); - if (tmp) { - entry->data = tmp; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else if (tmp2) { - entry->data = tmp2; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else { - if (!nowhitelist_flag && !arg_quiet && !arg_private) { - fprintf(stderr, "***\n"); - fprintf(stderr, "*** Warning: cannot whitelist Downloads directory\n"); - fprintf(stderr, "*** \tAny file saved will be lost when the sandbox is closed.\n"); - fprintf(stderr, "*** \tPlease create a proper Downloads directory for your application.\n"); - fprintf(stderr, "***\n"); - } - entry->data = EMPTY_STRING; - continue; - } - } + // resolve macros + if (is_macro(dataptr)) { + char *tmp = resolve_macro(dataptr); + if (tmp != NULL) + tmp = parse_nowhitelist(nowhitelist_flag, tmp); - // resolve ${MUSIC} - if (strcmp(dataptr, "${MUSIC}") == 0) { - char *tmp = resolve_xdg(nowhitelist_flag, "XDG_MUSIC_DIR=\"$HOME/", 21, "Music"); - char *tmp2 = resolve_hardcoded(nowhitelist_flag, mentry, "Music"); if (tmp) { entry->data = tmp; dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; } - else if (tmp2) { - entry->data = tmp2; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else { - if (!nowhitelist_flag && !arg_quiet && !arg_private) { - fprintf(stderr, "***\n"); - fprintf(stderr, "*** Warning: cannot whitelist Music directory\n"); - fprintf(stderr, "*** \tAny file saved will be lost when the sandbox is closed.\n"); - fprintf(stderr, "*** \tPlease create a proper Music directory for your application.\n"); - fprintf(stderr, "***\n"); - } - entry->data = EMPTY_STRING; - continue; - } - } - - // resolve ${VIDEOS} - if (strcmp(dataptr, "${VIDEOS}") == 0) { - char *tmp = resolve_xdg(nowhitelist_flag, "XDG_VIDEOS_DIR=\"$HOME/", 22, "Videos"); - char *tmp2 = resolve_hardcoded(nowhitelist_flag, ventry, "Videos"); - if (tmp) { - entry->data = tmp; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else if (tmp2) { - entry->data = tmp2; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else { - if (!nowhitelist_flag && !arg_quiet && !arg_private) { - fprintf(stderr, "***\n"); - fprintf(stderr, "*** Warning: cannot whitelist Videos directory\n"); - fprintf(stderr, "*** \tAny file saved will be lost when the sandbox is closed.\n"); - fprintf(stderr, "*** \tPlease create a proper Videos directory for your application.\n"); - fprintf(stderr, "***\n"); - } - entry->data = EMPTY_STRING; - continue; - } - } - - // resolve ${PICTURES} - if (strcmp(dataptr, "${PICTURES}") == 0) { - char *tmp = resolve_xdg(nowhitelist_flag, "XDG_PICTURES_DIR=\"$HOME/", 24, "Pictures"); - char *tmp2 = resolve_hardcoded(nowhitelist_flag, pentry, "Pictures"); - if (tmp) { - entry->data = tmp; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else if (tmp2) { - entry->data = tmp2; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } else { if (!nowhitelist_flag && !arg_quiet && !arg_private) { fprintf(stderr, "***\n"); - fprintf(stderr, "*** Warning: cannot whitelist Pictures directory\n"); - fprintf(stderr, "*** \tAny file saved will be lost when the sandbox is closed.\n"); - fprintf(stderr, "*** \tPlease create a proper Pictures directory for your application.\n"); + fprintf(stderr, "*** Warning: cannot whitelist %s directory\n", dataptr); + fprintf(stderr, "*** Any file saved in this directory will be lost when the sandbox is closed.\n"); fprintf(stderr, "***\n"); } entry->data = EMPTY_STRING; @@ -565,59 +391,24 @@ void fs_whitelist(void) { } } - // resolve ${DESKTOP} - if (strcmp(dataptr, "${DESKTOP}") == 0) { - char *tmp = resolve_xdg(nowhitelist_flag, "XDG_DESKTOP_DIR=\"$HOME/", 24, "Desktop"); - char *tmp2 = resolve_hardcoded(nowhitelist_flag, deentry, "Desktop"); - if (tmp) { - entry->data = tmp; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else if (tmp2) { - entry->data = tmp2; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else { - if (!nowhitelist_flag && !arg_quiet && !arg_private) { - fprintf(stderr, "***\n"); - fprintf(stderr, "*** Warning: cannot whitelist Desktop directory\n"); - fprintf(stderr, "*** \tAny file saved will be lost when the sandbox is closed.\n"); - fprintf(stderr, "*** \tPlease create a proper Desktop directory for your application.\n"); - fprintf(stderr, "***\n"); - } - entry->data = EMPTY_STRING; - continue; - } - } + // replace ~/ or ${HOME} into /home/username + new_name = expand_home(dataptr, cfg.homedir); + assert(new_name); - // resolve ${DOCUMENTS} - if (strcmp(dataptr, "${DOCUMENTS}") == 0) { - char *tmp = resolve_xdg(nowhitelist_flag, "XDG_DOCUMENTS_DIR=\"$HOME/", 25, "Documents"); - char *tmp2 = resolve_hardcoded(nowhitelist_flag, doentry, "Documents"); - if (tmp) { - entry->data = tmp; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else if (tmp2) { - entry->data = tmp2; - dataptr = (nowhitelist_flag)? entry->data + 12: entry->data + 10; - } - else { - if (!nowhitelist_flag && !arg_quiet && !arg_private) { - fprintf(stderr, "***\n"); - fprintf(stderr, "*** Warning: cannot whitelist Documents directory\n"); - fprintf(stderr, "*** \tAny file saved will be lost when the sandbox is closed.\n"); - fprintf(stderr, "*** \tPlease create a proper Documents directory for your application.\n"); - fprintf(stderr, "***\n"); - } - entry->data = EMPTY_STRING; - continue; + // trim trailing slashes or dots + char *end = strchr(new_name, '\0'); + assert(end); + if ((end - new_name) > 1) { + end--; + while (*end == '/' || + (*end == '.' && *(end - 1) == '/')) { + *end = '\0'; + end--; + if (end == new_name) + break; } } - // replace ~/ or ${HOME} into /home/username - new_name = expand_home(dataptr, cfg.homedir); - assert(new_name); if (arg_debug || arg_debug_whitelists) fprintf(stderr, "Debug %d: new_name #%s#, %s\n", __LINE__, new_name, (nowhitelist_flag)? "nowhitelist": "whitelist"); @@ -628,7 +419,6 @@ void fs_whitelist(void) { goto errexit; } - // extract the absolute path of the file // realpath function will fail with ENOENT if the file is not found // special processing for /dev/fd, /dev/stdin, /dev/stdout and /dev/stderr @@ -704,7 +494,6 @@ void fs_whitelist(void) { continue; } - // check for supported directories if (strncmp(new_name, cfg.homedir, strlen(cfg.homedir)) == 0) { // whitelisting home directory is disabled if --private option is present @@ -724,7 +513,7 @@ void fs_whitelist(void) { // both path and absolute path are under /home if (strncmp(fname, cfg.homedir, strlen(cfg.homedir)) == 0) { - // avoid naming issues, also entire home dirs are not allowed + // entire home directory is not allowed if (*(fname + strlen(cfg.homedir)) != '/') goto errexit; } @@ -740,12 +529,10 @@ void fs_whitelist(void) { entry->tmp_dir = 1; tmp_dir = 1; -#ifndef TEST_MOUNTINFO // both path and absolute path are under /tmp if (strncmp(fname, "/tmp/", 5) != 0) { goto errexit; } -#endif } else if (strncmp(new_name, "/media/", 7) == 0) { entry->media_dir = 1; @@ -871,7 +658,7 @@ void fs_whitelist(void) { entry->link = new_name; else { free(new_name); - new_name = NULL; + entry->link = NULL; } // change file name in entry->data @@ -901,7 +688,7 @@ void fs_whitelist(void) { if (mount(cfg.homedir, RUN_WHITELIST_HOME_USER_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) errExit("mount bind"); - // mount a tmpfs and initialize /home/user + // mount a tmpfs and initialize /home/user, overrides --allusers fs_private(); } else @@ -1113,14 +900,29 @@ void fs_whitelist(void) { // if the link is already there, do not bother if (lstat(entry->link, &s) != 0) { // create the path if necessary - mkpath(entry->link, 0755); - - int rv = symlink(entry->data + 10, entry->link); - if (rv) - fprintf(stderr, "Warning cannot create symbolic link %s\n", entry->link); + int fd = mkpath(entry->link, 0755); + if (fd == -1) { + if (arg_debug || arg_debug_whitelists) + printf("Debug %d: cannot create symbolic link %s\n", __LINE__, entry->link); + free(entry->link); + entry = entry->next; + continue; + } + // get file name of symlink + const char *file = gnu_basename(entry->link); + // create the link + int rv = symlinkat(entry->data + 10, fd, file); + if (rv) { + if (arg_debug || arg_debug_whitelists) { + perror("symlink"); + printf("Debug %d: cannot create symbolic link %s\n", __LINE__, entry->link); + } + } else if (arg_debug || arg_debug_whitelists) printf("Created symbolic link %s -> %s\n", entry->link, entry->data + 10); + close(fd); } + free(entry->link); } entry = entry->next; @@ -1203,9 +1005,6 @@ void fs_whitelist(void) { fs_logger2("tmpfs", RUN_WHITELIST_MODULE_DIR); } - if (new_name) - free(new_name); - return; errexit: diff --git a/src/firejail/join.c b/src/firejail/join.c index e6da4c248..729c7f797 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c @@ -49,7 +49,7 @@ static void extract_x11_display(pid_t pid) { if (!fp) return; - if (1 != fscanf(fp, "%d", &display)) { + if (1 != fscanf(fp, "%u", &display)) { fprintf(stderr, "Error: cannot read X11 display file\n"); fclose(fp); return; @@ -214,7 +214,7 @@ static void extract_umask(pid_t pid) { free(fname); if (!fp) return; - if (fscanf(fp, "%4o", &orig_umask) < 1) { + if (fscanf(fp, "%3o", &orig_umask) < 1) { fprintf(stderr, "Error: cannot read umask\n"); exit(1); } diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 79e4b679b..601cab4f8 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c @@ -198,6 +198,10 @@ char *expand_path(const char *path) { } else { // assume the file is in current working directory + if (!cfg.cwd) { + fprintf(stderr, "Error: current working directory has been deleted\n"); + exit(1); + } if (asprintf(&fname, "%s/%s", cfg.cwd, path) == -1) errExit("asprintf"); } @@ -206,6 +210,7 @@ char *expand_path(const char *path) { void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { EUID_ASSERT(); + assert(path1); // if the pid is that of a firejail process, use the pid of the first child process EUID_ROOT(); diff --git a/src/firejail/macros.c b/src/firejail/macros.c new file mode 100644 index 000000000..283de57f2 --- /dev/null +++ b/src/firejail/macros.c @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2014-2018 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#include "firejail.h" +#include +#define MAXBUF 4098 + +typedef struct macro_t { + char *name; // macro name + char *xdg; // xdg line in ~/.config/user-dirs.dirs +#define MAX_TRANSLATIONS 3 // several translations in case ~/.config/user-dirs.dirs not found + char *translation[MAX_TRANSLATIONS]; +} Macro; + +Macro macro[] = { + { + "${DOWNLOADS}", + "XDG_DOWNLOAD_DIR=\"$HOME/", + { "Downloads", "Загрузки", "Téléchargement" } + }, + + { + "${MUSIC}", + "XDG_MUSIC_DIR=\"$HOME/", + {"Music", "Музыка", "Musique"} + }, + + { + "${VIDEOS}", + "XDG_VIDEOS_DIR=\"$HOME/", + {"Videos", "Видео", "Vidéos"} + }, + + { + "${PICTURES}", + "XDG_PICTURES_DIR=\"$HOME/", + {"Pictures", "Изображения", "Photos"} + }, + + { + "${DESKTOP}", + "XDG_DESKTOP_DIR=\"$HOME/", + {"Desktop", "Рабочий стол", "Bureau"} + }, + + { + "${DOCUMENTS}", + "XDG_DOCUMENTS_DIR=\"$HOME/", + {"Documents", "Документы", "Documents"} + }, + + { 0 } +}; + +// return -1 if not found +static int macro_id(const char *name) { + int i = 0; + while (macro[i].name != NULL) { + if (strcmp(name, macro[i].name) == 0) + return i; + i++; + } + + return -1; +} + +int is_macro(const char *name) { + assert(name); + int len = strlen(name); + if (len <= 4) + return 0; + if (*name == '$' && name[1] == '{' && name[len - 1] == '}') + return 1; + return 0; +} + +// returns mallocated memory +static char *resolve_xdg(const char *var) { + char *fname; + struct stat s; + size_t length = strlen(var); + + 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); + + 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, var, length) == 0) { + char *ptr1 = ptr + length; + char *ptr2 = strchr(ptr1, '"'); + if (ptr2) { + fclose(fp); + *ptr2 = '\0'; + if (strlen(ptr1) != 0) { + if (asprintf(&fname, "%s/%s", cfg.homedir, ptr1) == -1) + errExit("asprintf"); + + if (stat(fname, &s) == -1) { + free(fname); + return NULL; + } + free(fname); + + char *rv = strdup(ptr1); + if (!rv) + errExit(ptr1); + return rv; + } + else + return NULL; + } + } + } + + fclose(fp); + return NULL; +} + +// returns mallocated memory +static char *resolve_hardcoded(char *entries[]) { + char *fname; + struct stat s; + + int i = 0; + while (entries[i] != NULL) { + if (asprintf(&fname, "%s/%s", cfg.homedir, entries[i]) == -1) + errExit("asprintf"); + + if (stat(fname, &s) == 0) { + free(fname); + char *rv = strdup(entries[i]); + if (!rv) + errExit("strdup"); + return rv; + } + free(fname); + i++; + } + + return NULL; +} + +// returns mallocated memory +char *resolve_macro(const char *name) { + char *rv = NULL; + int id = macro_id(name); + if (id == -1) + return NULL; + + rv = resolve_xdg(macro[id].xdg); + if (rv == NULL) + rv = resolve_hardcoded(macro[id].translation); + if (rv && arg_debug) + printf("Directory %s resolved as %s\n", name, rv); + + return rv; +} + +// This function takes a pathname supplied by the user and expands '~' and +// '${HOME}' at the start, to refer to a path relative to the user's home +// directory (supplied). +// The return value is allocated using malloc and must be freed by the caller. +// The function returns NULL if there are any errors. +char *expand_home(const char *path, const char *homedir) { + assert(path); + assert(homedir); + + int called_as_root = 0; + + if(geteuid() == 0) + called_as_root = 1; + + if(called_as_root) { + EUID_USER(); + } + + EUID_ASSERT(); + + // Replace home macro + char *new_name = NULL; + if (strncmp(path, "${HOME}", 7) == 0) { + if (asprintf(&new_name, "%s%s", homedir, path + 7) == -1) + errExit("asprintf"); + if(called_as_root) + EUID_ROOT(); + return new_name; + } + else if (*path == '~') { + if (asprintf(&new_name, "%s%s", homedir, path + 1) == -1) + errExit("asprintf"); + if(called_as_root) + EUID_ROOT(); + return new_name; + } + else if (strncmp(path, "${CFG}", 6) == 0) { + if (asprintf(&new_name, "%s%s", SYSCONFDIR, path + 6) == -1) + errExit("asprintf"); + if(called_as_root) + EUID_ROOT(); + return new_name; + } + else { + char *directory = resolve_macro(path); + if (directory) { + if (asprintf(&new_name, "%s/%s", cfg.homedir, directory) == -1) + errExit("asprintf"); + if(called_as_root) + EUID_ROOT(); + free(directory); + return new_name; + } + } + + char *rv = strdup(path); + if (!rv) + errExit("strdup"); + + if(called_as_root) + EUID_ROOT(); + + return rv; +} + +void invalid_filename(const char *fname, int globbing) { +// EUID_ASSERT(); + assert(fname); + const char *ptr = fname; + + if (strncmp(ptr, "${HOME}", 7) == 0) + ptr = fname + 7; + else if (strncmp(ptr, "${PATH}", 7) == 0) + ptr = fname + 7; + else { + int id = macro_id(fname); + if (id != -1) + return; + } + + int len = strlen(ptr); + + if (globbing) { + // file globbing ('*?[]') is allowed + if (strcspn(ptr, "\\&!\"'<>%^(){};,") != (size_t)len) { + fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); + exit(1); + } + } + else { + if (strcspn(ptr, "\\&!?\"'<>%^(){};,*[]") != (size_t)len) { + fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); + exit(1); + } + } +} diff --git a/src/firejail/main.c b/src/firejail/main.c index 891e73eda..d1f3c47c2 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -241,7 +241,10 @@ static void init_cfg(int argc, char **argv) { fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username); exit(1); } + cfg.cwd = getcwd(NULL, 0); + if (!cfg.cwd && errno != ENOENT) + errExit("getcwd"); // check user database if (!firejail_user_check(cfg.username)) { @@ -833,6 +836,7 @@ static void run_builder(int argc, char **argv) { (void) argc; // drop privileges + EUID_ROOT(); if (setgid(getgid()) < 0) errExit("setgid/getgid"); if (setuid(getuid()) < 0) @@ -1477,25 +1481,7 @@ int main(int argc, char **argv) { fprintf(stderr, "Error: please use --profile after --ignore\n"); exit(1); } - - if (*(argv[i] + 9) == '\0') { - fprintf(stderr, "Error: invalid ignore option\n"); - exit(1); - } - - // find an empty entry in profile_ignore array - int j; - for (j = 0; j < MAX_PROFILE_IGNORE; j++) { - if (cfg.profile_ignore[j] == NULL) - break; - } - if (j >= MAX_PROFILE_IGNORE) { - fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE); - exit(1); - } - // ... and configure it - else - cfg.profile_ignore[j] = argv[i] + 9; + profile_add_ignore(argv[i] + 9); } #ifndef LTS #ifdef HAVE_CHROOT @@ -1670,7 +1656,6 @@ int main(int argc, char **argv) { cfg.srv_private_keep = argv[i] + 14; arg_private_srv = 1; } - else if (strncmp(argv[i], "--private-bin=", 14) == 0) { // extract private bin list if (*(argv[i] + 14) == '\0') { diff --git a/src/firejail/profile.c b/src/firejail/profile.c index ab27c29a8..fb1beacd5 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -87,6 +87,31 @@ static int is_in_ignore_list(char *ptr) { return 0; } +void profile_add_ignore(const char *str) { + assert(str); + if (*str == '\0') { + fprintf(stderr, "Error: invalid ignore option\n"); + exit(1); + } + + // find an empty entry in profile_ignore array + int i; + for (i = 0; i < MAX_PROFILE_IGNORE; i++) { + if (cfg.profile_ignore[i] == NULL) + break; + } + if (i >= MAX_PROFILE_IGNORE) { + fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE); + exit(1); + } + // ... and configure it + else { + cfg.profile_ignore[i] = strdup(str); + if (!cfg.profile_ignore[i]) + errExit("strdup"); + } +} + // check profile line; if line == 0, this was generated from a command line option // return 1 if the command is to be added to the linked list of profile commands @@ -99,25 +124,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { return 0; if (strncmp(ptr, "ignore ", 7) == 0) { - char *str = strdup(ptr + 7); - if (*str == '\0') { - fprintf(stderr, "Error: invalid ignore option\n"); - exit(1); - } - // find an empty entry in profile_ignore array - int j; - for (j = 0; j < MAX_PROFILE_IGNORE; j++) { - if (cfg.profile_ignore[j] == NULL) - break; - } - if (j >= MAX_PROFILE_IGNORE) { - fprintf(stderr, "Error: maximum %d --ignore options are permitted\n", MAX_PROFILE_IGNORE); - exit(1); - } - // ... and configure it - else - cfg.profile_ignore[j] = str; - + profile_add_ignore(ptr + 7); return 0; } @@ -952,6 +959,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { return 0; } + #ifdef HAVE_OVERLAYFS if (strncmp(ptr, "overlay-named ", 14) == 0) { if (checkcfg(CFG_OVERLAYFS)) { diff --git a/src/firejail/run_symlink.c b/src/firejail/run_symlink.c index 5714206d4..ec8e0f1e5 100644 --- a/src/firejail/run_symlink.c +++ b/src/firejail/run_symlink.c @@ -34,6 +34,7 @@ void run_symlink(int argc, char **argv, int run_as_is) { return; // drop privileges + EUID_ROOT(); if (setgid(getgid()) < 0) errExit("setgid/getgid"); if (setuid(getuid()) < 0) diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 2335e9ed2..deb37d700 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -250,7 +250,7 @@ static int monitor_application(pid_t app_pid) { } while(rv != monitored_pid); if (arg_debug) - printf("Sandbox monitor: waitpid %u retval %d status %d\n", monitored_pid, rv, status); + printf("Sandbox monitor: waitpid %d retval %d status %d\n", monitored_pid, rv, status); if (rv == -1) { // we can get here if we have processes joining the sandbox (ECHILD) if (arg_debug) perror("waitpid"); @@ -294,7 +294,7 @@ static int monitor_application(pid_t app_pid) { closedir(dir); if (monitored_pid != 0 && arg_debug) - printf("Sandbox monitor: monitoring %u\n", monitored_pid); + printf("Sandbox monitor: monitoring %d\n", monitored_pid); } // return the latest exit status. diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 804bfb179..78cd30926 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -255,7 +255,7 @@ static char *usage_str = "\tlist all running sandboxes\n" "\n" "License GPL version 2 or later\n" - "Homepage: http://firejail.wordpress.com\n" + "Homepage: https://firejail.wordpress.com\n" "\n"; diff --git a/src/firejail/util.c b/src/firejail/util.c index fa32ffcc8..329ae141b 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -32,6 +32,9 @@ #include #define MAX_GROUPS 1024 +#define MAXBUF 4098 + + // send the error to /var/log/auth.log and exit after a small delay void errLogExit(char* fmt, ...) { @@ -723,38 +726,6 @@ void notify_other(int fd) { } -// This function takes a pathname supplied by the user and expands '~' and -// '${HOME}' at the start, to refer to a path relative to the user's home -// directory (supplied). -// The return value is allocated using malloc and must be freed by the caller. -// The function returns NULL if there are any errors. -char *expand_home(const char *path, const char* homedir) { - assert(path); - assert(homedir); - - // Replace home macro - char *new_name = NULL; - if (strncmp(path, "${HOME}", 7) == 0) { - if (asprintf(&new_name, "%s%s", homedir, path + 7) == -1) - errExit("asprintf"); - return new_name; - } - else if (*path == '~') { - if (asprintf(&new_name, "%s%s", homedir, path + 1) == -1) - errExit("asprintf"); - return new_name; - } - else if (strncmp(path, "${CFG}", 6) == 0) { - if (asprintf(&new_name, "%s%s", SYSCONFDIR, path + 6) == -1) - errExit("asprintf"); - return new_name; - } - - char *rv = strdup(path); - if (!rv) - errExit("strdup"); - return rv; -} // Equivalent to the GNU version of basename, which is incompatible with @@ -815,44 +786,6 @@ uid_t pid_get_uid(pid_t pid) { } -void invalid_filename(const char *fname, int globbing) { -// EUID_ASSERT(); - assert(fname); - const char *ptr = 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; - else if (strcmp(fname, "${MUSIC}") == 0) - return; - else if (strcmp(fname, "${VIDEOS}") == 0) - return; - else if (strcmp(fname, "${PICTURES}") == 0) - return; - else if (strcmp(fname, "${DESKTOP}") == 0) - return; - else if (strcmp(fname, "${DOCUMENTS}") == 0) - return; - - int len = strlen(ptr); - - if (globbing) { - // file globbing ('*?[]') is allowed - if (strcspn(ptr, "\\&!\"'<>%^(){};,") != (size_t)len) { - fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); - exit(1); - } - } - else { - if (strcspn(ptr, "\\&!?\"'<>%^(){};,*[]") != (size_t)len) { - fprintf(stderr, "Error: \"%s\" is an invalid filename\n", ptr); - exit(1); - } - } -} uid_t get_group_id(const char *group) { @@ -1059,54 +992,70 @@ void disable_file_path(const char *path, const char *file) { // user controlled paths. Passed flags are ignored if path is a top level directory. int safe_fd(const char *path, int flags) { assert(path); - int fd = -1; + + // reject empty string, relative path + if (*path != '/') + goto errexit; + // reject ".." + if (strstr(path, "..")) + goto errexit; // work with a copy of path char *dup = strdup(path); if (dup == NULL) errExit("strdup"); - // reject relative path and empty string - if (*dup != '/') { - fprintf(stderr, "Error: invalid pathname: %s\n", path); - exit(1); - } char *p = strrchr(dup, '/'); - if (p == NULL) - errExit("strrchr"); - // reject trailing slash and root dir - if (*(p + 1) == '\0') { - fprintf(stderr, "Error: invalid pathname: %s\n", path); - exit(1); - } + assert(p); + // reject trailing slash, root directory + if (*(p + 1) == '\0') + goto errexit; + // reject trailing dot + if (*(p + 1) == '.' && *(p + 2) == '\0') + goto errexit; + // if there is more than one path segment, keep the last one for later + if (p != dup) + *p = '\0'; int parentfd = open("/", O_PATH|O_DIRECTORY|O_CLOEXEC); if (parentfd == -1) errExit("open"); - // if there is more than one path segment, keep the last one for later - if (p != dup) - *p = '\0'; - - // traverse the path, return -1 if a symlink is encountered + // traverse the path and return -1 if a symlink is encountered + int entered = 0; + int fd = -1; char *tok = strtok(dup, "/"); - if (tok == NULL) - errExit("strtok"); while (tok) { + // skip all "/./" + if (strcmp(tok, ".") == 0) { + tok = strtok(NULL, "/"); + continue; + } + entered = 1; + + // open the directory fd = openat(parentfd, tok, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); close(parentfd); if (fd == -1) { free(dup); return -1; } + parentfd = fd; tok = strtok(NULL, "/"); } if (p != dup) { + // consistent flags for top level directories (////foo, /.///foo) + if (!entered) + flags = O_PATH|O_DIRECTORY|O_CLOEXEC; // open last path segment fd = openat(parentfd, p + 1, flags|O_NOFOLLOW); close(parentfd); } free(dup); return fd; // -1 if open failed + +errexit: + fprintf(stderr, "Error: cannot open \"%s\", invalid filename\n", path); + exit(1); } diff --git a/src/firemon/arp.c b/src/firemon/arp.c index aac1aeba3..9f3e50e94 100644 --- a/src/firemon/arp.c +++ b/src/firemon/arp.c @@ -51,7 +51,7 @@ static void print_arp(const char *fname) { char mac[64]; char mask[64]; char device[64]; - int rv = sscanf(start, "%s %s %s %s %s %s\n", ip, type, flags, mac, mask, device); + int rv = sscanf(start, "%63s %63s %63s %63s %63s %63s\n", ip, type, flags, mac, mask, device); if (rv != 6) continue; diff --git a/src/firemon/route.c b/src/firemon/route.c index 7426637df..6db212831 100644 --- a/src/firemon/route.c +++ b/src/firemon/route.c @@ -144,7 +144,7 @@ static void print_route(const char *fname) { char use[64]; char metric[64]; char mask[64]; - int rv = sscanf(start, "%s %s %s %s %s %s %s %s\n", ifname, destination, gateway, flags, refcnt, use, metric, mask); + int rv = sscanf(start, "%63s %63s %63s %63s %63s %63s %63s %63s\n", ifname, destination, gateway, flags, refcnt, use, metric, mask); if (rv != 8) continue; @@ -161,7 +161,7 @@ static void print_route(const char *fname) { // printf("#%s# #%s# #%s# #%s# #%s# #%s# #%s# #%s#\n", ifname, destination, gateway, flags, refcnt, use, metric, mask); if (gw != 0) - printf(" %u.%u.%u.%u/%u via %u.%u.%u.%u, dev %s, metric %s\n", + printf(" %d.%d.%d.%d/%u via %d.%d.%d.%d, dev %s, metric %s\n", PRINT_IP(destip), mask2bits(destmask), PRINT_IP(gw), ifname, @@ -169,7 +169,7 @@ static void print_route(const char *fname) { else { // this is an interface IfList *ifentry = list_find(destip, destmask); if (ifentry) { - printf(" %u.%u.%u.%u/%u, dev %s, scope link src %d.%d.%d.%d\n", + printf(" %d.%d.%d.%d/%u, dev %s, scope link src %d.%d.%d.%d\n", PRINT_IP(destip), mask2bits(destmask), ifname, PRINT_IP(ifentry->ip)); diff --git a/src/firemon/usage.c b/src/firemon/usage.c index a4d642d66..5714643cc 100644 --- a/src/firemon/usage.c +++ b/src/firemon/usage.c @@ -75,7 +75,7 @@ static char *help_str = "\tUser - The owner of the sandbox.\n" "\n" "License GPL version 2 or later\n" - "Homepage: http://firejail.wordpress.com\n" + "Homepage: https://firejail.wordpress.com\n" "\n"; void usage(void) { diff --git a/src/fnet/veth.c b/src/fnet/veth.c index 39a4f35d8..e4d3db21a 100644 --- a/src/fnet/veth.c +++ b/src/fnet/veth.c @@ -3,10 +3,10 @@ * Original source code: * * Information: - * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 + * https://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 * * Download: - * http://www.kernel.org/pub/linux/utils/net/iproute2/ + * https://www.kernel.org/pub/linux/utils/net/iproute2/ * * Repository: * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git diff --git a/src/fnetfilter/main.c b/src/fnetfilter/main.c index ba58ba3c9..34ebf5926 100644 --- a/src/fnetfilter/main.c +++ b/src/fnetfilter/main.c @@ -79,13 +79,17 @@ static void process_template(char *src, const char *dest) { *arg_start = '\0'; arg_start++; if (*arg_start == '\0') { - fprintf(stderr, "Error fnetfilter: you need to provide at least on argument\n"); + fprintf(stderr, "Error fnetfilter: you need to provide at least one argument\n"); exit(1); } // extract the arguments from command line char *token = strtok(arg_start, ","); while (token) { + if (argcnt == MAXARGS) { + fprintf(stderr, "Error fnetfilter: only up to %u arguments are supported\n", (unsigned) MAXARGS); + exit(1); + } // look for abnormal things int len = strlen(token); if (strcspn(token, "\\&!?\"'<>%^(){};,*[]") != (size_t)len) { @@ -125,7 +129,7 @@ for (i = 0; i < argcnt; i++) else { // parsing int index = 0; - int rv = sscanf(ptr, "$ARG%u", &index) ; + int rv = sscanf(ptr, "$ARG%d", &index) ; if (rv != 1) { fprintf(stderr, "Error fnetfilter: invalid template argument on line %d\n", line); exit(1); diff --git a/src/fsec-print/print.c b/src/fsec-print/print.c index faf59aa35..1042f0c3e 100644 --- a/src/fsec-print/print.c +++ b/src/fsec-print/print.c @@ -39,7 +39,7 @@ * for more details. * * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, see . + * along with this library; if not, see . */ #include "fsec_print.h" diff --git a/src/include/libnetlink.h b/src/include/libnetlink.h index 01fd2675d..0310ecad3 100644 --- a/src/include/libnetlink.h +++ b/src/include/libnetlink.h @@ -3,10 +3,10 @@ * Original source code: * * Information: - * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 + * https://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 * * Download: - * http://www.kernel.org/pub/linux/utils/net/iproute2/ + * https://www.kernel.org/pub/linux/utils/net/iproute2/ * * Repository: * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git diff --git a/src/lib/libnetlink.c b/src/lib/libnetlink.c index d2975bd57..5f6ecd95c 100644 --- a/src/lib/libnetlink.c +++ b/src/lib/libnetlink.c @@ -3,10 +3,10 @@ * Original source code: * * Information: - * http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 + * https://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 * * Download: - * http://www.kernel.org/pub/linux/utils/net/iproute2/ + * https://www.kernel.org/pub/linux/utils/net/iproute2/ * * Repository: * git://git.kernel.org/pub/scm/linux/kernel/git/shemminger/iproute2.git diff --git a/src/libtracelog/libtracelog.c b/src/libtracelog/libtracelog.c index 5ce41aca0..0f8d5a00d 100644 --- a/src/libtracelog/libtracelog.c +++ b/src/libtracelog/libtracelog.c @@ -64,9 +64,6 @@ static inline uint32_t hash(const char *str) { } static void storage_add(const char *str) { -#ifdef DEBUG - printf("add %s\n", str); -#endif if (!str) { #ifdef DEBUG printf("null pointer passed to storage_add\n"); @@ -74,6 +71,10 @@ static void storage_add(const char *str) { return; } +#ifdef DEBUG + printf("add %s\n", str); +#endif + ListElem *ptr = malloc(sizeof(ListElem)); if (!ptr) { fprintf(stderr, "Error: cannot allocate memory\n"); @@ -96,15 +97,17 @@ static void storage_add(const char *str) { static char* cwd = NULL; static char *storage_find(const char *str) { -#ifdef DEBUG - printf("storage find %s\n", str); -#endif if (!str) { #ifdef DEBUG printf("null pointer passed to storage_find\n"); #endif return NULL; } + +#ifdef DEBUG + printf("storage find %s\n", str); +#endif + const char *tofind = str; int allocated = 0; -- cgit v1.2.3-54-g00ecf