From 9a6e041913e178a296bd1f3085f184404fbb8cc1 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Wed, 15 Aug 2018 17:48:11 +0200 Subject: improve detection of symbolic links --- src/firejail/firejail.h | 1 + src/firejail/fs_whitelist.c | 15 ++------------- src/firejail/util.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index f31d6a2bc..5ce380503 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -515,6 +515,7 @@ void copy_file_from_user_to_root(const char *srcname, const char *destname, uid_ void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode); int is_dir(const char *fname); int is_link(const char *fname); +void trim_trailing_slash_or_dot(char *path); char *line_remove_spaces(const char *buf); char *split_comma(char *str); void check_unsigned(const char *str, const char *msg); diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index c3d34e259..602985b4e 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c @@ -395,19 +395,8 @@ void fs_whitelist(void) { new_name = expand_home(dataptr, cfg.homedir); assert(new_name); - // 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; - } - } + // remove trailing slashes and single dots + trim_trailing_slash_or_dot(new_name); if (arg_debug || arg_debug_whitelists) fprintf(stderr, "Debug %d: new_name #%s#, %s\n", __LINE__, new_name, (nowhitelist_flag)? "nowhitelist": "whitelist"); diff --git a/src/firejail/util.c b/src/firejail/util.c index 329ae141b..6db92b554 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -425,15 +425,48 @@ int is_link(const char *fname) { if (*fname == '\0') return 0; + char *dup = NULL; struct stat s; if (lstat(fname, &s) == 0) { if (S_ISLNK(s.st_mode)) return 1; + if (S_ISDIR(s.st_mode)) { + // remove trailing slashes and single dots and try again + dup = strdup(fname); + if (!dup) + errExit("strdup"); + trim_trailing_slash_or_dot(dup); + if (lstat(dup, &s) == 0) { + if (S_ISLNK(s.st_mode)) { + free(dup); + return 1; + } + } + } } + free(dup); return 0; } +// remove all slashes and single dots from the end of a path +// for example /foo/bar///././. -> /foo/bar +void trim_trailing_slash_or_dot(char *path) { + assert(path); + + char *end = strchr(path, '\0'); + assert(end); + if ((end - path) > 1) { + end--; + while (*end == '/' || + (*end == '.' && *(end - 1) == '/')) { + *end = '\0'; + end--; + if (end == path) + break; + } + } +} // remove multiple spaces and return allocated memory char *line_remove_spaces(const char *buf) { -- cgit v1.2.3-70-g09d2