mirror of
https://github.com/systemd/systemd.git
synced 2025-02-24 17:57:34 +03:00
Merge pull request #27137 from yuwata/id128-get-machine
sd-id128: introduce id128_get_machine() and _at()
This commit is contained in:
commit
78ebf8bfb6
@ -162,10 +162,7 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
|
||||
/* If we get AT_FDCWD or dir_fd points to "/", then we always resolve symlinks relative to
|
||||
* the host's root. Hence, CHASE_AT_RESOLVE_IN_ROOT is meaningless. */
|
||||
|
||||
if (dir_fd >= 0)
|
||||
r = dir_fd_is_root(dir_fd);
|
||||
else
|
||||
r = true;
|
||||
r = dir_fd_is_root_or_cwd(dir_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
@ -101,6 +102,9 @@ int read_nr_open(void);
|
||||
int fd_get_diskseq(int fd, uint64_t *ret);
|
||||
|
||||
int dir_fd_is_root(int dir_fd);
|
||||
static inline int dir_fd_is_root_or_cwd(int dir_fd) {
|
||||
return dir_fd == AT_FDCWD ? true : dir_fd_is_root(dir_fd);
|
||||
}
|
||||
|
||||
/* The maximum length a buffer for a /proc/self/fd/<fd> path needs */
|
||||
#define PROC_FD_PATH_MAX \
|
||||
|
@ -43,6 +43,7 @@ bool id128_is_valid(const char *s) {
|
||||
|
||||
int id128_read_fd(int fd, Id128Flag f, sd_id128_t *ret) {
|
||||
char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */
|
||||
sd_id128_t id;
|
||||
ssize_t l;
|
||||
int r;
|
||||
|
||||
@ -98,8 +99,18 @@ int id128_read_fd(int fd, Id128Flag f, sd_id128_t *ret) {
|
||||
return -EUCLEAN;
|
||||
}
|
||||
|
||||
r = sd_id128_from_string(buffer, ret);
|
||||
return r == -EINVAL ? -EUCLEAN : r;
|
||||
r = sd_id128_from_string(buffer, &id);
|
||||
if (r == -EINVAL)
|
||||
return -EUCLEAN;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (FLAGS_SET(f, ID128_REFUSE_NULL) && sd_id128_is_null(id))
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (ret)
|
||||
*ret = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int id128_read_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t *ret) {
|
||||
@ -123,6 +134,9 @@ int id128_write_fd(int fd, Id128Flag f, sd_id128_t id) {
|
||||
assert(fd >= 0);
|
||||
assert(IN_SET((f & ID128_FORMAT_ANY), ID128_FORMAT_PLAIN, ID128_FORMAT_UUID));
|
||||
|
||||
if (FLAGS_SET(f, ID128_REFUSE_NULL) && sd_id128_is_null(id))
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (FLAGS_SET(f, ID128_FORMAT_PLAIN)) {
|
||||
assert_se(sd_id128_to_string(id, buffer));
|
||||
sz = SD_ID128_STRING_MAX;
|
||||
|
@ -17,6 +17,7 @@ typedef enum Id128Flag {
|
||||
ID128_FORMAT_ANY = ID128_FORMAT_PLAIN | ID128_FORMAT_UUID,
|
||||
|
||||
ID128_SYNC_ON_WRITE = 1 << 2, /* Sync the file after write. Used only when writing an ID. */
|
||||
ID128_REFUSE_NULL = 1 << 3, /* Refuse all zero ID with -ENOMEDIUM. */
|
||||
} Id128Flag;
|
||||
|
||||
int id128_read_fd(int fd, Id128Flag f, sd_id128_t *ret);
|
||||
@ -31,6 +32,9 @@ static inline int id128_write(const char *path, Id128Flag f, sd_id128_t id) {
|
||||
return id128_write_at(AT_FDCWD, path, f, id);
|
||||
}
|
||||
|
||||
int id128_get_machine(const char *root, sd_id128_t *ret);
|
||||
int id128_get_machine_at(int rfd, sd_id128_t *ret);
|
||||
|
||||
void id128_hash_func(const sd_id128_t *p, struct siphash *state);
|
||||
int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_;
|
||||
extern const struct hash_ops id128_hash_ops;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "chase.h"
|
||||
#include "fd-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "hmac.h"
|
||||
@ -15,6 +16,7 @@
|
||||
#include "macro.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "missing_threads.h"
|
||||
#include "path-util.h"
|
||||
#include "random-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "user-util.h"
|
||||
@ -126,12 +128,9 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
|
||||
int r;
|
||||
|
||||
if (sd_id128_is_null(saved_machine_id)) {
|
||||
r = id128_read("/etc/machine-id", ID128_FORMAT_PLAIN, &saved_machine_id);
|
||||
r = id128_read("/etc/machine-id", ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, &saved_machine_id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sd_id128_is_null(saved_machine_id))
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
@ -139,19 +138,48 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int id128_get_machine_at(int rfd, sd_id128_t *ret) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int r;
|
||||
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
|
||||
r = dir_fd_is_root_or_cwd(rfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return sd_id128_get_machine(ret);
|
||||
|
||||
fd = chase_and_openat(rfd, "/etc/machine-id", CHASE_AT_RESOLVE_IN_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
return id128_read_fd(fd, ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, ret);
|
||||
}
|
||||
|
||||
int id128_get_machine(const char *root, sd_id128_t *ret) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
if (empty_or_root(root))
|
||||
return sd_id128_get_machine(ret);
|
||||
|
||||
fd = chase_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
return id128_read_fd(fd, ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, ret);
|
||||
}
|
||||
|
||||
_public_ int sd_id128_get_boot(sd_id128_t *ret) {
|
||||
static thread_local sd_id128_t saved_boot_id = {};
|
||||
int r;
|
||||
|
||||
if (sd_id128_is_null(saved_boot_id)) {
|
||||
r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID, &saved_boot_id);
|
||||
r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID | ID128_REFUSE_NULL, &saved_boot_id);
|
||||
if (r == -ENOENT && proc_mounted() == 0)
|
||||
return -ENOSYS;
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sd_id128_is_null(saved_boot_id))
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
|
||||
if (ret)
|
||||
|
@ -158,14 +158,11 @@ static int run(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
if (arg_commit) {
|
||||
const char *etc_machine_id;
|
||||
|
||||
r = machine_id_commit(arg_root);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
|
||||
r = id128_read(etc_machine_id, ID128_FORMAT_PLAIN, &id);
|
||||
r = id128_get_machine(arg_root, &id);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read machine ID back: %m");
|
||||
} else {
|
||||
|
@ -2828,8 +2828,6 @@ static int mount_tunnel_open(void) {
|
||||
}
|
||||
|
||||
static int setup_machine_id(const char *directory) {
|
||||
const char *etc_machine_id;
|
||||
sd_id128_t id;
|
||||
int r;
|
||||
|
||||
/* If the UUID in the container is already set, then that's what counts, and we use. If it isn't set, and the
|
||||
@ -2839,9 +2837,7 @@ static int setup_machine_id(const char *directory) {
|
||||
* in the container and our idea of the container UUID will always be in sync (at least if PID 1 in the
|
||||
* container behaves nicely). */
|
||||
|
||||
etc_machine_id = prefix_roota(directory, "/etc/machine-id");
|
||||
|
||||
r = id128_read(etc_machine_id, ID128_FORMAT_PLAIN, &id);
|
||||
r = id128_get_machine(directory, &arg_uuid);
|
||||
if (r < 0) {
|
||||
if (!ERRNO_IS_MACHINE_ID_UNSET(r)) /* If the file is missing, empty, or uninitialized, we don't mind */
|
||||
return log_error_errno(r, "Failed to read machine ID from container image: %m");
|
||||
@ -2851,12 +2847,6 @@ static int setup_machine_id(const char *directory) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to acquire randomized machine UUID: %m");
|
||||
}
|
||||
} else {
|
||||
if (sd_id128_is_null(id))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Machine ID in container image is zero, refusing.");
|
||||
|
||||
arg_uuid = id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -4909,24 +4909,14 @@ static int context_read_seed(Context *context, const char *root) {
|
||||
return 0;
|
||||
|
||||
if (!arg_randomize) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
fd = chase_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC, NULL);
|
||||
if (fd == -ENOENT)
|
||||
log_info("No machine ID set, using randomized partition UUIDs.");
|
||||
else if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to determine machine ID of image: %m");
|
||||
else {
|
||||
r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &context->seed);
|
||||
if (r < 0) {
|
||||
if (!ERRNO_IS_MACHINE_ID_UNSET(r))
|
||||
return log_error_errno(r, "Failed to parse machine ID of image: %m");
|
||||
|
||||
log_info("No machine ID set, using randomized partition UUIDs.");
|
||||
}
|
||||
|
||||
r = id128_get_machine(root, &context->seed);
|
||||
if (r >= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ERRNO_IS_MACHINE_ID_UNSET(r))
|
||||
return log_error_errno(r, "Failed to parse machine ID of image: %m");
|
||||
|
||||
log_info("No machine ID set, using randomized partition UUIDs.");
|
||||
}
|
||||
|
||||
r = sd_id128_randomize(&context->seed);
|
||||
|
@ -1173,23 +1173,9 @@ int image_read_metadata(Image *i) {
|
||||
|
||||
path = mfree(path);
|
||||
|
||||
r = chase("/etc/machine-id", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
log_debug_errno(r, "Failed to chase /etc/machine-id in image %s: %m", i->name);
|
||||
else if (r >= 0) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
log_debug_errno(errno, "Failed to open %s: %m", path);
|
||||
else {
|
||||
r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &machine_id);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Image %s contains invalid machine ID.", i->name);
|
||||
}
|
||||
}
|
||||
|
||||
path = mfree(path);
|
||||
r = id128_get_machine(i->path, &machine_id);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to read machine ID in image %s, ignoring: %m", i->name);
|
||||
|
||||
r = chase("/etc/machine-info", i->path, CHASE_PREFIX_ROOT|CHASE_TRAIL_SLASH, &path, NULL);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
|
@ -444,10 +444,7 @@ int find_esp_and_warn_at(
|
||||
|
||||
assert(rfd >= 0 || rfd == AT_FDCWD);
|
||||
|
||||
if (rfd >= 0)
|
||||
r = dir_fd_is_root(rfd);
|
||||
else
|
||||
r = true;
|
||||
r = dir_fd_is_root_or_cwd(rfd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to check if directory file descriptor is root: %m");
|
||||
if (r == 0)
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "sd-id128.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "chase.h"
|
||||
#include "fd-util.h"
|
||||
#include "id128-util.h"
|
||||
#include "io-util.h"
|
||||
@ -27,22 +28,16 @@
|
||||
#include "virt.h"
|
||||
|
||||
static int generate_machine_id(const char *root, sd_id128_t *ret) {
|
||||
const char *dbus_machine_id;
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
|
||||
/* First, try reading the D-Bus machine id, unless it is a symlink */
|
||||
dbus_machine_id = prefix_roota(root, "/var/lib/dbus/machine-id");
|
||||
fd = open(dbus_machine_id, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
|
||||
if (fd >= 0) {
|
||||
if (id128_read_fd(fd, ID128_FORMAT_PLAIN, ret) >= 0) {
|
||||
log_info("Initializing machine ID from D-Bus machine ID.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = safe_close(fd);
|
||||
fd = chase_and_open("/var/lib/dbus/machine-id", root, CHASE_PREFIX_ROOT | CHASE_NOFOLLOW, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
if (fd >= 0 && id128_read_fd(fd, ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, ret) >= 0) {
|
||||
log_info("Initializing machine ID from D-Bus machine ID.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isempty(root) && running_in_chroot() <= 0) {
|
||||
|
@ -187,19 +187,9 @@ int specifier_machine_id(char specifier, const void *data, const char *root, con
|
||||
|
||||
assert(ret);
|
||||
|
||||
if (root) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
|
||||
fd = chase_and_open("/etc/machine-id", root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_NOCTTY, NULL);
|
||||
if (fd < 0)
|
||||
/* Translate error for missing os-release file to EUNATCH. */
|
||||
return fd == -ENOENT ? -EUNATCH : fd;
|
||||
|
||||
r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &id);
|
||||
} else
|
||||
r = sd_id128_get_machine(&id);
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = id128_get_machine(root, &id);
|
||||
if (r < 0) /* Translate error for missing /etc/machine-id file to EUNATCH. */
|
||||
return r == -ENOENT ? -EUNATCH : r;
|
||||
|
||||
return specifier_id128(specifier, &id, root, userdata, ret);
|
||||
}
|
||||
|
@ -287,6 +287,36 @@ TEST(id128_at) {
|
||||
i = SD_ID128_NULL;
|
||||
assert_se(id128_read(p, ID128_FORMAT_PLAIN, &i) >= 0);
|
||||
assert_se(sd_id128_equal(id, i));
|
||||
|
||||
/* id128_get_machine_at() */
|
||||
i = SD_ID128_NULL;
|
||||
assert_se(id128_get_machine_at(tfd, &i) >= 0);
|
||||
assert_se(sd_id128_equal(id, i));
|
||||
|
||||
/* id128_get_machine() */
|
||||
i = SD_ID128_NULL;
|
||||
assert_se(id128_get_machine(t, &i) >= 0);
|
||||
assert_se(sd_id128_equal(id, i));
|
||||
}
|
||||
|
||||
TEST(ID128_REFUSE_NULL) {
|
||||
_cleanup_(rm_rf_physical_and_freep) char *t = NULL;
|
||||
_cleanup_close_ int tfd = -EBADF;
|
||||
sd_id128_t id;
|
||||
|
||||
tfd = mkdtemp_open(NULL, O_PATH, &t);
|
||||
assert_se(tfd >= 0);
|
||||
|
||||
assert_se(id128_write_at(tfd, "zero-id", ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, (sd_id128_t) {}) == -ENOMEDIUM);
|
||||
assert_se(unlinkat(tfd, "zero-id", 0) >= 0);
|
||||
assert_se(id128_write_at(tfd, "zero-id", ID128_FORMAT_PLAIN, (sd_id128_t) {}) >= 0);
|
||||
|
||||
assert_se(sd_id128_randomize(&id) == 0);
|
||||
assert_se(!sd_id128_equal(id, SD_ID128_NULL));
|
||||
assert_se(id128_read_at(tfd, "zero-id", ID128_FORMAT_PLAIN, &id) >= 0);
|
||||
assert_se(sd_id128_equal(id, SD_ID128_NULL));
|
||||
|
||||
assert_se(id128_read_at(tfd, "zero-id", ID128_FORMAT_PLAIN | ID128_REFUSE_NULL, &id) == -ENOMEDIUM);
|
||||
}
|
||||
|
||||
DEFINE_TEST_MAIN(LOG_INFO);
|
||||
|
@ -136,7 +136,7 @@ TEST(specifiers) {
|
||||
xsprintf(spec, "%%%c", s->specifier);
|
||||
|
||||
r = specifier_printf(spec, SIZE_MAX, specifier_table, NULL, NULL, &resolved);
|
||||
if (s->specifier == 'm' && IN_SET(r, -ENOENT, -ENOMEDIUM)) /* machine-id might be missing in build chroots */
|
||||
if (s->specifier == 'm' && IN_SET(r, -EUNATCH, -ENOMEDIUM)) /* machine-id might be missing in build chroots */
|
||||
continue;
|
||||
assert_se(r >= 0);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user