diff options
author | Thomas Haller <thaller@redhat.com> | 2019-04-12 07:22:35 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2019-04-12 07:33:52 +0200 |
commit | d3d45fd1f9adf4812a658cf8bd3600c361eb5ab4 (patch) | |
tree | daef05193264573d73798009aa688199f1e5fc76 | |
parent | a94ccc9acc47f08943f017a5040abeb05afee183 (diff) | |
parent | 2b1ea1613d16c7fed854d0e8e940bf32675a92b3 (diff) | |
download | NetworkManager-d3d45fd1f9adf4812a658cf8bd3600c361eb5ab4.tar.gz |
systemd: merge branch systemd into master
-rw-r--r-- | shared/systemd/src/basic/errno-util.h | 40 | ||||
-rw-r--r-- | shared/systemd/src/basic/fileio.c | 104 | ||||
-rw-r--r-- | shared/systemd/src/basic/fileio.h | 20 | ||||
-rw-r--r-- | shared/systemd/src/basic/hexdecoct.c | 75 | ||||
-rw-r--r-- | shared/systemd/src/basic/hexdecoct.h | 5 | ||||
-rw-r--r-- | shared/systemd/src/basic/log.h | 2 | ||||
-rw-r--r-- | shared/systemd/src/basic/socket-util.c | 13 | ||||
-rw-r--r-- | shared/systemd/src/basic/string-util.h | 10 | ||||
-rw-r--r-- | src/systemd/src/libsystemd/sd-id128/id128-util.h | 3 | ||||
-rw-r--r-- | src/systemd/src/systemd/sd-id128.h | 3 |
10 files changed, 210 insertions, 65 deletions
diff --git a/shared/systemd/src/basic/errno-util.h b/shared/systemd/src/basic/errno-util.h index 615b6a806a..d7a5ea771f 100644 --- a/shared/systemd/src/basic/errno-util.h +++ b/shared/systemd/src/basic/errno-util.h @@ -32,12 +32,38 @@ static inline int negative_errno(void) { * * Hint #2: The kernel sends e.g., EHOSTUNREACH or ENONET to userspace in some ICMP error cases. See the * icmp_err_convert[] in net/ipv4/icmp.c in the kernel sources */ -#define ERRNO_IS_DISCONNECT(r) \ - IN_SET(abs(r), \ - ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \ - ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, \ - ENONET, ESHUTDOWN) +static inline bool ERRNO_IS_DISCONNECT(int r) { + return IN_SET(abs(r), + ECONNABORTED, + ECONNREFUSED, + ECONNRESET, + EHOSTDOWN, + EHOSTUNREACH, + ENETDOWN, + ENETRESET, + ENETUNREACH, + ENONET, + ENOPROTOOPT, + ENOTCONN, + EPIPE, + EPROTO, + ESHUTDOWN); +} + +/* Transient errors we might get on accept() that we should ignore. As per error handling comment in + * the accept(2) man page. */ +static inline bool ERRNO_IS_ACCEPT_AGAIN(int r) { + return ERRNO_IS_DISCONNECT(r) || + IN_SET(abs(r), + EAGAIN, + EINTR, + EOPNOTSUPP); +} /* Resource exhaustion, could be our fault or general system trouble */ -#define ERRNO_IS_RESOURCE(r) \ - IN_SET(abs(r), ENOMEM, EMFILE, ENFILE) +static inline bool ERRNO_IS_RESOURCE(int r) { + return IN_SET(abs(r), + EMFILE, + ENFILE, + ENOMEM); +} diff --git a/shared/systemd/src/basic/fileio.c b/shared/systemd/src/basic/fileio.c index ee66190f72..0dfb457481 100644 --- a/shared/systemd/src/basic/fileio.c +++ b/shared/systemd/src/basic/fileio.c @@ -19,6 +19,7 @@ #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "hexdecoct.h" #include "log.h" #include "macro.h" #include "missing.h" @@ -268,26 +269,29 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) { } #endif /* NM_IGNORED */ -int read_full_stream( +int read_full_stream_full( FILE *f, + const char *filename, + ReadFullFileFlags flags, char **ret_contents, size_t *ret_size) { _cleanup_free_ char *buf = NULL; struct stat st; - size_t n, l; - int fd; + size_t n, n_next, l; + int fd, r; assert(f); assert(ret_contents); + assert(!(flags & READ_FULL_FILE_UNBASE64) || ret_size); - n = LINE_MAX; /* Start size */ + n_next = LINE_MAX; /* Start size */ fd = fileno(f); if (fd >= 0) { /* If the FILE* object is backed by an fd (as opposed to memory or such, see fmemopen(), let's * optimize our buffering) */ - if (fstat(fileno(f), &st) < 0) + if (fstat(fd, &st) < 0) return -errno; if (S_ISREG(st.st_mode)) { @@ -300,27 +304,44 @@ int read_full_stream( * size of 0. Note that we increase the size to read here by one, so that the first read attempt * already makes us notice the EOF. */ if (st.st_size > 0) - n = st.st_size + 1; + n_next = st.st_size + 1; + + if (flags & READ_FULL_FILE_SECURE) + (void) warn_file_is_world_accessible(filename, &st, NULL, 0); } } - l = 0; + n = l = 0; for (;;) { char *t; size_t k; - t = realloc(buf, n + 1); - if (!t) - return -ENOMEM; + if (flags & READ_FULL_FILE_SECURE) { + t = malloc(n_next + 1); + if (!t) { + r = -ENOMEM; + goto finalize; + } + memcpy_safe(t, buf, n); + explicit_bzero_safe(buf, n); + } else { + t = realloc(buf, n_next + 1); + if (!t) + return -ENOMEM; + } buf = t; + n = n_next; + errno = 0; k = fread(buf + l, 1, n - l, f); if (k > 0) l += k; - if (ferror(f)) - return errno > 0 ? -errno : -EIO; + if (ferror(f)) { + r = errno > 0 ? -errno : -EIO; + goto finalize; + } if (feof(f)) break; @@ -331,10 +352,18 @@ int read_full_stream( assert(l == n); /* Safety check */ - if (n >= READ_FULL_BYTES_MAX) - return -E2BIG; + if (n >= READ_FULL_BYTES_MAX) { + r = -E2BIG; + goto finalize; + } + + n_next = MIN(n * 2, READ_FULL_BYTES_MAX); + } - n = MIN(n * 2, READ_FULL_BYTES_MAX); + if (flags & READ_FULL_FILE_UNBASE64) { + buf[l++] = 0; + r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size); + goto finalize; } if (!ret_size) { @@ -342,8 +371,10 @@ int read_full_stream( * trailing NUL byte. But if there's an embedded NUL byte, then we should refuse operation as otherwise * there'd be ambiguity about what we just read. */ - if (memchr(buf, 0, l)) - return -EBADMSG; + if (memchr(buf, 0, l)) { + r = -EBADMSG; + goto finalize; + } } buf[l] = 0; @@ -353,21 +384,27 @@ int read_full_stream( *ret_size = l; return 0; + +finalize: + if (flags & READ_FULL_FILE_SECURE) + explicit_bzero_safe(buf, n); + + return r; } -int read_full_file(const char *fn, char **contents, size_t *size) { +int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) { _cleanup_fclose_ FILE *f = NULL; - assert(fn); + assert(filename); assert(contents); - f = fopen(fn, "re"); + f = fopen(filename, "re"); if (!f) return -errno; (void) __fsetlocking(f, FSETLOCKING_BYCALLER); - return read_full_stream(f, contents, size); + return read_full_stream_full(f, filename, flags, contents, size); } #if 0 /* NM_IGNORED */ @@ -830,3 +867,28 @@ int safe_fgetc(FILE *f, char *ret) { return 1; } #endif /* NM_IGNORED */ + +int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line) { + struct stat _st; + + if (!filename) + return 0; + + if (!st) { + if (stat(filename, &_st) < 0) + return -errno; + st = &_st; + } + + if ((st->st_mode & S_IRWXO) == 0) + return 0; + + if (unit) + log_syntax(unit, LOG_WARNING, filename, line, 0, + "%s has %04o mode that is too permissive, please adjust the access mode.", + filename, st->st_mode & 07777); + else + log_warning("%s has %04o mode that is too permissive, please adjust the access mode.", + filename, st->st_mode & 07777); + return 0; +} diff --git a/shared/systemd/src/basic/fileio.h b/shared/systemd/src/basic/fileio.h index 53e3f4ef5f..760e738688 100644 --- a/shared/systemd/src/basic/fileio.h +++ b/shared/systemd/src/basic/fileio.h @@ -5,6 +5,7 @@ #include <stdbool.h> #include <stddef.h> #include <stdio.h> +#include <sys/stat.h> #include <sys/types.h> #include "macro.h" @@ -27,6 +28,11 @@ typedef enum { } WriteStringFileFlags; +typedef enum { + READ_FULL_FILE_SECURE = 1 << 0, + READ_FULL_FILE_UNBASE64 = 1 << 1, +} ReadFullFileFlags; + int write_string_stream_ts(FILE *f, const char *line, WriteStringFileFlags flags, struct timespec *ts); static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) { return write_string_stream_ts(f, line, flags, NULL); @@ -38,9 +44,15 @@ static inline int write_string_file(const char *fn, const char *line, WriteStrin int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4); -int read_one_line_file(const char *fn, char **line); -int read_full_file(const char *fn, char **contents, size_t *size); -int read_full_stream(FILE *f, char **contents, size_t *size); +int read_one_line_file(const char *filename, char **line); +int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size); +static inline int read_full_file(const char *filename, char **contents, size_t *size) { + return read_full_file_full(filename, 0, contents, size); +} +int read_full_stream_full(FILE *f, const char *filename, ReadFullFileFlags flags, char **contents, size_t *size); +static inline int read_full_stream(FILE *f, char **contents, size_t *size) { + return read_full_stream_full(f, NULL, 0, contents, size); +} int verify_file(const char *fn, const char *blob, bool accept_extra_nl); @@ -76,3 +88,5 @@ static inline int read_nul_string(FILE *f, size_t limit, char **ret) { } int safe_fgetc(FILE *f, char *ret); + +int warn_file_is_world_accessible(const char *filename, struct stat *st, const char *unit, unsigned line); diff --git a/shared/systemd/src/basic/hexdecoct.c b/shared/systemd/src/basic/hexdecoct.c index b753ed351a..c81c09e8c4 100644 --- a/shared/systemd/src/basic/hexdecoct.c +++ b/shared/systemd/src/basic/hexdecoct.c @@ -691,11 +691,12 @@ static int unbase64_next(const char **p, size_t *l) { return ret; } -int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) { +int unbase64mem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_size) { _cleanup_free_ uint8_t *buf = NULL; const char *x; uint8_t *z; size_t len; + int r; assert(p || l == 0); assert(ret); @@ -718,36 +719,54 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) { a = unbase64_next(&x, &l); if (a == -EPIPE) /* End of string */ break; - if (a < 0) - return a; - if (a == INT_MAX) /* Padding is not allowed at the beginning of a 4ch block */ - return -EINVAL; + if (a < 0) { + r = a; + goto on_failure; + } + if (a == INT_MAX) { /* Padding is not allowed at the beginning of a 4ch block */ + r = -EINVAL; + goto on_failure; + } b = unbase64_next(&x, &l); - if (b < 0) - return b; - if (b == INT_MAX) /* Padding is not allowed at the second character of a 4ch block either */ - return -EINVAL; + if (b < 0) { + r = b; + goto on_failure; + } + if (b == INT_MAX) { /* Padding is not allowed at the second character of a 4ch block either */ + r = -EINVAL; + goto on_failure; + } c = unbase64_next(&x, &l); - if (c < 0) - return c; + if (c < 0) { + r = c; + goto on_failure; + } d = unbase64_next(&x, &l); - if (d < 0) - return d; + if (d < 0) { + r = d; + goto on_failure; + } if (c == INT_MAX) { /* Padding at the third character */ - if (d != INT_MAX) /* If the third character is padding, the fourth must be too */ - return -EINVAL; + if (d != INT_MAX) { /* If the third character is padding, the fourth must be too */ + r = -EINVAL; + goto on_failure; + } /* b == 00YY0000 */ - if (b & 15) - return -EINVAL; + if (b & 15) { + r = -EINVAL; + goto on_failure; + } - if (l > 0) /* Trailing rubbish? */ - return -ENAMETOOLONG; + if (l > 0) { /* Trailing rubbish? */ + r = -ENAMETOOLONG; + goto on_failure; + } *(z++) = (uint8_t) a << 2 | (uint8_t) (b >> 4); /* XXXXXXYY */ break; @@ -755,11 +774,15 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) { if (d == INT_MAX) { /* c == 00ZZZZ00 */ - if (c & 3) - return -EINVAL; + if (c & 3) { + r = -EINVAL; + goto on_failure; + } - if (l > 0) /* Trailing rubbish? */ - return -ENAMETOOLONG; + if (l > 0) { /* Trailing rubbish? */ + r = -ENAMETOOLONG; + goto on_failure; + } *(z++) = (uint8_t) a << 2 | (uint8_t) b >> 4; /* XXXXXXYY */ *(z++) = (uint8_t) b << 4 | (uint8_t) c >> 2; /* YYYYZZZZ */ @@ -777,6 +800,12 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) { *ret = TAKE_PTR(buf); return 0; + +on_failure: + if (secure) + explicit_bzero_safe(buf, len); + + return r; } #if 0 /* NM_IGNORED */ diff --git a/shared/systemd/src/basic/hexdecoct.h b/shared/systemd/src/basic/hexdecoct.h index 9477d16e37..fa6013ee75 100644 --- a/shared/systemd/src/basic/hexdecoct.h +++ b/shared/systemd/src/basic/hexdecoct.h @@ -33,6 +33,9 @@ ssize_t base64mem(const void *p, size_t l, char **out); int base64_append(char **prefix, int plen, const void *p, size_t l, int margin, int width); -int unbase64mem(const char *p, size_t l, void **mem, size_t *len); +int unbase64mem_full(const char *p, size_t l, bool secure, void **mem, size_t *len); +static inline int unbase64mem(const char *p, size_t l, void **mem, size_t *len) { + return unbase64mem_full(p, l, false, mem, len); +} void hexdump(FILE *f, const void *p, size_t s); diff --git a/shared/systemd/src/basic/log.h b/shared/systemd/src/basic/log.h index 3b3d7444dd..98c5f4d7b2 100644 --- a/shared/systemd/src/basic/log.h +++ b/shared/systemd/src/basic/log.h @@ -332,7 +332,7 @@ int log_syntax_invalid_utf8_internal( ({ \ int _level = (level), _e = (error); \ (log_get_max_level() >= LOG_PRI(_level)) \ - ? log_syntax_internal(unit, _level, config_file, config_line, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ + ? log_internal_realm(_level, _e, __FILE__, __LINE__, __func__, __VA_ARGS__) \ : -ERRNO_VALUE(_e); \ }) diff --git a/shared/systemd/src/basic/socket-util.c b/shared/systemd/src/basic/socket-util.c index 2fce3f5d81..b98b046133 100644 --- a/shared/systemd/src/basic/socket-util.c +++ b/shared/systemd/src/basic/socket-util.c @@ -17,6 +17,7 @@ #include <unistd.h> #include "alloc-util.h" +#include "errno-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" @@ -1242,22 +1243,22 @@ int flush_accept(int fd) { continue; return -errno; - - } else if (r == 0) + } + if (r == 0) return 0; cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC); if (cfd < 0) { - if (errno == EINTR) - continue; - if (errno == EAGAIN) return 0; + if (ERRNO_IS_ACCEPT_AGAIN(errno)) + continue; + return -errno; } - close(cfd); + safe_close(cfd); } } diff --git a/shared/systemd/src/basic/string-util.h b/shared/systemd/src/basic/string-util.h index 9cf11198b1..b23f4c8341 100644 --- a/shared/systemd/src/basic/string-util.h +++ b/shared/systemd/src/basic/string-util.h @@ -57,6 +57,16 @@ static inline const char *empty_to_dash(const char *str) { return isempty(str) ? "-" : str; } +static inline bool empty_or_dash(const char *str) { + return !str || + str[0] == 0 || + (str[0] == '-' && str[1] == 0); +} + +static inline const char *empty_or_dash_to_null(const char *p) { + return empty_or_dash(p) ? NULL : p; +} + static inline char *startswith(const char *s, const char *prefix) { size_t l; diff --git a/src/systemd/src/libsystemd/sd-id128/id128-util.h b/src/systemd/src/libsystemd/sd-id128/id128-util.h index 65f14ab252..82a69a77f3 100644 --- a/src/systemd/src/libsystemd/sd-id128/id128-util.h +++ b/src/systemd/src/libsystemd/sd-id128/id128-util.h @@ -10,9 +10,6 @@ char *id128_to_uuid_string(sd_id128_t id, char s[37]); -/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */ -#define ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" - bool id128_is_valid(const char *s) _pure_; typedef enum Id128Format { diff --git a/src/systemd/src/systemd/sd-id128.h b/src/systemd/src/systemd/sd-id128.h index bdf88ed53f..c5fbe0a4f1 100644 --- a/src/systemd/src/systemd/sd-id128.h +++ b/src/systemd/src/systemd/sd-id128.h @@ -63,6 +63,9 @@ int sd_id128_get_boot_app_specific(sd_id128_t app_id, sd_id128_t *ret); #define SD_ID128_FORMAT_STR "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" #define SD_ID128_FORMAT_VAL(x) (x).bytes[0], (x).bytes[1], (x).bytes[2], (x).bytes[3], (x).bytes[4], (x).bytes[5], (x).bytes[6], (x).bytes[7], (x).bytes[8], (x).bytes[9], (x).bytes[10], (x).bytes[11], (x).bytes[12], (x).bytes[13], (x).bytes[14], (x).bytes[15] +/* Like SD_ID128_FORMAT_STR, but formats as UUID, not in plain format */ +#define SD_ID128_UUID_FORMAT_STR "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" + #define SD_ID128_CONST_STR(x) \ ((const char[SD_ID128_STRING_MAX]) { \ ((x).bytes[0] >> 4) >= 10 ? 'a' + ((x).bytes[0] >> 4) - 10 : '0' + ((x).bytes[0] >> 4), \ |