Commit 8aa8d747 authored by Thomas Haller's avatar Thomas Haller

systemd: update code from upstream (2018-08-26)

This is a direct dump from systemd git.

======

SYSTEMD_DIR=../systemd
COMMIT=56663345dfb1dd3ff23cac5fbc955aba54477efa

(
  cd "$SYSTEMD_DIR"
  git checkout "$COMMIT"
  git reset --hard
  git clean -fdx
)

git ls-files :/src/systemd/src/ \
             :/shared/nm-utils/unaligned.h | \
  xargs -d '\n' rm -f

nm_copy_sd() {
    mkdir -p "./src/systemd/$(dirname "$1")"
    cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}

nm_copy_sd_shared() {
    mkdir -p "./shared/nm-utils/"
    cp "$SYSTEMD_DIR/$1" "./shared/nm-utils/${1##*/}"
}

nm_copy_sd "src/basic/alloc-util.c"
nm_copy_sd "src/basic/alloc-util.h"
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/env-util.c"
nm_copy_sd "src/basic/env-util.h"
nm_copy_sd "src/basic/escape.c"
nm_copy_sd "src/basic/escape.h"
nm_copy_sd "src/basic/ether-addr-util.c"
nm_copy_sd "src/basic/ether-addr-util.h"
nm_copy_sd "src/basic/extract-word.c"
nm_copy_sd "src/basic/extract-word.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/fd-util.c"
nm_copy_sd "src/basic/fd-util.h"
nm_copy_sd "src/basic/fs-util.c"
nm_copy_sd "src/basic/fs-util.h"
nm_copy_sd "src/basic/hash-funcs.c"
nm_copy_sd "src/basic/hash-funcs.h"
nm_copy_sd "src/basic/hashmap.c"
nm_copy_sd "src/basic/hashmap.h"
nm_copy_sd "src/basic/hexdecoct.c"
nm_copy_sd "src/basic/hexdecoct.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/io-util.c"
nm_copy_sd "src/basic/io-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/mempool.h"
nm_copy_sd "src/basic/mempool.c"
nm_copy_sd "src/basic/parse-util.c"
nm_copy_sd "src/basic/parse-util.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/prioq.h"
nm_copy_sd "src/basic/prioq.c"
nm_copy_sd "src/basic/process-util.h"
nm_copy_sd "src/basic/process-util.c"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/set.h"
nm_copy_sd "src/basic/signal-util.h"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.c"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/stat-util.c"
nm_copy_sd "src/basic/stat-util.h"
nm_copy_sd "src/basic/stdio-util.h"
nm_copy_sd "src/basic/string-table.c"
nm_copy_sd "src/basic/string-table.h"
nm_copy_sd "src/basic/string-util.c"
nm_copy_sd "src/basic/string-util.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/umask-util.h"
nm_copy_sd_shared "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/arp-util.c"
nm_copy_sd "src/libsystemd-network/arp-util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/lldp-internal.h"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd "src/libsystemd-network/lldp-network.c"
nm_copy_sd "src/libsystemd-network/lldp-network.h"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c"
nm_copy_sd "src/libsystemd-network/sd-lldp.c"
nm_copy_sd "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-ndisc.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4acd.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
nm_copy_sd "src/systemd/sd-lldp.h"
parent 353810cc
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
Copyright © 2014 Tom Gundersen
***/
#include <endian.h>
#include <stdint.h>
......
This diff is collapsed.
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include "macro.h"
#include "string.h"
bool env_name_is_valid(const char *e);
bool env_value_is_valid(const char *e);
bool env_assignment_is_valid(const char *e);
enum {
REPLACE_ENV_USE_ENVIRONMENT = 1u,
REPLACE_ENV_ALLOW_BRACELESS = 2u,
REPLACE_ENV_ALLOW_EXTENDED = 4u,
};
char *replace_env_n(const char *format, size_t n, char **env, unsigned flags);
char **replace_env_argv(char **argv, char **env);
static inline char *replace_env(const char *format, char **env, unsigned flags) {
return replace_env_n(format, strlen(format), env, flags);
}
bool strv_env_is_valid(char **e);
#define strv_env_clean(l) strv_env_clean_with_callback(l, NULL, NULL)
char **strv_env_clean_with_callback(char **l, void (*invalid_callback)(const char *p, void *userdata), void *userdata);
bool strv_env_name_is_valid(char **l);
bool strv_env_name_or_assignment_is_valid(char **l);
char **strv_env_merge(size_t n_lists, ...);
char **strv_env_delete(char **x, size_t n_lists, ...); /* New copy */
char **strv_env_set(char **x, const char *p); /* New copy ... */
char **strv_env_unset(char **l, const char *p); /* In place ... */
char **strv_env_unset_many(char **l, ...) _sentinel_;
int strv_env_replace(char ***l, char *p); /* In place ... */
char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure_;
char *strv_env_get(char **x, const char *n) _pure_;
int getenv_bool(const char *p);
int getenv_bool_secure(const char *p);
int serialize_environment(FILE *f, char **environment);
int deserialize_environment(char ***environment, const char *line);
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Tom Gundersen
***/
#include <errno.h>
#include <net/ethernet.h>
......
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
Copyright © 2014 Tom Gundersen
***/
#include <net/ethernet.h>
#include <stdbool.h>
......
......@@ -78,8 +78,12 @@ int acquire_data_fd(const void *data, size_t size, unsigned flags);
int fd_duplicate_data_fd(int fd);
/* Hint: ENETUNREACH happens if we try to connect to "non-existing" special IP addresses, such as ::5 */
#define ERRNO_IS_DISCONNECT(r) \
IN_SET(r, ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, ENETUNREACH)
/* 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(r, \
ENOTCONN, ECONNRESET, ECONNREFUSED, ECONNABORTED, EPIPE, \
ENETUNREACH, EHOSTUNREACH, ENOPROTOOPT, EHOSTDOWN, ENONET)
/* Resource exhaustion, could be our fault or general system trouble */
#define ERRNO_IS_RESOURCE(r) \
......
......@@ -1225,9 +1225,13 @@ int tempfn_xxxxxx(const char *p, const char *extra, char **ret) {
const char *fn;
char *t;
assert(p);
assert(ret);
if (isempty(p))
return -EINVAL;
if (path_equal(p, "/"))
return -EINVAL;
/*
* Turns this:
* /foo/bar/waldo
......@@ -1258,9 +1262,13 @@ int tempfn_random(const char *p, const char *extra, char **ret) {
uint64_t u;
unsigned i;
assert(p);
assert(ret);
if (isempty(p))
return -EINVAL;
if (path_equal(p, "/"))
return -EINVAL;
/*
* Turns this:
* /foo/bar/waldo
......@@ -1319,7 +1327,10 @@ int tempfn_random_child(const char *p, const char *extra, char **ret) {
if (!t)
return -ENOMEM;
x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
if (isempty(p))
x = stpcpy(stpcpy(t, ".#"), extra);
else
x = stpcpy(stpcpy(stpcpy(t, p), "/.#"), extra);
u = random_u64();
for (i = 0; i < 16; i++) {
......@@ -1404,7 +1415,8 @@ int open_tmpfile_unlinkable(const char *directory, int flags) {
r = tmp_dir(&directory);
if (r < 0)
return r;
}
} else if (isempty(directory))
return -EINVAL;
/* Returns an unlinked temporary file that cannot be linked into the file system anymore */
......@@ -1439,22 +1451,14 @@ int open_tmpfile_linkable(const char *target, int flags, char **ret_path) {
* which case "ret_path" will be returned as NULL. If not possible a the tempoary path name used is returned in
* "ret_path". Use link_tmpfile() below to rename the result after writing the file in full. */
{
_cleanup_free_ char *dn = NULL;
dn = dirname_malloc(target);
if (!dn)
return -ENOMEM;
fd = open(dn, O_TMPFILE|flags, 0640);
if (fd >= 0) {
*ret_path = NULL;
return fd;
}
log_debug_errno(errno, "Failed to use O_TMPFILE on %s: %m", dn);
fd = open_parent(target, O_TMPFILE|flags, 0640);
if (fd >= 0) {
*ret_path = NULL;
return fd;
}
log_debug_errno(fd, "Failed to use O_TMPFILE for %s: %m", target);
r = tempfn_random(target, NULL, &tmp);
if (r < 0)
return r;
......
......@@ -435,6 +435,31 @@ int mkfifo_atomic(const char *path, mode_t mode) {
return 0;
}
int mkfifoat_atomic(int dirfd, const char *path, mode_t mode) {
_cleanup_free_ char *t = NULL;
int r;
assert(path);
if (path_is_absolute(path))
return mkfifo_atomic(path, mode);
/* We're only interested in the (random) filename. */
r = tempfn_random_child("", NULL, &t);
if (r < 0)
return r;
if (mkfifoat(dirfd, t, mode) < 0)
return -errno;
if (renameat(dirfd, t, dirfd, path) < 0) {
unlink_noerrno(t);
return -errno;
}
return 0;
}
int get_files_in_directory(const char *path, char ***list) {
_cleanup_closedir_ DIR *d = NULL;
struct dirent *de;
......@@ -670,7 +695,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
if (!original_root && !ret && (flags & (CHASE_NONEXISTENT|CHASE_NO_AUTOFS|CHASE_SAFE|CHASE_OPEN|CHASE_STEP)) == CHASE_OPEN) {
/* Shortcut the CHASE_OPEN case if the caller isn't interested in the actual path and has no root set
* and doesn't care about any of the other special features we provide either. */
r = open(path, O_PATH|O_CLOEXEC);
r = open(path, O_PATH|O_CLOEXEC|((flags & CHASE_NOFOLLOW) ? O_NOFOLLOW : 0));
if (r < 0)
return -errno;
......@@ -825,7 +850,7 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags,
fd_is_fs_type(child, AUTOFS_SUPER_MAGIC) > 0)
return -EREMOTE;
if (S_ISLNK(st.st_mode)) {
if (S_ISLNK(st.st_mode) && !((flags & CHASE_NOFOLLOW) && isempty(todo))) {
char *joined;
_cleanup_free_ char *destination = NULL;
......@@ -1156,7 +1181,7 @@ int unlinkat_deallocate(int fd, const char *name, int flags) {
}
int fsync_directory_of_file(int fd) {
_cleanup_free_ char *path = NULL, *dn = NULL;
_cleanup_free_ char *path = NULL;
_cleanup_close_ int dfd = -1;
int r;
......@@ -1182,16 +1207,40 @@ int fsync_directory_of_file(int fd) {
if (!path_is_absolute(path))
return -EINVAL;
dn = dirname_malloc(path);
if (!dn)
return -ENOMEM;
dfd = open(dn, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
dfd = open_parent(path, O_CLOEXEC, 0);
if (dfd < 0)
return -errno;
return dfd;
if (fsync(dfd) < 0)
return -errno;
return 0;
}
int open_parent(const char *path, int flags, mode_t mode) {
_cleanup_free_ char *parent = NULL;
int fd;
if (isempty(path))
return -EINVAL;
if (path_equal(path, "/")) /* requesting the parent of the root dir is fishy, let's prohibit that */
return -EINVAL;
parent = dirname_malloc(path);
if (!parent)
return -ENOMEM;
/* Let's insist on O_DIRECTORY since the parent of a file or directory is a directory. Except if we open an
* O_TMPFILE file, because in that case we are actually create a regular file below the parent directory. */
if ((flags & O_PATH) == O_PATH)
flags |= O_DIRECTORY;
else if ((flags & O_TMPFILE) != O_TMPFILE)
flags |= O_DIRECTORY|O_RDONLY;
fd = open(parent, flags, mode);
if (fd < 0)
return -errno;
return fd;
}
......@@ -42,6 +42,7 @@ int symlink_idempotent(const char *from, const char *to);
int symlink_atomic(const char *from, const char *to);
int mknod_atomic(const char *path, mode_t mode, dev_t dev);
int mkfifo_atomic(const char *path, mode_t mode);
int mkfifoat_atomic(int dir_fd, const char *path, mode_t mode);
int get_files_in_directory(const char *path, char ***list);
......@@ -72,6 +73,7 @@ enum {
CHASE_OPEN = 1 << 4, /* If set, return an O_PATH object to the final component */
CHASE_TRAIL_SLASH = 1 << 5, /* If set, any trailing slash will be preserved */
CHASE_STEP = 1 << 6, /* If set, just execute a single step of the normalization */
CHASE_NOFOLLOW = 1 << 7, /* Only valid with CHASE_OPEN: when the path's right-most component refers to symlink return O_PATH fd of the symlink, rather than following it. */
};
/* How many iterations to execute before returning -ELOOP */
......@@ -103,3 +105,5 @@ void unlink_tempfilep(char (*p)[]);
int unlinkat_deallocate(int fd, const char *name, int flags);
int fsync_directory_of_file(int fd);
int open_parent(const char *path, int flags, mode_t mode);
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Michal Schmidt
***/
#include <string.h>
......@@ -74,7 +71,7 @@ void trivial_hash_func(const void *p, struct siphash *state) {
}
int trivial_compare_func(const void *a, const void *b) {
return a < b ? -1 : (a > b ? 1 : 0);
return CMP(a, b);
}
const struct hash_ops trivial_hash_ops = {
......@@ -90,7 +87,7 @@ int uint64_compare_func(const void *_a, const void *_b) {
uint64_t a, b;
a = *(const uint64_t*) _a;
b = *(const uint64_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0);
return CMP(a, b);
}
const struct hash_ops uint64_hash_ops = {
......@@ -107,7 +104,7 @@ int devt_compare_func(const void *_a, const void *_b) {
dev_t a, b;
a = *(const dev_t*) _a;
b = *(const dev_t*) _b;
return a < b ? -1 : (a > b ? 1 : 0);
return CMP(a, b);
}
const struct hash_ops devt_hash_ops = {
......
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
Copyright © 2014 Michal Schmidt
***/
#include "macro.h"
#include "siphash24.h"
......
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Michal Schmidt
***/
#include <errno.h>
#include <stdint.h>
......@@ -9,8 +6,9 @@
#include <string.h>
#include "alloc-util.h"
#include "hashmap.h"
#include "env-util.h"
#include "fileio.h"
#include "hashmap.h"
#include "macro.h"
#include "mempool.h"
#include "process-util.h"
......@@ -769,20 +767,31 @@ static void reset_direct_storage(HashmapBase *h) {
memset(p, DIB_RAW_INIT, sizeof(dib_raw_t) * hi->n_direct_buckets);
}
static bool use_pool(void) {
static int b = -1;
if (!is_main_thread())
return false;
if (b < 0)
b = getenv_bool("SYSTEMD_MEMPOOL") != 0;
return b;
}
static struct HashmapBase *hashmap_base_new(const struct hash_ops *hash_ops, enum HashmapType type HASHMAP_DEBUG_PARAMS) {
HashmapBase *h;
const struct hashmap_type_info *hi = &hashmap_type_info[type];
bool use_pool;
bool up;
use_pool = is_main_thread();
h = use_pool ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
up = use_pool();
h = up ? mempool_alloc0_tile(hi->mempool) : malloc0(hi->head_size);
if (!h)
return NULL;
h->type = type;
h->from_pool = use_pool;
h->from_pool = up;
h->hash_ops = hash_ops ? hash_ops : &trivial_hash_ops;
if (type == HASHMAP_TYPE_ORDERED) {
......@@ -860,9 +869,11 @@ static void hashmap_free_no_clear(HashmapBase *h) {
assert_se(pthread_mutex_unlock(&hashmap_debug_list_mutex) == 0);
#endif
if (h->from_pool)
if (h->from_pool) {
/* Ensure that the object didn't get migrated between threads. */
assert_se(is_main_thread());
mempool_free_tile(hashmap_type_info[h->type].mempool, h);
else
} else
free(h);
}
......
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
Copyright © 2014 Michal Schmidt
***/
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
......
......@@ -571,3 +571,26 @@ int in_addr_prefix_from_string_auto(
return 0;
}
void in_addr_data_hash_func(const void *p, struct siphash *state) {
const struct in_addr_data *a = p;
siphash24_compress(&a->family, sizeof(a->family), state);
siphash24_compress(&a->address, FAMILY_ADDRESS_SIZE(a->family), state);
}
int in_addr_data_compare_func(const void *a, const void *b) {
const struct in_addr_data *x = a, *y = b;
int r;
r = CMP(x->family, y->family);
if (r != 0)
return r;
return memcmp(&x->address, &y->address, FAMILY_ADDRESS_SIZE(x->family));
}
const struct hash_ops in_addr_data_hash_ops = {
.hash = in_addr_data_hash_func,
.compare = in_addr_data_compare_func,
};
......@@ -5,6 +5,7 @@
#include <stddef.h>
#include <sys/socket.h>
#include "hash-funcs.h"
#include "macro.h"
#include "util.h"
......@@ -53,3 +54,7 @@ static inline size_t FAMILY_ADDRESS_SIZE(int family) {
}
#define IN_ADDR_NULL ((union in_addr_union) {})
void in_addr_data_hash_func(const void *p, struct siphash *state);
int in_addr_data_compare_func(const void *a, const void *b);
extern const struct hash_ops in_addr_data_hash_ops;
This diff is collapsed.
/* SPDX-License-Identifier: LGPL-2.1+ */
/***
Copyright © 2014 Michal Schmidt
***/
#include <stdint.h>
#include <stdlib.h>
......
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
/***
Copyright © 2014 Michal Schmidt
***/
#include <stddef.h>
struct pool;
......
......@@ -637,6 +637,8 @@ int parse_permille_unbounded(const char *p) {
r = safe_atoi(n, &v);
if (r < 0)
return r;
if (v < 0)
return -ERANGE;
} else {
pc = endswith(p, "%");
if (!pc)
......@@ -657,15 +659,14 @@ int parse_permille_unbounded(const char *p) {
r = safe_atoi(n, &v);
if (r < 0)
return r;
if (v < 0)
return -ERANGE;
if (v > (INT_MAX - q) / 10)
return -ERANGE;
v = v * 10 + q;
}
if (v < 0)
return -ERANGE;
return v;
}
......
......@@ -110,10 +110,7 @@ int path_make_absolute_cwd(const char *p, char **ret) {
if (r < 0)
return r;
if (endswith(cwd, "/"))
c = strjoin(cwd, p);
else
c = strjoin(cwd, "/", p);
c = path_join(NULL, cwd, p);
}
if (!c)
return -ENOMEM;
......
......@@ -58,10 +58,10 @@ static inline bool path_equal_ptr(const char *a, const char *b) {
/* Note: the search terminates on the first NULL item. */
#define PATH_IN_SET(p, ...) \
({ \
char **s; \
char **_s; \
bool _found = false; \
STRV_FOREACH(s, STRV_MAKE(__VA_ARGS__)) \
if (path_equal(p, *s)) { \
STRV_FOREACH(_s, STRV_MAKE(__VA_ARGS__)) \
if (path_equal(p, *_s)) { \
_found = true; \
break; \
} \
......
......@@ -1108,12 +1108,7 @@ int pid_compare_func(const void *a, const void *b) {
const pid_t *p = a, *q = b;
/* Suitable for usage in qsort() */
if (*p < *q)
return -1;
if (*p > *q)
return 1;
return 0;
return CMP(*p, *q);
}
int ioprio_parse_priority(const char *s, int *ret) {
......@@ -1153,7 +1148,7 @@ void reset_cached_pid(void) {
/* We use glibc __register_atfork() + __dso_handle directly here, as they are not included in the glibc
* headers. __register_atfork() is mostly equivalent to pthread_atfork(), but doesn't require us to link against
* libpthread, as it is part of glibc anyway. */
extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void * __dso_handle);
extern int __register_atfork(void (*prepare) (void), void (*parent) (void), void (*child) (void), void *dso_handle);
extern void* __dso_handle __attribute__ ((__weak__));
pid_t getpid_cached(void) {
......
/* SPDX-License-Identifier: LGPL-2.1+ */
#ifdef __x86_64__
#include <cpuid.h>
#endif
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
......@@ -26,6 +30,41 @@
#include "random-util.h"
#include "time-util.h"
int rdrand64(uint64_t *ret) {
#ifdef __x86_64__
static int have_rdrand = -1;
unsigned char err;
if (have_rdrand < 0) {
uint32_t eax, ebx, ecx, edx;
/* Check if RDRAND is supported by the CPU */
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0) {
have_rdrand = false;
return -EOPNOTSUPP;
}
have_rdrand = !!(ecx & (1U << 30));
}
if (have_rdrand == 0)
return -EOPNOTSUPP;
asm volatile("rdrand %0;"
"setc %1"
: "=r" (*ret),
"=qm" (err));
if (!err)
return -EAGAIN;
return 0;
#else
return -EOPNOTSUPP;
#endif
}
int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
static int have_syscall = -1;
......@@ -68,8 +107,26 @@ int acquire_random_bytes(void *p, size_t n, bool high_quality_required) {
* a best-effort basis. */
have_syscall = true;
if (!high_quality_required)
return -ENODATA;
if (!high_quality_required) {
uint64_t u;
size_t k;
/* 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 invocatins or so. That's because we don't really care about the
* quality here. */
if (rdrand64(&u) < 0)
return -ENODATA;
k = MIN(n, sizeof(u));
memcpy(p, &u, k);
/* We only get 64bit out of RDRAND, the rest let's fill up with pseudo-random crap. */
pseudorandom_bytes((uint8_t*) p + k, n - k);
return 0;
}
} else
return -errno;