diff options
author | Harald Hoyer <harald@redhat.com> | 2013-02-14 12:26:13 +0100 |
---|---|---|
committer | Harald Hoyer <harald@redhat.com> | 2013-02-14 16:19:38 +0100 |
commit | a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7 (patch) | |
tree | b3cc19cede403ac324f56c54ca89db0feef2a72d /src/shared | |
parent | edc211f314f257921eb3599b5dca8d51984b9328 (diff) |
honor SELinux labels, when creating and writing config files
Also split out some fileio functions to fileio.c and provide a SELinux
aware pendant in fileio-label.c
see https://bugzilla.redhat.com/show_bug.cgi?id=881577
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/audit.c | 1 | ||||
-rw-r--r-- | src/shared/capability.c | 1 | ||||
-rw-r--r-- | src/shared/cgroup-util.c | 1 | ||||
-rw-r--r-- | src/shared/fileio-label.c | 55 | ||||
-rw-r--r-- | src/shared/fileio-label.h | 29 | ||||
-rw-r--r-- | src/shared/fileio.c | 383 | ||||
-rw-r--r-- | src/shared/fileio.h | 33 | ||||
-rw-r--r-- | src/shared/hwclock.c | 1 | ||||
-rw-r--r-- | src/shared/label.c | 4 | ||||
-rw-r--r-- | src/shared/label.h | 4 | ||||
-rw-r--r-- | src/shared/socket-util.c | 1 | ||||
-rw-r--r-- | src/shared/util.c | 359 | ||||
-rw-r--r-- | src/shared/util.h | 9 | ||||
-rw-r--r-- | src/shared/virt.c | 1 |
14 files changed, 515 insertions, 367 deletions
diff --git a/src/shared/audit.c b/src/shared/audit.c index e5c483ab08..138ca1d7fa 100644 --- a/src/shared/audit.c +++ b/src/shared/audit.c @@ -33,6 +33,7 @@ #include "audit.h" #include "util.h" #include "log.h" +#include "fileio.h" int audit_session_from_pid(pid_t pid, uint32_t *id) { char *s; diff --git a/src/shared/capability.c b/src/shared/capability.c index 9b743e86d0..cad718d749 100644 --- a/src/shared/capability.c +++ b/src/shared/capability.c @@ -34,6 +34,7 @@ #include "capability.h" #include "util.h" #include "log.h" +#include "fileio.h" int have_effective_cap(int value) { cap_t cap; diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c index 7efbc2ed39..be00b40fa2 100644 --- a/src/shared/cgroup-util.c +++ b/src/shared/cgroup-util.c @@ -37,6 +37,7 @@ #include "path-util.h" #include "strv.h" #include "unit-name.h" +#include "fileio.h" int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) { char *fs; diff --git a/src/shared/fileio-label.c b/src/shared/fileio-label.c new file mode 100644 index 0000000000..5bf127bcf1 --- /dev/null +++ b/src/shared/fileio-label.c @@ -0,0 +1,55 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + Copyright 2010 Harald Hoyer + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "fileio-label.h" +#include "label.h" + +int write_one_line_file_atomic_label(const char *fn, const char *line) { + int r; + + r = label_context_set(fn, S_IFREG); + if (r < 0) + return r; + + write_one_line_file_atomic(fn, line); + + label_context_clear(); + + return r; +} + +int write_env_file_label(const char *fname, char **l) { + int r; + + r = label_context_set(fname, S_IFREG); + if (r < 0) + return r; + + write_env_file(fname, l); + + label_context_clear(); + + return r; +} diff --git a/src/shared/fileio-label.h b/src/shared/fileio-label.h new file mode 100644 index 0000000000..cc5ce34708 --- /dev/null +++ b/src/shared/fileio-label.h @@ -0,0 +1,29 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + Copyright 2010 Harald Hoyer + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdio.h> +#include "fileio.h" + +int write_one_line_file_atomic_label(const char *fn, const char *line); +int write_env_file_label(const char *fname, char **l); diff --git a/src/shared/fileio.c b/src/shared/fileio.c new file mode 100644 index 0000000000..4e6ff16045 --- /dev/null +++ b/src/shared/fileio.c @@ -0,0 +1,383 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <unistd.h> +#include "fileio.h" +#include "util.h" +#include "strv.h" + +int write_one_line_file(const char *fn, const char *line) { + _cleanup_fclose_ FILE *f = NULL; + + assert(fn); + assert(line); + + f = fopen(fn, "we"); + if (!f) + return -errno; + + errno = 0; + if (fputs(line, f) < 0) + return errno ? -errno : -EIO; + + if (!endswith(line, "\n")) + fputc('\n', f); + + fflush(f); + + if (ferror(f)) + return errno ? -errno : -EIO; + + return 0; +} + +int write_one_line_file_atomic(const char *fn, const char *line) { + _cleanup_fclose_ FILE *f = NULL; + _cleanup_free_ char *p = NULL; + int r; + + assert(fn); + assert(line); + + r = fopen_temporary(fn, &f, &p); + if (r < 0) + return r; + + fchmod_umask(fileno(f), 0644); + + errno = 0; + if (fputs(line, f) < 0) { + r = -errno; + goto finish; + } + + if (!endswith(line, "\n")) + fputc('\n', f); + + fflush(f); + + if (ferror(f)) + r = errno ? -errno : -EIO; + else { + if (rename(p, fn) < 0) + r = -errno; + else + r = 0; + } + +finish: + if (r < 0) + unlink(p); + + return r; +} + +int read_one_line_file(const char *fn, char **line) { + _cleanup_fclose_ FILE *f = NULL; + char t[LINE_MAX], *c; + + assert(fn); + assert(line); + + f = fopen(fn, "re"); + if (!f) + return -errno; + + if (!fgets(t, sizeof(t), f)) { + + if (ferror(f)) + return errno ? -errno : -EIO; + + t[0] = 0; + } + + c = strdup(t); + if (!c) + return -ENOMEM; + truncate_nl(c); + + *line = c; + return 0; +} + +int read_full_file(const char *fn, char **contents, size_t *size) { + _cleanup_fclose_ FILE *f = NULL; + size_t n, l; + _cleanup_free_ char *buf = NULL; + struct stat st; + + assert(fn); + assert(contents); + + f = fopen(fn, "re"); + if (!f) + return -errno; + + if (fstat(fileno(f), &st) < 0) + return -errno; + + /* Safety check */ + if (st.st_size > 4*1024*1024) + return -E2BIG; + + n = st.st_size > 0 ? st.st_size : LINE_MAX; + l = 0; + + for (;;) { + char *t; + size_t k; + + t = realloc(buf, n+1); + if (!t) + return -ENOMEM; + + buf = t; + k = fread(buf + l, 1, n - l, f); + + if (k <= 0) { + if (ferror(f)) + return -errno; + + break; + } + + l += k; + n *= 2; + + /* Safety check */ + if (n > 4*1024*1024) + return -E2BIG; + } + + buf[l] = 0; + *contents = buf; + buf = NULL; + + if (size) + *size = l; + + return 0; +} + +int parse_env_file( + const char *fname, + const char *separator, ...) { + + int r = 0; + char *contents = NULL, *p; + + assert(fname); + assert(separator); + + if ((r = read_full_file(fname, &contents, NULL)) < 0) + return r; + + p = contents; + for (;;) { + const char *key = NULL; + + p += strspn(p, separator); + p += strspn(p, WHITESPACE); + + if (!*p) + break; + + if (!strchr(COMMENTS, *p)) { + va_list ap; + char **value; + + va_start(ap, separator); + while ((key = va_arg(ap, char *))) { + size_t n; + char *v; + + value = va_arg(ap, char **); + + n = strlen(key); + if (!strneq(p, key, n) || + p[n] != '=') + continue; + + p += n + 1; + n = strcspn(p, separator); + + if (n >= 2 && + strchr(QUOTES, p[0]) && + p[n-1] == p[0]) + v = strndup(p+1, n-2); + else + v = strndup(p, n); + + if (!v) { + r = -ENOMEM; + va_end(ap); + goto fail; + } + + if (v[0] == '\0') { + /* return empty value strings as NULL */ + free(v); + v = NULL; + } + + free(*value); + *value = v; + + p += n; + + r ++; + break; + } + va_end(ap); + } + + if (!key) + p += strcspn(p, separator); + } + +fail: + free(contents); + return r; +} + +int load_env_file(const char *fname, char ***rl) { + + _cleanup_fclose_ FILE *f; + _cleanup_strv_free_ char **m = NULL; + _cleanup_free_ char *c = NULL; + + assert(fname); + assert(rl); + + /* This reads an environment file, but will not complain about + * any invalid assignments, that needs to be done by the + * caller */ + + f = fopen(fname, "re"); + if (!f) + return -errno; + + while (!feof(f)) { + char l[LINE_MAX], *p, *cs, *b; + + if (!fgets(l, sizeof(l), f)) { + if (ferror(f)) + return -errno; + + /* The previous line was a continuation line? + * Let's process it now, before we leave the + * loop */ + if (c) + goto process; + + break; + } + + /* Is this a continuation line? If so, just append + * this to c, and go to next line right-away */ + cs = endswith(l, "\\\n"); + if (cs) { + *cs = '\0'; + b = strappend(c, l); + if (!b) + return -ENOMEM; + + free(c); + c = b; + continue; + } + + /* If the previous line was a continuation line, + * append the current line to it */ + if (c) { + b = strappend(c, l); + if (!b) + return -ENOMEM; + + free(c); + c = b; + } + + process: + p = strstrip(c ? c : l); + + if (*p && !strchr(COMMENTS, *p)) { + _cleanup_free_ char *u; + int k; + + u = normalize_env_assignment(p); + if (!u) + return -ENOMEM; + + k = strv_extend(&m, u); + if (k < 0) + return -ENOMEM; + } + + free(c); + c = NULL; + } + + *rl = m; + m = NULL; + + return 0; +} + +int write_env_file(const char *fname, char **l) { + char **i, *p; + FILE *f; + int r; + + r = fopen_temporary(fname, &f, &p); + if (r < 0) + return r; + + fchmod_umask(fileno(f), 0644); + + errno = 0; + STRV_FOREACH(i, l) { + fputs(*i, f); + fputc('\n', f); + } + + fflush(f); + + if (ferror(f)) { + if (errno != 0) + r = -errno; + else + r = -EIO; + } else { + if (rename(p, fname) < 0) + r = -errno; + else + r = 0; + } + + if (r < 0) + unlink(p); + + fclose(f); + free(p); + + return r; +} diff --git a/src/shared/fileio.h b/src/shared/fileio.h new file mode 100644 index 0000000000..0023204a73 --- /dev/null +++ b/src/shared/fileio.h @@ -0,0 +1,33 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +#pragma once + +/*** + This file is part of systemd. + + Copyright 2010 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ +#include <stddef.h> +#include "macro.h" + +int write_one_line_file(const char *fn, const char *line); +int write_one_line_file_atomic(const char *fn, const char *line); +int read_one_line_file(const char *fn, char **line); +int read_full_file(const char *fn, char **contents, size_t *size); + +int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; +int load_env_file(const char *fname, char ***l); +int write_env_file(const char *fname, char **l); diff --git a/src/shared/hwclock.c b/src/shared/hwclock.c index f9adf0369e..488c30e93f 100644 --- a/src/shared/hwclock.c +++ b/src/shared/hwclock.c @@ -41,6 +41,7 @@ #include "log.h" #include "strv.h" #include "hwclock.h" +#include "fileio.h" static int rtc_open(int flags) { int fd; diff --git a/src/shared/label.c b/src/shared/label.c index d353da57ec..a8bf6bd4f9 100644 --- a/src/shared/label.c +++ b/src/shared/label.c @@ -25,8 +25,12 @@ #include <malloc.h> #include <sys/socket.h> #include <sys/un.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> #include "label.h" +#include "strv.h" #include "util.h" #include "path-util.h" diff --git a/src/shared/label.h b/src/shared/label.h index 1220b18965..dda4d1c024 100644 --- a/src/shared/label.h +++ b/src/shared/label.h @@ -45,3 +45,7 @@ int label_mkdir(const char *path, mode_t mode, bool apply); void label_retest_selinux(void); int label_bind(int fd, const struct sockaddr *addr, socklen_t addrlen); + +int label_write_one_line_file_atomic(const char *fn, const char *line); +int label_write_env_file(const char *fname, char **l); +int label_fopen_temporary(const char *path, FILE **_f, char **_temp_path); diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c index 39b6142e88..6c94d69486 100644 --- a/src/shared/socket-util.c +++ b/src/shared/socket-util.c @@ -38,6 +38,7 @@ #include "path-util.h" #include "socket-util.h" #include "missing.h" +#include "fileio.h" int socket_address_parse(SocketAddress *a, const char *s) { int r; diff --git a/src/shared/util.c b/src/shared/util.c index 4f0b652f4f..152724949d 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -71,6 +71,7 @@ #include "exit-status.h" #include "hashmap.h" #include "env-util.h" +#include "fileio.h" int saved_argc = 0; char **saved_argv = NULL; @@ -528,31 +529,6 @@ int get_starttime_of_pid(pid_t pid, unsigned long long *st) { return 0; } -int write_one_line_file(const char *fn, const char *line) { - _cleanup_fclose_ FILE *f = NULL; - - assert(fn); - assert(line); - - f = fopen(fn, "we"); - if (!f) - return -errno; - - errno = 0; - if (fputs(line, f) < 0) - return errno ? -errno : -EIO; - - if (!endswith(line, "\n")) - fputc('\n', f); - - fflush(f); - - if (ferror(f)) - return errno ? -errno : -EIO; - - return 0; -} - int fchmod_umask(int fd, mode_t m) { mode_t u; int r; @@ -564,339 +540,6 @@ int fchmod_umask(int fd, mode_t m) { return r; } -int write_one_line_file_atomic(const char *fn, const char *line) { - _cleanup_fclose_ FILE *f = NULL; - _cleanup_free_ char *p = NULL; - int r; - - assert(fn); - assert(line); - - r = fopen_temporary(fn, &f, &p); - if (r < 0) - return r; - - fchmod_umask(fileno(f), 0644); - - errno = 0; - if (fputs(line, f) < 0) { - r = -errno; - goto finish; - } - - if (!endswith(line, "\n")) - fputc('\n', f); - - fflush(f); - - if (ferror(f)) - r = errno ? -errno : -EIO; - else { - if (rename(p, fn) < 0) - r = -errno; - else - r = 0; - } - -finish: - if (r < 0) - unlink(p); - - return r; -} - -int read_one_line_file(const char *fn, char **line) { - _cleanup_fclose_ FILE *f = NULL; - char t[LINE_MAX], *c; - - assert(fn); - assert(line); - - f = fopen(fn, "re"); - if (!f) - return -errno; - - if (!fgets(t, sizeof(t), f)) { - - if (ferror(f)) - return errno ? -errno : -EIO; - - t[0] = 0; - } - - c = strdup(t); - if (!c) - return -ENOMEM; - truncate_nl(c); - - *line = c; - return 0; -} - -int read_full_file(const char *fn, char **contents, size_t *size) { - _cleanup_fclose_ FILE *f = NULL; - size_t n, l; - _cleanup_free_ char *buf = NULL; - struct stat st; - - assert(fn); - assert(contents); - - f = fopen(fn, "re"); - if (!f) - return -errno; - - if (fstat(fileno(f), &st) < 0) - return -errno; - - /* Safety check */ - if (st.st_size > 4*1024*1024) - return -E2BIG; - - n = st.st_size > 0 ? st.st_size : LINE_MAX; - l = 0; - - for (;;) { - char *t; - size_t k; - - t = realloc(buf, n+1); - if (!t) - return -ENOMEM; - - buf = t; - k = fread(buf + l, 1, n - l, f); - - if (k <= 0) { - if (ferror(f)) - return -errno; - - break; - } - - l += k; - n *= 2; - - /* Safety check */ - if (n > 4*1024*1024) - return -E2BIG; - } - - buf[l] = 0; - *contents = buf; - buf = NULL; - - if (size) - *size = l; - - return 0; -} - -int parse_env_file( - const char *fname, - const char *separator, ...) { - - int r = 0; - char *contents = NULL, *p; - - assert(fname); - assert(separator); - - if ((r = read_full_file(fname, &contents, NULL)) < 0) - return r; - - p = contents; - for (;;) { - const char *key = NULL; - - p += strspn(p, separator); - p += strspn(p, WHITESPACE); - - if (!*p) - break; - - if (!strchr(COMMENTS, *p)) { - va_list ap; - char **value; - - va_start(ap, separator); - while ((key = va_arg(ap, char *))) { - size_t n; - char *v; - - value = va_arg(ap, char **); - - n = strlen(key); - if (!strneq(p, key, n) || - p[n] != '=') - continue; - - p += n + 1; - n = strcspn(p, separator); - - if (n >= 2 && - strchr(QUOTES, p[0]) && - p[n-1] == p[0]) - v = strndup(p+1, n-2); - else - v = strndup(p, n); - - if (!v) { - r = -ENOMEM; - va_end(ap); - goto fail; - } - - if (v[0] == '\0') { - /* return empty value strings as NULL */ - free(v); - v = NULL; - } - - free(*value); - *value = v; - - p += n; - - r ++; - break; - } - va_end(ap); - } - - if (!key) - p += strcspn(p, separator); - } - -fail: - free(contents); - return r; -} - -int load_env_file(const char *fname, char ***rl) { - - _cleanup_fclose_ FILE *f; - _cleanup_strv_free_ char **m = NULL; - _cleanup_free_ char *c = NULL; - - assert(fname); - assert(rl); - - /* This reads an environment file, but will not complain about - * any invalid assignments, that needs to be done by the - * caller */ - - f = fopen(fname, "re"); - if (!f) - return -errno; - - while (!feof(f)) { - char l[LINE_MAX], *p, *cs, *b; - - if (!fgets(l, sizeof(l), f)) { - if (ferror(f)) - return -errno; - - /* The previous line was a continuation line? - * Let's process it now, before we leave the - * loop */ - if (c) - goto process; - - break; - } - - /* Is this a continuation line? If so, just append - * this to c, and go to next line right-away */ - cs = endswith(l, "\\\n"); - if (cs) { - *cs = '\0'; - b = strappend(c, l); - if (!b) - return -ENOMEM; - - free(c); - c = b; - continue; - } - - /* If the previous line was a continuation line, - * append the current line to it */ - if (c) { - b = strappend(c, l); - if (!b) - return -ENOMEM; - - free(c); - c = b; - } - - process: - p = strstrip(c ? c : l); - - if (*p && !strchr(COMMENTS, *p)) { - _cleanup_free_ char *u; - int k; - - u = normalize_env_assignment(p); - if (!u) - return -ENOMEM; - - k = strv_extend(&m, u); - if (k < 0) - return -ENOMEM; - } - - free(c); - c = NULL; - } - - *rl = m; - m = NULL; - - return 0; -} - -int write_env_file(const char *fname, char **l) { - char **i, *p; - FILE *f; - int r; - - r = fopen_temporary(fname, &f, &p); - if (r < 0) - return r; - - fchmod_umask(fileno(f), 0644); - - errno = 0; - STRV_FOREACH(i, l) { - fputs(*i, f); - fputc('\n', f); - } - - fflush(f); - - if (ferror(f)) { - if (errno != 0) - r = -errno; - else - r = -EIO; - } else { - if (rename(p, fname) < 0) - r = -errno; - else - r = 0; - } - - if (r < 0) - unlink(p); - - fclose(f); - free(p); - - return r; -} - char *truncate_nl(char *s) { assert(s); diff --git a/src/shared/util.h b/src/shared/util.h index fcb0d9af17..88ef2f9040 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -177,15 +177,6 @@ char *split_quoted(const char *c, size_t *l, char **state); pid_t get_parent_of_pid(pid_t pid, pid_t *ppid); int get_starttime_of_pid(pid_t pid, unsigned long long *st); -int write_one_line_file(const char *fn, const char *line); -int write_one_line_file_atomic(const char *fn, const char *line); -int read_one_line_file(const char *fn, char **line); -int read_full_file(const char *fn, char **contents, size_t *size); - -int parse_env_file(const char *fname, const char *separator, ...) _sentinel_; -int load_env_file(const char *fname, char ***l); -int write_env_file(const char *fname, char **l); - char *strappend(const char *s, const char *suffix); char *strnappend(const char *s, const char *suffix, size_t length); diff --git a/src/shared/virt.c b/src/shared/virt.c index fc62c72328..eed321016d 100644 --- a/src/shared/virt.c +++ b/src/shared/virt.c @@ -25,6 +25,7 @@ #include "util.h" #include "virt.h" +#include "fileio.h" /* Returns a short identifier for the various VM implementations */ int detect_vm(const char **id) { |