New upstream version 252.4

This commit is contained in:
Luca Boccassi 2022-12-22 12:21:57 +01:00
parent 9fe6880f6c
commit a68108222d
41 changed files with 726 additions and 324 deletions

View File

@ -54,6 +54,13 @@ jobs:
- uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
- uses: systemd/mkosi@792cbc60eb2dc4a58d66bb3c212bf92f8d50f6ea
# FIXME: temporary workaround for a file conflict between systemd (C9S) and
# systemd-boot (EPEL9). Drop this once systemd in C9S is updated to v252
# (should be done by the end of 2022).
- name: Fix C9S/EPEL9
if: ${{ matrix.release == '9-stream' }}
run: sudo sed -i '/add_packages/s/systemd-boot/systemd/g' /usr/local/lib/python3.10/dist-packages/mkosi/__init__.py
- name: Install
run: sudo apt-get update && sudo apt-get install --no-install-recommends python3-pexpect python3-jinja2

View File

@ -4,8 +4,8 @@
# Docs: https://packit.dev/docs/
specfile_path: .packit_rpm/systemd.spec
synced_files:
- .packit.yaml
files_to_sync:
- .packit.yml
- src: .packit_rpm/systemd.spec
dest: systemd.spec
upstream_package_name: systemd
@ -32,14 +32,15 @@ actions:
# [0] https://github.com/mesonbuild/meson/issues/7360
# [1] https://github.com/systemd/systemd/pull/18908#issuecomment-792250110
- 'sed -i "/^CONFIGURE_OPTS=(/a--werror" .packit_rpm/systemd.spec'
# Ignore unpackages standalone binaries
- "sed -i 's/assert False,.*/pass/' .packit_rpm/split-files.py"
jobs:
- job: copr_build
trigger: pull_request
metadata:
targets:
- fedora-rawhide-aarch64
- fedora-rawhide-i386
- fedora-rawhide-ppc64le
- fedora-rawhide-s390x
- fedora-rawhide-x86_64
targets:
- fedora-rawhide-aarch64
- fedora-rawhide-i386
- fedora-rawhide-ppc64le
- fedora-rawhide-s390x
- fedora-rawhide-x86_64

View File

@ -268,6 +268,13 @@ All tools:
it is either set to `system` or `user` depending on whether the NSS/PAM
module is called by systemd in `--system` or `--user` mode.
* `$SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST` — can be set to override the mount
units burst rate limit for parsing `/proc/self/mountinfo`. On a system with
few resources but many mounts the rate limit may be hit, which will cause the
processing of mount units to stall. The burst limit may be adjusted when the
default is not appropriate for a given system. Defaults to `5`, accepts
positive integers.
`systemd-remount-fs`:
* `$SYSTEMD_REMOUNT_ROOT_RW=1` — if set and no entry for the root directory

View File

@ -13,7 +13,7 @@ Packages=
fdisk
iproute2
isc-dhcp-server
libbpf0
libbpf1
libfido2-1
libglib2.0-0
libgnutls30

View File

@ -3,23 +3,28 @@
ACTION=="remove", GOTO="evdev_end"
KERNEL!="event*", GOTO="evdev_end"
# skip later rules when we find something for this input device
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:", \
IMPORT{builtin}="keyboard", GOTO="evdev_end"
# Execute the match patterns below, from least-to-most specific.
# Device matching the modalias string (bustype, vendor, product, version, other properties)
IMPORT{builtin}="hwdb --subsystem=input --lookup-prefix=evdev:",
ENV{.HAVE_HWDB_PROPERTIES}="1"
# AT keyboard matching by the machine's DMI data
DRIVERS=="atkbd", \
IMPORT{builtin}="hwdb 'evdev:atkbd:$attr{[dmi/id]modalias}'", \
IMPORT{builtin}="keyboard", GOTO="evdev_end"
ENV{.HAVE_HWDB_PROPERTIES}="1"
# device matching the input device name + properties + the machine's DMI data
KERNELS=="input*", \
IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:phys:$attr{phys}:ev:$attr{capabilities/ev}:$attr{[dmi/id]modalias}'", \
IMPORT{builtin}="keyboard", GOTO="evdev_end"
# device matching the input device name and the machine's DMI data
# Device matching the input device name and the machine's DMI data
KERNELS=="input*", \
IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:$attr{[dmi/id]modalias}'", \
IMPORT{builtin}="keyboard", GOTO="evdev_end"
ENV{.HAVE_HWDB_PROPERTIES}="1"
# Device matching the input device name + properties + the machine's DMI data
KERNELS=="input*", \
IMPORT{builtin}="hwdb 'evdev:name:$attr{name}:phys:$attr{phys}:ev:$attr{capabilities/ev}:$attr{[dmi/id]modalias}'", \
ENV{.HAVE_HWDB_PROPERTIES}="1"
ENV{.HAVE_HWDB_PROPERTIES}=="1", \
IMPORT{builtin}="keyboard"
LABEL="evdev_end"

View File

@ -9,15 +9,15 @@ bool emoji_enabled(void) {
static int cached_emoji_enabled = -1;
if (cached_emoji_enabled < 0) {
int val;
int val = getenv_bool("SYSTEMD_EMOJI");
if (val >= 0)
return (cached_emoji_enabled = val);
val = getenv_bool("SYSTEMD_EMOJI");
if (val < 0)
cached_emoji_enabled =
is_locale_utf8() &&
!STRPTR_IN_SET(getenv("TERM"), "dumb", "linux");
else
cached_emoji_enabled = val;
const char *term = getenv("TERM");
if (!term || STR_IN_SET(term, "dumb", "linux"))
return (cached_emoji_enabled = false);
cached_emoji_enabled = is_locale_utf8();
}
return cached_emoji_enabled;

View File

@ -91,7 +91,16 @@ struct iovec_wrapper *iovw_new(void);
struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw);
struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw);
void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors);
int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len);
static inline int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) {
/* Move data into iovw or free on error */
int r = iovw_put(iovw, data, len);
if (r < 0)
free(data);
return r;
}
int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value);
int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value);
void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new);

View File

@ -179,7 +179,7 @@ static int load_etc_machine_id(void) {
int r;
r = sd_id128_get_machine(&arg_machine_id);
if (IN_SET(r, -ENOENT, -ENOMEDIUM)) /* Not set or empty */
if (IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG)) /* Not set or empty */
return 0;
if (r < 0)
return log_error_errno(r, "Failed to get machine-id: %m");

View File

@ -4158,7 +4158,7 @@ int compare_job_priority(const void *a, const void *b) {
int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
_cleanup_free_ char *path = NULL;
FreezerState target, kernel = _FREEZER_STATE_INVALID;
int r;
int r, ret;
assert(u);
assert(IN_SET(action, FREEZER_FREEZE, FREEZER_THAW));
@ -4166,9 +4166,23 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
if (!cg_freezer_supported())
return 0;
/* Ignore all requests to thaw init.scope or -.slice and reject all requests to freeze them */
if (unit_has_name(u, SPECIAL_ROOT_SLICE) || unit_has_name(u, SPECIAL_INIT_SCOPE))
return action == FREEZER_FREEZE ? -EPERM : 0;
if (!u->cgroup_realized)
return -EBUSY;
if (action == FREEZER_THAW) {
Unit *slice = UNIT_GET_SLICE(u);
if (slice) {
r = unit_cgroup_freezer_action(slice, FREEZER_THAW);
if (r < 0)
return log_unit_error_errno(u, r, "Failed to thaw slice %s of unit: %m", slice->id);
}
}
target = action == FREEZER_FREEZE ? FREEZER_FROZEN : FREEZER_RUNNING;
r = unit_freezer_state_kernel(u, &kernel);
@ -4177,8 +4191,11 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
if (target == kernel) {
u->freezer_state = target;
return 0;
}
if (action == FREEZER_FREEZE)
return 0;
ret = 0;
} else
ret = 1;
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.freeze", &path);
if (r < 0)
@ -4186,16 +4203,18 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
log_unit_debug(u, "%s unit.", action == FREEZER_FREEZE ? "Freezing" : "Thawing");
if (action == FREEZER_FREEZE)
u->freezer_state = FREEZER_FREEZING;
else
u->freezer_state = FREEZER_THAWING;
if (target != kernel) {
if (action == FREEZER_FREEZE)
u->freezer_state = FREEZER_FREEZING;
else
u->freezer_state = FREEZER_THAWING;
}
r = write_string_file(path, one_zero(action == FREEZER_FREEZE), WRITE_STRING_FILE_DISABLE_BUFFER);
if (r < 0)
return r;
return 1;
return ret;
}
int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {

View File

@ -782,14 +782,15 @@ static int bus_unit_method_freezer_generic(sd_bus_message *message, void *userda
if (r == 0)
reply_no_delay = true;
assert(!u->pending_freezer_message);
if (u->pending_freezer_message) {
bus_unit_send_pending_freezer_message(u, true);
assert(!u->pending_freezer_message);
}
r = sd_bus_message_new_method_return(message, &u->pending_freezer_message);
if (r < 0)
return r;
u->pending_freezer_message = sd_bus_message_ref(message);
if (reply_no_delay) {
r = bus_unit_send_pending_freezer_message(u);
r = bus_unit_send_pending_freezer_message(u, false);
if (r < 0)
return r;
}
@ -1661,7 +1662,8 @@ void bus_unit_send_pending_change_signal(Unit *u, bool including_new) {
bus_unit_send_change_signal(u);
}
int bus_unit_send_pending_freezer_message(Unit *u) {
int bus_unit_send_pending_freezer_message(Unit *u, bool cancelled) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
int r;
assert(u);
@ -1669,7 +1671,18 @@ int bus_unit_send_pending_freezer_message(Unit *u) {
if (!u->pending_freezer_message)
return 0;
r = sd_bus_send(NULL, u->pending_freezer_message, NULL);
if (cancelled)
r = sd_bus_message_new_method_error(
u->pending_freezer_message,
&reply,
&SD_BUS_ERROR_MAKE_CONST(
BUS_ERROR_FREEZE_CANCELLED, "Freeze operation aborted"));
else
r = sd_bus_message_new_method_return(u->pending_freezer_message, &reply);
if (r < 0)
return r;
r = sd_bus_send(NULL, reply, NULL);
if (r < 0)
log_warning_errno(r, "Failed to send queued message, ignoring: %m");

View File

@ -10,7 +10,7 @@ extern const sd_bus_vtable bus_unit_cgroup_vtable[];
void bus_unit_send_change_signal(Unit *u);
void bus_unit_send_pending_change_signal(Unit *u, bool including_new);
int bus_unit_send_pending_freezer_message(Unit *u);
int bus_unit_send_pending_freezer_message(Unit *u, bool cancelled);
void bus_unit_send_removed_signal(Unit *u);
int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error);

View File

@ -2662,6 +2662,7 @@ static int load_credential(
assert(id);
assert(path);
assert(unit);
assert(read_dfd >= 0 || read_dfd == AT_FDCWD);
assert(write_dfd >= 0);
assert(left);
@ -2888,7 +2889,7 @@ static int acquire_credentials(
lc->path,
lc->encrypted,
unit,
-1,
AT_FDCWD,
dfd,
uid,
ownership_ok,

View File

@ -1908,6 +1908,7 @@ static void mount_enumerate(Manager *m) {
mnt_init_debug(0);
if (!m->mount_monitor) {
unsigned mount_rate_limit_burst = 5;
int fd;
m->mount_monitor = mnt_new_monitor();
@ -1947,7 +1948,15 @@ static void mount_enumerate(Manager *m) {
goto fail;
}
r = sd_event_source_set_ratelimit(m->mount_event_source, 1 * USEC_PER_SEC, 5);
/* Let users override the default (5 in 1s), as it stalls the boot sequence on busy systems. */
const char *e = secure_getenv("SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST");
if (e) {
r = safe_atou(e, &mount_rate_limit_burst);
if (r < 0)
log_debug("Invalid value in $SYSTEMD_DEFAULT_MOUNT_RATE_LIMIT_BURST, ignoring: %s", e);
}
r = sd_event_source_set_ratelimit(m->mount_event_source, 1 * USEC_PER_SEC, mount_rate_limit_burst);
if (r < 0) {
log_error_errno(r, "Failed to enable rate limit for mount events: %m");
goto fail;

View File

@ -937,29 +937,17 @@ static int unit_reserve_dependencies(Unit *u, Unit *other) {
return 0;
}
static void unit_maybe_warn_about_dependency(
Unit *u,
const char *other_id,
UnitDependency dependency) {
assert(u);
static bool unit_should_warn_about_dependency(UnitDependency dependency) {
/* Only warn about some unit types */
if (!IN_SET(dependency,
UNIT_CONFLICTS,
UNIT_CONFLICTED_BY,
UNIT_BEFORE,
UNIT_AFTER,
UNIT_ON_SUCCESS,
UNIT_ON_FAILURE,
UNIT_TRIGGERS,
UNIT_TRIGGERED_BY))
return;
if (streq_ptr(u->id, other_id))
log_unit_warning(u, "Dependency %s=%s dropped", unit_dependency_to_string(dependency), u->id);
else
log_unit_warning(u, "Dependency %s=%s dropped, merged into %s", unit_dependency_to_string(dependency), strna(other_id), u->id);
return IN_SET(dependency,
UNIT_CONFLICTS,
UNIT_CONFLICTED_BY,
UNIT_BEFORE,
UNIT_AFTER,
UNIT_ON_SUCCESS,
UNIT_ON_FAILURE,
UNIT_TRIGGERS,
UNIT_TRIGGERED_BY);
}
static int unit_per_dependency_type_hashmap_update(
@ -1044,11 +1032,10 @@ static int unit_add_dependency_hashmap(
return unit_per_dependency_type_hashmap_update(per_type, other, origin_mask, destination_mask);
}
static void unit_merge_dependencies(
Unit *u,
Unit *other) {
int r;
static void unit_merge_dependencies(Unit *u, Unit *other) {
Hashmap *deps;
void *dt; /* Actually of type UnitDependency, except that we don't bother casting it here,
* since the hashmaps all want it as void pointer. */
assert(u);
assert(other);
@ -1056,18 +1043,29 @@ static void unit_merge_dependencies(
if (u == other)
return;
/* First, remove dependency to other. */
HASHMAP_FOREACH_KEY(deps, dt, u->dependencies) {
if (hashmap_remove(deps, other) && unit_should_warn_about_dependency(UNIT_DEPENDENCY_FROM_PTR(dt)))
log_unit_warning(u, "Dependency %s=%s is dropped, as %s is merged into %s.",
unit_dependency_to_string(UNIT_DEPENDENCY_FROM_PTR(dt)),
other->id, other->id, u->id);
if (hashmap_isempty(deps))
hashmap_free(hashmap_remove(u->dependencies, dt));
}
for (;;) {
_cleanup_(hashmap_freep) Hashmap *other_deps = NULL;
UnitDependencyInfo di_back;
Unit *back;
void *dt; /* Actually of type UnitDependency, except that we don't bother casting it here,
* since the hashmaps all want it as void pointer. */
/* Let's focus on one dependency type at a time, that 'other' has defined. */
other_deps = hashmap_steal_first_key_and_value(other->dependencies, &dt);
if (!other_deps)
break; /* done! */
deps = hashmap_get(u->dependencies, dt);
/* Now iterate through all dependencies of this dependency type, of 'other'. We refer to the
* referenced units as 'back'. */
HASHMAP_FOREACH_KEY(di_back.data, back, other_deps) {
@ -1077,7 +1075,12 @@ static void unit_merge_dependencies(
if (back == u) {
/* This is a dependency pointing back to the unit we want to merge with?
* Suppress it (but warn) */
unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
if (unit_should_warn_about_dependency(UNIT_DEPENDENCY_FROM_PTR(dt)))
log_unit_warning(u, "Dependency %s=%s in %s is dropped, as %s is merged into %s.",
unit_dependency_to_string(UNIT_DEPENDENCY_FROM_PTR(dt)),
u->id, other->id, other->id, u->id);
hashmap_remove(other_deps, back);
continue;
}
@ -1096,41 +1099,21 @@ static void unit_merge_dependencies(
di_move.origin_mask,
di_move.destination_mask) >= 0);
}
}
/* Now all references towards 'other' of the current type 'dt' are corrected to point to
* 'u'. Lets's now move the deps of type 'dt' from 'other' to 'u'. First, let's try to move
* them per type wholesale. */
r = hashmap_put(u->dependencies, dt, other_deps);
if (r == -EEXIST) {
Hashmap *deps;
/* The target unit already has dependencies of this type, let's then merge this individually. */
assert_se(deps = hashmap_get(u->dependencies, dt));
for (;;) {
UnitDependencyInfo di_move;
/* Get first dep */
di_move.data = hashmap_steal_first_key_and_value(other_deps, (void**) &back);
if (!di_move.data)
break; /* done */
if (back == u) {
/* Would point back to us, ignore */
unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
continue;
}
assert_se(unit_per_dependency_type_hashmap_update(deps, back, di_move.origin_mask, di_move.destination_mask) >= 0);
}
} else {
assert_se(r >= 0);
TAKE_PTR(other_deps);
if (hashmap_remove(other_deps, u))
unit_maybe_warn_about_dependency(u, other->id, UNIT_DEPENDENCY_FROM_PTR(dt));
if (deps)
assert_se(unit_per_dependency_type_hashmap_update(
deps,
back,
di_back.origin_mask,
di_back.destination_mask) >= 0);
}
/* Now all references towards 'other' of the current type 'dt' are corrected to point to 'u'.
* Lets's now move the deps of type 'dt' from 'other' to 'u'. If the unit does not have
* dependencies of this type, let's move them per type wholesale. */
if (!deps)
assert_se(hashmap_put(u->dependencies, dt, TAKE_PTR(other_deps)) >= 0);
}
other->dependencies = hashmap_free(other->dependencies);
@ -1176,11 +1159,6 @@ int unit_merge(Unit *u, Unit *other) {
if (r < 0)
return r;
/* Merge names */
r = unit_merge_names(u, other);
if (r < 0)
return r;
/* Redirect all references */
while (other->refs_by_target)
unit_ref_set(other->refs_by_target, other->refs_by_target->source, u);
@ -1188,6 +1166,11 @@ int unit_merge(Unit *u, Unit *other) {
/* Merge dependencies */
unit_merge_dependencies(u, other);
/* Merge names. It is better to do that after merging deps, otherwise the log message contains n/a. */
r = unit_merge_names(u, other);
if (r < 0)
return r;
other->load_state = UNIT_MERGED;
other->merged_into = u;
@ -3066,7 +3049,6 @@ int unit_add_dependency(
[UNIT_IN_SLICE] = UNIT_SLICE_OF,
[UNIT_SLICE_OF] = UNIT_IN_SLICE,
};
Unit *original_u = u, *original_other = other;
UnitDependencyAtom a;
int r;
@ -3085,7 +3067,9 @@ int unit_add_dependency(
/* We won't allow dependencies on ourselves. We will not consider them an error however. */
if (u == other) {
unit_maybe_warn_about_dependency(original_u, original_other->id, d);
if (unit_should_warn_about_dependency(d))
log_unit_warning(u, "Dependency %s=%s is dropped.",
unit_dependency_to_string(d), u->id);
return 0;
}
@ -5811,7 +5795,7 @@ void unit_frozen(Unit *u) {
u->freezer_state = FREEZER_FROZEN;
bus_unit_send_pending_freezer_message(u);
bus_unit_send_pending_freezer_message(u, false);
}
void unit_thawed(Unit *u) {
@ -5819,7 +5803,7 @@ void unit_thawed(Unit *u) {
u->freezer_state = FREEZER_RUNNING;
bus_unit_send_pending_freezer_message(u);
bus_unit_send_pending_freezer_message(u, false);
}
static int unit_freezer_action(Unit *u, FreezerAction action) {
@ -5844,7 +5828,8 @@ static int unit_freezer_action(Unit *u, FreezerAction action) {
if (s != UNIT_ACTIVE)
return -EHOSTDOWN;
if (IN_SET(u->freezer_state, FREEZER_FREEZING, FREEZER_THAWING))
if ((IN_SET(u->freezer_state, FREEZER_FREEZING, FREEZER_THAWING) && action == FREEZER_FREEZE) ||
(u->freezer_state == FREEZER_THAWING && action == FREEZER_THAW))
return -EALREADY;
r = method(u);

View File

@ -4,6 +4,7 @@
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/statvfs.h>
#include <sys/auxv.h>
#include <sys/xattr.h>
#include <unistd.h>
@ -106,24 +107,27 @@ enum {
META_EXE = _META_MANDATORY_MAX,
META_UNIT,
META_PROC_AUXV,
_META_MAX
};
static const char * const meta_field_names[_META_MAX] = {
[META_ARGV_PID] = "COREDUMP_PID=",
[META_ARGV_UID] = "COREDUMP_UID=",
[META_ARGV_GID] = "COREDUMP_GID=",
[META_ARGV_SIGNAL] = "COREDUMP_SIGNAL=",
[META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
[META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
[META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
[META_COMM] = "COREDUMP_COMM=",
[META_EXE] = "COREDUMP_EXE=",
[META_UNIT] = "COREDUMP_UNIT=",
[META_ARGV_PID] = "COREDUMP_PID=",
[META_ARGV_UID] = "COREDUMP_UID=",
[META_ARGV_GID] = "COREDUMP_GID=",
[META_ARGV_SIGNAL] = "COREDUMP_SIGNAL=",
[META_ARGV_TIMESTAMP] = "COREDUMP_TIMESTAMP=",
[META_ARGV_RLIMIT] = "COREDUMP_RLIMIT=",
[META_ARGV_HOSTNAME] = "COREDUMP_HOSTNAME=",
[META_COMM] = "COREDUMP_COMM=",
[META_EXE] = "COREDUMP_EXE=",
[META_UNIT] = "COREDUMP_UNIT=",
[META_PROC_AUXV] = "COREDUMP_PROC_AUXV=",
};
typedef struct Context {
const char *meta[_META_MAX];
size_t meta_size[_META_MAX];
pid_t pid;
bool is_pid1;
bool is_journald;
@ -138,9 +142,9 @@ typedef enum CoredumpStorage {
} CoredumpStorage;
static const char* const coredump_storage_table[_COREDUMP_STORAGE_MAX] = {
[COREDUMP_STORAGE_NONE] = "none",
[COREDUMP_STORAGE_NONE] = "none",
[COREDUMP_STORAGE_EXTERNAL] = "external",
[COREDUMP_STORAGE_JOURNAL] = "journal",
[COREDUMP_STORAGE_JOURNAL] = "journal",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP(coredump_storage, CoredumpStorage);
@ -156,13 +160,13 @@ static uint64_t arg_max_use = UINT64_MAX;
static int parse_config(void) {
static const ConfigTableItem items[] = {
{ "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage },
{ "Coredump", "Compress", config_parse_bool, 0, &arg_compress },
{ "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max },
{ "Coredump", "ExternalSizeMax", config_parse_iec_uint64_infinity, 0, &arg_external_size_max },
{ "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max },
{ "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free },
{ "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use },
{ "Coredump", "Storage", config_parse_coredump_storage, 0, &arg_storage },
{ "Coredump", "Compress", config_parse_bool, 0, &arg_compress },
{ "Coredump", "ProcessSizeMax", config_parse_iec_uint64, 0, &arg_process_size_max },
{ "Coredump", "ExternalSizeMax", config_parse_iec_uint64_infinity, 0, &arg_external_size_max },
{ "Coredump", "JournalSizeMax", config_parse_iec_size, 0, &arg_journal_size_max },
{ "Coredump", "KeepFree", config_parse_iec_uint64, 0, &arg_keep_free },
{ "Coredump", "MaxUse", config_parse_iec_uint64, 0, &arg_max_use },
{}
};
@ -185,13 +189,16 @@ static uint64_t storage_size_max(void) {
return 0;
}
static int fix_acl(int fd, uid_t uid) {
static int fix_acl(int fd, uid_t uid, bool allow_user) {
assert(fd >= 0);
assert(uid_is_valid(uid));
#if HAVE_ACL
int r;
assert(fd >= 0);
assert(uid_is_valid(uid));
/* We don't allow users to read coredumps if the uid or capabilities were changed. */
if (!allow_user)
return 0;
if (uid_is_system(uid) || uid_is_dynamic(uid) || uid == UID_NOBODY)
return 0;
@ -208,15 +215,15 @@ static int fix_acl(int fd, uid_t uid) {
static int fix_xattr(int fd, const Context *context) {
static const char * const xattrs[_META_MAX] = {
[META_ARGV_PID] = "user.coredump.pid",
[META_ARGV_UID] = "user.coredump.uid",
[META_ARGV_GID] = "user.coredump.gid",
[META_ARGV_SIGNAL] = "user.coredump.signal",
[META_ARGV_TIMESTAMP] = "user.coredump.timestamp",
[META_ARGV_RLIMIT] = "user.coredump.rlimit",
[META_ARGV_HOSTNAME] = "user.coredump.hostname",
[META_COMM] = "user.coredump.comm",
[META_EXE] = "user.coredump.exe",
[META_ARGV_PID] = "user.coredump.pid",
[META_ARGV_UID] = "user.coredump.uid",
[META_ARGV_GID] = "user.coredump.gid",
[META_ARGV_SIGNAL] = "user.coredump.signal",
[META_ARGV_TIMESTAMP] = "user.coredump.timestamp",
[META_ARGV_RLIMIT] = "user.coredump.rlimit",
[META_ARGV_HOSTNAME] = "user.coredump.hostname",
[META_COMM] = "user.coredump.comm",
[META_EXE] = "user.coredump.exe",
};
int r = 0;
@ -251,7 +258,8 @@ static int fix_permissions(
const char *filename,
const char *target,
const Context *context,
uid_t uid) {
uid_t uid,
bool allow_user) {
int r;
@ -261,7 +269,7 @@ static int fix_permissions(
/* Ignore errors on these */
(void) fchmod(fd, 0640);
(void) fix_acl(fd, uid);
(void) fix_acl(fd, uid, allow_user);
(void) fix_xattr(fd, context);
r = fsync_full(fd);
@ -331,6 +339,153 @@ static int make_filename(const Context *context, char **ret) {
return 0;
}
static int parse_auxv64(
const uint64_t *auxv,
size_t size_bytes,
int *at_secure,
uid_t *uid,
uid_t *euid,
gid_t *gid,
gid_t *egid) {
assert(auxv || size_bytes == 0);
if (size_bytes % (2 * sizeof(uint64_t)) != 0)
return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
size_t words = size_bytes / sizeof(uint64_t);
/* Note that we set output variables even on error. */
for (size_t i = 0; i + 1 < words; i += 2)
switch (auxv[i]) {
case AT_SECURE:
*at_secure = auxv[i + 1] != 0;
break;
case AT_UID:
*uid = auxv[i + 1];
break;
case AT_EUID:
*euid = auxv[i + 1];
break;
case AT_GID:
*gid = auxv[i + 1];
break;
case AT_EGID:
*egid = auxv[i + 1];
break;
case AT_NULL:
if (auxv[i + 1] != 0)
goto error;
return 0;
}
error:
return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
"AT_NULL terminator not found, cannot parse auxv structure.");
}
static int parse_auxv32(
const uint32_t *auxv,
size_t size_bytes,
int *at_secure,
uid_t *uid,
uid_t *euid,
gid_t *gid,
gid_t *egid) {
assert(auxv || size_bytes == 0);
size_t words = size_bytes / sizeof(uint32_t);
if (size_bytes % (2 * sizeof(uint32_t)) != 0)
return log_warning_errno(SYNTHETIC_ERRNO(EIO), "Incomplete auxv structure (%zu bytes).", size_bytes);
/* Note that we set output variables even on error. */
for (size_t i = 0; i + 1 < words; i += 2)
switch (auxv[i]) {
case AT_SECURE:
*at_secure = auxv[i + 1] != 0;
break;
case AT_UID:
*uid = auxv[i + 1];
break;
case AT_EUID:
*euid = auxv[i + 1];
break;
case AT_GID:
*gid = auxv[i + 1];
break;
case AT_EGID:
*egid = auxv[i + 1];
break;
case AT_NULL:
if (auxv[i + 1] != 0)
goto error;
return 0;
}
error:
return log_warning_errno(SYNTHETIC_ERRNO(ENODATA),
"AT_NULL terminator not found, cannot parse auxv structure.");
}
static int grant_user_access(int core_fd, const Context *context) {
int at_secure = -1;
uid_t uid = UID_INVALID, euid = UID_INVALID;
uid_t gid = GID_INVALID, egid = GID_INVALID;
int r;
assert(core_fd >= 0);
assert(context);
if (!context->meta[META_PROC_AUXV])
return log_warning_errno(SYNTHETIC_ERRNO(ENODATA), "No auxv data, not adjusting permissions.");
uint8_t elf[EI_NIDENT];
errno = 0;
if (pread(core_fd, &elf, sizeof(elf), 0) != sizeof(elf))
return log_warning_errno(errno_or_else(EIO),
"Failed to pread from coredump fd: %s", STRERROR_OR_EOF(errno));
if (elf[EI_MAG0] != ELFMAG0 ||
elf[EI_MAG1] != ELFMAG1 ||
elf[EI_MAG2] != ELFMAG2 ||
elf[EI_MAG3] != ELFMAG3 ||
elf[EI_VERSION] != EV_CURRENT)
return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Core file does not have ELF header, not adjusting permissions.");
if (!IN_SET(elf[EI_CLASS], ELFCLASS32, ELFCLASS64) ||
!IN_SET(elf[EI_DATA], ELFDATA2LSB, ELFDATA2MSB))
return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Core file has strange ELF class, not adjusting permissions.");
if ((elf[EI_DATA] == ELFDATA2LSB) != (__BYTE_ORDER == __LITTLE_ENDIAN))
return log_info_errno(SYNTHETIC_ERRNO(EUCLEAN),
"Core file has non-native endianness, not adjusting permissions.");
if (elf[EI_CLASS] == ELFCLASS64)
r = parse_auxv64((const uint64_t*) context->meta[META_PROC_AUXV],
context->meta_size[META_PROC_AUXV],
&at_secure, &uid, &euid, &gid, &egid);
else
r = parse_auxv32((const uint32_t*) context->meta[META_PROC_AUXV],
context->meta_size[META_PROC_AUXV],
&at_secure, &uid, &euid, &gid, &egid);
if (r < 0)
return r;
/* We allow access if we got all the data and at_secure is not set and
* the uid/gid matches euid/egid. */
bool ret =
at_secure == 0 &&
uid != UID_INVALID && euid != UID_INVALID && uid == euid &&
gid != GID_INVALID && egid != GID_INVALID && gid == egid;
log_debug("Will %s access (uid="UID_FMT " euid="UID_FMT " gid="GID_FMT " egid="GID_FMT " at_secure=%s)",
ret ? "permit" : "restrict",
uid, euid, gid, egid, yes_no(at_secure));
return ret;
}
static int save_external_coredump(
const Context *context,
int input_fd,
@ -453,6 +608,8 @@ static int save_external_coredump(
context->meta[META_ARGV_PID], context->meta[META_COMM]);
truncated = r == 1;
bool allow_user = grant_user_access(fd, context) > 0;
#if HAVE_COMPRESSION
if (arg_compress) {
_cleanup_(unlink_and_freep) char *tmp_compressed = NULL;
@ -490,7 +647,7 @@ static int save_external_coredump(
uncompressed_size += partial_uncompressed_size;
}
r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid);
r = fix_permissions(fd_compressed, tmp_compressed, fn_compressed, context, uid, allow_user);
if (r < 0)
return r;
@ -517,7 +674,7 @@ static int save_external_coredump(
"SIZE_LIMIT=%"PRIu64, max_size,
"MESSAGE_ID=" SD_MESSAGE_TRUNCATED_CORE_STR);
r = fix_permissions(fd, tmp, fn, context, uid);
r = fix_permissions(fd, tmp, fn, context, uid, allow_user);
if (r < 0)
return log_error_errno(r, "Failed to fix permissions and finalize coredump %s into %s: %m", coredump_tmpfile_name(tmp), fn);
@ -765,7 +922,7 @@ static int change_uid_gid(const Context *context) {
}
static int submit_coredump(
Context *context,
const Context *context,
struct iovec_wrapper *iovw,
int input_fd) {
@ -944,16 +1101,15 @@ static int save_context(Context *context, const struct iovec_wrapper *iovw) {
struct iovec *iovec = iovw->iovec + n;
for (size_t i = 0; i < ELEMENTSOF(meta_field_names); i++) {
char *p;
/* Note that these strings are NUL terminated, because we made sure that a
* trailing NUL byte is in the buffer, though not included in the iov_len
* count (see process_socket() and gather_pid_metadata_*()) */
assert(((char*) iovec->iov_base)[iovec->iov_len] == 0);
p = startswith(iovec->iov_base, meta_field_names[i]);
const char *p = startswith(iovec->iov_base, meta_field_names[i]);
if (p) {
context->meta[i] = p;
context->meta_size[i] = iovec->iov_len - strlen(meta_field_names[i]);
break;
}
}
@ -1190,6 +1346,7 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
uid_t owner_uid;
pid_t pid;
char *t;
size_t size;
const char *p;
int r;
@ -1254,13 +1411,26 @@ static int gather_pid_metadata(struct iovec_wrapper *iovw, Context *context) {
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_LIMITS=", t);
p = procfs_file_alloca(pid, "cgroup");
if (read_full_virtual_file(p, &t, NULL) >=0)
if (read_full_virtual_file(p, &t, NULL) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_CGROUP=", t);
p = procfs_file_alloca(pid, "mountinfo");
if (read_full_virtual_file(p, &t, NULL) >=0)
if (read_full_virtual_file(p, &t, NULL) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_PROC_MOUNTINFO=", t);
/* We attach /proc/auxv here. ELF coredumps also contain a note for this (NT_AUXV), see elf(5). */
p = procfs_file_alloca(pid, "auxv");
if (read_full_virtual_file(p, &t, &size) >= 0) {
char *buf = malloc(strlen("COREDUMP_PROC_AUXV=") + size + 1);
if (buf) {
/* Add a dummy terminator to make save_context() happy. */
*((uint8_t*) mempcpy(stpcpy(buf, "COREDUMP_PROC_AUXV="), t, size)) = '\0';
(void) iovw_consume(iovw, buf, size + strlen("COREDUMP_PROC_AUXV="));
}
free(t);
}
if (get_process_cwd(pid, &t) >= 0)
(void) iovw_put_string_field_free(iovw, "COREDUMP_CWD=", t);

View File

@ -18,6 +18,7 @@
#include "compress.h"
#include "def.h"
#include "dissect-image.h"
#include "escape.h"
#include "fd-util.h"
#include "format-table.h"
#include "fs-util.h"
@ -790,9 +791,10 @@ static int print_info(FILE *file, sd_journal *j, bool need_space) {
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
r = json_parse(pkgmeta_json, 0, &v, NULL, NULL);
if (r < 0)
log_warning_errno(r, "json_parse on %s failed, ignoring: %m", pkgmeta_json);
else {
if (r < 0) {
_cleanup_free_ char *esc = cescape(pkgmeta_json);
log_warning_errno(r, "json_parse on \"%s\" failed, ignoring: %m", strnull(esc));
} else {
const char *module_name;
JsonVariant *module_json;

View File

@ -110,6 +110,10 @@ static inline bool ascii_isdigit(sd_char a) {
return a >= '0' && a <= '9';
}
static inline bool ascii_ishex(sd_char a) {
return ascii_isdigit(a) || (a >= 'a' && a <= 'f') || (a >= 'A' && a <= 'F');
}
static inline bool ascii_isalpha(sd_char a) {
/* A pure ASCII, locale independent version of isalpha() */
return (a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z');

View File

@ -31,6 +31,7 @@
#define BUS_ERROR_NOTHING_TO_CLEAN "org.freedesktop.systemd1.NothingToClean"
#define BUS_ERROR_UNIT_BUSY "org.freedesktop.systemd1.UnitBusy"
#define BUS_ERROR_UNIT_INACTIVE "org.freedesktop.systemd1.UnitInactive"
#define BUS_ERROR_FREEZE_CANCELLED "org.freedesktop.systemd1.FreezeCancelled"
#define BUS_ERROR_NO_SUCH_MACHINE "org.freedesktop.machine1.NoSuchMachine"
#define BUS_ERROR_NO_SUCH_IMAGE "org.freedesktop.machine1.NoSuchImage"

View File

@ -2333,9 +2333,14 @@ _public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr,
sysattr, value, ret_value ? "" : ", ignoring");
if (ret_value)
return r;
} else if (ret_value)
*ret_value = TAKE_PTR(value);
return 0;
}
if (ret_value)
*ret_value = value;
TAKE_PTR(value);
return 0;
}

View File

@ -13,59 +13,48 @@
#include "sync-util.h"
bool id128_is_valid(const char *s) {
size_t i, l;
size_t l;
assert(s);
l = strlen(s);
if (l == 32) {
if (l == SD_ID128_STRING_MAX - 1)
/* Plain formatted 128bit hex string */
return in_charset(s, HEXDIGITS);
for (i = 0; i < l; i++) {
char c = s[i];
if (!ascii_isdigit(c) &&
!(c >= 'a' && c <= 'f') &&
!(c >= 'A' && c <= 'F'))
return false;
}
} else if (l == 36) {
if (l == SD_ID128_UUID_STRING_MAX - 1) {
/* Formatted UUID */
for (i = 0; i < l; i++) {
for (size_t i = 0; i < l; i++) {
char c = s[i];
if (IN_SET(i, 8, 13, 18, 23)) {
if (c != '-')
return false;
} else {
if (!ascii_isdigit(c) &&
!(c >= 'a' && c <= 'f') &&
!(c >= 'A' && c <= 'F'))
return false;
}
} else if (!ascii_ishex(c))
return false;
}
return true;
}
} else
return false;
return true;
return false;
}
int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
char buffer[36 + 2];
int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret) {
char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */
ssize_t l;
assert(fd >= 0);
assert(f < _ID128_FORMAT_MAX);
/* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
* optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they
* aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you
* accept". */
* accept".
*
* This returns the following:
* -ENOMEDIUM: an empty string,
* -ENOPKG: "uninitialized" or "uninitialized\n",
* -EINVAL: other invalid strings. */
l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
if (l < 0)
@ -75,33 +64,32 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
switch (l) {
case 13:
case 14:
/* Treat an "uninitialized" id file like an empty one */
return f == ID128_PLAIN_OR_UNINIT && strneq(buffer, "uninitialized\n", l) ? -ENOMEDIUM : -EINVAL;
case STRLEN("uninitialized"):
case STRLEN("uninitialized\n"):
return strneq(buffer, "uninitialized\n", l) ? -ENOPKG : -EINVAL;
case 33: /* plain UUID with trailing newline */
if (buffer[32] != '\n')
case SD_ID128_STRING_MAX: /* plain UUID with trailing newline */
if (buffer[SD_ID128_STRING_MAX-1] != '\n')
return -EINVAL;
_fallthrough_;
case 32: /* plain UUID without trailing newline */
if (f == ID128_UUID)
case SD_ID128_STRING_MAX-1: /* plain UUID without trailing newline */
if (!FLAGS_SET(f, ID128_FORMAT_PLAIN))
return -EINVAL;
buffer[32] = 0;
buffer[SD_ID128_STRING_MAX-1] = 0;
break;
case 37: /* RFC UUID with trailing newline */
if (buffer[36] != '\n')
case SD_ID128_UUID_STRING_MAX: /* RFC UUID with trailing newline */
if (buffer[SD_ID128_UUID_STRING_MAX-1] != '\n')
return -EINVAL;
_fallthrough_;
case 36: /* RFC UUID without trailing newline */
if (IN_SET(f, ID128_PLAIN, ID128_PLAIN_OR_UNINIT))
case SD_ID128_UUID_STRING_MAX-1: /* RFC UUID without trailing newline */
if (!FLAGS_SET(f, ID128_FORMAT_UUID))
return -EINVAL;
buffer[36] = 0;
buffer[SD_ID128_UUID_STRING_MAX-1] = 0;
break;
default:
@ -111,7 +99,7 @@ int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
return sd_id128_from_string(buffer, ret);
}
int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret) {
_cleanup_close_ int fd = -1;
fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
@ -121,24 +109,23 @@ int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
return id128_read_fd(fd, f, ret);
}
int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
char buffer[36 + 2];
int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync) {
char buffer[SD_ID128_UUID_STRING_MAX + 1]; /* +1 is for trailing newline */
size_t sz;
int r;
assert(fd >= 0);
assert(f < _ID128_FORMAT_MAX);
assert(IN_SET((f & ID128_FORMAT_ANY), ID128_FORMAT_PLAIN, ID128_FORMAT_UUID));
if (f != ID128_UUID) {
if (FLAGS_SET(f, ID128_FORMAT_PLAIN)) {
assert_se(sd_id128_to_string(id, buffer));
buffer[SD_ID128_STRING_MAX - 1] = '\n';
sz = SD_ID128_STRING_MAX;
} else {
assert_se(sd_id128_to_uuid_string(id, buffer));
buffer[SD_ID128_UUID_STRING_MAX - 1] = '\n';
sz = SD_ID128_UUID_STRING_MAX;
}
buffer[sz - 1] = '\n';
r = loop_write(fd, buffer, sz, false);
if (r < 0)
return r;
@ -152,7 +139,7 @@ int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
return 0;
}
int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) {
int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id, bool do_sync) {
_cleanup_close_ int fd = -1;
fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444);
@ -194,9 +181,9 @@ int id128_get_product(sd_id128_t *ret) {
/* Reads the systems product UUID from DMI or devicetree (where it is located on POWER). This is
* particularly relevant in VM environments, where VM managers typically place a VM uuid there. */
r = id128_read("/sys/class/dmi/id/product_uuid", ID128_UUID, &uuid);
r = id128_read("/sys/class/dmi/id/product_uuid", ID128_FORMAT_UUID, &uuid);
if (r == -ENOENT)
r = id128_read("/proc/device-tree/vm,uuid", ID128_UUID, &uuid);
r = id128_read("/proc/device-tree/vm,uuid", ID128_FORMAT_UUID, &uuid);
if (r < 0)
return r;

View File

@ -10,22 +10,17 @@
bool id128_is_valid(const char *s) _pure_;
typedef enum Id128Format {
ID128_ANY,
ID128_PLAIN, /* formatted as 32 hex chars as-is */
ID128_PLAIN_OR_UNINIT, /* formatted as 32 hex chars as-is; allow special "uninitialized"
* value when reading from file (id128_read() and id128_read_fd()).
*
* This format should be used when reading a machine-id file. */
ID128_UUID, /* formatted as 36 character uuid string */
_ID128_FORMAT_MAX,
} Id128Format;
typedef enum Id128FormatFlag {
ID128_FORMAT_PLAIN = 1 << 0, /* formatted as 32 hex chars as-is */
ID128_FORMAT_UUID = 1 << 1, /* formatted as 36 character uuid string */
ID128_FORMAT_ANY = ID128_FORMAT_PLAIN | ID128_FORMAT_UUID,
} Id128FormatFlag;
int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret);
int id128_read(const char *p, Id128Format f, sd_id128_t *ret);
int id128_read_fd(int fd, Id128FormatFlag f, sd_id128_t *ret);
int id128_read(const char *p, Id128FormatFlag f, sd_id128_t *ret);
int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync);
int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync);
int id128_write_fd(int fd, Id128FormatFlag f, sd_id128_t id, bool do_sync);
int id128_write(const char *p, Id128FormatFlag f, sd_id128_t id, bool do_sync);
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_;

View File

@ -19,14 +19,17 @@
#include "util.h"
_public_ char *sd_id128_to_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD_ID128_STRING_MAX]) {
size_t k = 0;
assert_return(s, NULL);
for (size_t n = 0; n < 16; n++) {
s[n*2] = hexchar(id.bytes[n] >> 4);
s[n*2+1] = hexchar(id.bytes[n] & 0xF);
for (size_t n = 0; n < sizeof(sd_id128_t); n++) {
s[k++] = hexchar(id.bytes[n] >> 4);
s[k++] = hexchar(id.bytes[n] & 0xF);
}
s[SD_ID128_STRING_MAX-1] = 0;
assert(k == SD_ID128_STRING_MAX - 1);
s[k] = 0;
return s;
}
@ -38,7 +41,7 @@ _public_ char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD
/* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
for (size_t n = 0; n < 16; n++) {
for (size_t n = 0; n < sizeof(sd_id128_t); n++) {
if (IN_SET(n, 4, 6, 8, 10))
s[k++] = '-';
@ -53,14 +56,14 @@ _public_ char *sd_id128_to_uuid_string(sd_id128_t id, char s[_SD_ARRAY_STATIC SD
return s;
}
_public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
unsigned n, i;
_public_ int sd_id128_from_string(const char *s, sd_id128_t *ret) {
size_t n, i;
sd_id128_t t;
bool is_guid = false;
assert_return(s, -EINVAL);
for (n = 0, i = 0; n < 16;) {
for (n = 0, i = 0; n < sizeof(sd_id128_t);) {
int a, b;
if (s[i] == '-') {
@ -90,7 +93,7 @@ _public_ int sd_id128_from_string(const char s[], sd_id128_t *ret) {
t.bytes[n++] = (a << 4) | b;
}
if (i != (is_guid ? 36 : 32))
if (i != (is_guid ? SD_ID128_UUID_STRING_MAX : SD_ID128_STRING_MAX) - 1)
return -EINVAL;
if (s[i] != 0)
@ -124,7 +127,7 @@ _public_ int sd_id128_get_machine(sd_id128_t *ret) {
assert_return(ret, -EINVAL);
if (sd_id128_is_null(saved_machine_id)) {
r = id128_read("/etc/machine-id", ID128_PLAIN, &saved_machine_id);
r = id128_read("/etc/machine-id", ID128_FORMAT_PLAIN, &saved_machine_id);
if (r < 0)
return r;
@ -143,7 +146,7 @@ _public_ int sd_id128_get_boot(sd_id128_t *ret) {
assert_return(ret, -EINVAL);
if (sd_id128_is_null(saved_boot_id)) {
r = id128_read("/proc/sys/kernel/random/boot_id", ID128_UUID, &saved_boot_id);
r = id128_read("/proc/sys/kernel/random/boot_id", ID128_FORMAT_UUID, &saved_boot_id);
if (r < 0)
return r;
}

View File

@ -370,7 +370,7 @@ static int journal_file_refresh_header(JournalFile *f) {
assert(f->header);
r = sd_id128_get_machine(&f->header->machine_id);
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
if (IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG))
/* We don't have a machine-id, let's continue without */
zero(f->header->machine_id);
else if (r < 0)

View File

@ -164,7 +164,7 @@ static int run(int argc, char *argv[]) {
return r;
etc_machine_id = prefix_roota(arg_root, "/etc/machine-id");
r = id128_read(etc_machine_id, ID128_PLAIN, &id);
r = id128_read(etc_machine_id, ID128_FORMAT_PLAIN, &id);
if (r < 0)
return log_error_errno(r, "Failed to read machine ID back: %m");
} else {

View File

@ -2195,7 +2195,7 @@ static int setup_boot_id(void) {
if (r < 0)
return log_error_errno(r, "Failed to generate random boot id: %m");
r = id128_write(path, ID128_UUID, rnd, false);
r = id128_write(path, ID128_FORMAT_UUID, rnd, false);
if (r < 0)
return log_error_errno(r, "Failed to write boot id: %m");
@ -2821,9 +2821,9 @@ static int setup_machine_id(const char *directory) {
etc_machine_id = prefix_roota(directory, "/etc/machine-id");
r = id128_read(etc_machine_id, ID128_PLAIN_OR_UNINIT, &id);
r = id128_read(etc_machine_id, ID128_FORMAT_PLAIN, &id);
if (r < 0) {
if (!IN_SET(r, -ENOENT, -ENOMEDIUM)) /* If the file is missing or empty, we don't mind */
if (!IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG)) /* 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");
if (sd_id128_is_null(arg_uuid)) {

View File

@ -4473,8 +4473,8 @@ static int context_read_seed(Context *context, const char *root) {
else if (fd < 0)
return log_error_errno(fd, "Failed to determine machine ID of image: %m");
else {
r = id128_read_fd(fd, ID128_PLAIN_OR_UNINIT, &context->seed);
if (r == -ENOMEDIUM)
r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &context->seed);
if (IN_SET(r, -ENOMEDIUM, -ENOPKG))
log_info("No machine ID set, using randomized partition UUIDs.");
else if (r < 0)
return log_error_errno(r, "Failed to parse machine ID of image: %m");

View File

@ -1768,36 +1768,30 @@ int dns_resource_record_get_cname_target(DnsResourceKey *key, DnsResourceRecord
return 0;
}
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *i) {
DnsTxtItem *n;
DnsTxtItem *dns_txt_item_free_all(DnsTxtItem *first) {
LIST_FOREACH(items, i, first)
free(i);
if (!i)
return NULL;
n = i->items_next;
free(i);
return dns_txt_item_free_all(n);
return NULL;
}
bool dns_txt_item_equal(DnsTxtItem *a, DnsTxtItem *b) {
DnsTxtItem *bb = b;
if (a == b)
return true;
if (!a != !b)
return false;
LIST_FOREACH(items, aa, a) {
if (!bb)
return false;
if (!a)
return true;
if (memcmp_nn(aa->data, aa->length, bb->data, bb->length) != 0)
return false;
if (a->length != b->length)
return false;
bb = bb->items_next;
}
if (memcmp(a->data, b->data, a->length) != 0)
return false;
return dns_txt_item_equal(a->items_next, b->items_next);
return !bb;
}
DnsTxtItem *dns_txt_item_copy(DnsTxtItem *first) {

View File

@ -1153,7 +1153,7 @@ int image_read_metadata(Image *i) {
if (fd < 0)
log_debug_errno(errno, "Failed to open %s: %m", path);
else {
r = id128_read_fd(fd, ID128_PLAIN, &machine_id);
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);
}

View File

@ -74,9 +74,15 @@
/* how many times to wait for the device nodes to appear */
#define N_DEVICE_NODE_LIST_ATTEMPTS 10
int probe_filesystem_full(int fd, const char *path, char **ret_fstype) {
int probe_filesystem_full(
int fd,
const char *path,
uint64_t offset,
uint64_t size,
char **ret_fstype) {
/* Try to find device content type and return it in *ret_fstype. If nothing is found,
* 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and an
* 0/NULL will be returned. -EUCLEAN will be returned for ambiguous results, and a
* different error otherwise. */
#if HAVE_BLKID
@ -105,12 +111,19 @@ int probe_filesystem_full(int fd, const char *path, char **ret_fstype) {
path = path_by_fd;
}
if (size == 0) /* empty size? nothing found! */
goto not_found;
b = blkid_new_probe();
if (!b)
return -ENOMEM;
errno = 0;
r = blkid_probe_set_device(b, fd, 0, 0);
r = blkid_probe_set_device(
b,
fd,
offset,
size == UINT64_MAX ? 0 : size); /* when blkid sees size=0 it understands "everything". We prefer using UINT64_MAX for that */
if (r != 0)
return errno_or_else(ENOMEM);
@ -152,7 +165,7 @@ not_found:
}
#if HAVE_BLKID
static int dissected_image_probe_filesystem(DissectedImage *m) {
static int dissected_image_probe_filesystems(DissectedImage *m, int fd) {
int r;
assert(m);
@ -165,9 +178,14 @@ static int dissected_image_probe_filesystem(DissectedImage *m) {
if (!p->found)
continue;
if (!p->fstype && p->mount_node_fd >= 0 && !p->decrypted_node) {
r = probe_filesystem_full(p->mount_node_fd, p->node, &p->fstype);
if (r < 0 && r != -EUCLEAN)
if (!p->fstype) {
/* If we have an fd referring to the partition block device, use that. Otherwise go
* via the whole block device or backing regular file, and read via offset. */
if (p->mount_node_fd >= 0)
r = probe_filesystem_full(p->mount_node_fd, p->node, 0, UINT64_MAX, &p->fstype);
else
r = probe_filesystem_full(fd, p->node, p->offset, p->size, &p->fstype);
if (r < 0)
return r;
}
@ -1217,6 +1235,10 @@ static int dissect_image(
}
}
r = dissected_image_probe_filesystems(m, fd);
if (r < 0)
return r;
return 0;
}
#endif
@ -2339,7 +2361,7 @@ int dissected_image_decrypt(
}
if (!p->decrypted_fstype && p->mount_node_fd >= 0 && p->decrypted_node) {
r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, &p->decrypted_fstype);
r = probe_filesystem_full(p->mount_node_fd, p->decrypted_node, 0, UINT64_MAX, &p->decrypted_fstype);
if (r < 0 && r != -EUCLEAN)
return r;
}
@ -3041,10 +3063,6 @@ int dissect_loop_device(
if (r < 0)
return r;
r = dissected_image_probe_filesystem(m);
if (r < 0)
return r;
*ret = TAKE_PTR(m);
return 0;
#else

View File

@ -271,9 +271,9 @@ MountOptions* mount_options_free_all(MountOptions *options);
DEFINE_TRIVIAL_CLEANUP_FUNC(MountOptions*, mount_options_free_all);
const char* mount_options_from_designator(const MountOptions *options, PartitionDesignator designator);
int probe_filesystem_full(int fd, const char *path, char **ret_fstype);
int probe_filesystem_full(int fd, const char *path, uint64_t offset, uint64_t size, char **ret_fstype);
static inline int probe_filesystem(const char *path, char **ret_fstype) {
return probe_filesystem_full(-1, path, ret_fstype);
return probe_filesystem_full(-1, path, 0, UINT64_MAX, ret_fstype);
}
int dissect_image_file(
const char *path,

View File

@ -15,6 +15,7 @@
#include "dlfcn-util.h"
#include "elf-util.h"
#include "errno-util.h"
#include "escape.h"
#include "fileio.h"
#include "fd-util.h"
#include "format-util.h"
@ -397,8 +398,10 @@ static int parse_package_metadata(const char *name, JsonVariant *id_json, Elf *e
}
r = json_parse(payload, 0, &v, NULL, NULL);
if (r < 0)
return log_error_errno(r, "json_parse on %s failed: %m", payload);
if (r < 0) {
_cleanup_free_ char *esc = cescape(payload);
return log_error_errno(r, "json_parse on \"%s\" failed: %m", strnull(esc));
}
/* If we have a build-id, merge it in the same JSON object so that it appears all
* nicely together in the logs/metadata. */

View File

@ -38,7 +38,7 @@ static int generate_machine_id(const char *root, sd_id128_t *ret) {
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_PLAIN, ret) >= 0) {
if (id128_read_fd(fd, ID128_FORMAT_PLAIN, ret) >= 0) {
log_info("Initializing machine ID from D-Bus machine ID.");
return 0;
}
@ -123,7 +123,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_
if (sd_id128_is_null(machine_id)) {
/* Try to read any existing machine ID */
if (id128_read_fd(fd, ID128_PLAIN, ret) >= 0)
if (id128_read_fd(fd, ID128_FORMAT_PLAIN, ret) >= 0)
return 0;
/* Hmm, so, the id currently stored is not useful, then let's generate one */
@ -152,7 +152,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_
if (r < 0)
return log_error_errno(r, "Failed to sync %s: %m", etc_machine_id);
} else {
r = id128_write_fd(fd, ID128_PLAIN, machine_id, true);
r = id128_write_fd(fd, ID128_FORMAT_PLAIN, machine_id, true);
if (r < 0)
return log_error_errno(r, "Failed to write %s: %m", etc_machine_id);
else
@ -168,7 +168,7 @@ int machine_id_setup(const char *root, bool force_transient, sd_id128_t machine_
run_machine_id = prefix_roota(root, "/run/machine-id");
RUN_WITH_UMASK(0022)
r = id128_write(run_machine_id, ID128_PLAIN, machine_id, false);
r = id128_write(run_machine_id, ID128_FORMAT_PLAIN, machine_id, false);
if (r < 0) {
(void) unlink(run_machine_id);
return log_error_errno(r, "Cannot write %s: %m", run_machine_id);
@ -240,7 +240,7 @@ int machine_id_commit(const char *root) {
"%s is not on a temporary file system.",
etc_machine_id);
r = id128_read_fd(fd, ID128_PLAIN, &id);
r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &id);
if (r < 0)
return log_error_errno(r, "We didn't find a valid machine ID in %s: %m", etc_machine_id);
@ -261,7 +261,7 @@ int machine_id_commit(const char *root) {
return r;
/* Update a persistent version of etc_machine_id */
r = id128_write(etc_machine_id, ID128_PLAIN, id, true);
r = id128_write(etc_machine_id, ID128_FORMAT_PLAIN, id, true);
if (r < 0)
return log_error_errno(r, "Cannot write %s. This is mandatory to get a persistent machine ID: %m", etc_machine_id);

View File

@ -195,7 +195,7 @@ int specifier_machine_id(char specifier, const void *data, const char *root, con
/* Translate error for missing os-release file to EUNATCH. */
return fd == -ENOENT ? -EUNATCH : fd;
r = id128_read_fd(fd, ID128_PLAIN, &id);
r = id128_read_fd(fd, ID128_FORMAT_PLAIN, &id);
} else
r = sd_id128_get_machine(&id);
if (r < 0)

View File

@ -374,7 +374,7 @@ static int freeze_thaw_user_slice(const char **method) {
}
static int execute_s2h(const SleepConfig *sleep_config) {
_unused_ _cleanup_(freeze_thaw_user_slice) const char *auto_method_thaw = NULL;
_unused_ _cleanup_(freeze_thaw_user_slice) const char *auto_method_thaw = "ThawUnit";
int r, k;
assert(sleep_config);
@ -382,8 +382,6 @@ static int execute_s2h(const SleepConfig *sleep_config) {
r = freeze_thaw_user_slice(&(const char*) { "FreezeUnit" });
if (r < 0)
log_debug_errno(r, "Failed to freeze unit user.slice, ignoring: %m");
else
auto_method_thaw = "ThawUnit"; /* from now on we want automatic thawing */;
r = check_wakeup_type();
if (r < 0)

View File

@ -250,7 +250,7 @@ TEST(condition_test_host) {
int r;
r = sd_id128_get_machine(&id);
if (IN_SET(r, -ENOENT, -ENOMEDIUM))
if (IN_SET(r, -ENOENT, -ENOMEDIUM, -ENOPKG))
return (void) log_tests_skipped("/etc/machine-id missing");
assert_se(r >= 0);

View File

@ -326,7 +326,7 @@ TEST(chase_symlinks) {
assert_se(fd >= 0);
safe_close(pfd);
assert_se(id128_read_fd(fd, ID128_PLAIN, &a) >= 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &a) >= 0);
assert_se(sd_id128_get_machine(&b) >= 0);
assert_se(sd_id128_equal(a, b));
}

View File

@ -86,17 +86,17 @@ TEST(id128) {
/* First, write as UUID */
assert_se(sd_id128_randomize(&id) >= 0);
assert_se(id128_write_fd(fd, ID128_UUID, id, false) >= 0);
assert_se(id128_write_fd(fd, ID128_FORMAT_UUID, id, false) >= 0);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
/* Second, write as plain */
@ -104,17 +104,17 @@ TEST(id128) {
assert_se(ftruncate(fd, 0) >= 0);
assert_se(sd_id128_randomize(&id) >= 0);
assert_se(id128_write_fd(fd, ID128_PLAIN, id, false) >= 0);
assert_se(id128_write_fd(fd, ID128_FORMAT_PLAIN, id, false) >= 0);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL);
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_ANY, &id2) >= 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
/* Third, write plain without trailing newline */
@ -125,13 +125,13 @@ TEST(id128) {
assert_se(write(fd, sd_id128_to_string(id, t), 32) == 32);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_UUID, &id2) == -EINVAL);
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) == -EINVAL);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) >= 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
/* Third, write UUID without trailing newline */
/* Fourth, write UUID without trailing newline */
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(ftruncate(fd, 0) >= 0);
@ -139,12 +139,37 @@ TEST(id128) {
assert_se(write(fd, sd_id128_to_uuid_string(id, q), 36) == 36);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_PLAIN, &id2) == -EINVAL);
assert_se(id128_read_fd(fd, ID128_FORMAT_PLAIN, &id2) == -EINVAL);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_UUID, &id2) >= 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_UUID, &id2) >= 0);
assert_se(sd_id128_equal(id, id2));
/* Fifth, tests for "uninitialized" */
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(ftruncate(fd, 0) >= 0);
assert_se(write(fd, "uninitialized", STRLEN("uninitialized")) == STRLEN("uninitialized"));
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -ENOPKG);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(ftruncate(fd, 0) >= 0);
assert_se(write(fd, "uninitialized\n", STRLEN("uninitialized\n")) == STRLEN("uninitialized\n"));
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -ENOPKG);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(ftruncate(fd, 0) >= 0);
assert_se(write(fd, "uninitialized\nfoo", STRLEN("uninitialized\nfoo")) == STRLEN("uninitialized\nfoo"));
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL);
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(ftruncate(fd, 0) >= 0);
assert_se(write(fd, "uninit", STRLEN("uninit")) == STRLEN("uninit"));
assert_se(lseek(fd, 0, SEEK_SET) == 0);
assert_se(id128_read_fd(fd, ID128_FORMAT_ANY, NULL) == -EINVAL);
if (sd_booted() > 0 && access("/etc/machine-id", F_OK) >= 0) {
assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id) >= 0);
assert_se(sd_id128_get_machine_app_specific(SD_ID128_MAKE(f0,3d,aa,eb,1c,33,4b,43,a7,32,17,29,44,bf,77,2e), &id2) >= 0);

View File

@ -4,6 +4,8 @@
#include <linux/loop.h>
#include <pthread.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include "alloc-util.h"
#include "capability-util.h"
@ -44,6 +46,15 @@ static void verify_dissected_image(DissectedImage *dissected) {
assert_se(dissected->partitions[PARTITION_HOME].node);
}
static void verify_dissected_image_harder(DissectedImage *dissected) {
verify_dissected_image(dissected);
assert_se(streq(dissected->partitions[PARTITION_ESP].fstype, "vfat"));
assert_se(streq(dissected->partitions[PARTITION_XBOOTLDR].fstype, "vfat"));
assert_se(streq(dissected->partitions[PARTITION_ROOT].fstype, "ext4"));
assert_se(streq(dissected->partitions[PARTITION_HOME].fstype, "ext4"));
}
static void* thread_func(void *ptr) {
int fd = PTR_TO_FD(ptr);
int r;
@ -246,8 +257,23 @@ static int run(int argc, char *argv[]) {
assert_se(make_filesystem(dissected->partitions[PARTITION_HOME].node, "ext4", "home", NULL, id, true) >= 0);
dissected = dissected_image_unref(dissected);
/* We created the file systems now via the per-partition block devices. But the dissection code might
* probe them via the whole block device. These block devices have separate buffer caches though,
* hence what was written via the partition device might not appear on the whole block device
* yet. Let's hence explicitly flush the whole block device, so that the read-back definitely
* works. */
assert_se(ioctl(loop->fd, BLKFLSBUF, 0) >= 0);
/* Try to read once, without pinning or adding partitions, i.e. by only accessing the whole block
* device. */
assert_se(dissect_loop_device(loop, NULL, NULL, 0, &dissected) >= 0);
verify_dissected_image_harder(dissected);
dissected = dissected_image_unref(dissected);
/* Now go via the loopback device after all, but this time add/pin, because now we want to mount it. */
assert_se(dissect_loop_device(loop, NULL, NULL, DISSECT_IMAGE_ADD_PARTITION_DEVICES|DISSECT_IMAGE_PIN_PARTITION_DEVICES, &dissected) >= 0);
verify_dissected_image(dissected);
verify_dissected_image_harder(dissected);
assert_se(mkdtemp_malloc(NULL, &mounted) >= 0);

View File

@ -119,8 +119,10 @@ static int manager_send_request(Manager *m) {
m->event_timeout = sd_event_source_unref(m->event_timeout);
r = manager_listen_setup(m);
if (r < 0)
return log_warning_errno(r, "Failed to set up connection socket: %m");
if (r < 0) {
log_warning_errno(r, "Failed to set up connection socket: %m");
return manager_connect(m);
}
/*
* Set transmit timestamp, remember it; the server will send that back
@ -752,7 +754,7 @@ static int manager_resolve_handler(sd_resolve_query *q, int ret, const struct ad
assert(ai->ai_addrlen >= offsetof(struct sockaddr, sa_data));
if (!IN_SET(ai->ai_addr->sa_family, AF_INET, AF_INET6)) {
log_warning("Unsuitable address protocol for %s", m->current_server_name->string);
log_debug("Ignoring unsuitable address protocol for %s.", m->current_server_name->string);
continue;
}
@ -806,11 +808,6 @@ int manager_connect(Manager *m) {
if (m->current_server_address && m->current_server_address->addresses_next)
manager_set_server_address(m, m->current_server_address->addresses_next);
else {
static const struct addrinfo hints = {
.ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
.ai_socktype = SOCK_DGRAM,
};
/* Hmm, we are through all addresses, let's look for the next host instead */
if (m->current_server_name && m->current_server_name->names_next)
manager_set_server_name(m, m->current_server_name->names_next);
@ -878,6 +875,12 @@ int manager_connect(Manager *m) {
log_debug("Resolving %s...", m->current_server_name->string);
struct addrinfo hints = {
.ai_flags = AI_NUMERICSERV|AI_ADDRCONFIG,
.ai_socktype = SOCK_DGRAM,
.ai_family = socket_ipv6_is_supported() ? AF_UNSPEC : AF_INET,
};
r = resolve_getaddrinfo(m->resolve, &m->resolve_query, m->current_server_name->string, "123", &hints, manager_resolve_handler, NULL, m);
if (r < 0)
return log_error_errno(r, "Failed to create resolver: %m");

View File

@ -1328,7 +1328,7 @@ create_empty_image() {
fi
# Partition sizes are in MiBs
local root_size=500
local root_size=1000
local data_size=50
if ! get_bool "$NO_BUILD"; then
if meson configure "${BUILD_DIR:?}" | grep 'static-lib\|standalone-binaries' | awk '{ print $2 }' | grep -q 'true'; then

View File

@ -3,10 +3,18 @@
set -eux
set -o pipefail
# shellcheck source=test/units/assert.sh
. "$(dirname "$0")"/assert.sh
: >/failed
at_exit() {
if [[ -v UNIT_NAME && -e "/usr/lib/systemd/system/$UNIT_NAME" ]]; then
rm -fv "/usr/lib/systemd/system/$UNIT_NAME"
fi
rm -f /etc/init.d/issue-24990
return 0
}
trap at_exit EXIT
@ -284,6 +292,110 @@ systemctl unset-environment IMPORT_THIS IMPORT_THIS_TOO
(! systemctl show-environment | grep "^IMPORT_THIS=")
(! systemctl show-environment | grep "^IMPORT_THIS_TOO=")
echo OK >/testok
# test for sysv-generator (issue #24990)
if [[ -x /usr/lib/systemd/system-generators/systemd-sysv-generator ]]; then
exit 0
# invalid dependency
cat >/etc/init.d/issue-24990 <<\EOF
#!/bin/bash
### BEGIN INIT INFO
# Provides:test1 test2
# Required-Start:test1 $remote_fs $network
# Required-Stop:test1 $remote_fs $network
# Description:Test
# Short-Description: Test
### END INIT INFO
case "$1" in
start)
echo "Starting issue-24990.service"
sleep 1000 &
;;
stop)
echo "Stopping issue-24990.service"
sleep 10 &
;;
*)
echo "Usage: service test {start|stop|restart|status}"
;;
esac
EOF
chmod +x /etc/init.d/issue-24990
systemctl daemon-reload
[[ -L /run/systemd/generator.late/test1.service ]]
[[ -L /run/systemd/generator.late/test2.service ]]
assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
output=$(systemctl cat issue-24990)
assert_in "SourcePath=/etc/init.d/issue-24990" "$output"
assert_in "Description=LSB: Test" "$output"
assert_in "After=test1.service" "$output"
assert_in "After=remote-fs.target" "$output"
assert_in "After=network-online.target" "$output"
assert_in "Wants=network-online.target" "$output"
assert_in "ExecStart=/etc/init.d/issue-24990 start" "$output"
assert_in "ExecStop=/etc/init.d/issue-24990 stop" "$output"
systemctl status issue-24990 || :
systemctl show issue-24990
assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"
assert_not_in "issue-24990.service" "$(systemctl show --property=Before --value)"
if ! systemctl is-active network-online.target; then
systemctl start network-online.target
fi
systemctl restart issue-24990
systemctl stop issue-24990
# valid dependency
cat >/etc/init.d/issue-24990 <<\EOF
#!/bin/bash
### BEGIN INIT INFO
# Provides:test1 test2
# Required-Start:$remote_fs
# Required-Stop:$remote_fs
# Description:Test
# Short-Description: Test
### END INIT INFO
case "$1" in
start)
echo "Starting issue-24990.service"
sleep 1000 &
;;
stop)
echo "Stopping issue-24990.service"
sleep 10 &
;;
*)
echo "Usage: service test {start|stop|restart|status}"
;;
esac
EOF
chmod +x /etc/init.d/issue-24990
systemctl daemon-reload
[[ -L /run/systemd/generator.late/test1.service ]]
[[ -L /run/systemd/generator.late/test2.service ]]
assert_eq "$(readlink -f /run/systemd/generator.late/test1.service)" "/run/systemd/generator.late/issue-24990.service"
assert_eq "$(readlink -f /run/systemd/generator.late/test2.service)" "/run/systemd/generator.late/issue-24990.service"
output=$(systemctl cat issue-24990)
assert_in "SourcePath=/etc/init.d/issue-24990" "$output"
assert_in "Description=LSB: Test" "$output"
assert_in "After=remote-fs.target" "$output"
assert_in "ExecStart=/etc/init.d/issue-24990 start" "$output"
assert_in "ExecStop=/etc/init.d/issue-24990 stop" "$output"
systemctl status issue-24990 || :
systemctl show issue-24990
assert_not_in "issue-24990.service" "$(systemctl show --property=After --value)"
assert_not_in "issue-24990.service" "$(systemctl show --property=Before --value)"
systemctl restart issue-24990
systemctl stop issue-24990
fi
touch /testok
rm /failed