From 0f4743651081b5367ab06f238827ddfd4da74e74 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 22 Oct 2015 19:28:31 +0200 Subject: util-lib: get_current_dir_name() can return errors other than ENOMEM get_current_dir_name() can return a variety of errors, not just ENOMEM, hence don't blindly turn its errors to ENOMEM, but return correct errors in path_make_absolute_cwd(). This trickles down into a couple of other functions, some of which receive unrelated minor fixes too with this commit. --- src/basic/path-util.c | 60 ++++++++++++++++++------------ src/basic/path-util.h | 6 +-- src/basic/selinux-util.c | 94 +++++++++++++++++++++++++---------------------- src/firstboot/firstboot.c | 12 ++---- src/journal/coredumpctl.c | 24 ++++++------ src/machine/machinectl.c | 13 +++---- src/nspawn/nspawn.c | 7 ++-- src/shared/path-lookup.c | 27 +++++++------- src/sysusers/sysusers.c | 10 ++--- src/tmpfiles/tmpfiles.c | 10 ++--- 10 files changed, 139 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/basic/path-util.c b/src/basic/path-util.c index 9aeb8c23fd..96705cc9d8 100644 --- a/src/basic/path-util.c +++ b/src/basic/path-util.c @@ -84,20 +84,25 @@ int path_get_parent(const char *path, char **_r) { return 0; } -char **path_split_and_make_absolute(const char *p) { +int path_split_and_make_absolute(const char *p, char ***ret) { char **l; + int r; + assert(p); + assert(ret); l = strv_split(p, ":"); if (!l) return NULL; - if (!path_strv_make_absolute_cwd(l)) { + r = path_strv_make_absolute_cwd(l); + if (r < 0) { strv_free(l); - return NULL; + return r; } - return l; + *ret = l; + return r; } char *path_make_absolute(const char *p, const char *prefix) { @@ -112,22 +117,31 @@ char *path_make_absolute(const char *p, const char *prefix) { return strjoin(prefix, "/", p, NULL); } -char *path_make_absolute_cwd(const char *p) { - _cleanup_free_ char *cwd = NULL; +int path_make_absolute_cwd(const char *p, char **ret) { + char *c; assert(p); + assert(ret); /* Similar to path_make_absolute(), but prefixes with the * current working directory. */ if (path_is_absolute(p)) - return strdup(p); + c = strdup(p); + else { + _cleanup_free_ char *cwd = NULL; - cwd = get_current_dir_name(); - if (!cwd) - return NULL; + cwd = get_current_dir_name(); + if (!cwd) + return -errno; + + c = strjoin(cwd, "/", p, NULL); + } + if (!c) + return -ENOMEM; - return strjoin(cwd, "/", p, NULL); + *ret = c; + return 0; } int path_make_relative(const char *from_dir, const char *to_path, char **_r) { @@ -215,8 +229,9 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r) { return 0; } -char **path_strv_make_absolute_cwd(char **l) { +int path_strv_make_absolute_cwd(char **l) { char **s; + int r; /* Goes through every item in the string list and makes it * absolute. This works in place and won't rollback any @@ -225,15 +240,15 @@ char **path_strv_make_absolute_cwd(char **l) { STRV_FOREACH(s, l) { char *t; - t = path_make_absolute_cwd(*s); - if (!t) - return NULL; + r = path_make_absolute_cwd(*s, &t); + if (r < 0) + return r; free(*s); *s = t; } - return l; + return 0; } char **path_strv_resolve(char **l, const char *prefix) { @@ -719,13 +734,9 @@ int find_binary(const char *name, char **ret) { return -errno; if (ret) { - char *rs; - - rs = path_make_absolute_cwd(name); - if (!rs) - return -ENOMEM; - - *ret = rs; + r = path_make_absolute_cwd(name, ret); + if (r < 0) + return r; } return 0; @@ -750,6 +761,9 @@ int find_binary(const char *name, char **ret) { if (r == 0) break; + if (!path_is_absolute(element)) + continue; + j = strjoin(element, "/", name, NULL); if (!j) return -ENOMEM; diff --git a/src/basic/path-util.h b/src/basic/path-util.h index 03e1ac5d60..c37c131bff 100644 --- a/src/basic/path-util.h +++ b/src/basic/path-util.h @@ -36,11 +36,11 @@ #endif bool is_path(const char *p) _pure_; -char** path_split_and_make_absolute(const char *p); +int path_split_and_make_absolute(const char *p, char ***ret); int path_get_parent(const char *path, char **parent); bool path_is_absolute(const char *p) _pure_; char* path_make_absolute(const char *p, const char *prefix); -char* path_make_absolute_cwd(const char *p); +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); char* path_startswith(const char *path, const char *prefix) _pure_; @@ -49,7 +49,7 @@ bool path_equal(const char *a, const char *b) _pure_; bool path_equal_or_files_same(const char *a, const char *b); char* path_join(const char *root, const char *path, const char *rest); -char** path_strv_make_absolute_cwd(char **l); +int path_strv_make_absolute_cwd(char **l); char** path_strv_resolve(char **l, const char *prefix); char** path_strv_resolve_uniq(char **l, const char *prefix); diff --git a/src/basic/selinux-util.c b/src/basic/selinux-util.c index 747e6f4dbb..7a7dc90e3c 100644 --- a/src/basic/selinux-util.c +++ b/src/basic/selinux-util.c @@ -171,15 +171,15 @@ int mac_selinux_fix(const char *path, bool ignore_enoent, bool ignore_erofs) { int mac_selinux_apply(const char *path, const char *label) { #ifdef HAVE_SELINUX - assert(path); - assert(label); - if (!mac_selinux_use()) return 0; + assert(path); + assert(label); + if (setfilecon(path, (security_context_t) label) < 0) { log_enforcing("Failed to set SELinux security context %s on path %s: %m", label, path); - if (security_getenforce() == 1) + if (security_getenforce() > 0) return -errno; } #endif @@ -312,10 +312,10 @@ char* mac_selinux_free(char *label) { } int mac_selinux_create_file_prepare(const char *path, mode_t mode) { - int r = 0; #ifdef HAVE_SELINUX _cleanup_security_context_free_ security_context_t filecon = NULL; + int r; assert(path); @@ -325,34 +325,33 @@ int mac_selinux_create_file_prepare(const char *path, mode_t mode) { if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &filecon, path, mode); else { - _cleanup_free_ char *newpath; + _cleanup_free_ char *newpath = NULL; - newpath = path_make_absolute_cwd(path); - if (!newpath) - return -ENOMEM; + r = path_make_absolute_cwd(path, &newpath); + if (r < 0) + return r; r = selabel_lookup_raw(label_hnd, &filecon, newpath, mode); } - /* No context specified by the policy? Proceed without setting it. */ - if (r < 0 && errno == ENOENT) - return 0; + if (r < 0) { + /* No context specified by the policy? Proceed without setting it. */ + if (errno == ENOENT) + return 0; - if (r < 0) - r = -errno; - else { - r = setfscreatecon(filecon); - if (r < 0) { - log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path); - r = -errno; - } + log_enforcing("Failed to determine SELinux security context for %s: %m", path); + } else { + if (setfscreatecon(filecon) >= 0) + return 0; /* Success! */ + + log_enforcing("Failed to set SELinux security context %s for %s: %m", filecon, path); } - if (r < 0 && security_getenforce() == 0) - r = 0; -#endif + if (security_getenforce() > 0) + return -errno; - return r; +#endif + return 0; } void mac_selinux_create_file_clear(void) { @@ -405,6 +404,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { #ifdef HAVE_SELINUX _cleanup_security_context_free_ security_context_t fcon = NULL; const struct sockaddr_un *un; + bool context_changed = false; char *path; int r; @@ -420,7 +420,7 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { goto skipped; /* Filter out anonymous sockets */ - if (addrlen < sizeof(sa_family_t) + 1) + if (addrlen < offsetof(struct sockaddr_un, sun_path) + 1) goto skipped; /* Filter out abstract namespace sockets */ @@ -433,36 +433,44 @@ int mac_selinux_bind(int fd, const struct sockaddr *addr, socklen_t addrlen) { if (path_is_absolute(path)) r = selabel_lookup_raw(label_hnd, &fcon, path, S_IFSOCK); else { - _cleanup_free_ char *newpath; + _cleanup_free_ char *newpath = NULL; - newpath = path_make_absolute_cwd(path); - if (!newpath) - return -ENOMEM; + r = path_make_absolute_cwd(path, &newpath); + if (r < 0) + return r; r = selabel_lookup_raw(label_hnd, &fcon, newpath, S_IFSOCK); } - if (r == 0) - r = setfscreatecon(fcon); + if (r < 0) { + /* No context specified by the policy? Proceed without setting it */ + if (errno == ENOENT) + goto skipped; - if (r < 0 && errno != ENOENT) { - log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path); + log_enforcing("Failed to determine SELinux security context for %s: %m", path); + if (security_getenforce() > 0) + return -errno; - if (security_getenforce() == 1) { - r = -errno; - goto finish; - } + } else { + if (setfscreatecon(fcon) < 0) { + log_enforcing("Failed to set SELinux security context %s for %s: %m", fcon, path); + if (security_getenforce() > 0) + return -errno; + } else + context_changed = true; } - r = bind(fd, addr, addrlen); - if (r < 0) - r = -errno; + r = bind(fd, addr, addrlen) < 0 ? -errno : 0; + + if (context_changed) + setfscreatecon(NULL); -finish: - setfscreatecon(NULL); return r; skipped: #endif - return bind(fd, addr, addrlen) < 0 ? -errno : 0; + if (bind(fd, addr, addrlen) < 0) + return -errno; + + return 0; } diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 82ebb91788..cee05de7a1 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -690,16 +690,12 @@ static int parse_argv(int argc, char *argv[]) { return version(); case ARG_ROOT: - free(arg_root); - arg_root = path_make_absolute_cwd(optarg); - if (!arg_root) - return log_oom(); + arg_root = mfree(arg_root); + r = path_make_absolute_cwd(optarg, &arg_root); + if (r < 0) + return log_error_errno(r, "Failed to make root path absolute: %m"); path_kill_slashes(arg_root); - - if (path_equal(arg_root, "/")) - arg_root = mfree(arg_root); - break; case ARG_LOCALE: diff --git a/src/journal/coredumpctl.c b/src/journal/coredumpctl.c index dde56008c1..97a721c114 100644 --- a/src/journal/coredumpctl.c +++ b/src/journal/coredumpctl.c @@ -84,37 +84,35 @@ static Set *new_matches(void) { } static int add_match(Set *set, const char *match) { - int r = -ENOMEM; - unsigned pid; - const char* prefix; - char *pattern = NULL; _cleanup_free_ char *p = NULL; + char *pattern = NULL; + const char* prefix; + pid_t pid; + int r; if (strchr(match, '=')) prefix = ""; else if (strchr(match, '/')) { - p = path_make_absolute_cwd(match); - if (!p) + r = path_make_absolute_cwd(match, &p); + if (r < 0) goto fail; - match = p; prefix = "COREDUMP_EXE="; - } - else if (safe_atou(match, &pid) == 0) + } else if (parse_pid(match, &pid) >= 0) prefix = "COREDUMP_PID="; else prefix = "COREDUMP_COMM="; pattern = strjoin(prefix, match, NULL); - if (!pattern) + if (!pattern) { + r = -ENOMEM; goto fail; + } log_debug("Adding pattern: %s", pattern); r = set_consume(set, pattern); - if (r < 0) { - log_error_errno(r, "Failed to add pattern: %m"); + if (r < 0) goto fail; - } return 0; fail: diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index d7e0395690..f44f4edc0a 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -1092,9 +1092,10 @@ static int copy_files(int argc, char *argv[], void *userdata) { container_path = copy_from ? argv[2] : dest; if (!path_is_absolute(host_path)) { - abs_host_path = path_make_absolute_cwd(host_path); - if (!abs_host_path) - return log_oom(); + r = path_make_absolute_cwd(host_path, &abs_host_path); + if (r < 0) + return log_error_errno(r, "Failed to make path absolute: %m"); + host_path = abs_host_path; } @@ -1110,10 +1111,8 @@ static int copy_files(int argc, char *argv[], void *userdata) { argv[1], copy_from ? container_path : host_path, copy_from ? host_path : container_path); - if (r < 0) { - log_error("Failed to copy: %s", bus_error_message(&error, -r)); - return r; - } + if (r < 0) + return log_error_errno(r, "Failed to copy: %s", bus_error_message(&error, r)); return 0; } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 99e24cf4ff..056b4ce5f3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -278,6 +278,7 @@ static int custom_mounts_prepare(void) { static int set_sanitized_path(char **b, const char *path) { char *p; + int r; assert(b); assert(path); @@ -287,9 +288,9 @@ static int set_sanitized_path(char **b, const char *path) { if (errno != ENOENT) return -errno; - p = path_make_absolute_cwd(path); - if (!p) - return -ENOMEM; + r = path_make_absolute_cwd(path, &p); + if (r < 0) + return r; } free(*b); diff --git a/src/shared/path-lookup.c b/src/shared/path-lookup.c index 34eec959ef..897dc9065f 100644 --- a/src/shared/path-lookup.c +++ b/src/shared/path-lookup.c @@ -210,7 +210,7 @@ static char** user_dirs( if (strv_extend(&res, generator_late) < 0) return NULL; - if (!path_strv_make_absolute_cwd(res)) + if (path_strv_make_absolute_cwd(res) < 0) return NULL; tmp = res; @@ -244,6 +244,7 @@ int lookup_paths_init( const char *e; bool append = false; /* Add items from SYSTEMD_UNIT_PATH before normal directories */ + int r; assert(p); @@ -259,9 +260,9 @@ int lookup_paths_init( /* FIXME: empty components in other places should be * rejected. */ - p->unit_path = path_split_and_make_absolute(e); - if (!p->unit_path) - return -ENOMEM; + r = path_split_and_make_absolute(e, &p->unit_path); + if (r < 0) + return r; } else p->unit_path = NULL; @@ -269,7 +270,6 @@ int lookup_paths_init( /* Let's figure something out. */ _cleanup_strv_free_ char **unit_path; - int r; /* For the user units we include share/ in the search * path in order to comply with the XDG basedir spec. @@ -342,9 +342,9 @@ int lookup_paths_init( e = getenv("SYSTEMD_SYSVINIT_PATH"); if (e) { - p->sysvinit_path = path_split_and_make_absolute(e); - if (!p->sysvinit_path) - return -ENOMEM; + r = path_split_and_make_absolute(e, &p->sysvinit_path); + if (r < 0) + return r; } else p->sysvinit_path = NULL; @@ -360,9 +360,9 @@ int lookup_paths_init( e = getenv("SYSTEMD_SYSVRCND_PATH"); if (e) { - p->sysvrcnd_path = path_split_and_make_absolute(e); - if (!p->sysvrcnd_path) - return -ENOMEM; + r = path_split_and_make_absolute(e, &p->sysvrcnd_path); + if (r < 0) + return r; } else p->sysvrcnd_path = NULL; @@ -417,9 +417,8 @@ void lookup_paths_free(LookupPaths *p) { p->unit_path = strv_free(p->unit_path); #ifdef HAVE_SYSV_COMPAT - strv_free(p->sysvinit_path); - strv_free(p->sysvrcnd_path); - p->sysvinit_path = p->sysvrcnd_path = NULL; + p->sysvinit_path = strv_free(p->sysvinit_path); + p->sysvrcnd_path = strv_free(p->sysvrcnd_path); #endif } diff --git a/src/sysusers/sysusers.c b/src/sysusers/sysusers.c index ba09727080..e594053ee8 100644 --- a/src/sysusers/sysusers.c +++ b/src/sysusers/sysusers.c @@ -1762,7 +1762,7 @@ static int parse_argv(int argc, char *argv[]) { {} }; - int c; + int c, r; assert(argc >= 0); assert(argv); @@ -1779,10 +1779,10 @@ static int parse_argv(int argc, char *argv[]) { return version(); case ARG_ROOT: - free(arg_root); - arg_root = path_make_absolute_cwd(optarg); - if (!arg_root) - return log_oom(); + arg_root = mfree(arg_root); + r = path_make_absolute_cwd(optarg, &arg_root); + if (r < 0) + return log_error_errno(r, "Failed to make root path absolute: %m"); path_kill_slashes(arg_root); break; diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 09b6ca5c2c..693a3da2f4 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2101,7 +2101,7 @@ static int parse_argv(int argc, char *argv[]) { {} }; - int c; + int c, r; assert(argc >= 0); assert(argv); @@ -2144,10 +2144,10 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_ROOT: - free(arg_root); - arg_root = path_make_absolute_cwd(optarg); - if (!arg_root) - return log_oom(); + arg_root = mfree(arg_root); + r = path_make_absolute_cwd(optarg, &arg_root); + if (r < 0) + return log_error_errno(r, "Failed to make root path absolute: %m"); path_kill_slashes(arg_root); break; -- cgit v1.2.3-54-g00ecf