systemd: merge branch systemd into master

This commit is contained in:
Thomas Haller
2019-05-14 15:31:37 +02:00
25 changed files with 387 additions and 167 deletions

View File

@@ -30,6 +30,17 @@
/*****************************************************************************/
/* systemd detects whether compiler supports "-Wstringop-truncation" to disable
* the warning at particular places. Since we anyway build with -Wno-pragma,
* we don't do that and just let systemd call
*
* _Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"")
*
* regadless whether that would result in a -Wpragma warning. */
#define HAVE_WSTRINGOP_TRUNCATION 1
/*****************************************************************************/
static inline int
_nm_log_get_max_level_realm (void)
{
@@ -86,6 +97,14 @@ G_STMT_START { \
#include <sys/syscall.h>
#include <sys/ioctl.h>
/*****************************************************************************/
/* systemd cannot be compiled with "-Wdeclaration-after-statement". In particular
* in combintation with assert_cc(). */
NM_PRAGMA_WARNING_DISABLE ("-Wdeclaration-after-statement")
/*****************************************************************************/
static inline pid_t
raw_getpid (void) {
#if defined(__alpha__)

View File

@@ -66,8 +66,31 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size) {
if (!q)
return NULL;
if (size > 0) {
size_t bn;
/* Adjust for the 64 byte minimum */
newalloc = a / size;
bn = malloc_usable_size(q) / size;
if (bn > newalloc) {
void *qq;
/* The actual size allocated is larger than what we asked for. Let's call realloc() again to
* take possession of the extra space. This should be cheap, since libc doesn't have to move
* the memory for this. */
qq = realloc(q, bn * size);
if (_likely_(qq)) {
*p = qq;
*allocated = bn;
return qq;
}
}
}
*p = q;
*allocated = _unlikely_(size == 0) ? newalloc : malloc_usable_size(q) / size;
*allocated = newalloc;
return q;
}

View File

@@ -2,8 +2,6 @@
#include "nm-sd-adapt-shared.h"
#include <stdio_ext.h>
#include "alloc-util.h"
#include "env-file.h"
#include "env-util.h"
@@ -548,7 +546,6 @@ int write_env_file(const char *fname, char **l) {
if (r < 0)
return r;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod_umask(fileno(f), 0644);
STRV_FOREACH(i, l)

View File

@@ -31,6 +31,52 @@
#define READ_FULL_BYTES_MAX (4U*1024U*1024U)
int fopen_unlocked(const char *path, const char *options, FILE **ret) {
assert(ret);
FILE *f = fopen(path, options);
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
*ret = f;
return 0;
}
int fdopen_unlocked(int fd, const char *options, FILE **ret) {
assert(ret);
FILE *f = fdopen(fd, options);
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
*ret = f;
return 0;
}
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc) {
FILE *f = open_memstream(ptr, sizeloc);
if (!f)
return NULL;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
return f;
}
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode) {
FILE *f = fmemopen(buf, size, mode);
if (!f)
return NULL;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
return f;
}
#if 0 /* NM_IGNORED */
int write_string_stream_ts(
FILE *f,
@@ -98,7 +144,6 @@ static int write_string_file_atomic(
if (r < 0)
return r;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod_umask(fileno(f), 0644);
r = write_string_stream_ts(f, line, flags, ts);
@@ -144,11 +189,9 @@ int write_string_file_ts(
assert(!ts);
if (flags & WRITE_STRING_FILE_CREATE) {
f = fopen(fn, "we");
if (!f) {
r = -errno;
r = fopen_unlocked(fn, "we", &f);
if (r < 0)
goto fail;
}
} else {
int fd;
@@ -160,16 +203,13 @@ int write_string_file_ts(
goto fail;
}
f = fdopen(fd, "w");
if (!f) {
r = -errno;
r = fdopen_unlocked(fd, "w", &f);
if (r < 0) {
safe_close(fd);
goto fail;
}
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
if (flags & WRITE_STRING_FILE_DISABLE_BUFFER)
setvbuf(f, NULL, _IONBF, 0);
@@ -216,15 +256,14 @@ int write_string_filef(
int read_one_line_file(const char *fn, char **line) {
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(fn);
assert(line);
f = fopen(fn, "re");
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(fn, "re", &f);
if (r < 0)
return r;
return read_line(f, LONG_LINE_MAX, line);
}
@@ -233,6 +272,7 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *buf = NULL;
size_t l, k;
int r;
assert(fn);
assert(blob);
@@ -246,11 +286,9 @@ int verify_file(const char *fn, const char *blob, bool accept_extra_nl) {
if (!buf)
return -ENOMEM;
f = fopen(fn, "re");
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(fn, "re", &f);
if (r < 0)
return r;
/* We try to read one byte more than we need, so that we know whether we hit eof */
errno = 0;
@@ -283,7 +321,8 @@ int read_full_stream_full(
assert(f);
assert(ret_contents);
assert(!(flags & READ_FULL_FILE_UNBASE64) || ret_size);
assert(!FLAGS_SET(flags, READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX));
assert(!(flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) || ret_size);
n_next = LINE_MAX; /* Start size */
@@ -324,6 +363,7 @@ int read_full_stream_full(
}
memcpy_safe(t, buf, n);
explicit_bzero_safe(buf, n);
buf = mfree(buf);
} else {
t = realloc(buf, n_next + 1);
if (!t)
@@ -360,9 +400,12 @@ int read_full_stream_full(
n_next = MIN(n * 2, READ_FULL_BYTES_MAX);
}
if (flags & READ_FULL_FILE_UNBASE64) {
if (flags & (READ_FULL_FILE_UNBASE64 | READ_FULL_FILE_UNHEX)) {
buf[l++] = 0;
r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
if (flags & READ_FULL_FILE_UNBASE64)
r = unbase64mem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
else
r = unhexmem_full(buf, l, flags & READ_FULL_FILE_SECURE, (void **) ret_contents, ret_size);
goto finalize;
}
@@ -394,15 +437,14 @@ finalize:
int read_full_file_full(const char *filename, ReadFullFileFlags flags, char **contents, size_t *size) {
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(filename);
assert(contents);
f = fopen(filename, "re");
if (!f)
return -errno;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(filename, "re", &f);
if (r < 0)
return r;
return read_full_stream_full(f, filename, flags, contents, size);
}

View File

@@ -31,8 +31,14 @@ typedef enum {
typedef enum {
READ_FULL_FILE_SECURE = 1 << 0,
READ_FULL_FILE_UNBASE64 = 1 << 1,
READ_FULL_FILE_UNHEX = 1 << 2,
} ReadFullFileFlags;
int fopen_unlocked(const char *path, const char *options, FILE **ret);
int fdopen_unlocked(int fd, const char *options, FILE **ret);
FILE* open_memstream_unlocked(char **ptr, size_t *sizeloc);
FILE* fmemopen_unlocked(void *buf, size_t size, const char *mode);
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);

View File

@@ -110,10 +110,12 @@ static int unhex_next(const char **p, size_t *l) {
return r;
}
int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
int unhexmem_full(const char *p, size_t l, bool secure, void **ret, size_t *ret_len) {
_cleanup_free_ uint8_t *buf = NULL;
size_t buf_size;
const char *x;
uint8_t *z;
int r;
assert(ret);
assert(ret_len);
@@ -123,7 +125,8 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
l = strlen(p);
/* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */
buf = malloc((l + 1) / 2 + 1);
buf_size = (l + 1) / 2 + 1;
buf = malloc(buf_size);
if (!buf)
return -ENOMEM;
@@ -133,12 +136,16 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
a = unhex_next(&x, &l);
if (a == -EPIPE) /* End of string */
break;
if (a < 0)
return a;
if (a < 0) {
r = a;
goto on_failure;
}
b = unhex_next(&x, &l);
if (b < 0)
return b;
if (b < 0) {
r = b;
goto on_failure;
}
*(z++) = (uint8_t) a << 4 | (uint8_t) b;
}
@@ -149,6 +156,12 @@ int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) {
*ret = TAKE_PTR(buf);
return 0;
on_failure:
if (secure)
explicit_bzero_safe(buf, buf_size);
return r;
}
#if 0 /* NM_IGNORED */

View File

@@ -18,7 +18,10 @@ char hexchar(int x) _const_;
int unhexchar(char c) _const_;
char *hexmem(const void *p, size_t l);
int unhexmem(const char *p, size_t l, void **mem, size_t *len);
int unhexmem_full(const char *p, size_t l, bool secure, void **mem, size_t *len);
static inline int unhexmem(const char *p, size_t l, void **mem, size_t *len) {
return unhexmem_full(p, l, false, mem, len);
}
char base32hexchar(int x) _const_;
int unbase32hexchar(char c) _const_;

View File

@@ -106,6 +106,15 @@
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wincompatible-pointer-types\"")
#if HAVE_WSTRINGOP_TRUNCATION
# define DISABLE_WARNING_STRINGOP_TRUNCATION \
_Pragma("GCC diagnostic push"); \
_Pragma("GCC diagnostic ignored \"-Wstringop-truncation\"")
#else
# define DISABLE_WARNING_STRINGOP_TRUNCATION \
_Pragma("GCC diagnostic push")
#endif
#define REENABLE_WARNING \
_Pragma("GCC diagnostic pop")
#else

View File

@@ -10,7 +10,6 @@
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
@@ -111,7 +110,7 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
char *k;
_cleanup_free_ char *ans = NULL;
const char *p;
int c;
int c, r;
assert(line);
assert(pid >= 0);
@@ -126,15 +125,11 @@ int get_process_cmdline(pid_t pid, size_t max_length, bool comm_fallback, char *
* comm_fallback is false). Returns 0 and sets *line otherwise. */
p = procfs_file_alloca(pid, "cmdline");
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(p, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
if (max_length == 0) {
/* This is supposed to be a safety guard against runaway command lines. */
@@ -518,14 +513,11 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) {
return -EINVAL;
p = procfs_file_alloca(pid, "status");
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(p, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
for (;;) {
_cleanup_free_ char *line = NULL;
@@ -607,14 +599,11 @@ int get_process_environ(pid_t pid, char **env) {
p = procfs_file_alloca(pid, "environ");
f = fopen(p, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(p, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
for (;;) {
char c;
@@ -900,15 +889,11 @@ int getenv_for_pid(pid_t pid, const char *field, char **ret) {
path = procfs_file_alloca(pid, "environ");
f = fopen(path, "re");
if (!f) {
if (errno == ENOENT)
return -ESRCH;
return -errno;
}
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
r = fopen_unlocked(path, "re", &f);
if (r == -ENOENT)
return -ESRCH;
if (r < 0)
return r;
l = strlen(field);
for (;;) {

View File

@@ -30,13 +30,15 @@
#include "io-util.h"
#include "missing.h"
#include "random-util.h"
#include "siphash24.h"
#include "time-util.h"
int rdrand(unsigned long *ret) {
#if defined(__i386__) || defined(__x86_64__)
static int have_rdrand = -1;
unsigned char err;
unsigned long v;
uint8_t success;
if (have_rdrand < 0) {
uint32_t eax, ebx, ecx, edx;
@@ -47,7 +49,12 @@ int rdrand(unsigned long *ret) {
return -EOPNOTSUPP;
}
have_rdrand = !!(ecx & (1U << 30));
/* Compat with old gcc where bit_RDRND didn't exist yet */
#ifndef bit_RDRND
#define bit_RDRND (1U << 30)
#endif
have_rdrand = !!(ecx & bit_RDRND);
}
if (have_rdrand == 0)
@@ -55,12 +62,24 @@ int rdrand(unsigned long *ret) {
asm volatile("rdrand %0;"
"setc %1"
: "=r" (*ret),
"=qm" (err));
msan_unpoison(&err, sizeof(err));
if (!err)
: "=r" (v),
"=qm" (success));
msan_unpoison(&success, sizeof(success));
if (!success)
return -EAGAIN;
/* Apparently on some AMD CPUs RDRAND will sometimes (after a suspend/resume cycle?) report success
* via the carry flag but nonetheless return the same fixed value -1 in all cases. This appears to be
* a bad bug in the CPU or firmware. Let's deal with that and work-around this by explicitly checking
* for this special value (and also 0, just to be sure) and filtering it out. This is a work-around
* only however and something AMD really should fix properly. The Linux kernel should probably work
* around this issue by turning off RDRAND altogether on those CPUs. See:
* https://github.com/systemd/systemd/issues/11810 */
if (v == 0 || v == ULONG_MAX)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
"RDRAND returned suspicious value %lx, assuming bad hardware RNG, not using value.", v);
*ret = v;
return 0;
#else
return -EOPNOTSUPP;
@@ -73,21 +92,22 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
bool got_some = false;
int r;
/* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This call won't
* block, unless the RANDOM_BLOCK flag is set. If RANDOM_DONT_DRAIN is set, an error is returned if the random
* pool is not initialized. Otherwise it will always return some data from the kernel, regardless of whether
* the random pool is fully initialized or not. */
/* Gathers some randomness from the kernel (or the CPU if the RANDOM_ALLOW_RDRAND flag is set). This
* call won't block, unless the RANDOM_BLOCK flag is set. If RANDOM_MAY_FAIL is set, an error is
* returned if the random pool is not initialized. Otherwise it will always return some data from the
* kernel, regardless of whether the random pool is fully initialized or not. */
if (n == 0)
return 0;
if (FLAGS_SET(flags, RANDOM_ALLOW_RDRAND))
/* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is not
* required, as we don't trust it (who does?). Note that we only do a single iteration of RDRAND here,
* even though the Intel docs suggest calling this in a tight loop of 10 invocations or so. That's
* because we don't really care about the quality here. We generally prefer using RDRAND if the caller
* allows us too, since this way we won't drain the kernel randomness pool if we don't need it, as the
* pool's entropy is scarce. */
/* Try x86-64' RDRAND intrinsic if we have it. We only use it if high quality randomness is
* not required, as we don't trust it (who does?). Note that we only do a single iteration of
* RDRAND here, even though the Intel docs suggest calling this in a tight loop of 10
* invocations or so. That's because we don't really care about the quality here. We
* generally prefer using RDRAND if the caller allows us to, since this way we won't upset
* the kernel's random subsystem by accessing it before the pool is initialized (after all it
* will kmsg log about every attempt to do so)..*/
for (;;) {
unsigned long u;
size_t m;
@@ -162,12 +182,13 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
break;
} else if (errno == EAGAIN) {
/* The kernel has no entropy whatsoever. Let's remember to use the syscall the next
* time again though.
/* The kernel has no entropy whatsoever. Let's remember to use the syscall
* the next time again though.
*
* If RANDOM_DONT_DRAIN is set, return an error so that random_bytes() can produce some
* pseudo-random bytes instead. Otherwise, fall back to /dev/urandom, which we know is empty,
* but the kernel will produce some bytes for us on a best-effort basis. */
* If RANDOM_MAY_FAIL is set, return an error so that random_bytes() can
* produce some pseudo-random bytes instead. Otherwise, fall back to
* /dev/urandom, which we know is empty, but the kernel will produce some
* bytes for us on a best-effort basis. */
have_syscall = true;
if (got_some && FLAGS_SET(flags, RANDOM_EXTEND_WITH_PSEUDO)) {
@@ -176,7 +197,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
return 0;
}
if (FLAGS_SET(flags, RANDOM_DONT_DRAIN))
if (FLAGS_SET(flags, RANDOM_MAY_FAIL))
return -ENODATA;
/* Use /dev/urandom instead */
@@ -205,14 +226,19 @@ void initialize_srand(void) {
return;
#if HAVE_SYS_AUXV_H
/* The kernel provides us with 16 bytes of entropy in auxv, so let's
* try to make use of that to seed the pseudo-random generator. It's
* better than nothing... */
/* The kernel provides us with 16 bytes of entropy in auxv, so let's try to make use of that to seed
* the pseudo-random generator. It's better than nothing... But let's first hash it to make it harder
* to recover the original value by watching any pseudo-random bits we generate. After all the
* AT_RANDOM data might be used by other stuff too (in particular: ASLR), and we probably shouldn't
* leak the seed for that. */
auxv = (const void*) getauxval(AT_RANDOM);
auxv = ULONG_TO_PTR(getauxval(AT_RANDOM));
if (auxv) {
assert_cc(sizeof(x) <= 16);
memcpy(&x, auxv, sizeof(x));
static const uint8_t auxval_hash_key[16] = {
0x92, 0x6e, 0xfe, 0x1b, 0xcf, 0x00, 0x52, 0x9c, 0xcc, 0x42, 0xcf, 0xdc, 0x94, 0x1f, 0x81, 0x0f
};
x = (unsigned) siphash24(auxv, 16, auxval_hash_key);
} else
#endif
x = 0;
@@ -259,7 +285,7 @@ void pseudo_random_bytes(void *p, size_t n) {
void random_bytes(void *p, size_t n) {
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_DONT_DRAIN|RANDOM_ALLOW_RDRAND) >= 0)
if (genuine_random_bytes(p, n, RANDOM_EXTEND_WITH_PSEUDO|RANDOM_MAY_FAIL|RANDOM_ALLOW_RDRAND) >= 0)
return;
/* If for some reason some user made /dev/urandom unavailable to us, or the kernel has no entropy, use a PRNG instead. */

View File

@@ -8,11 +8,11 @@
typedef enum RandomFlags {
RANDOM_EXTEND_WITH_PSEUDO = 1 << 0, /* If we can't get enough genuine randomness, but some, fill up the rest with pseudo-randomness */
RANDOM_BLOCK = 1 << 1, /* Rather block than return crap randomness (only if the kernel supports that) */
RANDOM_DONT_DRAIN = 1 << 2, /* If we can't get any randomness at all, return early with -EAGAIN */
RANDOM_MAY_FAIL = 1 << 2, /* If we can't get any randomness at all, return early with -ENODATA */
RANDOM_ALLOW_RDRAND = 1 << 3, /* Allow usage of the CPU RNG */
} RandomFlags;
int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled upwith pseudo random, if not enough is available */
int genuine_random_bytes(void *p, size_t n, RandomFlags flags); /* returns "genuine" randomness, optionally filled up with pseudo random, if not enough is available */
void pseudo_random_bytes(void *p, size_t n); /* returns only pseudo-randommess (but possibly seeded from something better) */
void random_bytes(void *p, size_t n); /* returns genuine randomness if cheaply available, and pseudo randomness if not. */

View File

@@ -1224,17 +1224,34 @@ fallback:
}
#if 0 /* NM_IGNORED */
/* Put a limit on how many times will attempt to call accept4(). We loop
* only on "transient" errors, but let's make sure we don't loop forever. */
#define MAX_FLUSH_ITERATIONS 1024
int flush_accept(int fd) {
struct pollfd pollfd = {
.fd = fd,
.events = POLLIN,
};
int r;
int r, b;
socklen_t l = sizeof(b);
/* Similar to flush_fd() but flushes all incoming connection by accepting them and immediately closing them. */
/* Similar to flush_fd() but flushes all incoming connections by accepting and immediately closing
* them. */
for (;;) {
if (getsockopt(fd, SOL_SOCKET, SO_ACCEPTCONN, &b, &l) < 0)
return -errno;
assert(l == sizeof(b));
if (!b) /* Let's check if this socket accepts connections before calling accept(). accept4() can
* return EOPNOTSUPP if the fd is not a listening socket, which we should treat as a fatal
* error, or in case the incoming TCP connection triggered a network issue, which we want to
* treat as a transient error. Thus, let's rule out the first reason for EOPNOTSUPP early, so
* we can loop safely on transient errors below. */
return -ENOTTY;
for (unsigned iteration = 0;; iteration++) {
int cfd;
r = poll(&pollfd, 1, 0);
@@ -1247,6 +1264,10 @@ int flush_accept(int fd) {
if (r == 0)
return 0;
if (iteration >= MAX_FLUSH_ITERATIONS)
return log_debug_errno(SYNTHETIC_ERRNO(EBUSY),
"Failed to flush connections within " STRINGIFY(MAX_FLUSH_ITERATIONS) " iterations.");
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK|SOCK_CLOEXEC);
if (cfd < 0) {
if (errno == EAGAIN)

View File

@@ -6,7 +6,6 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
@@ -736,6 +735,7 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
return ret;
}
#if 0 /* NM_IGNORED */
static void advance_offsets(ssize_t diff, size_t offsets[static 2], size_t shift[static 2], size_t size) {
if (!offsets)
return;
@@ -767,23 +767,20 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
* 2. Strips ANSI color sequences (a subset of CSI), i.e. ESC '[' … 'm' sequences
* 3. Strips ANSI operating system sequences (CSO), i.e. ESC ']' … BEL sequences
*
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as are any
* other special characters. Truncated ANSI sequences are left-as is too. This call is supposed to suppress the
* most basic formatting noise, but nothing else.
* Everything else will be left as it is. In particular other ANSI sequences are left as they are, as
* are any other special characters. Truncated ANSI sequences are left-as is too. This call is
* supposed to suppress the most basic formatting noise, but nothing else.
*
* Why care for CSO sequences? Well, to undo what terminal_urlify() and friends generate. */
isz = _isz ? *_isz : strlen(*ibuf);
f = open_memstream(&obuf, &osz);
/* Note we turn off internal locking on f for performance reasons. It's safe to do so since we
* created f here and it doesn't leave our scope. */
f = open_memstream_unlocked(&obuf, &osz);
if (!f)
return NULL;
/* Note we turn off internal locking on f for performance reasons. It's safe to do so since we created f here
* and it doesn't leave our scope. */
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
for (i = *ibuf; i < *ibuf + isz + 1; i++) {
switch (state) {
@@ -872,7 +869,6 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz, size_t highlight[2]) {
return obuf;
}
#if 0 /* NM_IGNORED */
char *strextend_with_separator(char **x, const char *separator, ...) {
bool need_separator;
size_t f, l, l_separator;

View File

@@ -212,6 +212,12 @@ static inline size_t strlen_ptr(const char *s) {
return strlen(s);
}
DISABLE_WARNING_STRINGOP_TRUNCATION;
static inline void strncpy_exact(char *buf, const char *src, size_t buf_len) {
strncpy(buf, src, buf_len);
}
REENABLE_WARNING;
/* Like startswith(), but operates on arbitrary memory blocks */
static inline void *memory_startswith(const void *p, size_t sz, const char *token) {
size_t n;

View File

@@ -6,6 +6,7 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
#include "hexdecoct.h"
#include "macro.h"
@@ -39,12 +40,15 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) {
return -errno;
}
f = fdopen(fd, "w");
if (!f) {
unlink_noerrno(t);
/* This assumes that returned FILE object is short-lived and used within the same single-threaded
* context and never shared externally, hence locking is not necessary. */
r = fdopen_unlocked(fd, "w", &f);
if (r < 0) {
unlink(t);
free(t);
safe_close(fd);
return -errno;
return r;
}
*_f = f;

View File

@@ -8,21 +8,19 @@
#include "macro.h"
static inline void umaskp(mode_t *u) {
umask(*u);
umask(*u & 0777);
}
#define _cleanup_umask_ _cleanup_(umaskp)
struct _umask_struct_ {
mode_t mask;
bool quit;
};
/* We make use of the fact here that the umask() concept is using only the lower 9 bits of mode_t, although
* mode_t has space for the file type in the bits further up. We simply OR in the file type mask S_IFMT to
* distinguish the first and the second iteration of the RUN_WITH_UMASK() loop, so that we can run the first
* one, and exit on the second. */
static inline void _reset_umask_(struct _umask_struct_ *s) {
umask(s->mask);
};
assert_cc((S_IFMT & 0777) == 0);
#define RUN_WITH_UMASK(mask) \
for (_cleanup_(_reset_umask_) struct _umask_struct_ _saved_umask_ = { umask(mask), false }; \
!_saved_umask_.quit ; \
_saved_umask_.quit = true)
for (_cleanup_umask_ mode_t _saved_umask_ = umask(mask) | S_IFMT; \
FLAGS_SET(_saved_umask_, S_IFMT); \
_saved_umask_ &= 0777)

View File

@@ -636,13 +636,13 @@ bound4_handle (NMDhcpSystemd *self)
options);
}
static void
static int
dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
{
NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data);
NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self);
g_assert (priv->client4 == client);
nm_assert (priv->client4 == client);
_LOGD ("client event %d", event);
@@ -658,10 +658,14 @@ dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data)
case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE:
bound4_handle (self);
break;
case SD_DHCP_CLIENT_EVENT_SELECTING:
break;
default:
_LOGW ("unhandled DHCP event %d", event);
break;
}
return 0;
}
static gboolean

View File

@@ -5,7 +5,7 @@
Copyright © 2014 Axis Communications AB. All rights reserved.
***/
#include <netinet/if_ether.h>
#include <net/ethernet.h>
#include "socket-util.h"
#include "sparse-endian.h"

View File

@@ -616,7 +616,7 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz
assert(data);
hex_buf = hexmem(data, size);
if (hex_buf == NULL)
if (!hex_buf)
return -ENOMEM;
fprintf(f, "%s=%s\n", key, hex_buf);

View File

@@ -89,7 +89,8 @@ struct sd_dhcp_client {
uint32_t mtu;
uint32_t xid;
usec_t start_time;
unsigned attempt;
uint64_t attempt;
uint64_t max_attempts;
usec_t request_sent;
sd_event_source *timeout_t1;
sd_event_source *timeout_t2;
@@ -524,10 +525,18 @@ int sd_dhcp_client_set_mtu(sd_dhcp_client *client, uint32_t mtu) {
return 0;
}
int sd_dhcp_client_set_max_attempts(sd_dhcp_client *client, uint64_t max_attempts) {
assert_return(client, -EINVAL);
client->max_attempts = max_attempts;
return 0;
}
int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
assert_return(client, -EINVAL);
if (!IN_SET(client->state, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
if (!IN_SET(client->state, DHCP_STATE_SELECTING, DHCP_STATE_BOUND, DHCP_STATE_RENEWING, DHCP_STATE_REBINDING))
return -EADDRNOTAVAIL;
if (ret)
@@ -536,11 +545,13 @@ int sd_dhcp_client_get_lease(sd_dhcp_client *client, sd_dhcp_lease **ret) {
return 0;
}
static void client_notify(sd_dhcp_client *client, int event) {
static int client_notify(sd_dhcp_client *client, int event) {
assert(client);
if (client->callback)
client->callback(client, event, client->userdata);
return client->callback(client, event, client->userdata);
return 0;
}
static int client_initialize(sd_dhcp_client *client) {
@@ -555,7 +566,7 @@ static int client_initialize(sd_dhcp_client *client) {
(void) event_source_disable(client->timeout_t2);
(void) event_source_disable(client->timeout_expire);
client->attempt = 1;
client->attempt = 0;
client->state = DHCP_STATE_INIT;
client->xid = 0;
@@ -599,7 +610,7 @@ static int client_message_init(
assert(ret);
assert(_optlen);
assert(_optoffset);
assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST));
assert(IN_SET(type, DHCP_DISCOVER, DHCP_REQUEST, DHCP_RELEASE));
optlen = DHCP_MIN_OPTIONS_SIZE;
size = sizeof(DHCPPacket) + optlen;
@@ -690,7 +701,7 @@ static int client_message_init(
MAY contain the Parameter Request List option. */
/* NOTE: in case that there would be an option to do not send
* any PRL at all, the size should be checked before sending */
if (client->req_opts_size > 0) {
if (client->req_opts_size > 0 && type != DHCP_RELEASE) {
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_PARAMETER_REQUEST_LIST,
client->req_opts_size, client->req_opts);
@@ -722,7 +733,7 @@ static int client_message_init(
*/
/* RFC7844 section 3:
SHOULD NOT contain any other option. */
if (!client->anonymize) {
if (!client->anonymize && type != DHCP_RELEASE) {
max_size = htobe16(size);
r = dhcp_option_append(&packet->dhcp, client->mtu, &optoffset, 0,
SD_DHCP_OPTION_MAXIMUM_MESSAGE_SIZE,
@@ -854,6 +865,41 @@ static int client_send_discover(sd_dhcp_client *client) {
return 0;
}
static int client_send_release(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *release = NULL;
size_t optoffset, optlen;
int r;
assert(client);
assert(!IN_SET(client->state, DHCP_STATE_STOPPED));
r = client_message_init(client, &release, DHCP_RELEASE,
&optlen, &optoffset);
if (r < 0)
return r;
/* Fill up release IP and MAC */
release->dhcp.ciaddr = client->lease->address;
memcpy(&release->dhcp.chaddr, &client->mac_addr, client->mac_addr_len);
r = dhcp_option_append(&release->dhcp, optlen, &optoffset, 0,
SD_DHCP_OPTION_END, 0, NULL);
if (r < 0)
return r;
r = dhcp_network_send_udp_socket(client->fd,
client->lease->server_address,
DHCP_PORT_SERVER,
&release->dhcp,
sizeof(DHCPMessage) + optoffset);
if (r < 0)
return r;
log_dhcp_client(client, "RELEASE");
return 0;
}
static int client_send_request(sd_dhcp_client *client) {
_cleanup_free_ DHCPPacket *request = NULL;
size_t optoffset, optlen;
@@ -1054,10 +1100,12 @@ static int client_timeout_resend(
case DHCP_STATE_REQUESTING:
case DHCP_STATE_BOUND:
if (client->attempt < 64)
client->attempt *= 2;
if (client->attempt < client->max_attempts)
client->attempt++;
else
goto error;
next_timeout = time_now + (client->attempt - 1) * USEC_PER_SEC;
next_timeout = time_now + ((UINT64_C(1) << MIN(client->attempt, (uint64_t) 6)) - 1) * USEC_PER_SEC;
break;
@@ -1081,17 +1129,15 @@ static int client_timeout_resend(
r = client_send_discover(client);
if (r >= 0) {
client->state = DHCP_STATE_SELECTING;
client->attempt = 1;
} else {
if (client->attempt >= 64)
goto error;
}
client->attempt = 0;
} else if (client->attempt >= client->max_attempts)
goto error;
break;
case DHCP_STATE_SELECTING:
r = client_send_discover(client);
if (r < 0 && client->attempt >= 64)
if (r < 0 && client->attempt >= client->max_attempts)
goto error;
break;
@@ -1101,7 +1147,7 @@ static int client_timeout_resend(
case DHCP_STATE_RENEWING:
case DHCP_STATE_REBINDING:
r = client_send_request(client);
if (r < 0 && client->attempt >= 64)
if (r < 0 && client->attempt >= client->max_attempts)
goto error;
if (client->state == DHCP_STATE_INIT_REBOOT)
@@ -1253,7 +1299,7 @@ static int client_timeout_t2(sd_event_source *s, uint64_t usec, void *userdata)
client->fd = asynchronous_close(client->fd);
client->state = DHCP_STATE_REBINDING;
client->attempt = 1;
client->attempt = 0;
r = dhcp_network_bind_raw_socket(client->ifindex, &client->link,
client->xid, client->mac_addr,
@@ -1273,7 +1319,7 @@ static int client_timeout_t1(sd_event_source *s, uint64_t usec, void *userdata)
DHCP_CLIENT_DONT_DESTROY(client);
client->state = DHCP_STATE_RENEWING;
client->attempt = 1;
client->attempt = 0;
return client_initialize_time_events(client);
}
@@ -1323,6 +1369,9 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer, size_
sd_dhcp_lease_unref(client->lease);
client->lease = TAKE_PTR(lease);
if (client_notify(client, SD_DHCP_CLIENT_EVENT_SELECTING) < 0)
return -ENOMSG;
log_dhcp_client(client, "OFFER");
return 0;
@@ -1557,7 +1606,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
if (r >= 0) {
client->state = DHCP_STATE_REQUESTING;
client->attempt = 1;
client->attempt = 0;
r = event_reset_time(client->event, &client->timeout_resend,
clock_boottime_or_monotonic(),
@@ -1592,7 +1641,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i
notify_event = r;
client->state = DHCP_STATE_BOUND;
client->attempt = 1;
client->attempt = 0;
client->last_addr = client->lease->address;
@@ -1848,6 +1897,14 @@ int sd_dhcp_client_start(sd_dhcp_client *client) {
return r;
}
int sd_dhcp_client_send_release(sd_dhcp_client *client) {
assert_return(client, -EINVAL);
client_send_release(client);
return 0;
}
int sd_dhcp_client_stop(sd_dhcp_client *client) {
DHCP_CLIENT_DONT_DESTROY(client);
@@ -1931,10 +1988,10 @@ int sd_dhcp_client_new(sd_dhcp_client **ret, int anonymize) {
.state = DHCP_STATE_INIT,
.ifindex = -1,
.fd = -1,
.attempt = 1,
.mtu = DHCP_DEFAULT_MIN_SIZE,
.port = DHCP_PORT_CLIENT,
.anonymize = !!anonymize,
.max_attempts = (uint64_t) -1,
};
/* NOTE: this could be moved to a function. */
if (anonymize) {

View File

@@ -7,7 +7,6 @@
#include <arpa/inet.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -833,7 +832,6 @@ int dhcp_lease_save(sd_dhcp_lease *lease, const char *lease_file) {
if (r < 0)
goto fail;
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
(void) fchmod(fileno(f), 0644);
fprintf(f,

View File

@@ -341,6 +341,12 @@ fail:
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_event, sd_event, event_free);
_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) {
if (s)
(void) sd_event_source_set_enabled(s, SD_EVENT_OFF);
return sd_event_source_unref(s);
}
static bool event_pid_changed(sd_event *e) {
assert(e);
@@ -3026,7 +3032,7 @@ static void event_close_inode_data_fds(sd_event *e) {
/* Close the fds pointing to the inodes to watch now. We need to close them as they might otherwise pin
* filesystems. But we can't close them right-away as we need them as long as the user still wants to make
* adjustments to the even source, such as changing the priority (which requires us to remove and readd a watch
* adjustments to the even source, such as changing the priority (which requires us to remove and re-add a watch
* for the inode). Hence, let's close them when entering the first iteration after they were added, as a
* compromise. */

View File

@@ -41,7 +41,7 @@ int dns_label_unescape(const char **name, char *dest, size_t sz, DNSLabelFlags f
d = dest;
for (;;) {
if (*n == 0 || *n == '.') {
if (IN_SET(*n, 0, '.')) {
if (FLAGS_SET(flags, DNS_LABEL_LDH) && last_char == '-')
/* Trailing dash */
return -EINVAL;

View File

@@ -38,6 +38,7 @@ enum {
SD_DHCP_CLIENT_EVENT_IP_CHANGE = 2,
SD_DHCP_CLIENT_EVENT_EXPIRED = 3,
SD_DHCP_CLIENT_EVENT_RENEW = 4,
SD_DHCP_CLIENT_EVENT_SELECTING = 5,
};
enum {
@@ -98,7 +99,7 @@ enum {
typedef struct sd_dhcp_client sd_dhcp_client;
typedef void (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
typedef int (*sd_dhcp_client_callback_t)(sd_dhcp_client *client, int event, void *userdata);
int sd_dhcp_client_set_callback(
sd_dhcp_client *client,
sd_dhcp_client_callback_t cb,
@@ -154,6 +155,9 @@ int sd_dhcp_client_get_client_id(
int sd_dhcp_client_set_mtu(
sd_dhcp_client *client,
uint32_t mtu);
int sd_dhcp_client_set_max_attempts(
sd_dhcp_client *client,
uint64_t attempt);
int sd_dhcp_client_set_client_port(
sd_dhcp_client *client,
uint16_t port);
@@ -172,6 +176,7 @@ int sd_dhcp_client_get_lease(
int sd_dhcp_client_stop(sd_dhcp_client *client);
int sd_dhcp_client_start(sd_dhcp_client *client);
int sd_dhcp_client_send_release(sd_dhcp_client *client);
sd_dhcp_client *sd_dhcp_client_ref(sd_dhcp_client *client);
sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client);

View File

@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret);
sd_event_source* sd_event_source_ref(sd_event_source *s);
sd_event_source* sd_event_source_unref(sd_event_source *s);
sd_event_source* sd_event_source_disable_unref(sd_event_source *s);
sd_event *sd_event_source_get_event(sd_event_source *s);
void* sd_event_source_get_userdata(sd_event_source *s);
@@ -149,6 +150,7 @@ int sd_event_source_set_floating(sd_event_source *s, int b);
/* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_unref);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event_source, sd_event_source_disable_unref);
_SD_END_DECLARATIONS;