diff --git a/src/basic/path-util.c b/src/basic/path-util.c index ab4778d4ed..df94629385 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -81,14 +81,36 @@ char *path_make_absolute(const char *p, const char *prefix) { /* Makes every item in the list an absolute path by prepending * the prefix, if specified and necessary */ - if (path_is_absolute(p) || !prefix) + if (path_is_absolute(p) || isempty(prefix)) return strdup(p); - return strjoin(prefix, "/", p); + if (endswith(prefix, "/")) + return strjoin(prefix, p); + else + return strjoin(prefix, "/", p); +} + +int safe_getcwd(char **ret) { + char *cwd; + + cwd = get_current_dir_name(); + if (!cwd) + return negative_errno(); + + /* Let's make sure the directory is really absolute, to protect us from the logic behind + * CVE-2018-1000001 */ + if (cwd[0] != '/') { + free(cwd); + return -ENOMEDIUM; + } + + *ret = cwd; + return 0; } int path_make_absolute_cwd(const char *p, char **ret) { char *c; + int r; assert(p); assert(ret); @@ -101,11 +123,14 @@ int path_make_absolute_cwd(const char *p, char **ret) { else { _cleanup_free_ char *cwd = NULL; - cwd = get_current_dir_name(); - if (!cwd) - return negative_errno(); + r = safe_getcwd(&cwd); + if (r < 0) + return r; - c = strjoin(cwd, "/", p); + if (endswith(cwd, "/")) + c = strjoin(cwd, p); + else + c = strjoin(cwd, "/", p); } if (!c) return -ENOMEM; diff --git a/src/basic/path-util.h b/src/basic/path-util.h index f79cdf928e..89c285e076 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -41,6 +41,7 @@ bool is_path(const char *p) _pure_; int path_split_and_make_absolute(const char *p, char ***ret); bool path_is_absolute(const char *p) _pure_; char* path_make_absolute(const char *p, const char *prefix); +int safe_getcwd(char **ret); int path_make_absolute_cwd(const char *p, char **ret); int path_make_relative(const char *from_dir, const char *to_path, char **_r); char* path_kill_slashes(char *path); diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index fb44b9f669..bd8c6a0059 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -277,9 +277,9 @@ int main(int argc, char *argv[]) { if (!arg_machine) { _cleanup_free_ char *cwd = NULL; - cwd = get_current_dir_name(); - if (!cwd) { - r = log_error_errno(errno, "Cannot determine current working directory: %m"); + r = safe_getcwd(&cwd); + if (r < 0) { + log_error_errno(r, "Cannot determine current working directory: %m"); goto finish; } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index f580b46f86..0f05ecff03 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -2163,8 +2163,11 @@ static int determine_names(void) { if (!arg_ephemeral) arg_read_only = arg_read_only || i->read_only; - } else - arg_directory = get_current_dir_name(); + } else { + r = safe_getcwd(&arg_directory); + if (r < 0) + return log_error_errno(r, "Failed to determine current directory: %m"); + } if (!arg_directory && !arg_image) { log_error("Failed to determine path, please use -D or -i."); diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index cda6d9cc72..9f3a500080 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -326,7 +326,7 @@ static void test_readlink_and_make_absolute(void) { free(r); assert_se(unlink(name_alias) >= 0); - assert_se(pwd = get_current_dir_name()); + assert_se(safe_getcwd(&pwd) >= 0); assert_se(chdir(tempdir) >= 0); assert_se(symlink(name2, name_alias) >= 0);