diff --git a/0002-0001-udev-ignore-error-caused-by-device-disconnection.patch b/0002-0001-udev-ignore-error-caused-by-device-disconnection.patch new file mode 100644 index 0000000000000000000000000000000000000000..26336b49a4a8ab6b5c860226aac42bd4af7de323 --- /dev/null +++ b/0002-0001-udev-ignore-error-caused-by-device-disconnection.patch @@ -0,0 +1,71 @@ +From b64b83d13eedfdfc616c16c4a108ef28bf6d3b33 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 12 Nov 2019 14:58:25 +0900 +Subject: [PATCH] udev: ignore error caused by device disconnection + +During an add or change event, the device may be disconnected. + +Fixes #13976. +--- + src/udev/udev-node.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c +index 2d72570..a34b8d6 100644 +--- a/src/udev/udev-node.c ++++ b/src/udev/udev-node.c +@@ -296,8 +296,11 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, + else + mode |= S_IFCHR; + +- if (lstat(devnode, &stats) < 0) ++ if (lstat(devnode, &stats) < 0) { ++ if (errno == ENOENT) ++ return 0; /* this is necessarily racey, so ignore missing the device */ + return log_device_debug_errno(dev, errno, "cannot stat() node %s: %m", devnode); ++ } + + if ((mode != MODE_INVALID && (stats.st_mode & S_IFMT) != (mode & S_IFMT)) || stats.st_rdev != devnum) + return log_device_debug_errno(dev, SYNTHETIC_ERRNO(EEXIST), +@@ -322,11 +325,13 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, + + r = chmod_and_chown(devnode, mode, uid, gid); + if (r < 0) +- log_device_warning_errno(dev, r, "Failed to set owner/mode of %s to uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o: %m", +- devnode, +- uid_is_valid(uid) ? uid : stats.st_uid, +- gid_is_valid(gid) ? gid : stats.st_gid, +- mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); ++ log_device_full(dev, r == -ENOENT ? LOG_DEBUG : LOG_ERR, r, ++ "Failed to set owner/mode of %s to uid=" UID_FMT ++ ", gid=" GID_FMT ", mode=%#o: %m", ++ devnode, ++ uid_is_valid(uid) ? uid : stats.st_uid, ++ gid_is_valid(gid) ? gid : stats.st_gid, ++ mode != MODE_INVALID ? mode & 0777 : stats.st_mode & 0777); + } else + log_device_debug(dev, "Preserve permissions of %s, uid=" UID_FMT ", gid=" GID_FMT ", mode=%#o", + devnode, +@@ -343,7 +348,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, + + q = mac_selinux_apply(devnode, label); + if (q < 0) +- log_device_error_errno(dev, q, "SECLABEL: failed to set SELinux label '%s': %m", label); ++ log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, ++ "SECLABEL: failed to set SELinux label '%s': %m", label); + else + log_device_debug(dev, "SECLABEL: set SELinux label '%s'", label); + +@@ -352,7 +358,8 @@ static int node_permissions_apply(sd_device *dev, bool apply_mac, + + q = mac_smack_apply(devnode, SMACK_ATTR_ACCESS, label); + if (q < 0) +- log_device_error_errno(dev, q, "SECLABEL: failed to set SMACK label '%s': %m", label); ++ log_device_full(dev, q == -ENOENT ? LOG_DEBUG : LOG_ERR, q, ++ "SECLABEL: failed to set SMACK label '%s': %m", label); + else + log_device_debug(dev, "SECLABEL: set SMACK label '%s'", label); + +-- +1.8.3.1 + diff --git a/0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch b/0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch new file mode 100644 index 0000000000000000000000000000000000000000..dead4f2b9d026a369eea4e52bb2d29604ff4ac72 --- /dev/null +++ b/0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch @@ -0,0 +1,33 @@ +From 42837b8134844c1d08014e480f9497d165c57ef6 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Dec 2019 16:31:48 +0100 +Subject: [PATCH] core: don't check error parameter of get_name_owner_handler() + +It's a *return* parameter, not an input parameter. Yes, this is a bit +confusing for method call replies, but we try to use the same message +handler for all incoming messages, hence the parameter. We are supposed +to write any error into it we encounter, if we want, and our caller will +log it, but that's it. +--- + src/core/unit.c | 5 ----- + 1 file changed, 5 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 03b4b57..c54abe9 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3218,11 +3218,6 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu + + u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot); + +- if (sd_bus_error_is_set(error)) { +- log_error("Failed to get name owner from bus: %s", error->message); +- return 0; +- } +- + e = sd_bus_message_get_error(message); + if (sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner")) + return 0; +-- +1.8.3.1 + diff --git a/0004-0001-core-dont-check-potentially-NULL-error.patch b/0004-0001-core-dont-check-potentially-NULL-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..b3b60d4ceaddedc674d85ace50200e4b408e677a --- /dev/null +++ b/0004-0001-core-dont-check-potentially-NULL-error.patch @@ -0,0 +1,32 @@ +From a54654ba700b1fc6f5cc92e88e2c5544fd7ad2fd Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Dec 2019 16:35:15 +0100 +Subject: [PATCH] core: don't check potentially NULL error, it's not gonna work + anyway + +--- + src/core/unit.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index c54abe9..7ea0e8a 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3219,11 +3219,10 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu + u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot); + + e = sd_bus_message_get_error(message); +- if (sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner")) +- return 0; +- + if (e) { +- log_error("Unexpected error response from GetNameOwner: %s", e->message); ++ if (!sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner")) ++ log_unit_error(u, "Unexpected error response from GetNameOwner(): %s", e->message); ++ + return 0; + } + +-- +1.8.3.1 + diff --git a/0005-0001-core-shorten-code-a-bit.patch b/0005-0001-core-shorten-code-a-bit.patch new file mode 100644 index 0000000000000000000000000000000000000000..765434c5de9757e557c4e6a9f74a15dbb31456a9 --- /dev/null +++ b/0005-0001-core-shorten-code-a-bit.patch @@ -0,0 +1,27 @@ +From 17bda1f19d5394290d7552d9db0c423b207dc40a Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Dec 2019 16:35:28 +0100 +Subject: [PATCH] core: shorten code a bit + +The return parameter here cannot be NULL, the bus call either succeeds +or fails but will never uceed and return an empty owner. +--- + src/core/unit.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 7ea0e8a..be92d97 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3232,8 +3232,6 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu + return 0; + } + +- new_owner = empty_to_null(new_owner); +- + if (UNIT_VTABLE(u)->bus_name_owner_change) + UNIT_VTABLE(u)->bus_name_owner_change(u, NULL, new_owner); + +-- +1.8.3.1 + diff --git a/0006-0001-core-no-need-to-eat-up-error.patch b/0006-0001-core-no-need-to-eat-up-error.patch new file mode 100644 index 0000000000000000000000000000000000000000..b0f8368ccf1116ef628053f8c702e254ef5f0f6f --- /dev/null +++ b/0006-0001-core-no-need-to-eat-up-error.patch @@ -0,0 +1,31 @@ +From 5085ef0d711f1faaacddaf5519daeb150794ea99 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Dec 2019 16:35:44 +0100 +Subject: [PATCH] core: no need to eat up error + +This is a method call reply. We might as well propagate the error. The +worst that happens is that sd-bus logs about it. +--- + src/core/unit.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index be92d97..5cf16c6 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3227,10 +3227,8 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu + } + + r = sd_bus_message_read(message, "s", &new_owner); +- if (r < 0) { +- bus_log_parse_error(r); +- return 0; +- } ++ if (r < 0) ++ return bus_log_parse_error(r); + + if (UNIT_VTABLE(u)->bus_name_owner_change) + UNIT_VTABLE(u)->bus_name_owner_change(u, NULL, new_owner); +-- +1.8.3.1 + diff --git a/0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch b/0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch new file mode 100644 index 0000000000000000000000000000000000000000..eb7d1c1f18632415c8ccef564bb753310df4cbf7 --- /dev/null +++ b/0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch @@ -0,0 +1,108 @@ +From a5b07847950c603605acf85b472b210cd2da40fb Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Dec 2019 16:48:18 +0100 +Subject: [PATCH] core: create/remove unit bus name slots always together + +When a service unit watches a bus name (i.e. because of BusName= being +set), then we do two things: we install a match slot to watch how its +ownership changes, and we inquire about the current owner. Make sure we +always do both together or neither. + +This in particular fixes a corner-case memleak when destroying bus +connections, since we never freed the GetNameOwner() bus slots when +destroying a bus when they were still ongoing. +--- + src/core/dbus.c | 11 ++++------- + src/core/unit.c | 32 +++++++++++++++++++++----------- + 2 files changed, 25 insertions(+), 18 deletions(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 3c40f29..cef1789 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -1051,13 +1051,10 @@ static void destroy_bus(Manager *m, sd_bus **bus) { + + /* Make sure all bus slots watching names are released. */ + HASHMAP_FOREACH(u, m->watch_bus, i) { +- if (!u->match_bus_slot) +- continue; +- +- if (sd_bus_slot_get_bus(u->match_bus_slot) != *bus) +- continue; +- +- u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); ++ if (u->match_bus_slot && sd_bus_slot_get_bus(u->match_bus_slot) == *bus) ++ u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); ++ if (u->get_name_owner_slot && sd_bus_slot_get_bus(u->get_name_owner_slot) == *bus) ++ u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot); + } + + /* Get rid of tracked clients on this bus */ +diff --git a/src/core/unit.c b/src/core/unit.c +index 5cf16c6..8781132 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3238,12 +3238,13 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu + + int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { + const char *match; ++ int r; + + assert(u); + assert(bus); + assert(name); + +- if (u->match_bus_slot) ++ if (u->match_bus_slot || u->get_name_owner_slot) + return -EBUSY; + + match = strjoina("type='signal'," +@@ -3253,19 +3254,27 @@ int unit_install_bus_match(Unit *u, sd_bus *bus, const char *name) { + "member='NameOwnerChanged'," + "arg0='", name, "'"); + +- int r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u); ++ r = sd_bus_add_match_async(bus, &u->match_bus_slot, match, signal_name_owner_changed, NULL, u); + if (r < 0) + return r; + +- return sd_bus_call_method_async(bus, +- &u->get_name_owner_slot, +- "org.freedesktop.DBus", +- "/org/freedesktop/DBus", +- "org.freedesktop.DBus", +- "GetNameOwner", +- get_name_owner_handler, +- u, +- "s", name); ++ r = sd_bus_call_method_async( ++ bus, ++ &u->get_name_owner_slot, ++ "org.freedesktop.DBus", ++ "/org/freedesktop/DBus", ++ "org.freedesktop.DBus", ++ "GetNameOwner", ++ get_name_owner_handler, ++ u, ++ "s", name); ++ if (r < 0) { ++ u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); ++ return r; ++ } ++ ++ log_unit_debug(u, "Watching D-Bus name '%s'.", name); ++ return 0; + } + + int unit_watch_bus_name(Unit *u, const char *name) { +@@ -3288,6 +3297,7 @@ int unit_watch_bus_name(Unit *u, const char *name) { + r = hashmap_put(u->manager->watch_bus, name, u); + if (r < 0) { + u->match_bus_slot = sd_bus_slot_unref(u->match_bus_slot); ++ u->get_name_owner_slot = sd_bus_slot_unref(u->get_name_owner_slot); + return log_warning_errno(r, "Failed to put bus name to hashmap: %m"); + } + +-- +1.8.3.1 + diff --git a/0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch b/0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch new file mode 100644 index 0000000000000000000000000000000000000000..6ed1791c28c02b0e6f844f57b3c89a7d30eae304 --- /dev/null +++ b/0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch @@ -0,0 +1,331 @@ +From fc67a943d989d5e74577adea9676cdc7928b08fc Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 23 Dec 2019 17:31:34 +0100 +Subject: [PATCH] core: drop initial ListNames() bus call from PID 1 + +Previously, when first connecting to the bus after connecting to it we'd +issue a ListNames() bus call to the driver to figure out which bus names +are currently active. This information was then used to initialize the +initial state for services that use BusName=. + +This change removes the whole code for this and replaces it with +something vastly simpler. + +First of all, the ListNames() call was issues synchronosuly, which meant +if dbus was for some reason synchronously calling into PID1 for some +reason we'd deadlock. As it turns out there's now a good chance it does: +the nss-systemd userdb hookup means that any user dbus-daemon resolves +might result in a varlink call into PID 1, and dbus resolves quite a lot +of users while parsing its policy. My original goal was to fix this +deadlock. + +But as it turns out we don't need the ListNames() call at all anymore, +since #12957 has been merged. That PR was supposed to fix a race where +asynchronous installation of bus matches would cause us missing the +initial owner of a bus name when a service is first started. It fixed it +(correctly) by enquiring with GetOwnerName() who currently owns the +name, right after installing the match. But this means whenever we start watching a bus name we anyway +issue a GetOwnerName() for it, and that means also when first connecting +to the bus we don't need to issue ListNames() anymore since that just +tells us the same info: which names are currently owned. + +hence, let's drop ListNames() and instead make better use of the +GetOwnerName() result: if it failed the name is not owned. + +Also, while we are at it, let's simplify the unit's owner_name_changed() +callback(): let's drop the "old_owner" argument. We never used that +besides logging, and it's hard to synthesize from just the return of a +GetOwnerName(), hence don't bother. +--- + src/core/dbus.c | 112 ----------------------------------------------------- + src/core/dbus.h | 2 - + src/core/manager.c | 4 -- + src/core/manager.h | 2 - + src/core/service.c | 15 ++----- + src/core/unit.c | 23 ++++++----- + src/core/unit.h | 2 +- + 7 files changed, 16 insertions(+), 144 deletions(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index cef1789..941219f 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -719,114 +719,6 @@ static int bus_on_connection(sd_event_source *s, int fd, uint32_t revents, void + return 0; + } + +-static int manager_dispatch_sync_bus_names(sd_event_source *es, void *userdata) { +- _cleanup_strv_free_ char **names = NULL; +- Manager *m = userdata; +- const char *name; +- Iterator i; +- Unit *u; +- int r; +- +- assert(es); +- assert(m); +- assert(m->sync_bus_names_event_source == es); +- +- /* First things first, destroy the defer event so that we aren't triggered again */ +- m->sync_bus_names_event_source = sd_event_source_unref(m->sync_bus_names_event_source); +- +- /* Let's see if there's anything to do still? */ +- if (!m->api_bus) +- return 0; +- if (hashmap_isempty(m->watch_bus)) +- return 0; +- +- /* OK, let's sync up the names. Let's see which names are currently on the bus. */ +- r = sd_bus_list_names(m->api_bus, &names, NULL); +- if (r < 0) +- return log_error_errno(r, "Failed to get initial list of names: %m"); +- +- /* We have to synchronize the current bus names with the +- * list of active services. To do this, walk the list of +- * all units with bus names. */ +- HASHMAP_FOREACH_KEY(u, name, m->watch_bus, i) { +- Service *s = SERVICE(u); +- +- assert(s); +- +- if (!streq_ptr(s->bus_name, name)) { +- log_unit_warning(u, "Bus name has changed from %s → %s, ignoring.", s->bus_name, name); +- continue; +- } +- +- /* Check if a service's bus name is in the list of currently +- * active names */ +- if (strv_contains(names, name)) { +- _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; +- const char *unique; +- +- /* If it is, determine its current owner */ +- r = sd_bus_get_name_creds(m->api_bus, name, SD_BUS_CREDS_UNIQUE_NAME, &creds); +- if (r < 0) { +- log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get bus name owner %s: %m", name); +- continue; +- } +- +- r = sd_bus_creds_get_unique_name(creds, &unique); +- if (r < 0) { +- log_full_errno(r == -ENXIO ? LOG_DEBUG : LOG_ERR, r, "Failed to get unique name for %s: %m", name); +- continue; +- } +- +- /* Now, let's compare that to the previous bus owner, and +- * if it's still the same, all is fine, so just don't +- * bother the service. Otherwise, the name has apparently +- * changed, so synthesize a name owner changed signal. */ +- +- if (!streq_ptr(unique, s->bus_name_owner)) +- UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, unique); +- } else { +- /* So, the name we're watching is not on the bus. +- * This either means it simply hasn't appeared yet, +- * or it was lost during the daemon reload. +- * Check if the service has a stored name owner, +- * and synthesize a name loss signal in this case. */ +- +- if (s->bus_name_owner) +- UNIT_VTABLE(u)->bus_name_owner_change(u, s->bus_name_owner, NULL); +- } +- } +- +- return 0; +-} +- +-int manager_enqueue_sync_bus_names(Manager *m) { +- int r; +- +- assert(m); +- +- /* Enqueues a request to synchronize the bus names in a later event loop iteration. The callers generally don't +- * want us to invoke ->bus_name_owner_change() unit calls from their stack frames as this might result in event +- * dispatching on its own creating loops, hence we simply create a defer event for the event loop and exit. */ +- +- if (m->sync_bus_names_event_source) +- return 0; +- +- r = sd_event_add_defer(m->event, &m->sync_bus_names_event_source, manager_dispatch_sync_bus_names, m); +- if (r < 0) +- return log_error_errno(r, "Failed to create bus name synchronization event: %m"); +- +- r = sd_event_source_set_priority(m->sync_bus_names_event_source, SD_EVENT_PRIORITY_IDLE); +- if (r < 0) +- return log_error_errno(r, "Failed to set event priority: %m"); +- +- r = sd_event_source_set_enabled(m->sync_bus_names_event_source, SD_EVENT_ONESHOT); +- if (r < 0) +- return log_error_errno(r, "Failed to set even to oneshot: %m"); +- +- (void) sd_event_source_set_description(m->sync_bus_names_event_source, "manager-sync-bus-names"); +- return 0; +-} +- + static int bus_setup_api(Manager *m, sd_bus *bus) { + Iterator i; + char *name; +@@ -910,10 +802,6 @@ int bus_init_api(Manager *m) { + + m->api_bus = TAKE_PTR(bus); + +- r = manager_enqueue_sync_bus_names(m); +- if (r < 0) +- return r; +- + return 0; + } + +diff --git a/src/core/dbus.h b/src/core/dbus.h +index f1c0fa8..d5ba653 100644 +--- a/src/core/dbus.h ++++ b/src/core/dbus.h +@@ -21,8 +21,6 @@ int bus_fdset_add_all(Manager *m, FDSet *fds); + void bus_track_serialize(sd_bus_track *t, FILE *f, const char *prefix); + int bus_track_coldplug(Manager *m, sd_bus_track **t, bool recursive, char **l); + +-int manager_enqueue_sync_bus_names(Manager *m); +- + int bus_foreach_bus(Manager *m, sd_bus_track *subscribed2, int (*send_message)(sd_bus *bus, void *userdata), void *userdata); + + int bus_verify_manage_units_async(Manager *m, sd_bus_message *call, sd_bus_error *error); +diff --git a/src/core/manager.c b/src/core/manager.c +index 171ff04..dbd25af 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1373,7 +1373,6 @@ Manager* manager_free(Manager *m) { + sd_event_source_unref(m->jobs_in_progress_event_source); + sd_event_source_unref(m->run_queue_event_source); + sd_event_source_unref(m->user_lookup_event_source); +- sd_event_source_unref(m->sync_bus_names_event_source); + + safe_close(m->signal_fd); + safe_close(m->notify_fd); +@@ -1610,9 +1609,6 @@ static void manager_ready(Manager *m) { + manager_recheck_journal(m); + manager_recheck_dbus(m); + +- /* Sync current state of bus names with our set of listening units */ +- (void) manager_enqueue_sync_bus_names(m); +- + /* Let's finally catch up with any changes that took place while we were reloading/reexecing */ + manager_catchup(m); + +diff --git a/src/core/manager.h b/src/core/manager.h +index 51df7f8..8ca8e38 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -219,8 +219,6 @@ struct Manager { + int user_lookup_fds[2]; + sd_event_source *user_lookup_event_source; + +- sd_event_source *sync_bus_names_event_source; +- + UnitFileScope unit_file_scope; + LookupPaths lookup_paths; + Hashmap *unit_id_map; +diff --git a/src/core/service.c b/src/core/service.c +index 49ad166..447c7af 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -4062,24 +4062,17 @@ static int service_get_timeout(Unit *u, usec_t *timeout) { + return 1; + } + +-static void service_bus_name_owner_change( +- Unit *u, +- const char *old_owner, +- const char *new_owner) { ++static void service_bus_name_owner_change(Unit *u, const char *new_owner) { + + Service *s = SERVICE(u); + int r; + + assert(s); + +- assert(old_owner || new_owner); +- +- if (old_owner && new_owner) +- log_unit_debug(u, "D-Bus name %s changed owner from %s to %s", s->bus_name, old_owner, new_owner); +- else if (old_owner) +- log_unit_debug(u, "D-Bus name %s no longer registered by %s", s->bus_name, old_owner); ++ if (new_owner) ++ log_unit_debug(u, "D-Bus name %s now owned by %s", s->bus_name, new_owner); + else +- log_unit_debug(u, "D-Bus name %s now registered by %s", s->bus_name, new_owner); ++ log_unit_debug(u, "D-Bus name %s now not owned by anyone.", s->bus_name); + + s->bus_name_good = !!new_owner; + +diff --git a/src/core/unit.c b/src/core/unit.c +index 8781132..e137acc 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3185,24 +3185,21 @@ int unit_load_related_unit(Unit *u, const char *type, Unit **_found) { + } + + static int signal_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error) { +- const char *name, *old_owner, *new_owner; ++ const char *new_owner; + Unit *u = userdata; + int r; + + assert(message); + assert(u); + +- r = sd_bus_message_read(message, "sss", &name, &old_owner, &new_owner); ++ r = sd_bus_message_read(message, "sss", NULL, NULL, &new_owner); + if (r < 0) { + bus_log_parse_error(r); + return 0; + } + +- old_owner = empty_to_null(old_owner); +- new_owner = empty_to_null(new_owner); +- + if (UNIT_VTABLE(u)->bus_name_owner_change) +- UNIT_VTABLE(u)->bus_name_owner_change(u, old_owner, new_owner); ++ UNIT_VTABLE(u)->bus_name_owner_change(u, empty_to_null(new_owner)); + + return 0; + } +@@ -3223,15 +3220,17 @@ static int get_name_owner_handler(sd_bus_message *message, void *userdata, sd_bu + if (!sd_bus_error_has_name(e, "org.freedesktop.DBus.Error.NameHasNoOwner")) + log_unit_error(u, "Unexpected error response from GetNameOwner(): %s", e->message); + +- return 0; +- } ++ new_owner = NULL; ++ } else { ++ r = sd_bus_message_read(message, "s", &new_owner); ++ if (r < 0) ++ return bus_log_parse_error(r); + +- r = sd_bus_message_read(message, "s", &new_owner); +- if (r < 0) +- return bus_log_parse_error(r); ++ assert(!isempty(new_owner)); ++ } + + if (UNIT_VTABLE(u)->bus_name_owner_change) +- UNIT_VTABLE(u)->bus_name_owner_change(u, NULL, new_owner); ++ UNIT_VTABLE(u)->bus_name_owner_change(u, new_owner); + + return 0; + } +diff --git a/src/core/unit.h b/src/core/unit.h +index c5d8170..4410014 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -530,7 +530,7 @@ typedef struct UnitVTable { + void (*notify_message)(Unit *u, const struct ucred *ucred, char **tags, FDSet *fds); + + /* Called whenever a name this Unit registered for comes or goes away. */ +- void (*bus_name_owner_change)(Unit *u, const char *old_owner, const char *new_owner); ++ void (*bus_name_owner_change)(Unit *u, const char *new_owner); + + /* Called for each property that is being set */ + int (*bus_set_property)(Unit *u, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error); +-- +1.8.3.1 + diff --git a/0001-update-rtc-with-system-clock-when-shutdown.patch b/0009-1605-update-rtc-with-system-clock-when-shutdown.patch similarity index 89% rename from 0001-update-rtc-with-system-clock-when-shutdown.patch rename to 0009-1605-update-rtc-with-system-clock-when-shutdown.patch index 2f90dc6ab01d678c5e148d545ca5fc90d62956d2..86a87e457bf0e9774d8c537dc2c5bd1d914c9d16 100644 --- a/0001-update-rtc-with-system-clock-when-shutdown.patch +++ b/0009-1605-update-rtc-with-system-clock-when-shutdown.patch @@ -1,11 +1,12 @@ -From a13f14c6a2da55b9f797b6f33449ba523c07dd46 Mon Sep 17 00:00:00 2001 +m a13f14c6a2da55b9f797b6f33449ba523c07dd46 Mon Sep 17 00:00:00 2001 From: update-rtc-with-system-clock-when-shutdown Date: Sat, 2 Feb 2019 02:54:52 -0500 Subject: [PATCH] Module: modification summary + --- units/hwclock-save.service.in | 19 +++++++++++++++++++ units/meson.build | 2 ++ - 2 files changed, 21 insertions(+) + create mode 100644 units/hwclock-save.service.in diff --git a/units/hwclock-save.service.in b/units/hwclock-save.service.in @@ -34,10 +35,10 @@ index 0000000..db33418 +WantedBy=default.target + diff --git a/units/meson.build b/units/meson.build -index aa2ed11..9992389 100644 +index e4ac6ce..67126d6 100644 --- a/units/meson.build +++ b/units/meson.build -@@ -220,6 +220,8 @@ in_units = [ +@@ -211,6 +211,8 @@ in_units = [ 'sysinit.target.wants/'], ['systemd-update-done.service', '', 'sysinit.target.wants/'], @@ -47,5 +48,5 @@ index aa2ed11..9992389 100644 'multi-user.target.wants/ graphical.target.wants/ rescue.target.wants/'], ['systemd-update-utmp.service', 'ENABLE_UTMP', -- -2.23.0 +1.8.3.1 diff --git a/0002-udev-add-actions-while-rename-netif-failed.patch b/0010-1603-udev-add-actions-while-rename-netif-failed.patch similarity index 82% rename from 0002-udev-add-actions-while-rename-netif-failed.patch rename to 0010-1603-udev-add-actions-while-rename-netif-failed.patch index 3482482348e87448e1c404bd04cb28c333abe08e..6d829466f00f9c933e1c4b907877fbfbbb5fb704 100644 --- a/0002-udev-add-actions-while-rename-netif-failed.patch +++ b/0010-1603-udev-add-actions-while-rename-netif-failed.patch @@ -7,21 +7,21 @@ Subject: [PATCH] udev-add-actions-while-rename-netif-failed 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c -index e1c2baf..b64d279 100644 +index 8cfa2cd..46bbcb1 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c -@@ -820,6 +820,7 @@ static int rename_netif(UdevEvent *event) { +@@ -788,6 +788,7 @@ static int rename_netif(UdevEvent *event) { sd_device *dev = event->dev; const char *oldname; int ifindex, r; + char name[IFNAMSIZ]; - + if (!event->name) return 0; /* No new name is requested. */ -@@ -860,12 +861,45 @@ static int rename_netif(UdevEvent *event) { +@@ -808,10 +809,43 @@ static int rename_netif(UdevEvent *event) { if (r < 0) - return log_device_debug_errno(event->dev_db_clone, r, "Failed to update database under /run/udev/data/: %m"); - + return log_device_error_errno(dev, r, "Failed to get ifindex: %m"); + - r = rtnl_set_link_name(&event->rtnl, ifindex, event->name); + strscpy(name, IFNAMSIZ, event->name); + @@ -62,12 +62,18 @@ index e1c2baf..b64d279 100644 + nanosleep(&duration, NULL); + } + } + + /* Set ID_RENAMING boolean property here, and drop it in the corresponding move uevent later. */ + r = device_add_property(dev, "ID_RENAMING", "1"); +@@ -822,7 +856,7 @@ static int rename_netif(UdevEvent *event) { + if (r < 0) + return log_device_warning_errno(dev, r, "Failed to update properties with new name '%s': %m", event->name); - log_device_debug(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name); + log_device_info(dev, "Network interface %i is renamed from '%s' to '%s'", ifindex, oldname, event->name); return 1; } --- -2.23.0 +-- +2.19.1 diff --git a/0011-CVE-2020-1712-1.patch b/0011-CVE-2020-1712-1.patch new file mode 100644 index 0000000000000000000000000000000000000000..59aa7b8c041857f8aafcd266b4286c8622fcf429 --- /dev/null +++ b/0011-CVE-2020-1712-1.patch @@ -0,0 +1,84 @@ +From 7f56982289275ce84e20f0554475864953e6aaab Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 22 Jan 2020 16:52:10 +0100 +Subject: [PATCH 1610/1760] polkit: on async pk requests, re-validate + action/details + +When we do an async pk request, let's store which action/details we used +for the original request, and when we are called for the second time, +let's compare. If the action/details changed, let's not allow the access +to go through. + +https://github.com/systemd/systemd/commit/7f56982289275ce84e20f0554475864953e6aaab + +--- + src/shared/bus-util.c | 30 +++++++++++++++++++++++++++--- + 1 file changed, 27 insertions(+), 3 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index ce4ece6..4bfdd3a 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -318,6 +318,9 @@ int bus_test_polkit( + #if ENABLE_POLKIT + + typedef struct AsyncPolkitQuery { ++ char *action; ++ char **details; ++ + sd_bus_message *request, *reply; + sd_bus_message_handler_t callback; + void *userdata; +@@ -338,6 +341,9 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { + sd_bus_message_unref(q->request); + sd_bus_message_unref(q->reply); + ++ free(q->action); ++ strv_free(q->details); ++ + free(q); + } + +@@ -402,11 +408,17 @@ int bus_verify_polkit_async( + if (q) { + int authorized, challenge; + +- /* This is the second invocation of this function, and +- * there's already a response from polkit, let's +- * process it */ ++ /* This is the second invocation of this function, and there's already a response from ++ * polkit, let's process it */ + assert(q->reply); + ++ /* If the operation we want to authenticate changed between the first and the second time, ++ * let's not use this authentication, it might be out of date as the object and context we ++ * operate on might have changed. */ ++ if (!streq(q->action, action) || ++ !strv_equal(q->details, (char**) details)) ++ return -ESTALE; ++ + if (sd_bus_message_is_method_error(q->reply, NULL)) { + const sd_bus_error *e; + +@@ -512,6 +524,18 @@ int bus_verify_polkit_async( + q->callback = callback; + q->userdata = userdata; + ++ q->action = strdup(action); ++ if (!q->action) { ++ async_polkit_query_free(q); ++ return -ENOMEM; ++ } ++ ++ q->details = strv_copy((char**) details); ++ if (!q->details) { ++ async_polkit_query_free(q); ++ return -ENOMEM; ++ } ++ + r = hashmap_put(*registry, call, q); + if (r < 0) { + async_polkit_query_free(q); +-- +2.19.1 + diff --git a/0012-CVE-2020-1712-2.patch b/0012-CVE-2020-1712-2.patch new file mode 100644 index 0000000000000000000000000000000000000000..502b86e2c57aa4b7d22d884a73b0e9bc3ea02009 --- /dev/null +++ b/0012-CVE-2020-1712-2.patch @@ -0,0 +1,70 @@ +From 1068447e6954dc6ce52f099ed174c442cb89ed54 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 22 Jan 2020 17:05:17 +0100 +Subject: [PATCH 1612/1760] sd-bus: introduce API for re-enqueuing incoming + messages + +When authorizing via PolicyKit we want to process incoming method calls +twice: once to process and figure out that we need PK authentication, +and a second time after we aquired PK authentication to actually execute +the operation. With this new call sd_bus_enqueue_for_read() we have a +way to put an incoming message back into the read queue for this +purpose. + +This might have other uses too, for example debugging. + +https://github.com/systemd/systemd/commit/1068447e6954dc6ce52f099ed174c442cb89ed54 + +--- + src/libsystemd/sd-bus/sd-bus.c | 25 +++++++++++++++++++++++++ + src/systemd/sd-bus.h | 1 + + 2 files changed, 26 insertions(+) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 615346d..05593d1 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -4198,3 +4198,28 @@ _public_ int sd_bus_get_close_on_exit(sd_bus *bus) { + + return bus->close_on_exit; + } ++ ++ ++_public_ int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m) { ++ int r; ++ ++ assert_return(bus, -EINVAL); ++ assert_return(bus = bus_resolve(bus), -ENOPKG); ++ assert_return(m, -EINVAL); ++ assert_return(m->sealed, -EINVAL); ++ assert_return(!bus_pid_changed(bus), -ECHILD); ++ ++ if (!BUS_IS_OPEN(bus->state)) ++ return -ENOTCONN; ++ ++ /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication, ++ * where we want accept a message, then determine we need to interactively authenticate the user, and ++ * when we have that process the message again. */ ++ ++ r = bus_rqueue_make_room(bus); ++ if (r < 0) ++ return r; ++ ++ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus); ++ return 0; ++} +diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h +index 84ceb62..2e104f8 100644 +--- a/src/systemd/sd-bus.h ++++ b/src/systemd/sd-bus.h +@@ -201,6 +201,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r); + int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); + int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); + int sd_bus_flush(sd_bus *bus); ++int sd_bus_enqeue_for_read(sd_bus *bus, sd_bus_message *m); + + sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); + sd_bus_message* sd_bus_get_current_message(sd_bus *bus); +-- +2.19.1 + diff --git a/0013-CVE-2020-1712-3.patch b/0013-CVE-2020-1712-3.patch new file mode 100644 index 0000000000000000000000000000000000000000..ecd5d4df817c47d81e43812738debae7e5bcc81b --- /dev/null +++ b/0013-CVE-2020-1712-3.patch @@ -0,0 +1,109 @@ +From 95f82ae9d774f3508ce89dcbdd0714ef7385df59 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 22 Jan 2020 16:44:43 +0100 +Subject: [PATCH] polkit: reuse some common bus message appending code + +https://github.com/systemd/systemd/commit/95f82ae9d774f3508ce89dcbdd0714ef7385df59 + +--- + src/shared/bus-util.c | 56 ++++++++++++++++++++++++------------------- + 1 file changed, 32 insertions(+), 24 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 4bfdd3a..04153d6 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -211,6 +211,34 @@ static int check_good_user(sd_bus_message *m, uid_t good_user) { + return sender_uid == good_user; + } + ++#if ENABLE_POLKIT ++static int bus_message_append_strv_key_value( ++ sd_bus_message *m, ++ const char **l) { ++ ++ const char **k, **v; ++ int r; ++ ++ assert(m); ++ ++ r = sd_bus_message_open_container(m, 'a', "{ss}"); ++ if (r < 0) ++ return r; ++ ++ STRV_FOREACH_PAIR(k, v, l) { ++ r = sd_bus_message_append(m, "{ss}", *k, *v); ++ if (r < 0) ++ return r; ++ } ++ ++ r = sd_bus_message_close_container(m); ++ if (r < 0) ++ return r; ++ ++ return r; ++} ++#endif ++ + int bus_test_polkit( + sd_bus_message *call, + int capability, +@@ -241,7 +269,7 @@ int bus_test_polkit( + _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + int authorized = false, challenge = false; +- const char *sender, **k, **v; ++ const char *sender; + + sender = sd_bus_message_get_sender(call); + if (!sender) +@@ -265,17 +293,7 @@ int bus_test_polkit( + if (r < 0) + return r; + +- r = sd_bus_message_open_container(request, 'a', "{ss}"); +- if (r < 0) +- return r; +- +- STRV_FOREACH_PAIR(k, v, details) { +- r = sd_bus_message_append(request, "{ss}", *k, *v); +- if (r < 0) +- return r; +- } +- +- r = sd_bus_message_close_container(request); ++ r = bus_message_append_strv_key_value(request, details); + if (r < 0) + return r; + +@@ -388,7 +406,7 @@ int bus_verify_polkit_async( + #if ENABLE_POLKIT + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; + AsyncPolkitQuery *q; +- const char *sender, **k, **v; ++ const char *sender; + sd_bus_message_handler_t callback; + void *userdata; + int c; +@@ -498,17 +516,7 @@ int bus_verify_polkit_async( + if (r < 0) + return r; + +- r = sd_bus_message_open_container(pk, 'a', "{ss}"); +- if (r < 0) +- return r; +- +- STRV_FOREACH_PAIR(k, v, details) { +- r = sd_bus_message_append(pk, "{ss}", *k, *v); +- if (r < 0) +- return r; +- } +- +- r = sd_bus_message_close_container(pk); ++ r = bus_message_append_strv_key_value(pk, details); + if (r < 0) + return r; + +-- +2.19.1 + diff --git a/0014-CVE-2020-1712-4.patch b/0014-CVE-2020-1712-4.patch new file mode 100644 index 0000000000000000000000000000000000000000..17ccb888caf9ddf79f003b9168d2c47b002d5f48 --- /dev/null +++ b/0014-CVE-2020-1712-4.patch @@ -0,0 +1,38 @@ +From f4425c72c7395ec93ae00052916a66e2f60f200b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 22 Jan 2020 16:53:59 +0100 +Subject: [PATCH] polkit: use structured initialization + +https://github.com/systemd/systemd/commit/f4425c72c7395ec93ae00052916a66e2f60f200b + +--- + src/shared/bus-util.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 04153d6..0690a82 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -524,13 +524,15 @@ int bus_verify_polkit_async( + if (r < 0) + return r; + +- q = new0(AsyncPolkitQuery, 1); ++ q = new(AsyncPolkitQuery, 1); + if (!q) + return -ENOMEM; + +- q->request = sd_bus_message_ref(call); +- q->callback = callback; +- q->userdata = userdata; ++ *q = (AsyncPolkitQuery) { ++ .request = sd_bus_message_ref(call), ++ .callback = callback, ++ .userdata = userdata, ++ }; + + q->action = strdup(action); + if (!q->action) { +-- +2.19.1 + diff --git a/0015-CVE-2020-1712-5.patch b/0015-CVE-2020-1712-5.patch new file mode 100644 index 0000000000000000000000000000000000000000..616f36eaf3d5b8f6278cfdb4ed7029627aae501c --- /dev/null +++ b/0015-CVE-2020-1712-5.patch @@ -0,0 +1,164 @@ +From 637486261528e8aa3da9f26a4487dc254f4b7abb Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 22 Jan 2020 17:07:47 +0100 +Subject: [PATCH 1613/1760] polkit: when authorizing via PK let's re-resolve + callback/userdata instead of caching it + +Previously, when doing an async PK query we'd store the original +callback/userdata pair and call it again after the PK request is +complete. This is problematic, since PK queries might be slow and in the +meantime the userdata might be released and re-acquired. Let's avoid +this by always traversing through the message handlers so that we always +re-resolve the callback and userdata pair and thus can be sure it's +up-to-date and properly valid. + +https://github.com/systemd/systemd/commit/637486261528e8aa3da9f26a4487dc254f4b7abb + +--- + src/shared/bus-util.c | 75 ++++++++++++++++++++++++++++--------------- + 1 file changed, 50 insertions(+), 25 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 0690a82..41288a7 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -340,14 +340,13 @@ typedef struct AsyncPolkitQuery { + char **details; + + sd_bus_message *request, *reply; +- sd_bus_message_handler_t callback; +- void *userdata; + sd_bus_slot *slot; ++ + Hashmap *registry; ++ sd_event_source *defer_event_source; + } AsyncPolkitQuery; + + static void async_polkit_query_free(AsyncPolkitQuery *q) { +- + if (!q) + return; + +@@ -362,9 +361,22 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { + free(q->action); + strv_free(q->details); + ++ sd_event_source_disable_unref(q->defer_event_source); + free(q); + } + ++static int async_polkit_defer(sd_event_source *s, void *userdata) { ++ AsyncPolkitQuery *q = userdata; ++ ++ assert(s); ++ ++ /* This is called as idle event source after we processed the async polkit reply, hopefully after the ++ * method call we re-enqueued has been properly processed. */ ++ ++ async_polkit_query_free(q); ++ return 0; ++} ++ + static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + AsyncPolkitQuery *q = userdata; +@@ -373,19 +385,45 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e + assert(reply); + assert(q); + ++ assert(q->slot); + q->slot = sd_bus_slot_unref(q->slot); ++ ++ assert(!q->reply); + q->reply = sd_bus_message_ref(reply); + ++ /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the ++ * whole message processing again, and thus re-validating and re-retrieving the "userdata" field ++ * again. ++ * ++ * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again, ++ * i.e. after the second time the message is processed is complete. */ ++ ++ assert(!q->defer_event_source); ++ r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT); ++ if (r < 0) ++ goto fail; ++ + r = sd_bus_message_rewind(q->request, true); +- if (r < 0) { +- r = sd_bus_reply_method_errno(q->request, r, NULL); +- goto finish; +- } ++ if (r < 0) ++ goto fail; + +- r = q->callback(q->request, q->userdata, &error_buffer); +- r = bus_maybe_reply_error(q->request, r, &error_buffer); ++ r = sd_bus_enqeue_for_read(sd_bus_message_get_bus(q->request), q->request); ++ if (r < 0) ++ goto fail; ++ ++ return 1; + +-finish: ++fail: ++ log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m"); ++ (void) sd_bus_reply_method_errno(q->request, r, NULL); + async_polkit_query_free(q); + + return r; +@@ -406,11 +444,9 @@ int bus_verify_polkit_async( + #if ENABLE_POLKIT + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; + AsyncPolkitQuery *q; +- const char *sender; +- sd_bus_message_handler_t callback; +- void *userdata; + int c; + #endif ++ const char *sender; + int r; + + assert(call); +@@ -474,20 +510,11 @@ int bus_verify_polkit_async( + else if (r > 0) + return 1; + +-#if ENABLE_POLKIT +- if (sd_bus_get_current_message(call->bus) != call) +- return -EINVAL; +- +- callback = sd_bus_get_current_handler(call->bus); +- if (!callback) +- return -EINVAL; +- +- userdata = sd_bus_get_current_userdata(call->bus); +- + sender = sd_bus_message_get_sender(call); + if (!sender) + return -EBADMSG; + ++#if ENABLE_POLKIT + c = sd_bus_message_get_allow_interactive_authorization(call); + if (c < 0) + return c; +@@ -530,8 +557,6 @@ int bus_verify_polkit_async( + + *q = (AsyncPolkitQuery) { + .request = sd_bus_message_ref(call), +- .callback = callback, +- .userdata = userdata, + }; + + q->action = strdup(action); +-- +2.19.1 + diff --git a/0016-sd-journal-close-journal-files-that-were-deleted-by-.patch b/0016-sd-journal-close-journal-files-that-were-deleted-by-.patch new file mode 100644 index 0000000000000000000000000000000000000000..4d6247fe6581093d519b72841175a870e6a1e062 --- /dev/null +++ b/0016-sd-journal-close-journal-files-that-were-deleted-by-.patch @@ -0,0 +1,75 @@ +From 28ca867abdb20d0e4ac1901e2ed669cdb41ea3f6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Tue, 4 Feb 2020 14:23:14 +0100 +Subject: [PATCH] sd-journal: close journal files that were deleted by journald + before we've setup inotify watch +url:https://github.com/systemd/systemd/commit/28ca867abdb20d0e4ac1901e2ed669cdb41ea3f6.patch + +Fixes #14695 +--- + src/journal/journal-file.c | 2 +- + src/journal/journal-file.h | 1 + + src/journal/sd-journal.c | 15 +++++++++++++++ + 3 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index 505191999b..bd53635860 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -601,7 +601,7 @@ static int journal_file_verify_header(JournalFile *f) { + return 0; + } + +-static int journal_file_fstat(JournalFile *f) { ++int journal_file_fstat(JournalFile *f) { + int r; + + assert(f); +diff --git a/src/journal/journal-file.h b/src/journal/journal-file.h +index 502f1f567d..cf0f7691fb 100644 +--- a/src/journal/journal-file.h ++++ b/src/journal/journal-file.h +@@ -145,6 +145,7 @@ int journal_file_open( + int journal_file_set_offline(JournalFile *f, bool wait); + bool journal_file_is_offlining(JournalFile *f); + JournalFile* journal_file_close(JournalFile *j); ++int journal_file_fstat(JournalFile *f); + DEFINE_TRIVIAL_CLEANUP_FUNC(JournalFile*, journal_file_close); + + int journal_file_open_reliably( +diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c +index bced8af3e3..3fa98dfda2 100644 +--- a/src/journal/sd-journal.c ++++ b/src/journal/sd-journal.c +@@ -2661,6 +2661,8 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { + assert_return(!journal_pid_changed(j), -ECHILD); + + if (j->inotify_fd < 0) { ++ Iterator i; ++ JournalFile *f; + + /* This is the first invocation, hence create the + * inotify watch */ +@@ -2668,6 +2670,19 @@ _public_ int sd_journal_wait(sd_journal *j, uint64_t timeout_usec) { + if (r < 0) + return r; + ++ /* Server might have done some vacuuming while we weren't watching. ++ Get rid of the deleted files now so they don't stay around indefinitely. */ ++ ORDERED_HASHMAP_FOREACH(f, j->files, i) { ++ r = journal_file_fstat(f); ++ if (r < 0) { ++ log_debug_errno(r,"Failed to fstat() journal file '%s' : %m", f->path); ++ continue; ++ } ++ ++ if (f->last_stat.st_nlink <= 0) ++ remove_file_real(j, f); ++ } ++ + /* The journal might have changed since the context + * object was created and we weren't watching before, + * hence don't wait for anything, and return +-- +2.19.1 + diff --git a/0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch b/0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch new file mode 100644 index 0000000000000000000000000000000000000000..5b2f120dcb90eb5c02125f7df08fad321dcfa15d --- /dev/null +++ b/0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch @@ -0,0 +1,66 @@ +From bb46b12cbb84411e378cd45f2ac320a9ce53551c Mon Sep 17 00:00:00 2001 +From: openEuler Buildteam +Date: Tue, 10 Mar 2020 21:01:43 +0800 +Subject: [PATCH] pid1 bump DefaultTasksMax to 80% of the kernel pid.max value + +--- + man/systemd-system.conf.xml | 2 +- + src/basic/cgroup-util.h | 4 ++-- + src/core/system.conf.in | 2 +- + units/user-.slice.d/10-defaults.conf | 2 +- + 4 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml +index e403fa5..afd51ed 100644 +--- a/man/systemd-system.conf.xml ++++ b/man/systemd-system.conf.xml +@@ -360,7 +360,7 @@ + Configure the default value for the per-unit TasksMax= setting. See + systemd.resource-control5 + for details. This setting applies to all unit types that support resource control settings, with the exception +- of slice units. Defaults to 15%, which equals 4915 with the kernel's defaults on the host, but might be smaller ++ of slice units. Defaults to 80%, which equals 26214 with the kernel's defaults on the host, but might be smaller + in OS containers. + + +diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h +index a39ab45..f2f2c09 100644 +--- a/src/basic/cgroup-util.h ++++ b/src/basic/cgroup-util.h +@@ -128,8 +128,8 @@ static inline bool CGROUP_BLKIO_WEIGHT_IS_OK(uint64_t x) { + } + + /* Default resource limits */ +-#define DEFAULT_TASKS_MAX_PERCENTAGE 15U /* 15% of PIDs, 4915 on default settings */ +-#define DEFAULT_USER_TASKS_MAX_PERCENTAGE 33U /* 33% of PIDs, 10813 on default settings */ ++#define DEFAULT_TASKS_MAX_PERCENTAGE 80U /* 80% of PIDs, 4915 on default settings */ ++#define DEFAULT_USER_TASKS_MAX_PERCENTAGE 80U /* 80% of PIDs, 10813 on default settings */ + + typedef enum CGroupUnified { + CGROUP_UNIFIED_UNKNOWN = -1, +diff --git a/src/core/system.conf.in b/src/core/system.conf.in +index 8112125..9e75b14 100644 +--- a/src/core/system.conf.in ++++ b/src/core/system.conf.in +@@ -51,7 +51,7 @@ + #DefaultBlockIOAccounting=no + #DefaultMemoryAccounting=@MEMORY_ACCOUNTING_DEFAULT@ + #DefaultTasksAccounting=yes +-#DefaultTasksMax=15% ++#DefaultTasksMax=80% + #DefaultLimitCPU= + #DefaultLimitFSIZE= + #DefaultLimitDATA= +diff --git a/units/user-.slice.d/10-defaults.conf b/units/user-.slice.d/10-defaults.conf +index c81a00e..3b14c35 100644 +--- a/units/user-.slice.d/10-defaults.conf ++++ b/units/user-.slice.d/10-defaults.conf +@@ -14,4 +14,4 @@ After=systemd-user-sessions.service + StopWhenUnneeded=yes + + [Slice] +-TasksMax=33% ++TasksMax=80% +-- +1.8.3.1 + diff --git a/0003-fix-two-VF-virtual-machines-have-same-mac-address.patch b/0018-fix-two-VF-virtual-machines-have-same-mac-address.patch similarity index 90% rename from 0003-fix-two-VF-virtual-machines-have-same-mac-address.patch rename to 0018-fix-two-VF-virtual-machines-have-same-mac-address.patch index f7b0335fe784019645127096662256a24b168c66..7c5adce5e290842cdd0ad1c76f4e2068e7e201bc 100644 --- a/0003-fix-two-VF-virtual-machines-have-same-mac-address.patch +++ b/0018-fix-two-VF-virtual-machines-have-same-mac-address.patch @@ -1,3 +1,4 @@ +From 48b21956443a03ac94f29480e213b05b86fcf525 Mon Sep 17 00:00:00 2001 From: fangxiuning Date: Thu, 5 Sep 2019 07:40:41 +0800 Subject: fix two vf virtual machine has same mac address @@ -26,20 +27,22 @@ and "locally administered" bits set. none Keeps the MAC address assigned by the kernel. + + --- network/99-default.link | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/99-default.link b/network/99-default.link -index dc7a42bf58..2b8f46a84c 100644 +index 347d4b7..54f1f58 100644 --- a/network/99-default.link +++ b/network/99-default.link -@@ -13,4 +13,4 @@ OriginalName=* +@@ -12,4 +12,4 @@ OriginalName=* + [Link] NamePolicy=keep kernel database onboard slot path - AlternativeNamesPolicy=database onboard slot path -MACAddressPolicy=persistent +MACAddressPolicy=none -- -2.23.0 +1.8.3.1 diff --git a/0004-logind-set-RemoveIPC-to-false-by-default.patch b/0019-logind-set-RemoveIPC-to-false-by-default.patch similarity index 87% rename from 0004-logind-set-RemoveIPC-to-false-by-default.patch rename to 0019-logind-set-RemoveIPC-to-false-by-default.patch index 02df6b3588d3c027eac9aebe05b40933bc92e318..846e34ee1e0028aadec3470466cea9f0717474e5 100644 --- a/0004-logind-set-RemoveIPC-to-false-by-default.patch +++ b/0019-logind-set-RemoveIPC-to-false-by-default.patch @@ -11,10 +11,10 @@ Resolves: #1523233 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man/logind.conf.xml b/man/logind.conf.xml -index b00daf366d..a9fed78aa6 100644 +index 4cbfd09..c6ff5c3 100644 --- a/man/logind.conf.xml +++ b/man/logind.conf.xml -@@ -340,7 +340,7 @@ +@@ -327,7 +327,7 @@ user fully logs out. Takes a boolean argument. If enabled, the user may not consume IPC resources after the last of the user's sessions terminated. This covers System V semaphores, shared memory and message queues, as well as POSIX shared memory and message queues. Note that IPC objects of the root user and other system users @@ -24,10 +24,10 @@ index b00daf366d..a9fed78aa6 100644 diff --git a/src/login/logind-core.c b/src/login/logind-core.c -index 4289461df6..556945be20 100644 +index 1d21e90..2ac7860 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c -@@ -35,7 +35,7 @@ void manager_reset_config(Manager *m) { +@@ -34,7 +34,7 @@ void manager_reset_config(Manager *m) { m->n_autovts = 6; m->reserve_vt = 6; @@ -37,17 +37,17 @@ index 4289461df6..556945be20 100644 m->user_stop_delay = 10 * USEC_PER_SEC; diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in -index ed1084b06e..07ff0d195e 100644 +index 1029e29..c7346f9 100644 --- a/src/login/logind.conf.in +++ b/src/login/logind.conf.in -@@ -33,6 +33,6 @@ +@@ -32,6 +32,6 @@ + #IdleAction=ignore #IdleActionSec=30min #RuntimeDirectorySize=10% - #RuntimeDirectoryInodes=400k -#RemoveIPC=yes +#RemoveIPC=no #InhibitorsMax=8192 #SessionsMax=8192 -- -2.23.0 +2.19.1 diff --git a/0005-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch b/0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch similarity index 67% rename from 0005-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch rename to 0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch index af9c43cabaf031a9c4102bc56c44e2fef218b869..a9a20f1462bd6603e2687c0277cedddc7ac4b019 100644 --- a/0005-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch +++ b/0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch @@ -6,16 +6,16 @@ Subject: rules: add rule for naming Dell iDRAC USB Virtual NIC Related: #1523227 --- - rules.d/73-idrac.rules | 6 ++++++ - rules.d/meson.build | 1 + + rules/73-idrac.rules | 6 ++++++ + rules/meson.build | 1 + 2 files changed, 7 insertions(+) - create mode 100644 rules.d/73-idrac.rules + create mode 100644 rules/73-idrac.rules -diff --git a/rules.d/73-idrac.rules b/rules.d/73-idrac.rules +diff --git a/rules/73-idrac.rules b/rules/73-idrac.rules new file mode 100644 -index 0000000000..d67fc425b1 +index 0000000..d67fc42 --- /dev/null -+++ b/rules.d/73-idrac.rules ++++ b/rules/73-idrac.rules @@ -0,0 +1,6 @@ +# do not edit this file, it will be overwritten on update + @@ -23,11 +23,11 @@ index 0000000000..d67fc425b1 +# with terminates in the iDRAC. Help identify this with 'idrac' + +ACTION=="add", SUBSYSTEM=="net", SUBSYSTEMS=="usb", ATTRS{idVendor}=="413c", ATTRS{idProduct}=="a102", NAME="idrac" -diff --git a/rules.d/meson.build b/rules.d/meson.build -index 13d1d330cf..b06edf0621 100644 ---- a/rules.d/meson.build -+++ b/rules.d/meson.build -@@ -18,6 +18,7 @@ rules = files(''' +diff --git a/rules/meson.build b/rules/meson.build +index e7e4362..e04a18a 100644 +--- a/rules/meson.build ++++ b/rules/meson.build +@@ -17,6 +17,7 @@ rules = files(''' 70-joystick.rules 70-mouse.rules 70-touchpad.rules @@ -36,5 +36,5 @@ index 13d1d330cf..b06edf0621 100644 75-probe_mtd.rules 78-sound-card.rules -- -2.23.0 +1.8.3.1 diff --git a/0006-unit-don-t-add-Requires-for-tmp.mount.patch b/0021-unit-don-t-add-Requires-for-tmp.mount.patch similarity index 100% rename from 0006-unit-don-t-add-Requires-for-tmp.mount.patch rename to 0021-unit-don-t-add-Requires-for-tmp.mount.patch diff --git a/0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch b/0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch new file mode 100644 index 0000000000000000000000000000000000000000..75b0f1b5341dd2899b0cee4f5678d35318826ac0 --- /dev/null +++ b/0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch @@ -0,0 +1,29 @@ +From 47b256d63ac092137fe44e27560a14ee4aa5b7c8 Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Fri, 8 Feb 2019 10:54:34 +0100 +Subject: Revert "sysctl.d: switch net.ipv4.conf.all.rp_filter + from 1 to 2" + +This reverts commit 75c9af80cf3529c76988451e63f98010c86f48f1. + +Resolves: #1653824 +--- + sysctl.d/50-default.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysctl.d/50-default.conf b/sysctl.d/50-default.conf +index b0645f3..e263cf0 100644 +--- a/sysctl.d/50-default.conf ++++ b/sysctl.d/50-default.conf +@@ -22,7 +22,7 @@ kernel.sysrq = 16 + kernel.core_uses_pid = 1 + + # Source route verification +-net.ipv4.conf.all.rp_filter = 2 ++net.ipv4.conf.all.rp_filter = 1 + + # Do not accept source routing + net.ipv4.conf.all.accept_source_route = 0 +-- +1.8.3.1 + diff --git a/0007-rules-add-elevator-kernel-command-line-parameter.patch b/0023-rules-add-elevator-kernel-command-line-parameter.patch similarity index 82% rename from 0007-rules-add-elevator-kernel-command-line-parameter.patch rename to 0023-rules-add-elevator-kernel-command-line-parameter.patch index 4e5f12616f1a04ed272e7ec65ad8fadbce67d6ab..9b2c69ef346250de1962790f7183a32d10e55785 100644 --- a/0007-rules-add-elevator-kernel-command-line-parameter.patch +++ b/0023-rules-add-elevator-kernel-command-line-parameter.patch @@ -6,16 +6,17 @@ Subject: [PATCH] rules: add elevator= kernel command line parameter Kernel removed the elevator= option Resolves: #1670126 + --- - rules.d/40-elevator.rules | 20 ++++++++++++++++++++ + rules/40-elevator.rules | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) - create mode 100644 rules.d/40-elevator.rules + create mode 100644 rules/40-elevator.rules -diff --git a/rules.d/40-elevator.rules b/rules.d/40-elevator.rules +diff --git a/rules/40-elevator.rules b/rules/40-elevator.rules new file mode 100644 -index 0000000000..5f615bf51a +index 0000000..dbe8fc8 --- /dev/null -+++ b/rules.d/40-elevator.rules ++++ b/rules/40-elevator.rules @@ -0,0 +1,20 @@ +# We aren't adding devices skip the elevator check +ACTION!="add", GOTO="sched_out" @@ -38,5 +39,5 @@ index 0000000000..5f615bf51a + +LABEL="sched_out" -- -2.23.0 +1.8.3.1 diff --git a/0008-rules-add-the-rule-that-adds-elevator-kernel-command.patch b/0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch similarity index 60% rename from 0008-rules-add-the-rule-that-adds-elevator-kernel-command.patch rename to 0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch index 768c72b5c7f95b349659194f38f46c1f12ad2100..2e5faab8f39e61ed02d64df74355e2df6a8ba420 100644 --- a/0008-rules-add-the-rule-that-adds-elevator-kernel-command.patch +++ b/0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch @@ -7,21 +7,21 @@ Subject: [PATCH] rules: add the rule that adds elevator= kernel Resolves: #1670126 --- - rules.d/meson.build | 1 + + rules/meson.build | 1 + 1 file changed, 1 insertion(+) -diff --git a/rules.d/meson.build b/rules.d/meson.build -index 62026fd..4a3c32f 100644 ---- a/rules.d/meson.build -+++ b/rules.d/meson.build -@@ -5,6 +5,7 @@ install_data( - install_dir : udevrulesdir) +diff --git a/rules/meson.build b/rules/meson.build +index 0fb5c6a..a2dbf2b 100644 +--- a/rules/meson.build ++++ b/rules/meson.build +@@ -1,6 +1,7 @@ + # SPDX-License-Identifier: LGPL-2.1+ rules = files(''' + 40-elevator.rules - 60-autosuspend.rules 60-block.rules 60-cdrom_id.rules + 60-drm.rules -- 2.23.0 diff --git a/0009-units-add-Install-section-to-tmp.mount.patch b/0025-units-add-Install-section-to-tmp.mount.patch similarity index 78% rename from 0009-units-add-Install-section-to-tmp.mount.patch rename to 0025-units-add-Install-section-to-tmp.mount.patch index 14288973274ff265dc56c8c4565c2d69f2272640..b1a615a0decf92a4dafbb8f7f3a2f36eef6b8f06 100644 --- a/0009-units-add-Install-section-to-tmp.mount.patch +++ b/0025-units-add-Install-section-to-tmp.mount.patch @@ -9,17 +9,17 @@ Resolves: #1667065 1 file changed, 4 insertions(+) diff --git a/units/tmp.mount b/units/tmp.mount -index cf68378..66d9a32 100644 +index 742d863..b558047 100644 --- a/units/tmp.mount +++ b/units/tmp.mount -@@ -23,3 +23,7 @@ What=tmpfs +@@ -22,3 +22,7 @@ What=tmpfs Where=/tmp Type=tmpfs - Options=mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=400k + Options=mode=1777,strictatime,nosuid,nodev + +# Make 'systemctl enable tmp.mount' work: +[Install] +WantedBy=local-fs.target -- -2.23.0 +1.8.3.1 diff --git a/0010-Make-systemd-udevd.service-start-after-systemd-remou.patch b/0026-Make-systemd-udevd.service-start-after-systemd-remou.patch similarity index 88% rename from 0010-Make-systemd-udevd.service-start-after-systemd-remou.patch rename to 0026-Make-systemd-udevd.service-start-after-systemd-remou.patch index 18bdc3763dc18c5d98597fedf79e47f68a914036..d4dd22d652b92b06f08098a7628c7bab9eacbc5f 100644 --- a/0010-Make-systemd-udevd.service-start-after-systemd-remou.patch +++ b/0026-Make-systemd-udevd.service-start-after-systemd-remou.patch @@ -2,16 +2,17 @@ From 4c230d1d73e9f9a6d1fe654599a63881c344a00c Mon Sep 17 00:00:00 2001 From: openEuler Buildteam Date: Tue, 29 Jan 2019 22:54:34 -0500 Subject: [PATCH] Make systemd-udevd.service start after systemd-remount-fs.service. + --- units/systemd-udevd.service.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in -index 9ada3a6a74..17f15bba83 100644 +index 6a3814e..3b09923 100644 --- a/units/systemd-udevd.service.in +++ b/units/systemd-udevd.service.in @@ -11,7 +11,7 @@ - Description=Rule-based Manager for Device Events and Files + Description=udev Kernel Device Manager Documentation=man:systemd-udevd.service(8) man:udev(7) DefaultDependencies=no -After=systemd-sysusers.service systemd-hwdb-update.service @@ -20,5 +21,5 @@ index 9ada3a6a74..17f15bba83 100644 ConditionPathIsReadWrite=/sys -- -2.23.0 +1.8.3.1 diff --git a/0011-udev-virsh-shutdown-vm.patch b/0027-udev-virsh-shutdown-vm.patch similarity index 100% rename from 0011-udev-virsh-shutdown-vm.patch rename to 0027-udev-virsh-shutdown-vm.patch diff --git a/0028-fix-fd-leak-in-no-memory-condition.patch b/0028-fix-fd-leak-in-no-memory-condition.patch new file mode 100644 index 0000000000000000000000000000000000000000..256182bc3adcb3f245c833901a7733397ad5e2cc --- /dev/null +++ b/0028-fix-fd-leak-in-no-memory-condition.patch @@ -0,0 +1,33 @@ +From 43681c404794341a42ba0a34b9730103f4f2c560 Mon Sep 17 00:00:00 2001 +From: Gaurav +Date: Mon, 8 Apr 2019 10:13:26 +0530 +Subject: [PATCH] Fix fd leak in no memory condition + +In case of no memory situation, fd is not being close. +Please review. + +https://github.com/systemd/systemd/commit/43681c404794341a42ba0a34b9730103f4f2c560.patch + +--- + src/libsystemd/sd-event/sd-event.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 5adbcee..5d0e057 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -900,8 +900,10 @@ _public_ int sd_event_add_io( + assert_return(!event_pid_changed(e), -ECHILD); + + s = source_new(e, !ret, SOURCE_IO); +- if (!s) ++ if (!s) { ++ fd = safe_close(fd); + return -ENOMEM; ++ } + + s->wakeup = WAKEUP_EVENT_SOURCE; + s->io.fd = fd; +-- +2.19.1 + diff --git a/0029-dbus-execute-avoid-extra-strdup.patch b/0029-dbus-execute-avoid-extra-strdup.patch new file mode 100644 index 0000000000000000000000000000000000000000..3c0f80ff4640630bf3f4ae6b92dd924cb2b1ecc0 --- /dev/null +++ b/0029-dbus-execute-avoid-extra-strdup.patch @@ -0,0 +1,41 @@ +From 66ca4903ca74604b193802635d36c48b0fcaf291 Mon Sep 17 00:00:00 2001 +From: Topi Miettinen +Date: Thu, 2 Jan 2020 19:59:48 +0200 +Subject: [PATCH] dbus-execute: avoid extra strdup() + +bind_mount_add does the strdup(), so we can avoid +strdup()ing the strings. + +https://github.com/systemd/systemd/commit/66ca4903ca74604b193802635d36c48b0fcaf291 + +--- + src/core/dbus-execute.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 2be3db2..abd60ea 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -2370,7 +2370,7 @@ int bus_exec_context_set_transient_property( + return 1; + + } else if (STR_IN_SET(name, "BindPaths", "BindReadOnlyPaths")) { +- const char *source, *destination; ++ char *source, *destination; + int ignore_enoent; + uint64_t mount_flags; + bool empty = true; +@@ -2391,8 +2391,8 @@ int bus_exec_context_set_transient_property( + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + r = bind_mount_add(&c->bind_mounts, &c->n_bind_mounts, + &(BindMount) { +- .source = strdup(source), +- .destination = strdup(destination), ++ .source = source, ++ .destination = destination, + .read_only = !!strstr(name, "ReadOnly"), + .recursive = !!(mount_flags & MS_REC), + .ignore_enoent = ignore_enoent, +-- +2.19.1 + diff --git a/0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch b/0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch new file mode 100644 index 0000000000000000000000000000000000000000..63d6d3d35ff48f26a631deb7474e97c610ab5f3a --- /dev/null +++ b/0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch @@ -0,0 +1,43 @@ +From f58c5ced373c2532b5cc44ba2e0c3a28b41472f2 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Tue, 15 May 2018 09:24:20 +0200 +Subject: [PATCH] Avoid /tmp being mounted as tmpfs without the user's + will + +Ensure PrivateTmp doesn't require tmpfs through tmp.mount, but rather +adds an After relationship. + +Resolves: #1578772 + +--- + src/core/unit.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 10e314f..bb4836a 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1036,13 +1036,14 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c) { + return 0; + + if (c->private_tmp) { +- const char *p; + +- FOREACH_STRING(p, "/tmp", "/var/tmp") { +- r = unit_require_mounts_for(u, p, UNIT_DEPENDENCY_FILE); +- if (r < 0) +- return r; +- } ++ r = unit_add_dependency_by_name(u, UNIT_AFTER, "tmp.mount", true, UNIT_DEPENDENCY_FILE); ++ if (r < 0) ++ return r; ++ ++ r = unit_require_mounts_for(u, "/var/tmp", UNIT_DEPENDENCY_FILE); ++ if (r < 0) ++ return r; + + r = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_TMPFILES_SETUP_SERVICE, true, UNIT_DEPENDENCY_FILE); + if (r < 0) +-- +2.19.1 + diff --git a/0012-sd-bus-properly-initialize-containers.patch b/0031-sd-bus-properly-initialize-containers.patch similarity index 100% rename from 0012-sd-bus-properly-initialize-containers.patch rename to 0031-sd-bus-properly-initialize-containers.patch diff --git a/0013-Revert-core-one-step-back-again-for-nspawn-we-actual.patch b/0032-Revert-core-one-step-back-again-for-nspawn-we-actual.patch similarity index 100% rename from 0013-Revert-core-one-step-back-again-for-nspawn-we-actual.patch rename to 0032-Revert-core-one-step-back-again-for-nspawn-we-actual.patch diff --git a/0014-journal-don-t-enable-systemd-journald-audit.socket-b.patch b/0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch similarity index 45% rename from 0014-journal-don-t-enable-systemd-journald-audit.socket-b.patch rename to 0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch index ca97a3ef021f120f6a4bbc920af5b75cca02137e..bdb9129b23351e99f83f56d8a2383c4caec5157c 100644 --- a/0014-journal-don-t-enable-systemd-journald-audit.socket-b.patch +++ b/0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch @@ -7,37 +7,22 @@ Subject: [PATCH] journal: don't enable systemd-journald-audit.socket Resolves: #1699287 --- - units/meson.build | 3 +-- units/systemd-journald.service.in | 2 +- - 2 files changed, 2 insertions(+), 3 deletions(-) + 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/units/meson.build b/units/meson.build -index 4eb09a3..ccea8a6 100644 ---- a/units/meson.build -+++ b/units/meson.build -@@ -110,8 +110,7 @@ units = [ - 'sysinit.target.wants/'], - ['systemd-journal-gatewayd.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'], - ['systemd-journal-remote.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'], -- ['systemd-journald-audit.socket', '', -- 'sockets.target.wants/'], -+ ['systemd-journald-audit.socket', ''], - ['systemd-journald-dev-log.socket', '', - 'sockets.target.wants/'], - ['systemd-journald.socket', '', diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in -index 0cb1bfa..fa7348a 100644 +index 089bc38..7436619 100644 --- a/units/systemd-journald.service.in +++ b/units/systemd-journald.service.in -@@ -34,7 +34,7 @@ RestrictRealtime=yes +@@ -31,7 +31,7 @@ RestrictAddressFamilies=AF_UNIX AF_NETLINK + RestrictNamespaces=yes + RestrictRealtime=yes RestrictSUIDSGID=yes - RuntimeDirectory=systemd/journal - RuntimeDirectoryPreserve=yes -Sockets=systemd-journald.socket systemd-journald-dev-log.socket systemd-journald-audit.socket +Sockets=systemd-journald.socket systemd-journald-dev-log.socket StandardOutput=null SystemCallArchitectures=native SystemCallErrorNumber=EPERM -- -2.23.0 +2.19.1 diff --git a/0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch b/0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch new file mode 100644 index 0000000000000000000000000000000000000000..e12236a743e689df5645a4553501162ef9fcc2c7 --- /dev/null +++ b/0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch @@ -0,0 +1,289 @@ +From 91e0ee5f16321656ed6f827742ecbeb2b36027f2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 10 Jul 2019 18:01:13 +0200 +Subject: [PATCH] pid1: drop unit caches only based on mtime + +v2: +- do not watch mtime of transient and generated dirs + + We'd reload the map after every transient unit we created, which we don't + need to do, since we create those units ourselves and know their fragment + path. + +revert pid1 drop unit caches only based on mtime +--- + src/analyze/analyze.c | 2 +- + src/core/load-fragment.c | 9 -------- + src/core/manager.c | 14 ++++++++++-- + src/core/manager.h | 1 - + src/shared/unit-file.c | 57 +---------------------------------------------- + src/shared/unit-file.h | 2 -- + src/systemctl/systemctl.c | 2 +- + src/test/test-unit-file.c | 13 +---------- + 8 files changed, 16 insertions(+), 84 deletions(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index 4d81026..322be1a 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -1569,7 +1569,7 @@ static int do_unit_files(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "lookup_paths_init() failed: %m"); + +- r = unit_file_build_name_map(&lp, NULL, &unit_ids, &unit_names, NULL); ++ r = unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL); + if (r < 0) + return log_error_errno(r, "unit_file_build_name_map() failed: %m"); + +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 8eaf8b3..9821a92 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -4605,15 +4605,6 @@ int unit_load_fragment(Unit *u) { + return 0; + } + +- /* Possibly rebuild the fragment map to catch new units */ +- r = unit_file_build_name_map(&u->manager->lookup_paths, +- &u->manager->unit_cache_mtime, +- &u->manager->unit_id_map, +- &u->manager->unit_name_map, +- &u->manager->unit_path_cache); +- if (r < 0) +- log_error_errno(r, "Failed to rebuild name map: %m"); +- + r = unit_file_find_fragment(u->manager->unit_id_map, + u->manager->unit_name_map, + u->id, +diff --git a/src/core/manager.c b/src/core/manager.c +index 5efcf45..8b1ce70 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -693,7 +693,6 @@ static void manager_free_unit_name_maps(Manager *m) { + m->unit_id_map = hashmap_free(m->unit_id_map); + m->unit_name_map = hashmap_free(m->unit_name_map); + m->unit_path_cache = set_free_free(m->unit_path_cache); +- m->unit_cache_mtime = 0; + } + + static int manager_setup_run_queue(Manager *m) { +@@ -1642,6 +1641,11 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { + + lookup_paths_log(&m->lookup_paths); + ++ manager_free_unit_name_maps(m); ++ r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); ++ if (r < 0) ++ return log_error_errno(r, "Failed to build name map: %m"); ++ + { + /* This block is (optionally) done with the reloading counter bumped */ + _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; +@@ -2858,6 +2862,10 @@ int manager_loop(Manager *m) { + assert(m); + assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ + ++ /* Release the path and unit name caches */ ++ manager_free_unit_name_maps(m); ++ // FIXME: once this happens, we cannot load any more units ++ + manager_check_finished(m); + + /* There might still be some zombies hanging around from before we were exec()'ed. Let's reap them. */ +@@ -3531,8 +3539,10 @@ int manager_reload(Manager *m) { + + lookup_paths_log(&m->lookup_paths); + +- /* We flushed out generated files, for which we don't watch mtime, so we should flush the old map. */ + manager_free_unit_name_maps(m); ++ r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); ++ if (r < 0) ++ log_warning_errno(r, "Failed to build name map: %m"); + + /* First, enumerate what we can from kernel and suchlike */ + manager_enumerate_perpetual(m); +diff --git a/src/core/manager.h b/src/core/manager.h +index 815c5ec..9ca82ac 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -223,7 +223,6 @@ struct Manager { + Hashmap *unit_id_map; + Hashmap *unit_name_map; + Set *unit_path_cache; +- usec_t unit_cache_mtime; + + char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ + char **client_environment; /* Environment variables created by clients through the bus API */ +diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c +index 4a5f23e..bad92a3 100644 +--- a/src/shared/unit-file.c ++++ b/src/shared/unit-file.c +@@ -152,47 +152,8 @@ static int unit_ids_map_get( + return -ELOOP; + } + +-static bool lookup_paths_mtime_exclude(const LookupPaths *lp, const char *path) { +- /* Paths that are under our exclusive control. Users shall not alter those directly. */ +- +- return streq_ptr(path, lp->generator) || +- streq_ptr(path, lp->generator_early) || +- streq_ptr(path, lp->generator_late) || +- streq_ptr(path, lp->transient) || +- streq_ptr(path, lp->persistent_control) || +- streq_ptr(path, lp->runtime_control); +-} +- +-static bool lookup_paths_mtime_good(const LookupPaths *lp, usec_t mtime) { +- char **dir; +- +- STRV_FOREACH(dir, (char**) lp->search_path) { +- struct stat st; +- +- if (lookup_paths_mtime_exclude(lp, *dir)) +- continue; +- +- /* Determine the latest lookup path modification time */ +- if (stat(*dir, &st) < 0) { +- if (errno == ENOENT) +- continue; +- +- log_debug_errno(errno, "Failed to stat %s, ignoring: %m", *dir); +- continue; +- } +- +- if (timespec_load(&st.st_mtim) > mtime) { +- log_debug_errno(errno, "Unit dir %s has changed, need to update cache.", *dir); +- return false; +- } +- } +- +- return true; +-} +- + int unit_file_build_name_map( + const LookupPaths *lp, +- usec_t *cache_mtime, + Hashmap **ret_unit_ids_map, + Hashmap **ret_unit_names_map, + Set **ret_path_cache) { +@@ -210,12 +171,6 @@ int unit_file_build_name_map( + _cleanup_set_free_free_ Set *paths = NULL; + char **dir; + int r; +- usec_t mtime = 0; +- +- /* Before doing anything, check if the mtime that was passed is still valid. If +- * yes, do nothing. If *cache_time == 0, always build the cache. */ +- if (cache_mtime && *cache_mtime > 0 && lookup_paths_mtime_good(lp, *cache_mtime)) +- return 0; + + if (ret_path_cache) { + paths = set_new(&path_hash_ops); +@@ -226,7 +181,6 @@ int unit_file_build_name_map( + STRV_FOREACH(dir, (char**) lp->search_path) { + struct dirent *de; + _cleanup_closedir_ DIR *d = NULL; +- struct stat st; + + d = opendir(*dir); + if (!d) { +@@ -235,13 +189,6 @@ int unit_file_build_name_map( + continue; + } + +- /* Determine the latest lookup path modification time */ +- if (fstat(dirfd(d), &st) < 0) +- return log_error_errno(errno, "Failed to fstat %s: %m", *dir); +- +- if (!lookup_paths_mtime_exclude(lp, *dir)) +- mtime = MAX(mtime, timespec_load(&st.st_mtim)); +- + FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { + char *filename; + _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; +@@ -378,14 +325,12 @@ int unit_file_build_name_map( + basename(dst), src); + } + +- if (cache_mtime) +- *cache_mtime = mtime; + *ret_unit_ids_map = TAKE_PTR(ids); + *ret_unit_names_map = TAKE_PTR(names); + if (ret_path_cache) + *ret_path_cache = TAKE_PTR(paths); + +- return 1; ++ return 0; + } + + int unit_file_find_fragment( +diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h +index 54cc787..52e17f7 100644 +--- a/src/shared/unit-file.h ++++ b/src/shared/unit-file.h +@@ -4,7 +4,6 @@ + #include + + #include "hashmap.h" +-#include "time-util.h" + #include "unit-name.h" + + typedef enum UnitFileState UnitFileState; +@@ -43,7 +42,6 @@ int unit_validate_alias_symlink_and_warn(const char *filename, const char *targe + + int unit_file_build_name_map( + const LookupPaths *lp, +- usec_t *ret_time, + Hashmap **ret_unit_ids_map, + Hashmap **ret_unit_names_map, + Set **ret_path_cache); +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index dcf76be..69063ee 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -2594,7 +2594,7 @@ static int unit_find_paths( + _cleanup_set_free_free_ Set *names = NULL; + + if (!cached_name_map) { +- r = unit_file_build_name_map(lp, NULL, &cached_id_map, &cached_name_map, NULL); ++ r = unit_file_build_name_map(lp, &cached_id_map, &cached_name_map, NULL); + if (r < 0) + return r; + } +diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c +index 8bc5bf6..988ac15 100644 +--- a/src/test/test-unit-file.c ++++ b/src/test/test-unit-file.c +@@ -32,12 +32,10 @@ static void test_unit_file_build_name_map(char **ids) { + Iterator i; + const char *k, *dst; + char **v; +- usec_t mtime = 0; +- int r; + + assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0); + +- assert_se(unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL) == 1); ++ assert_se(unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL) == 0); + + HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) + log_info("ids: %s → %s", k, dst); +@@ -47,15 +45,6 @@ static void test_unit_file_build_name_map(char **ids) { + log_info("aliases: %s ← %s", k, j); + } + +- char buf[FORMAT_TIMESTAMP_MAX]; +- log_debug("Last modification time: %s", format_timestamp(buf, sizeof buf, mtime)); +- +- r = unit_file_build_name_map(&lp, &mtime, &unit_ids, &unit_names, NULL); +- assert_se(IN_SET(r, 0, 1)); +- if (r == 0) +- log_debug("Cache rebuild skipped based on mtime."); +- +- + char **id; + STRV_FOREACH(id, ids) { + const char *fragment, *name; +-- +1.8.3.1 + diff --git a/0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch b/0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch new file mode 100644 index 0000000000000000000000000000000000000000..65c5162ec85b61920d291883cea7ec5ceb2960d1 --- /dev/null +++ b/0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch @@ -0,0 +1,93 @@ +From e67cd21d7d174cdafd12beca4cfb6e19e61f6fb5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 8 Jul 2019 17:33:25 +0200 +Subject: [PATCH] analyze: add "unit-files" to dump the unit fragment map + +I'm not convinced that this is useful enough to be included... But it is +certainly nice when debugging. + +revert analyze add unit files to dump the unit fragment map +--- + src/analyze/analyze.c | 50 -------------------------------------------------- + 1 file changed, 50 deletions(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index 322be1a..6de26f4 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -1546,53 +1546,6 @@ static int get_or_set_log_target(int argc, char *argv[], void *userdata) { + return (argc == 1) ? get_log_target(argc, argv, userdata) : set_log_target(argc, argv, userdata); + } + +-static bool strv_fnmatch_strv_or_empty(char* const* patterns, char **strv, int flags) { +- char **s; +- STRV_FOREACH(s, strv) +- if (strv_fnmatch_or_empty(patterns, *s, flags)) +- return true; +- +- return false; +-} +- +-static int do_unit_files(int argc, char *argv[], void *userdata) { +- _cleanup_(lookup_paths_free) LookupPaths lp = {}; +- _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; +- _cleanup_hashmap_free_ Hashmap *unit_names = NULL; +- char **patterns = strv_skip(argv, 1); +- Iterator i; +- const char *k, *dst; +- char **v; +- int r; +- +- r = lookup_paths_init(&lp, arg_scope, 0, NULL); +- if (r < 0) +- return log_error_errno(r, "lookup_paths_init() failed: %m"); +- +- r = unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL); +- if (r < 0) +- return log_error_errno(r, "unit_file_build_name_map() failed: %m"); +- +- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) { +- if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && +- !strv_fnmatch_or_empty(patterns, dst, FNM_NOESCAPE)) +- continue; +- +- printf("ids: %s → %s\n", k, dst); +- } +- +- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { +- if (!strv_fnmatch_or_empty(patterns, k, FNM_NOESCAPE) && +- !strv_fnmatch_strv_or_empty(patterns, v, FNM_NOESCAPE)) +- continue; +- +- _cleanup_free_ char *j = strv_join(v, ", "); +- printf("aliases: %s ← %s\n", k, j); +- } +- +- return 0; +-} +- + static int dump_unit_paths(int argc, char *argv[], void *userdata) { + _cleanup_(lookup_paths_free) LookupPaths paths = {}; + int r; +@@ -2263,7 +2216,6 @@ static int help(int argc, char *argv[], void *userdata) { + " log-target [TARGET] Get/set logging target for manager\n" + " dump Output state serialization of service manager\n" + " cat-config Show configuration file and drop-ins\n" +- " unit-files List files and symlinks for units\n" + " unit-paths List load directories for units\n" + " exit-status [STATUS...] List exit status definitions\n" + " syscall-filter [NAME...] Print list of syscalls in seccomp filter\n" +@@ -2467,10 +2419,8 @@ static int run(int argc, char *argv[]) { + { "get-log-level", VERB_ANY, 1, 0, get_log_level }, + { "set-log-target", 2, 2, 0, set_log_target }, + { "get-log-target", VERB_ANY, 1, 0, get_log_target }, +- + { "dump", VERB_ANY, 1, 0, dump }, + { "cat-config", 2, VERB_ANY, 0, cat_config }, +- { "unit-files", VERB_ANY, VERB_ANY, 0, do_unit_files }, + { "unit-paths", 1, 1, 0, dump_unit_paths }, + { "exit-status", VERB_ANY, VERB_ANY, 0, dump_exit_status }, + { "syscall-filter", VERB_ANY, VERB_ANY, 0, dump_syscall_filters }, +-- +1.8.3.1 + diff --git a/0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch b/0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch new file mode 100644 index 0000000000000000000000000000000000000000..7dc96a5a6b40b7830b81934adaa078c508b062b0 --- /dev/null +++ b/0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch @@ -0,0 +1,1226 @@ +From e8630e695232bdfcd16b55f3faafb4329c961104 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 18 Jul 2019 13:11:28 +0200 +Subject: [PATCH] pid1: use a cache for all unit aliases + +This reworks how we load units from disk. Instead of chasing symlinks every +time we are asked to load a unit by name, we slurp all symlinks from disk +and build two hashmaps: +1. from unit name to either alias target, or fragment on disk + (if an alias, we put just the target name in the hashmap, if a fragment + we put an absolute path, so we can distinguish both). +2. from a unit name to all aliases + +Reading all this data can be pretty costly (40 ms) on my machine, so we keep it +around for reuse. + +The advantage is that we can reliably know what all the aliases of a given unit +are. This means we can reliably load dropins under all names. This fixes #11972. + +revert pid1 use a cache for all unit aliases +--- + src/core/load-fragment.c | 350 +++++++++++++++++++++++++++-------- + src/core/manager.c | 73 ++++++-- + src/core/manager.h | 2 - + src/core/unit.c | 3 - + src/shared/unit-file.c | 362 ------------------------------------- + src/shared/unit-file.h | 15 -- + src/systemctl/systemctl.c | 47 +++-- + src/test/test-unit-file.c | 40 ---- + test/TEST-15-DROPIN/test-dropin.sh | 33 ++-- + 9 files changed, 378 insertions(+), 547 deletions(-) + +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 9821a92..9dd86e8 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -4553,48 +4553,251 @@ int config_parse_ip_filter_bpf_progs( + return 0; + } + ++#define FOLLOW_MAX 8 ++ ++static int open_follow(char **filename, FILE **_f, Set *names, char **_final) { ++ char *id = NULL; ++ unsigned c = 0; ++ int fd, r; ++ FILE *f; ++ ++ assert(filename); ++ assert(*filename); ++ assert(_f); ++ assert(names); ++ ++ /* This will update the filename pointer if the loaded file is ++ * reached by a symlink. The old string will be freed. */ ++ ++ for (;;) { ++ char *target, *name; ++ ++ if (c++ >= FOLLOW_MAX) ++ return -ELOOP; ++ ++ path_simplify(*filename, false); ++ ++ /* Add the file name we are currently looking at to ++ * the names of this unit, but only if it is a valid ++ * unit name. */ ++ name = basename(*filename); ++ if (unit_name_is_valid(name, UNIT_NAME_ANY)) { ++ ++ id = set_get(names, name); ++ if (!id) { ++ id = strdup(name); ++ if (!id) ++ return -ENOMEM; ++ ++ r = set_consume(names, id); ++ if (r < 0) ++ return r; ++ } ++ } ++ ++ /* Try to open the file name, but don't if its a symlink */ ++ fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); ++ if (fd >= 0) ++ break; ++ ++ if (errno != ELOOP) ++ return -errno; ++ ++ /* Hmm, so this is a symlink. Let's read the name, and follow it manually */ ++ r = readlink_and_make_absolute(*filename, &target); ++ if (r < 0) ++ return r; ++ ++ free_and_replace(*filename, target); ++ } ++ ++ f = fdopen(fd, "r"); ++ if (!f) { ++ safe_close(fd); ++ return -errno; ++ } ++ ++ *_f = f; ++ *_final = id; ++ ++ return 0; ++} ++ + static int merge_by_names(Unit **u, Set *names, const char *id) { + char *k; + int r; + + assert(u); + assert(*u); ++ assert(names); + +- /* Let's try to add in all names that are aliases of this unit */ ++ /* Let's try to add in all symlink names we found */ + while ((k = set_steal_first(names))) { +- _cleanup_free_ _unused_ char *free_k = k; + +- /* First try to merge in the other name into our unit */ ++ /* First try to merge in the other name into our ++ * unit */ + r = unit_merge_by_name(*u, k); + if (r < 0) { + Unit *other; + +- /* Hmm, we couldn't merge the other unit into ours? Then let's try it the other way +- * round. */ ++ /* Hmm, we couldn't merge the other unit into ++ * ours? Then let's try it the other way ++ * round */ + +- other = manager_get_unit((*u)->manager, k); +- if (!other) +- return r; /* return previous failure */ ++ /* If the symlink name we are looking at is unit template, then ++ we must search for instance of this template */ ++ if (unit_name_is_valid(k, UNIT_NAME_TEMPLATE) && (*u)->instance) { ++ _cleanup_free_ char *instance = NULL; + +- r = unit_merge(other, *u); +- if (r < 0) +- return r; ++ r = unit_name_replace_instance(k, (*u)->instance, &instance); ++ if (r < 0) ++ return r; + +- *u = other; +- return merge_by_names(u, names, NULL); ++ other = manager_get_unit((*u)->manager, instance); ++ } else ++ other = manager_get_unit((*u)->manager, k); ++ ++ free(k); ++ ++ if (other) { ++ r = unit_merge(other, *u); ++ if (r >= 0) { ++ *u = other; ++ return merge_by_names(u, names, NULL); ++ } ++ } ++ ++ return r; + } + +- if (streq_ptr(id, k)) ++ if (id == k) + unit_choose_id(*u, id); ++ ++ free(k); ++ } ++ ++ return 0; ++} ++ ++static int load_from_path(Unit *u, const char *path) { ++ _cleanup_set_free_free_ Set *symlink_names = NULL; ++ _cleanup_fclose_ FILE *f = NULL; ++ _cleanup_free_ char *filename = NULL; ++ char *id = NULL; ++ Unit *merged; ++ struct stat st; ++ int r; ++ ++ assert(u); ++ assert(path); ++ ++ symlink_names = set_new(&string_hash_ops); ++ if (!symlink_names) ++ return -ENOMEM; ++ ++ if (path_is_absolute(path)) { ++ ++ filename = strdup(path); ++ if (!filename) ++ return -ENOMEM; ++ ++ r = open_follow(&filename, &f, symlink_names, &id); ++ if (r < 0) { ++ filename = mfree(filename); ++ if (r != -ENOENT) ++ return r; ++ } ++ ++ } else { ++ char **p; ++ ++ STRV_FOREACH(p, u->manager->lookup_paths.search_path) { ++ ++ /* Instead of opening the path right away, we manually ++ * follow all symlinks and add their name to our unit ++ * name set while doing so */ ++ filename = path_make_absolute(path, *p); ++ if (!filename) ++ return -ENOMEM; ++ ++ if (u->manager->unit_path_cache && ++ !set_get(u->manager->unit_path_cache, filename)) ++ r = -ENOENT; ++ else ++ r = open_follow(&filename, &f, symlink_names, &id); ++ if (r >= 0) ++ break; ++ ++ /* ENOENT means that the file is missing or is a dangling symlink. ++ * ENOTDIR means that one of paths we expect to be is a directory ++ * is not a directory, we should just ignore that. ++ * EACCES means that the directory or file permissions are wrong. ++ */ ++ if (r == -EACCES) ++ log_debug_errno(r, "Cannot access \"%s\": %m", filename); ++ else if (!IN_SET(r, -ENOENT, -ENOTDIR)) ++ return r; ++ ++ filename = mfree(filename); ++ /* Empty the symlink names for the next run */ ++ set_clear_free(symlink_names); ++ } ++ } ++ ++ if (!filename) ++ /* Hmm, no suitable file found? */ ++ return 0; ++ ++ if (!unit_type_may_alias(u->type) && set_size(symlink_names) > 1) { ++ log_unit_warning(u, "Unit type of %s does not support alias names, refusing loading via symlink.", u->id); ++ return -ELOOP; ++ } ++ ++ merged = u; ++ r = merge_by_names(&merged, symlink_names, id); ++ if (r < 0) ++ return r; ++ ++ if (merged != u) { ++ u->load_state = UNIT_MERGED; ++ return 0; ++ } ++ ++ if (fstat(fileno(f), &st) < 0) ++ return -errno; ++ ++ if (null_or_empty(&st)) { ++ u->load_state = UNIT_MASKED; ++ u->fragment_mtime = 0; ++ } else { ++ u->load_state = UNIT_LOADED; ++ u->fragment_mtime = timespec_load(&st.st_mtim); ++ ++ /* Now, parse the file contents */ ++ r = config_parse(u->id, filename, f, ++ UNIT_VTABLE(u)->sections, ++ config_item_perf_lookup, load_fragment_gperf_lookup, ++ CONFIG_PARSE_ALLOW_INCLUDE, u); ++ if (r < 0) ++ return r; ++ } ++ ++ free_and_replace(u->fragment_path, filename); ++ ++ if (u->source_path) { ++ if (stat(u->source_path, &st) >= 0) ++ u->source_mtime = timespec_load(&st.st_mtim); ++ else ++ u->source_mtime = 0; + } + + return 0; + } + + int unit_load_fragment(Unit *u) { +- const char *fragment; +- _cleanup_set_free_free_ Set *names = NULL; + int r; ++ Iterator i; ++ const char *t; + + assert(u); + assert(u->load_state == UNIT_STUB); +@@ -4605,79 +4808,78 @@ int unit_load_fragment(Unit *u) { + return 0; + } + +- r = unit_file_find_fragment(u->manager->unit_id_map, +- u->manager->unit_name_map, +- u->id, +- &fragment, +- &names); +- if (r < 0 && r != -ENOENT) ++ /* First, try to find the unit under its id. We always look ++ * for unit files in the default directories, to make it easy ++ * to override things by placing things in /etc/systemd/system */ ++ r = load_from_path(u, u->id); ++ if (r < 0) + return r; + +- if (fragment) { +- /* Open the file, check if this is a mask, otherwise read. */ +- _cleanup_fclose_ FILE *f = NULL; +- struct stat st; ++ /* Try to find an alias we can load this with */ ++ if (u->load_state == UNIT_STUB) { ++ SET_FOREACH(t, u->names, i) { + +- /* Try to open the file name. A symlink is OK, for example for linked files or masks. We +- * expect that all symlinks within the lookup paths have been already resolved, but we don't +- * verify this here. */ +- f = fopen(fragment, "re"); +- if (!f) +- return log_unit_notice_errno(u, errno, "Failed to open %s: %m", fragment); ++ if (t == u->id) ++ continue; + +- if (fstat(fileno(f), &st) < 0) +- return -errno; ++ r = load_from_path(u, t); ++ if (r < 0) ++ return r; + +- r = free_and_strdup(&u->fragment_path, fragment); ++ if (u->load_state != UNIT_STUB) ++ break; ++ } ++ } ++ ++ /* And now, try looking for it under the suggested (originally linked) path */ ++ if (u->load_state == UNIT_STUB && u->fragment_path) { ++ ++ r = load_from_path(u, u->fragment_path); + if (r < 0) + return r; + +- if (null_or_empty(&st)) { +- u->load_state = UNIT_MASKED; +- u->fragment_mtime = 0; +- } else { +- u->load_state = UNIT_LOADED; +- u->fragment_mtime = timespec_load(&st.st_mtim); +- +- /* Now, parse the file contents */ +- r = config_parse(u->id, fragment, f, +- UNIT_VTABLE(u)->sections, +- config_item_perf_lookup, load_fragment_gperf_lookup, +- CONFIG_PARSE_ALLOW_INCLUDE, u); +- if (r == -ENOEXEC) +- log_unit_notice_errno(u, r, "Unit configuration has fatal error, unit will not be started."); +- if (r < 0) +- return r; +- } ++ if (u->load_state == UNIT_STUB) ++ /* Hmm, this didn't work? Then let's get rid ++ * of the fragment path stored for us, so that ++ * we don't point to an invalid location. */ ++ u->fragment_path = mfree(u->fragment_path); + } + +- /* We do the merge dance here because for some unit types, the unit might have aliases which are not +- * declared in the file system. In particular, this is true (and frequent) for device and swap units. +- */ +- Unit *merged; +- const char *id = u->id; +- _cleanup_free_ char *free_id = NULL; ++ /* Look for a template */ ++ if (u->load_state == UNIT_STUB && u->instance) { ++ _cleanup_free_ char *k = NULL; + +- if (fragment) { +- id = basename(fragment); +- if (unit_name_is_valid(id, UNIT_NAME_TEMPLATE)) { +- assert(u->instance); /* If we're not trying to use a template for non-instanced unit, +- * this must be set. */ ++ r = unit_name_template(u->id, &k); ++ if (r < 0) ++ return r; + +- r = unit_name_replace_instance(id, u->instance, &free_id); +- if (r < 0) +- return log_debug_errno(r, "Failed to build id (%s + %s): %m", id, u->instance); +- id = free_id; ++ r = load_from_path(u, k); ++ if (r < 0) { ++ if (r == -ENOEXEC) ++ log_unit_notice(u, "Unit configuration has fatal error, unit will not be started."); ++ return r; + } +- } + +- merged = u; +- r = merge_by_names(&merged, names, id); +- if (r < 0) +- return r; ++ if (u->load_state == UNIT_STUB) { ++ SET_FOREACH(t, u->names, i) { ++ _cleanup_free_ char *z = NULL; + +- if (merged != u) +- u->load_state = UNIT_MERGED; ++ if (t == u->id) ++ continue; ++ ++ r = unit_name_template(t, &z); ++ if (r < 0) ++ return r; ++ ++ r = load_from_path(u, z); ++ if (r < 0) ++ return r; ++ ++ if (u->load_state != UNIT_STUB) ++ break; ++ } ++ } ++ } + + return 0; + } +diff --git a/src/core/manager.c b/src/core/manager.c +index 8b1ce70..cfeaca6 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -689,12 +689,6 @@ static int manager_setup_prefix(Manager *m) { + return 0; + } + +-static void manager_free_unit_name_maps(Manager *m) { +- m->unit_id_map = hashmap_free(m->unit_id_map); +- m->unit_name_map = hashmap_free(m->unit_name_map); +- m->unit_path_cache = set_free_free(m->unit_path_cache); +-} +- + static int manager_setup_run_queue(Manager *m) { + int r; + +@@ -1383,7 +1377,7 @@ Manager* manager_free(Manager *m) { + strv_free(m->client_environment); + + hashmap_free(m->cgroup_unit); +- manager_free_unit_name_maps(m); ++ set_free_free(m->unit_path_cache); + + free(m->switch_root); + free(m->switch_root_init); +@@ -1487,6 +1481,56 @@ static void manager_catchup(Manager *m) { + } + } + ++static void manager_build_unit_path_cache(Manager *m) { ++ char **i; ++ int r; ++ ++ assert(m); ++ ++ set_free_free(m->unit_path_cache); ++ ++ m->unit_path_cache = set_new(&path_hash_ops); ++ if (!m->unit_path_cache) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ /* This simply builds a list of files we know exist, so that ++ * we don't always have to go to disk */ ++ ++ STRV_FOREACH(i, m->lookup_paths.search_path) { ++ _cleanup_closedir_ DIR *d = NULL; ++ struct dirent *de; ++ ++ d = opendir(*i); ++ if (!d) { ++ if (errno != ENOENT) ++ log_warning_errno(errno, "Failed to open directory %s, ignoring: %m", *i); ++ continue; ++ } ++ ++ FOREACH_DIRENT(de, d, r = -errno; goto fail) { ++ char *p; ++ ++ p = path_join(*i, de->d_name); ++ if (!p) { ++ r = -ENOMEM; ++ goto fail; ++ } ++ ++ r = set_consume(m->unit_path_cache, p); ++ if (r < 0) ++ goto fail; ++ } ++ } ++ ++ return; ++ ++fail: ++ log_warning_errno(r, "Failed to build unit path cache, proceeding without: %m"); ++ m->unit_path_cache = set_free_free(m->unit_path_cache); ++} ++ + static void manager_distribute_fds(Manager *m, FDSet *fds) { + Iterator i; + Unit *u; +@@ -1641,10 +1685,7 @@ int manager_startup(Manager *m, FILE *serialization, FDSet *fds) { + + lookup_paths_log(&m->lookup_paths); + +- manager_free_unit_name_maps(m); +- r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); +- if (r < 0) +- return log_error_errno(r, "Failed to build name map: %m"); ++ manager_build_unit_path_cache(m); + + { + /* This block is (optionally) done with the reloading counter bumped */ +@@ -2862,9 +2903,8 @@ int manager_loop(Manager *m) { + assert(m); + assert(m->objective == MANAGER_OK); /* Ensure manager_startup() has been called */ + +- /* Release the path and unit name caches */ +- manager_free_unit_name_maps(m); +- // FIXME: once this happens, we cannot load any more units ++ /* Release the path cache */ ++ m->unit_path_cache = set_free_free(m->unit_path_cache); + + manager_check_finished(m); + +@@ -3539,10 +3579,7 @@ int manager_reload(Manager *m) { + + lookup_paths_log(&m->lookup_paths); + +- manager_free_unit_name_maps(m); +- r = unit_file_build_name_map(&m->lookup_paths, &m->unit_id_map, &m->unit_name_map, &m->unit_path_cache); +- if (r < 0) +- log_warning_errno(r, "Failed to build name map: %m"); ++ manager_build_unit_path_cache(m); + + /* First, enumerate what we can from kernel and suchlike */ + manager_enumerate_perpetual(m); +diff --git a/src/core/manager.h b/src/core/manager.h +index 9ca82ac..daeb454 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -220,8 +220,6 @@ struct Manager { + + UnitFileScope unit_file_scope; + LookupPaths lookup_paths; +- Hashmap *unit_id_map; +- Hashmap *unit_name_map; + Set *unit_path_cache; + + char **transient_environment; /* The environment, as determined from config files, kernel cmdline and environment generators */ +diff --git a/src/core/unit.c b/src/core/unit.c +index f96e6e4..1b8d5d9 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -959,9 +959,6 @@ int unit_merge_by_name(Unit *u, const char *name) { + Unit *other; + int r; + +- /* Either add name to u, or if a unit with name already exists, merge it with u. +- * If name is a template, do the same for name@instance, where instance is u's instance. */ +- + assert(u); + assert(name); + +diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c +index bad92a3..cde38c4 100644 +--- a/src/shared/unit-file.c ++++ b/src/shared/unit-file.c +@@ -1,14 +1,7 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + +-#include "dirent-util.h" +-#include "fd-util.h" +-#include "fs-util.h" + #include "macro.h" +-#include "path-lookup.h" +-#include "set.h" +-#include "stat-util.h" + #include "string-util.h" +-#include "strv.h" + #include "unit-file.h" + + bool unit_type_may_alias(UnitType type) { +@@ -101,358 +94,3 @@ int unit_validate_alias_symlink_and_warn(const char *filename, const char *targe + + return 0; + } +- +-#define FOLLOW_MAX 8 +- +-static int unit_ids_map_get( +- Hashmap *unit_ids_map, +- const char *unit_name, +- const char **ret_fragment_path) { +- +- /* Resolve recursively until we hit an absolute path, i.e. a non-aliased unit. +- * +- * We distinguish the case where unit_name was not found in the hashmap at all, and the case where +- * some symlink was broken. +- * +- * If a symlink target points to an instance name, then we also check for the template. */ +- +- const char *id = NULL; +- int r; +- +- for (unsigned n = 0; n < FOLLOW_MAX; n++) { +- const char *t = hashmap_get(unit_ids_map, id ?: unit_name); +- if (!t) { +- _cleanup_free_ char *template = NULL; +- +- if (!id) +- return -ENOENT; +- +- r = unit_name_template(id, &template); +- if (r == -EINVAL) +- return -ENXIO; /* we failed to find the symlink target */ +- if (r < 0) +- return log_error_errno(r, "Failed to determine template name for %s: %m", id); +- +- t = hashmap_get(unit_ids_map, template); +- if (!t) +- return -ENXIO; +- +- /* We successfully switched from instanced name to a template, let's continue */ +- } +- +- if (path_is_absolute(t)) { +- if (ret_fragment_path) +- *ret_fragment_path = t; +- return 0; +- } +- +- id = t; +- } +- +- return -ELOOP; +-} +- +-int unit_file_build_name_map( +- const LookupPaths *lp, +- Hashmap **ret_unit_ids_map, +- Hashmap **ret_unit_names_map, +- Set **ret_path_cache) { +- +- /* Build two mappings: any name → main unit (i.e. the end result of symlink resolution), unit name → +- * all aliases (i.e. the entry for a given key is a a list of all names which point to this key). The +- * key is included in the value iff we saw a file or symlink with that name. In other words, if we +- * have a key, but it is not present in the value for itself, there was an alias pointing to it, but +- * the unit itself is not loadable. +- * +- * At the same, build a cache of paths where to find units. +- */ +- +- _cleanup_hashmap_free_ Hashmap *ids = NULL, *names = NULL; +- _cleanup_set_free_free_ Set *paths = NULL; +- char **dir; +- int r; +- +- if (ret_path_cache) { +- paths = set_new(&path_hash_ops); +- if (!paths) +- return log_oom(); +- } +- +- STRV_FOREACH(dir, (char**) lp->search_path) { +- struct dirent *de; +- _cleanup_closedir_ DIR *d = NULL; +- +- d = opendir(*dir); +- if (!d) { +- if (errno != ENOENT) +- log_warning_errno(errno, "Failed to open \"%s\", ignoring: %m", *dir); +- continue; +- } +- +- FOREACH_DIRENT_ALL(de, d, log_warning_errno(errno, "Failed to read \"%s\", ignoring: %m", *dir)) { +- char *filename; +- _cleanup_free_ char *_filename_free = NULL, *simplified = NULL; +- const char *suffix, *dst = NULL; +- bool valid_unit_name; +- +- valid_unit_name = unit_name_is_valid(de->d_name, UNIT_NAME_ANY); +- +- /* We only care about valid units and dirs with certain suffixes, let's ignore the +- * rest. */ +- if (!valid_unit_name && +- !ENDSWITH_SET(de->d_name, ".wants", ".requires", ".d")) +- continue; +- +- filename = path_join(*dir, de->d_name); +- if (!filename) +- return log_oom(); +- +- if (ret_path_cache) { +- r = set_consume(paths, filename); +- if (r < 0) +- return log_oom(); +- /* We will still use filename below. This is safe because we know the set +- * holds a reference. */ +- } else +- _filename_free = filename; /* Make sure we free the filename. */ +- +- if (!valid_unit_name) +- continue; +- assert_se(suffix = strrchr(de->d_name, '.')); +- +- /* search_path is ordered by priority (highest first). If the name is already mapped +- * to something (incl. itself), it means that we have already seen it, and we should +- * ignore it here. */ +- if (hashmap_contains(ids, de->d_name)) +- continue; +- +- if (de->d_type == DT_LNK) { +- /* We don't explicitly check for alias loops here. unit_ids_map_get() which +- * limits the number of hops should be used to access the map. */ +- +- _cleanup_free_ char *target = NULL, *target_abs = NULL; +- +- r = readlinkat_malloc(dirfd(d), de->d_name, &target); +- if (r < 0) { +- log_warning_errno(r, "Failed to read symlink %s/%s, ignoring: %m", +- *dir, de->d_name); +- continue; +- } +- +- if (!path_is_absolute(target)) { +- target_abs = path_join(*dir, target); +- if (!target_abs) +- return log_oom(); +- +- free_and_replace(target, target_abs); +- } +- +- /* Get rid of "." and ".." components in target path */ +- r = chase_symlinks(target, lp->root_dir, CHASE_NOFOLLOW | CHASE_NONEXISTENT, &simplified); +- if (r < 0) { +- log_warning_errno(r, "Failed to resolve symlink %s pointing to %s, ignoring: %m", +- filename, target); +- continue; +- } +- +- /* Check if the symlink goes outside of our search path. +- * If yes, it's a linked unit file or mask, and we don't care about the target name. +- * Let's just store the link destination directly. +- * If not, let's verify that it's a good symlink. */ +- char *tail = path_startswith_strv(simplified, lp->search_path); +- if (tail) { +- bool self_alias; +- +- dst = basename(simplified); +- self_alias = streq(dst, de->d_name); +- +- if (is_path(tail)) +- log_full(self_alias ? LOG_DEBUG : LOG_WARNING, +- "Suspicious symlink %s→%s, treating as alias.", +- filename, simplified); +- +- r = unit_validate_alias_symlink_and_warn(filename, simplified); +- if (r < 0) +- continue; +- +- if (self_alias) { +- /* A self-alias that has no effect */ +- log_debug("%s: self-alias: %s/%s → %s, ignoring.", +- __func__, *dir, de->d_name, dst); +- continue; +- } +- +- log_debug("%s: alias: %s/%s → %s", __func__, *dir, de->d_name, dst); +- } else { +- dst = simplified; +- +- log_debug("%s: linked unit file: %s/%s → %s", __func__, *dir, de->d_name, dst); +- } +- +- } else { +- dst = filename; +- log_debug("%s: normal unit file: %s", __func__, dst); +- } +- +- r = hashmap_put_strdup(&ids, de->d_name, dst); +- if (r < 0) +- return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", +- de->d_name, dst); +- } +- } +- +- /* Let's also put the names in the reverse db. */ +- Iterator it; +- const char *dummy, *src; +- HASHMAP_FOREACH_KEY(dummy, src, ids, it) { +- const char *dst; +- +- r = unit_ids_map_get(ids, src, &dst); +- if (r < 0) +- continue; +- +- if (null_or_empty_path(dst) != 0) +- continue; +- +- /* Do not treat instance symlinks that point to the template as aliases */ +- if (unit_name_is_valid(basename(dst), UNIT_NAME_TEMPLATE) && +- unit_name_is_valid(src, UNIT_NAME_INSTANCE)) +- continue; +- +- r = string_strv_hashmap_put(&names, basename(dst), src); +- if (r < 0) +- return log_warning_errno(r, "Failed to add entry to hashmap (%s→%s): %m", +- basename(dst), src); +- } +- +- *ret_unit_ids_map = TAKE_PTR(ids); +- *ret_unit_names_map = TAKE_PTR(names); +- if (ret_path_cache) +- *ret_path_cache = TAKE_PTR(paths); +- +- return 0; +-} +- +-int unit_file_find_fragment( +- Hashmap *unit_ids_map, +- Hashmap *unit_name_map, +- const char *unit_name, +- const char **ret_fragment_path, +- Set **ret_names) { +- +- const char *fragment = NULL; +- _cleanup_free_ char *template = NULL, *instance = NULL; +- _cleanup_set_free_free_ Set *names = NULL; +- char **t, **nnn; +- int r, name_type; +- +- /* Finds a fragment path, and returns the set of names: +- * if we have …/foo.service and …/foo-alias.service→foo.service, +- * and …/foo@.service and …/foo-alias@.service→foo@.service, +- * and …/foo@inst.service, +- * this should return: +- * foo.service → …/foo.service, {foo.service, foo-alias.service}, +- * foo-alias.service → …/foo.service, {foo.service, foo-alias.service}, +- * foo@.service → …/foo@.service, {foo@.service, foo-alias@.service}, +- * foo-alias@.service → …/foo@.service, {foo@.service, foo-alias@.service}, +- * foo@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, +- * foo-alias@bar.service → …/foo@.service, {foo@bar.service, foo-alias@bar.service}, +- * foo-alias@inst.service → …/foo@inst.service, {foo@inst.service, foo-alias@inst.service}. +- */ +- +- name_type = unit_name_to_instance(unit_name, &instance); +- if (name_type < 0) +- return name_type; +- +- names = set_new(&string_hash_ops); +- if (!names) +- return -ENOMEM; +- +- /* The unit always has its own name if it's not a template. */ +- if (IN_SET(name_type, UNIT_NAME_PLAIN, UNIT_NAME_INSTANCE)) { +- r = set_put_strdup(names, unit_name); +- if (r < 0) +- return r; +- } +- +- /* First try to load fragment under the original name */ +- r = unit_ids_map_get(unit_ids_map, unit_name, &fragment); +- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) +- return log_debug_errno(r, "Cannot load unit %s: %m", unit_name); +- +- if (fragment) { +- /* Add any aliases of the original name to the set of names */ +- nnn = hashmap_get(unit_name_map, basename(fragment)); +- STRV_FOREACH(t, nnn) { +- if (name_type == UNIT_NAME_INSTANCE && unit_name_is_valid(*t, UNIT_NAME_TEMPLATE)) { +- char *inst; +- +- r = unit_name_replace_instance(*t, instance, &inst); +- if (r < 0) +- return log_debug_errno(r, "Cannot build instance name %s+%s: %m", *t, instance); +- +- if (!streq(unit_name, inst)) +- log_debug("%s: %s has alias %s", __func__, unit_name, inst); +- +- log_info("%s: %s+%s → %s", __func__, *t, instance, inst); +- r = set_consume(names, inst); +- } else { +- if (!streq(unit_name, *t)) +- log_debug("%s: %s has alias %s", __func__, unit_name, *t); +- +- r = set_put_strdup(names, *t); +- } +- if (r < 0) +- return r; +- } +- } +- +- if (!fragment && name_type == UNIT_NAME_INSTANCE) { +- /* Look for a fragment under the template name */ +- +- r = unit_name_template(unit_name, &template); +- if (r < 0) +- return log_error_errno(r, "Failed to determine template name: %m"); +- +- r = unit_ids_map_get(unit_ids_map, template, &fragment); +- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) +- return log_debug_errno(r, "Cannot load template %s: %m", template); +- +- if (fragment) { +- /* Add any aliases of the original name to the set of names */ +- nnn = hashmap_get(unit_name_map, basename(fragment)); +- STRV_FOREACH(t, nnn) { +- _cleanup_free_ char *inst = NULL; +- const char *inst_fragment = NULL; +- +- r = unit_name_replace_instance(*t, instance, &inst); +- if (r < 0) +- return log_debug_errno(r, "Cannot build instance name %s+%s: %m", template, instance); +- +- /* Exclude any aliases that point in some other direction. */ +- r = unit_ids_map_get(unit_ids_map, inst, &inst_fragment); +- if (r < 0 && !IN_SET(r, -ENOENT, -ENXIO)) +- return log_debug_errno(r, "Cannot find instance fragment %s: %m", inst); +- +- if (inst_fragment && +- !streq(basename(inst_fragment), basename(fragment))) { +- log_debug("Instance %s has fragment %s and is not an alias of %s.", +- inst, inst_fragment, unit_name); +- continue; +- } +- +- if (!streq(unit_name, inst)) +- log_debug("%s: %s has alias %s", __func__, unit_name, inst); +- r = set_consume(names, TAKE_PTR(inst)); +- if (r < 0) +- return r; +- } +- } +- } +- +- *ret_fragment_path = fragment; +- *ret_names = TAKE_PTR(names); +- +- // FIXME: if instance, consider any unit names with different template name +- return 0; +-} +diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h +index 52e17f7..e57f472 100644 +--- a/src/shared/unit-file.h ++++ b/src/shared/unit-file.h +@@ -3,12 +3,10 @@ + + #include + +-#include "hashmap.h" + #include "unit-name.h" + + typedef enum UnitFileState UnitFileState; + typedef enum UnitFileScope UnitFileScope; +-typedef struct LookupPaths LookupPaths; + + enum UnitFileState { + UNIT_FILE_ENABLED, +@@ -39,16 +37,3 @@ bool unit_type_may_alias(UnitType type) _const_; + bool unit_type_may_template(UnitType type) _const_; + + int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); +- +-int unit_file_build_name_map( +- const LookupPaths *lp, +- Hashmap **ret_unit_ids_map, +- Hashmap **ret_unit_names_map, +- Set **ret_path_cache); +- +-int unit_file_find_fragment( +- Hashmap *unit_ids_map, +- Hashmap *unit_name_map, +- const char *unit_name, +- const char **ret_fragment_path, +- Set **names); +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 69063ee..48e0bad 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -33,7 +33,6 @@ + #include "cgroup-util.h" + #include "copy.h" + #include "cpu-set-util.h" +-#include "dirent-util.h" + #include "dropin.h" + #include "efivars.h" + #include "env-util.h" +@@ -167,18 +166,12 @@ static bool arg_jobs_before = false; + static bool arg_jobs_after = false; + static char **arg_clean_what = NULL; + +-/* This is a global cache that will be constructed on first use. */ +-static Hashmap *cached_id_map = NULL; +-static Hashmap *cached_name_map = NULL; +- + STATIC_DESTRUCTOR_REGISTER(arg_wall, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_root, freep); + STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_properties, strv_freep); + STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep); +-STATIC_DESTRUCTOR_REGISTER(cached_id_map, hashmap_freep); +-STATIC_DESTRUCTOR_REGISTER(cached_name_map, hashmap_freep); + + static int daemon_reload(int argc, char *argv[], void* userdata); + static int trivial_method(int argc, char *argv[], void *userdata); +@@ -2590,24 +2583,38 @@ static int unit_find_paths( + return log_error_errno(r, "Failed to get DropInPaths: %s", bus_error_message(&error, r)); + } + } else { +- const char *_path; +- _cleanup_set_free_free_ Set *names = NULL; ++ _cleanup_set_free_ Set *names = NULL; ++ _cleanup_free_ char *template = NULL; + +- if (!cached_name_map) { +- r = unit_file_build_name_map(lp, &cached_id_map, &cached_name_map, NULL); +- if (r < 0) +- return r; +- } ++ names = set_new(NULL); ++ if (!names) ++ return log_oom(); + +- r = unit_file_find_fragment(cached_id_map, cached_name_map, unit_name, &_path, &names); ++ r = unit_find_template_path(unit_name, lp, &path, &template); + if (r < 0) + return r; ++ if (r > 0) { ++ if (null_or_empty_path(path)) ++ /* The template is masked. Let's cut the process short. */ ++ return -ERFKILL; ++ ++ /* We found the unit file. If we followed symlinks, this name might be ++ * different then the unit_name with started with. Look for dropins matching ++ * that "final" name. */ ++ r = set_put(names, basename(path)); ++ } else if (!template) ++ /* No unit file, let's look for dropins matching the original name. ++ * systemd has fairly complicated rules (based on unit type and provenience), ++ * which units are allowed not to have the main unit file. We err on the ++ * side of including too many files, and always try to load dropins. */ ++ r = set_put(names, unit_name); ++ else ++ /* The cases where we allow a unit to exist without the main file are ++ * never valid for templates. Don't try to load dropins in this case. */ ++ goto not_found; + +- if (_path) { +- path = strdup(_path); +- if (!path) +- return log_oom(); +- } ++ if (r < 0) ++ return log_error_errno(r, "Failed to add unit name: %m"); + + if (ret_dropin_paths) { + r = unit_file_find_dropin_paths(arg_root, lp->search_path, NULL, +diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c +index 988ac15..b626b5f 100644 +--- a/src/test/test-unit-file.c ++++ b/src/test/test-unit-file.c +@@ -25,50 +25,10 @@ static void test_unit_validate_alias_symlink_and_warn(void) { + assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL); + } + +-static void test_unit_file_build_name_map(char **ids) { +- _cleanup_(lookup_paths_free) LookupPaths lp = {}; +- _cleanup_hashmap_free_ Hashmap *unit_ids = NULL; +- _cleanup_hashmap_free_ Hashmap *unit_names = NULL; +- Iterator i; +- const char *k, *dst; +- char **v; +- +- assert_se(lookup_paths_init(&lp, UNIT_FILE_SYSTEM, 0, NULL) >= 0); +- +- assert_se(unit_file_build_name_map(&lp, &unit_ids, &unit_names, NULL) == 0); +- +- HASHMAP_FOREACH_KEY(dst, k, unit_ids, i) +- log_info("ids: %s → %s", k, dst); +- +- HASHMAP_FOREACH_KEY(v, k, unit_names, i) { +- _cleanup_free_ char *j = strv_join(v, ", "); +- log_info("aliases: %s ← %s", k, j); +- } +- +- char **id; +- STRV_FOREACH(id, ids) { +- const char *fragment, *name; +- Iterator it; +- _cleanup_set_free_free_ Set *names = NULL; +- log_info("*** %s ***", *id); +- r = unit_file_find_fragment(unit_ids, +- unit_names, +- *id, +- &fragment, +- &names); +- assert(r == 0); +- log_info("fragment: %s", fragment); +- log_info("names:"); +- SET_FOREACH(name, names, it) +- log_info(" %s", name); +- } +-} +- + int main(int argc, char **argv) { + test_setup_logging(LOG_DEBUG); + + test_unit_validate_alias_symlink_and_warn(); +- test_unit_file_build_name_map(strv_skip(argv, 1)); + + return 0; + } +diff --git a/test/TEST-15-DROPIN/test-dropin.sh b/test/TEST-15-DROPIN/test-dropin.sh +index 2cef5a3..f785680 100755 +--- a/test/TEST-15-DROPIN/test-dropin.sh ++++ b/test/TEST-15-DROPIN/test-dropin.sh +@@ -158,14 +158,14 @@ EOF + systemctl show -p Names,Requires bar@0 + systemctl show -p Names,Requires bar-alias@0 + check_ok bar@0 Names bar@0 +- check_ok bar@0 Names bar-alias@0 ++ check_ko bar@0 Names bar-alias@0 + + check_ok bar@0 After bar-template-after.device + + check_ok bar@0 Requires bar-0-requires.device +- check_ok bar@0 Requires bar-alias-0-requires.device ++ check_ko bar@0 Requires bar-alias-0-requires.device + check_ok bar@0 Requires bar-template-requires.device +- check_ok bar@0 Requires bar-alias-template-requires.device ++ check_ko bar@0 Requires bar-alias-template-requires.device + check_ko bar@0 Requires yup-template-requires.device + + check_ok bar-alias@0 After bar-template-after.device +@@ -181,15 +181,15 @@ EOF + systemctl show -p Names,Requires bar@1 + systemctl show -p Names,Requires bar-alias@1 + check_ok bar@1 Names bar@1 +- check_ok bar@1 Names bar-alias@1 ++ check_ko bar@1 Names bar-alias@1 + + check_ok bar@1 After bar-template-after.device + + check_ok bar@1 Requires bar-1-requires.device +- check_ok bar@1 Requires bar-alias-1-requires.device ++ check_ko bar@1 Requires bar-alias-1-requires.device + check_ok bar@1 Requires bar-template-requires.device + # See https://github.com/systemd/systemd/pull/13119#discussion_r308145418 +- check_ok bar@1 Requires bar-alias-template-requires.device ++ check_ko bar@1 Requires bar-alias-template-requires.device + check_ko bar@1 Requires yup-template-requires.device + check_ko bar@1 Requires yup-1-requires.device + +@@ -241,14 +241,14 @@ EOF + check_ko bar@3 Requires yup-template-requires.device + check_ko bar@3 Requires yup-3-requires.device + +- check_ko bar-alias@3 After bar-template-after.device ++ check_ok bar-alias@3 After bar-template-after.device + +- check_ko bar-alias@3 Requires bar-3-requires.device ++ check_ok bar-alias@3 Requires bar-3-requires.device + check_ok bar-alias@3 Requires bar-alias-3-requires.device +- check_ko bar-alias@3 Requires bar-template-requires.device ++ check_ok bar-alias@3 Requires bar-template-requires.device + check_ok bar-alias@3 Requires bar-alias-template-requires.device +- check_ok bar-alias@3 Requires yup-template-requires.device +- check_ok bar-alias@3 Requires yup-3-requires.device ++ check_ko bar-alias@3 Requires yup-template-requires.device ++ check_ko bar-alias@3 Requires yup-3-requires.device + + clear_services foo {bar,yup,bar-alias}@{,1,2,3} + } +@@ -267,7 +267,14 @@ test_alias_dropins () { + rm /etc/systemd/system/b1.service + clear_services a b + +- # Check that dependencies don't vary. ++ # A weird behavior: the dependencies for 'a' may vary. It can be ++ # changed by loading an alias... ++ # ++ # [1] 'a1' is loaded and then "renamed" into 'a'. 'a1' is therefore ++ # part of the names set so all its specific dropins are loaded. ++ # ++ # [2] 'a' is already loaded. 'a1' is simply only merged into 'a' so ++ # none of its dropins are loaded ('y' is missing from the deps). + echo "*** test 2" + create_services a x y + mkdir -p /etc/systemd/system/a1.service.wants/ +@@ -278,7 +285,7 @@ test_alias_dropins () { + check_ok a1 Wants y.service + systemctl start a + check_ok a1 Wants x.service # see [2] +- check_ok a1 Wants y.service ++ check_ko a1 Wants y.service + systemctl stop a x y + rm /etc/systemd/system/a1.service + +-- +1.8.3.1 + diff --git a/0037-revert-shared-unit-file-add-a-function-to-validate-u.patch b/0037-revert-shared-unit-file-add-a-function-to-validate-u.patch new file mode 100644 index 0000000000000000000000000000000000000000..89667563b160521dffa303b42674de1b8a3b53a9 --- /dev/null +++ b/0037-revert-shared-unit-file-add-a-function-to-validate-u.patch @@ -0,0 +1,177 @@ +From 7d1e91d1a9504ab1bc03894038f90a8e87a4e982 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 2 Apr 2019 11:22:56 +0200 +Subject: [PATCH] shared/unit-file: add a function to validate unit alias + symlinks + +It turns out most possible symlinks are invalid, because the type has to match, +and template units can only be linked to template units. + +I'm not sure if the existing code made the same checks consistently. At least +I don't see the same rules expressed in a single place. + +revert shared unit file add a function to validate unit alias symlinks +--- + src/shared/unit-file.c | 73 ----------------------------------------------- + src/shared/unit-file.h | 2 -- + src/test/meson.build | 4 --- + src/test/test-unit-file.c | 34 ---------------------- + 4 files changed, 113 deletions(-) + delete mode 100644 src/test/test-unit-file.c + +diff --git a/src/shared/unit-file.c b/src/shared/unit-file.c +index cde38c4..deed7dc 100644 +--- a/src/shared/unit-file.c ++++ b/src/shared/unit-file.c +@@ -1,7 +1,6 @@ + /* SPDX-License-Identifier: LGPL-2.1+ */ + + #include "macro.h" +-#include "string-util.h" + #include "unit-file.h" + + bool unit_type_may_alias(UnitType type) { +@@ -22,75 +21,3 @@ bool unit_type_may_template(UnitType type) { + UNIT_TIMER, + UNIT_PATH); + } +- +-int unit_validate_alias_symlink_and_warn(const char *filename, const char *target) { +- const char *src, *dst; +- _cleanup_free_ char *src_instance = NULL, *dst_instance = NULL; +- UnitType src_unit_type, dst_unit_type; +- int src_name_type, dst_name_type; +- +- /* Check if the *alias* symlink is valid. This applies to symlinks like +- * /etc/systemd/system/dbus.service → dbus-broker.service, but not to .wants or .requires symlinks +- * and such. Neither does this apply to symlinks which *link* units, i.e. symlinks to outside of the +- * unit lookup path. +- * +- * -EINVAL is returned if the something is wrong with the source filename or the source unit type is +- * not allowed to symlink, +- * -EXDEV if the target filename is not a valid unit name or doesn't match the source. +- */ +- +- src = basename(filename); +- dst = basename(target); +- +- /* src checks */ +- +- src_name_type = unit_name_to_instance(src, &src_instance); +- if (src_name_type < 0) +- return log_notice_errno(src_name_type, +- "%s: not a valid unit name \"%s\": %m", filename, src); +- +- src_unit_type = unit_name_to_type(src); +- assert(src_unit_type >= 0); /* unit_name_to_instance() checked the suffix already */ +- +- if (!unit_type_may_alias(src_unit_type)) +- return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), +- "%s: symlinks are not allowed for units of this type, rejecting.", +- filename); +- +- if (src_name_type != UNIT_NAME_PLAIN && +- !unit_type_may_template(src_unit_type)) +- return log_notice_errno(SYNTHETIC_ERRNO(EINVAL), +- "%s: templates not allowed for %s units, rejecting.", +- filename, unit_type_to_string(src_unit_type)); +- +- /* dst checks */ +- +- dst_name_type = unit_name_to_instance(dst, &dst_instance); +- if (dst_name_type < 0) +- return log_notice_errno(dst_name_type == -EINVAL ? SYNTHETIC_ERRNO(EXDEV) : dst_name_type, +- "%s points to \"%s\" which is not a valid unit name: %m", +- filename, dst); +- +- if (!(dst_name_type == src_name_type || +- (src_name_type == UNIT_NAME_INSTANCE && dst_name_type == UNIT_NAME_TEMPLATE))) +- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), +- "%s: symlink target name type \"%s\" does not match source, rejecting.", +- filename, dst); +- +- if (dst_name_type == UNIT_NAME_INSTANCE) { +- assert(src_instance); +- assert(dst_instance); +- if (!streq(src_instance, dst_instance)) +- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), +- "%s: unit symlink target \"%s\" instance name doesn't match, rejecting.", +- filename, dst); +- } +- +- dst_unit_type = unit_name_to_type(dst); +- if (dst_unit_type != src_unit_type) +- return log_notice_errno(SYNTHETIC_ERRNO(EXDEV), +- "%s: symlink target \"%s\" has incompatible suffix, rejecting.", +- filename, dst); +- +- return 0; +-} +diff --git a/src/shared/unit-file.h b/src/shared/unit-file.h +index e57f472..2b9df65 100644 +--- a/src/shared/unit-file.h ++++ b/src/shared/unit-file.h +@@ -35,5 +35,3 @@ enum UnitFileScope { + + bool unit_type_may_alias(UnitType type) _const_; + bool unit_type_may_template(UnitType type) _const_; +- +-int unit_validate_alias_symlink_and_warn(const char *filename, const char *target); +diff --git a/src/test/meson.build b/src/test/meson.build +index de31e97..5625e68 100644 +--- a/src/test/meson.build ++++ b/src/test/meson.build +@@ -137,10 +137,6 @@ tests += [ + [], + 'ENABLE_EFI'], + +- [['src/test/test-unit-file.c'], +- [], +- []], +- + [['src/test/test-unit-name.c', + 'src/test/test-helper.c'], + [libcore, +diff --git a/src/test/test-unit-file.c b/src/test/test-unit-file.c +deleted file mode 100644 +index b626b5f..0000000 +--- a/src/test/test-unit-file.c ++++ /dev/null +@@ -1,34 +0,0 @@ +-/* SPDX-License-Identifier: LGPL-2.1+ */ +- +-#include "path-lookup.h" +-#include "set.h" +-#include "strv.h" +-#include "tests.h" +-#include "unit-file.h" +- +-static void test_unit_validate_alias_symlink_and_warn(void) { +- log_info("/* %s */", __func__); +- +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.socket") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b.foobar") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@.socket") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@YYY.socket") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b@YYY.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@XXX.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@XXX.service", "/other/b@.service") == 0); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.service", "/other/b.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.service", "/other/b@.service") == -EXDEV); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a@.slice", "/other/b.slice") == -EINVAL); +- assert_se(unit_validate_alias_symlink_and_warn("/path/a.slice", "/other/b.slice") == -EINVAL); +-} +- +-int main(int argc, char **argv) { +- test_setup_logging(LOG_DEBUG); +- +- test_unit_validate_alias_symlink_and_warn(); +- +- return 0; +-} +-- +1.8.3.1 + diff --git a/0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch b/0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch new file mode 100644 index 0000000000000000000000000000000000000000..62ec61d75cb3f16dc4f76e3f7aa34e7e4c468241 --- /dev/null +++ b/0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch @@ -0,0 +1,52 @@ +From bec31cf5f0037dd049299e8665e03fc74024e357 Mon Sep 17 00:00:00 2001 +From: Alin Popa +Date: Fri, 14 Feb 2020 09:33:43 +0100 +Subject: [PATCH] systemd: Fix busctl crash on aarch64 when setting output + table format + +The enum used for column names is integer type while table_set_display() is parsing +arguments on size_t alignment which may result in assert in table_set_display() if +the size between types missmatch. This patch cast the enums to size_t. +An alternative solution would be to change the table_set_display() function +arguments to unsigned type. +--- + src/busctl/busctl.c | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c +index 5f3d5dd..b4e133f 100644 +--- a/src/busctl/busctl.c ++++ b/src/busctl/busctl.c +@@ -212,9 +212,27 @@ static int list_bus_names(int argc, char **argv, void *userdata) { + return log_error_errno(r, "Failed to set sort column: %m"); + + if (arg_show_machine) +- r = table_set_display(table, COLUMN_NAME, COLUMN_PID, COLUMN_PROCESS, COLUMN_USER, COLUMN_CONNECTION, COLUMN_UNIT, COLUMN_SESSION, COLUMN_DESCRIPTION, COLUMN_MACHINE, (size_t) -1); ++ r = table_set_display(table, (size_t) COLUMN_NAME, ++ (size_t) COLUMN_PID, ++ (size_t) COLUMN_PROCESS, ++ (size_t) COLUMN_USER, ++ (size_t) COLUMN_CONNECTION, ++ (size_t) COLUMN_UNIT, ++ (size_t) COLUMN_SESSION, ++ (size_t) COLUMN_DESCRIPTION, ++ (size_t) COLUMN_MACHINE, ++ (size_t) -1); + else +- r = table_set_display(table, COLUMN_NAME, COLUMN_PID, COLUMN_PROCESS, COLUMN_USER, COLUMN_CONNECTION, COLUMN_UNIT, COLUMN_SESSION, COLUMN_DESCRIPTION, (size_t) -1); ++ r = table_set_display(table, (size_t) COLUMN_NAME, ++ (size_t) COLUMN_PID, ++ (size_t) COLUMN_PROCESS, ++ (size_t) COLUMN_USER, ++ (size_t) COLUMN_CONNECTION, ++ (size_t) COLUMN_UNIT, ++ (size_t) COLUMN_SESSION, ++ (size_t) COLUMN_DESCRIPTION, ++ (size_t) -1); ++ + if (r < 0) + return log_error_errno(r, "Failed to set columns to display: %m"); + +-- +1.8.3.1 + diff --git a/0039-seccomp-more-comprehensive-protection-against-libsec.patch b/0039-seccomp-more-comprehensive-protection-against-libsec.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e28c85f3e67c4ad4d05e5fa60c3d6d503ddd3e1 --- /dev/null +++ b/0039-seccomp-more-comprehensive-protection-against-libsec.patch @@ -0,0 +1,145 @@ +From 4df8fe8415eaf4abd5b93c3447452547c6ea9e5f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 14 Nov 2019 17:51:30 +0100 +Subject: [PATCH] seccomp: more comprehensive protection against libseccomp's + __NR_xyz namespace invasion + +A follow-up for 59b657296a2fe104f112b91bbf9301724067cc81, adding the +same conditioning for all cases of our __NR_xyz use. + +Fixes: #14031 +--- + src/basic/missing_syscall.h | 10 +++++----- + src/test/test-seccomp.c | 19 ++++++++++--------- + 2 files changed, 15 insertions(+), 14 deletions(-) + +diff --git a/src/basic/missing_syscall.h b/src/basic/missing_syscall.h +index 6d9b125..1255d8b 100644 +--- a/src/basic/missing_syscall.h ++++ b/src/basic/missing_syscall.h +@@ -274,7 +274,7 @@ static inline int missing_renameat2(int oldfd, const char *oldname, int newfd, c + + #if !HAVE_KCMP + static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long idx1, unsigned long idx2) { +-# ifdef __NR_kcmp ++# if defined __NR_kcmp && __NR_kcmp > 0 + return syscall(__NR_kcmp, pid1, pid2, type, idx1, idx2); + # else + errno = ENOSYS; +@@ -289,7 +289,7 @@ static inline int missing_kcmp(pid_t pid1, pid_t pid2, int type, unsigned long i + + #if !HAVE_KEYCTL + static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { +-# ifdef __NR_keyctl ++# if defined __NR_keyctl && __NR_keyctl > 0 + return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); + # else + errno = ENOSYS; +@@ -300,7 +300,7 @@ static inline long missing_keyctl(int cmd, unsigned long arg2, unsigned long arg + } + + static inline key_serial_t missing_add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid) { +-# ifdef __NR_add_key ++# if defined __NR_add_key && __NR_add_key > 0 + return syscall(__NR_add_key, type, description, payload, plen, ringid); + # else + errno = ENOSYS; +@@ -311,7 +311,7 @@ static inline key_serial_t missing_add_key(const char *type, const char *descrip + } + + static inline key_serial_t missing_request_key(const char *type, const char *description, const char * callout_info, key_serial_t destringid) { +-# ifdef __NR_request_key ++# if defined __NR_request_key && __NR_request_key > 0 + return syscall(__NR_request_key, type, description, callout_info, destringid); + # else + errno = ENOSYS; +@@ -496,7 +496,7 @@ enum { + static inline long missing_set_mempolicy(int mode, const unsigned long *nodemask, + unsigned long maxnode) { + long i; +-# ifdef __NR_set_mempolicy ++# if defined __NR_set_mempolicy && __NR_set_mempolicy > 0 + i = syscall(__NR_set_mempolicy, mode, nodemask, maxnode); + # else + errno = ENOSYS; +diff --git a/src/test/test-seccomp.c b/src/test/test-seccomp.c +index 018c20f..c669204 100644 +--- a/src/test/test-seccomp.c ++++ b/src/test/test-seccomp.c +@@ -28,7 +28,8 @@ + #include "tmpfile-util.h" + #include "virt.h" + +-#if SCMP_SYS(socket) < 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) ++/* __NR_socket may be invalid due to libseccomp */ ++#if !defined(__NR_socket) || __NR_socket <= 0 || defined(__i386__) || defined(__s390x__) || defined(__s390__) + /* On these archs, socket() is implemented via the socketcall() syscall multiplexer, + * and we can't restrict it hence via seccomp. */ + # define SECCOMP_RESTRICT_ADDRESS_FAMILIES_BROKEN 1 +@@ -304,14 +305,14 @@ static void test_protect_sysctl(void) { + assert_se(pid >= 0); + + if (pid == 0) { +-#if __NR__sysctl > 0 ++#if defined __NR__sysctl && __NR__sysctl > 0 + assert_se(syscall(__NR__sysctl, NULL) < 0); + assert_se(errno == EFAULT); + #endif + + assert_se(seccomp_protect_sysctl() >= 0); + +-#if __NR__sysctl > 0 ++#if defined __NR__sysctl && __NR__sysctl > 0 + assert_se(syscall(__NR__sysctl, 0, 0, 0) < 0); + assert_se(errno == EPERM); + #endif +@@ -640,7 +641,7 @@ static void test_load_syscall_filter_set_raw(void) { + assert_se(poll(NULL, 0, 0) == 0); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(access) >= 0 ++#if defined __NR_access && __NR_access > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(-1)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(-1)) >= 0); +@@ -656,7 +657,7 @@ static void test_load_syscall_filter_set_raw(void) { + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(access) >= 0 ++#if defined __NR_access && __NR_access > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_access + 1), INT_TO_PTR(EILSEQ)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_faccessat + 1), INT_TO_PTR(EILSEQ)) >= 0); +@@ -672,7 +673,7 @@ static void test_load_syscall_filter_set_raw(void) { + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(poll) >= 0 ++#if defined __NR_poll && __NR_poll > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(-1)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(-1)) >= 0); +@@ -689,7 +690,7 @@ static void test_load_syscall_filter_set_raw(void) { + s = hashmap_free(s); + + assert_se(s = hashmap_new(NULL)); +-#if SCMP_SYS(poll) >= 0 ++#if defined __NR_poll && __NR_poll > 0 + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_poll + 1), INT_TO_PTR(EILSEQ)) >= 0); + #else + assert_se(hashmap_put(s, UINT32_TO_PTR(__NR_ppoll + 1), INT_TO_PTR(EILSEQ)) >= 0); +@@ -767,8 +768,8 @@ static int real_open(const char *path, int flags, mode_t mode) { + * testing purposes that calls the real syscall, on architectures where SYS_open is defined. On + * other architectures, let's just fall back to the glibc call. */ + +-#ifdef SYS_open +- return (int) syscall(SYS_open, path, flags, mode); ++#if defined __NR_open && __NR_open > 0 ++ return (int) syscall(__NR_open, path, flags, mode); + #else + return open(path, flags, mode); + #endif +-- +1.8.3.1 + diff --git a/0040-network-fix-double-free-in-macsec_receive_channel_fr.patch b/0040-network-fix-double-free-in-macsec_receive_channel_fr.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b266b60926a09046efa0929e187b23198bb34d3 --- /dev/null +++ b/0040-network-fix-double-free-in-macsec_receive_channel_fr.patch @@ -0,0 +1,45 @@ +From 0e77fc66bceb9832da82a56a4c1040fe49f8d805 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 29 May 2020 16:56:09 +0900 +Subject: [PATCH] network: fix double free in macsec_receive_channel_free() + +Fixes #15941. +Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=22547 +--- + src/network/netdev/macsec.c | 2 +- + test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 | 10 ++++++++++ + 2 files changed, 11 insertions(+), 1 deletion(-) + create mode 100644 test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 + +diff --git a/src/network/netdev/macsec.c b/src/network/netdev/macsec.c +index 3542f9652a..8f7559e9ae 100644 +--- a/src/network/netdev/macsec.c ++++ b/src/network/netdev/macsec.c +@@ -102,7 +102,7 @@ static void macsec_receive_channel_free(ReceiveChannel *c) { + + if (c->macsec) { + if (c->sci.as_uint64 > 0) +- ordered_hashmap_remove(c->macsec->receive_channels, &c->sci.as_uint64); ++ ordered_hashmap_remove_value(c->macsec->receive_channels, &c->sci.as_uint64, c); + + if (c->section) + ordered_hashmap_remove(c->macsec->receive_channels_by_section, c->section); +diff --git a/test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 b/test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 +new file mode 100644 +index 0000000000..ca55a33ae9 +--- /dev/null ++++ b/test/fuzz/fuzz-netdev-parser/oss-fuzz-22547 +@@ -0,0 +1,10 @@ ++[NetDev] ++Name=o ++Kind=macsec ++ ++[MACsecReceiveChannel] ++MACAddress=12.0.4 ++Port=913 ++[MACsecReceiveChannel] ++MACAddress=12.0.4 ++Port=913 +-- +2.23.0 + diff --git a/0041-network-L2TP-fix-crash.patch b/0041-network-L2TP-fix-crash.patch new file mode 100644 index 0000000000000000000000000000000000000000..d3cd0e9f858221a2b925522eb5c4e71e08129585 --- /dev/null +++ b/0041-network-L2TP-fix-crash.patch @@ -0,0 +1,59 @@ +From a1422af564e3b1128fc7754596b4c2f8b36a4620 Mon Sep 17 00:00:00 2001 +From: Susant Sahani +Date: Sat, 30 May 2020 06:35:28 +0200 +Subject: [PATCH] network: L2TP fix crash + +``` +=220358== Invalid read of size 8 +==220358== at 0x452F05: l2tp_session_free (l2tp-tunnel.c:46) +==220358== by 0x456926: l2tp_tunnel_done (l2tp-tunnel.c:725) +==220358== by 0x43CF4D: netdev_free (netdev.c:205) +==220358== by 0x43D045: netdev_unref (netdev.c:210) +==220358== by 0x4198B7: manager_free (networkd-manager.c:1877) +==220358== by 0x40D0B3: manager_freep (networkd-manager.h:105) +==220358== by 0x40DE1C: run (networkd.c:21) +==220358== by 0x40DE75: main (networkd.c:130) +==220358== Address 0x5c035d0 is 0 bytes inside a block of size 40 free'd +==220358== at 0x483A9F5: free (vg_replace_malloc.c:538) +==220358== by 0x452F87: l2tp_session_free (l2tp-tunnel.c:57) +==220358== by 0x456857: netdev_l2tp_tunnel_verify (l2tp-tunnel.c:710) +==220358== by 0x440947: netdev_load_one (netdev.c:738) +==220358== by 0x441222: netdev_load (netdev.c:851) +==220358== by 0x419C50: manager_load_config (networkd-manager.c:1934) +==220358== by 0x40D7BE: run (networkd.c:87) +==220358== by 0x40DE75: main (networkd.c:130) +==220358== Block was alloc'd at +==220358== at 0x4839809: malloc (vg_replace_malloc.c:307) +==220358== by 0x452A76: malloc_multiply (alloc-util.h:96) +==220358== by 0x4531E6: l2tp_session_new_static (l2tp-tunnel.c:82) +==220358== by 0x455C01: config_parse_l2tp_session_id (l2tp-tunnel.c:535) +==220358== by 0x48E6D72: next_assignment (conf-parser.c:133) +==220358== by 0x48E77A3: parse_line (conf-parser.c:271) +==220358== by 0x48E7E4F: config_parse (conf-parser.c:396) +==220358== by 0x48E80E5: config_parse_many_files (conf-parser.c:453) +==220358== by 0x48E8490: config_parse_many (conf-parser.c:512) +==220358== by 0x44089C: netdev_load_one (netdev.c:729) +==220358== by 0x441222: netdev_load (netdev.c:851) +==220358== by 0x419C50: manager_load_config (networkd-manager.c:1934) + +``` +--- + src/network/netdev/l2tp-tunnel.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/network/netdev/l2tp-tunnel.c b/src/network/netdev/l2tp-tunnel.c +index 19683c0a00..91788c3681 100644 +--- a/src/network/netdev/l2tp-tunnel.c ++++ b/src/network/netdev/l2tp-tunnel.c +@@ -44,7 +44,7 @@ static void l2tp_session_free(L2tpSession *s) { + return; + + if (s->tunnel && s->section) +- ordered_hashmap_remove(s->tunnel->sessions_by_section, s); ++ ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section); + + network_config_section_free(s->section); + +-- +2.23.0 + diff --git a/0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch b/0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch new file mode 100644 index 0000000000000000000000000000000000000000..20d450f113e03eb2e7493cf43ba83ce13f5e4522 --- /dev/null +++ b/0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch @@ -0,0 +1,25 @@ +From 13f697b7b1f3837d144ba6f60188bc7dc4d1fbaa Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 13 Oct 2019 00:54:34 +0900 +Subject: [PATCH] systemctl: fix memleak caused by wrong cleanup func + +--- + src/systemctl/systemctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 98a71c4460..738b9af536 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -7977,7 +7977,7 @@ static void help_states(void) { + + static int help_boot_loader_entry(void) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +- _cleanup_free_ char **l = NULL; ++ _cleanup_strv_free_ char **l = NULL; + sd_bus *bus; + char **i; + int r; +-- +2.23.0 + diff --git a/0043-analyze-fix-minor-memleak.patch b/0043-analyze-fix-minor-memleak.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e62c2c839f64ef1e54c74204d0737a187b4a1f9 --- /dev/null +++ b/0043-analyze-fix-minor-memleak.patch @@ -0,0 +1,25 @@ +From 81610e9609c966a33dcff15a4f3b173aa8f07e4b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 25 Oct 2019 16:05:11 +0200 +Subject: [PATCH] analyze: fix minor memleak + +--- + src/analyze/analyze.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index 1871a4363e..2d541fe701 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -1713,7 +1713,7 @@ static void kernel_syscalls_remove(Set *s, const SyscallFilterSet *set) { + if (syscall[0] == '@') + continue; + +- (void) set_remove(s, syscall); ++ free(set_remove(s, syscall)); + } + } + +-- +2.23.0 + diff --git a/0044-network-add-one-more-section-validty-check.patch b/0044-network-add-one-more-section-validty-check.patch new file mode 100644 index 0000000000000000000000000000000000000000..f2107bb69bcdf261b46d9c14edb30d005a5108eb --- /dev/null +++ b/0044-network-add-one-more-section-validty-check.patch @@ -0,0 +1,28 @@ +From 714a199e481c294b9986b7d5160a89a65d8b375a Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 19 Sep 2019 15:20:00 +0900 +Subject: [PATCH] network: add one more section validty check + +Follow-up for 203d4df5732b1fdcf50db498ddeb74a934b21f87. +--- + src/network/networkd-network.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index d1c4cddeb1..a2cd7f4c60 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -300,6 +300,10 @@ int network_verify(Network *network) { + if (section_is_invalid(prefix->section)) + prefix_free(prefix); + ++ LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_route_prefixes) ++ if (section_is_invalid(prefix->section)) ++ prefix_free(prefix); ++ + LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + if (routing_policy_rule_section_verify(rule) < 0) + routing_policy_rule_free(rule); +-- +2.23.0 + diff --git a/0045-network-use-fix-invalid-free-function.patch b/0045-network-use-fix-invalid-free-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..e81147020f39140de521a902503bde788dcd0ca5 --- /dev/null +++ b/0045-network-use-fix-invalid-free-function.patch @@ -0,0 +1,26 @@ +From acb71754e12f98ebd01963869a297ea262494740 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 09:36:39 +0900 +Subject: [PATCH] network: use fix invalid free function + +Fixes #13938. +--- + src/network/networkd-network.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 90d86f35a9..5e82b3c5e0 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -306,7 +306,7 @@ int network_verify(Network *network) { + + LIST_FOREACH_SAFE(prefixes, prefix, prefix_next, network->static_route_prefixes) + if (section_is_invalid(prefix->section)) +- prefix_free(prefix); ++ route_prefix_free(prefix); + + LIST_FOREACH_SAFE(rules, rule, rule_next, network->rules) + if (routing_policy_rule_section_verify(rule) < 0) +-- +2.23.0 + diff --git a/0046-network-fix-memleak.patch b/0046-network-fix-memleak.patch new file mode 100644 index 0000000000000000000000000000000000000000..5aef90cbff2e1b5facb416f2745107f2a0b07d6b --- /dev/null +++ b/0046-network-fix-memleak.patch @@ -0,0 +1,34 @@ +From 9be6ae775fb303deb49ee8e4c5013ce98dc48b93 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 09:39:44 +0900 +Subject: [PATCH] network: fix memleak + +--- + src/network/networkd-network.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 5e82b3c5e0..f6d02fb274 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -586,6 +586,9 @@ static Network *network_free(Network *network) { + while ((prefix = network->static_prefixes)) + prefix_free(prefix); + ++ while ((prefix = network->static_route_prefixes)) ++ route_prefix_free(prefix); ++ + while ((rule = network->rules)) + routing_policy_rule_free(rule); + +@@ -596,6 +599,7 @@ static Network *network_free(Network *network) { + hashmap_free(network->neighbors_by_section); + hashmap_free(network->address_labels_by_section); + hashmap_free(network->prefixes_by_section); ++ hashmap_free(network->route_prefixes_by_section); + hashmap_free(network->rules_by_section); + + if (network->manager) { +-- +2.23.0 + diff --git a/0047-network-Add-support-to-advertie-ipv6-route.patch b/0047-network-Add-support-to-advertie-ipv6-route.patch new file mode 100644 index 0000000000000000000000000000000000000000..4c3e4040503edeb9eb1bd0ad734e7591dbb9b100 --- /dev/null +++ b/0047-network-Add-support-to-advertie-ipv6-route.patch @@ -0,0 +1,711 @@ +From 203d4df5732b1fdcf50db498ddeb74a934b21f87 Mon Sep 17 00:00:00 2001 +From: Susant Sahani +Date: Sat, 14 Sep 2019 16:44:22 +0530 +Subject: [PATCH] network: Add support to advertie ipv6 route + +Implements https://tools.ietf.org/html/rfc4191 + +cat veth99.network +``` +[Match] +Name=veth99 + +[Network] +DHCP=no +IPv6PrefixDelegation=yes +Address=2001:db8:0:1::1/64 + +[IPv6Prefix] +Prefix=2001:db8:0:1::4/64 + +[IPv6RoutePrefix] +Route=2001:db0:fff::/48 + +``` +Wireshark + +``` +Frame 481: 142 bytes on wire (1136 bits), 142 bytes captured (1136 bits) on interface 0 +Ethernet II, Src: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4), Dst: IPv6mcast_01 (33:33:00:00:00:01) +Internet Protocol Version 6, Src: fe80::1c04:f8ff:feb8:2fd4, Dst: ff02::1 +Internet Control Message Protocol v6 + Type: Router Advertisement (134) + Code: 0 + Checksum: 0xec77 [correct] + [Checksum Status: Good] + Cur hop limit: 0 + Flags: 0x00, Prf (Default Router Preference): Medium + Router lifetime (s): 0 + Reachable time (ms): 0 + Retrans timer (ms): 0 + ICMPv6 Option (Source link-layer address : 1e:04:f8:b8:2f:d4) + Type: Source link-layer address (1) + Length: 1 (8 bytes) + Link-layer address: 1e:04:f8:b8:2f:d4 (1e:04:f8:b8:2f:d4) + ICMPv6 Option (MTU : 1500) + Type: MTU (5) + Length: 1 (8 bytes) + Reserved + MTU: 1500 + ICMPv6 Option (Prefix information : 2001:db8:0:1::4/64) + Type: Prefix information (3) + Length: 4 (32 bytes) + Prefix Length: 64 + Flag: 0xc0, On-link flag(L), Autonomous address-configuration flag(A) + Valid Lifetime: 2592000 + Preferred Lifetime: 604800 + Reserved + Prefix: 2001:db8:0:1::4 + ICMPv6 Option (Route Information : Medium 2001:db0:fff::/48) + Type: Route Information (24) + Length: 3 (24 bytes) + Prefix Length: 48 + Flag: 0x00, Route Preference: Medium + ...0 0... = Route Preference: Medium (0) + 000. .000 = Reserved: 0 + Route Lifetime: 604800 + Prefix: 2001:db0:fff:: +``` +--- + man/systemd.network.xml | 33 ++- + src/libsystemd-network/radv-internal.h | 26 +++ + src/libsystemd-network/sd-radv.c | 130 +++++++++++- + src/network/networkd-network-gperf.gperf | 2 + + src/network/networkd-network.c | 1 + + src/network/networkd-network.h | 3 + + src/network/networkd-radv.c | 195 +++++++++++++++++- + src/network/networkd-radv.h | 9 + + src/systemd/sd-radv.h | 10 + + .../fuzz-network-parser/directives.network | 3 + + 10 files changed, 400 insertions(+), 12 deletions(-) + +diff --git a/man/systemd.network.xml b/man/systemd.network.xml +index 155c0868b2..8ecc39ce5e 100644 +--- a/man/systemd.network.xml ++++ b/man/systemd.network.xml +@@ -1886,7 +1886,7 @@ + + + +- ++ + [IPv6Prefix] Section Options + One or more [IPv6Prefix] sections contain the IPv6 + prefixes that are announced via Router Advertisements. See +@@ -1931,6 +1931,37 @@ + + + ++ ++ [IPv6RoutePrefix] Section Options ++ One or more [IPv6RoutePrefix] sections contain the IPv6 ++ prefix routes that are announced via Router Advertisements. See ++ RFC 4191 ++ for further details. ++ ++ ++ ++ ++ Route= ++ ++ The IPv6 route that is to be distributed to hosts. ++ Similarly to configuring static IPv6 routes, the setting is ++ configured as an IPv6 prefix routes and its prefix route length, ++ separated by a/ character. Use multiple ++ [IPv6PrefixRoutes] sections to configure multiple IPv6 ++ prefix routes. ++ ++ ++ ++ LifetimeSec= ++ ++ Lifetime for the route prefix measured in ++ seconds. LifetimeSec= defaults to 604800 seconds (one week). ++ ++ ++ ++ ++ ++ + + [Bridge] Section Options + The [Bridge] section accepts the +diff --git a/src/libsystemd-network/radv-internal.h b/src/libsystemd-network/radv-internal.h +index 7b09c7a66c..fb6617bedd 100644 +--- a/src/libsystemd-network/radv-internal.h ++++ b/src/libsystemd-network/radv-internal.h +@@ -19,6 +19,7 @@ assert_cc(SD_RADV_DEFAULT_MIN_TIMEOUT_USEC <= SD_RADV_DEFAULT_MAX_TIMEOUT_USEC); + #define SD_RADV_MIN_DELAY_BETWEEN_RAS 3 + #define SD_RADV_MAX_RA_DELAY_TIME_USEC (500*USEC_PER_MSEC) + ++#define SD_RADV_OPT_ROUTE_INFORMATION 24 + #define SD_RADV_OPT_RDNSS 25 + #define SD_RADV_OPT_DNSSL 31 + +@@ -58,6 +59,9 @@ struct sd_radv { + unsigned n_prefixes; + LIST_HEAD(sd_radv_prefix, prefixes); + ++ unsigned n_route_prefixes; ++ LIST_HEAD(sd_radv_route_prefix, route_prefixes); ++ + size_t n_rdnss; + struct sd_radv_opt_dns *rdnss; + struct sd_radv_opt_dns *dnssl; +@@ -98,6 +102,28 @@ struct sd_radv_prefix { + usec_t preferred_until; + }; + ++#define radv_route_prefix_opt__contents { \ ++ uint8_t type; \ ++ uint8_t length; \ ++ uint8_t prefixlen; \ ++ uint8_t flags_reserved; \ ++ be32_t lifetime; \ ++ struct in6_addr in6_addr; \ ++} ++ ++struct radv_route_prefix_opt radv_route_prefix_opt__contents; ++ ++struct radv_route_prefix_opt__packed radv_route_prefix_opt__contents _packed_; ++assert_cc(sizeof(struct radv_route_prefix_opt) == sizeof(struct radv_route_prefix_opt__packed)); ++ ++struct sd_radv_route_prefix { ++ unsigned n_ref; ++ ++ struct radv_route_prefix_opt opt; ++ ++ LIST_FIELDS(struct sd_radv_route_prefix, prefix); ++}; ++ + #define log_radv_full(level, error, fmt, ...) log_internal(level, error, PROJECT_FILE, __LINE__, __func__, "RADV: " fmt, ##__VA_ARGS__) + #define log_radv_errno(error, fmt, ...) log_radv_full(LOG_DEBUG, error, fmt, ##__VA_ARGS__) + #define log_radv(fmt, ...) log_radv_errno(0, fmt, ##__VA_ARGS__) +diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c +index 185b55e1c5..d531f52326 100644 +--- a/src/libsystemd-network/sd-radv.c ++++ b/src/libsystemd-network/sd-radv.c +@@ -116,6 +116,7 @@ static sd_radv *radv_free(sd_radv *ra) { + DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv, sd_radv, radv_free); + + static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_lifetime) { ++ sd_radv_route_prefix *rt; + sd_radv_prefix *p; + struct sockaddr_in6 dst_addr = { + .sin6_family = AF_INET6, +@@ -136,9 +137,9 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li + .nd_opt_mtu_type = ND_OPT_MTU, + .nd_opt_mtu_len = 1, + }; +- /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, RDNSS ++ /* Reserve iov space for RA header, linkaddr, MTU, N prefixes, N routes, RDNSS + and DNSSL */ +- struct iovec iov[5 + ra->n_prefixes]; ++ struct iovec iov[5 + ra->n_prefixes + ra->n_route_prefixes]; + struct msghdr msg = { + .msg_name = &dst_addr, + .msg_namelen = sizeof(dst_addr), +@@ -190,6 +191,9 @@ static int radv_send(sd_radv *ra, const struct in6_addr *dst, uint32_t router_li + iov[msg.msg_iovlen++] = IOVEC_MAKE(&p->opt, sizeof(p->opt)); + } + ++ LIST_FOREACH(prefix, rt, ra->route_prefixes) ++ iov[msg.msg_iovlen++] = IOVEC_MAKE(&rt->opt, sizeof(rt->opt)); ++ + if (ra->rdnss) + iov[msg.msg_iovlen++] = IOVEC_MAKE(ra->rdnss, ra->rdnss->length * 8); + +@@ -606,6 +610,77 @@ _public_ sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, + return cur; + } + ++_public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic) { ++ char time_string_valid[FORMAT_TIMESPAN_MAX]; ++ usec_t time_now, valid, valid_until; ++ _cleanup_free_ char *pretty = NULL; ++ sd_radv_route_prefix *cur; ++ int r; ++ ++ assert_return(ra, -EINVAL); ++ ++ if (!p) ++ return -EINVAL; ++ ++ (void) in_addr_to_string(AF_INET6, ++ (union in_addr_union*) &p->opt.in6_addr, ++ &pretty); ++ ++ LIST_FOREACH(prefix, cur, ra->route_prefixes) { ++ _cleanup_free_ char *addr = NULL; ++ ++ r = in_addr_prefix_intersect(AF_INET6, ++ (union in_addr_union*) &cur->opt.in6_addr, ++ cur->opt.prefixlen, ++ (union in_addr_union*) &p->opt.in6_addr, ++ p->opt.prefixlen); ++ if (r < 0) ++ return r; ++ if (r == 0) ++ continue; ++ ++ if (dynamic && cur->opt.prefixlen == p->opt.prefixlen) ++ goto update; ++ ++ (void) in_addr_to_string(AF_INET6, ++ (union in_addr_union*) &cur->opt.in6_addr, ++ &addr); ++ log_radv("IPv6 route prefix %s/%u already configured, ignoring %s/%u", ++ strempty(addr), cur->opt.prefixlen, ++ strempty(pretty), p->opt.prefixlen); ++ ++ return -EEXIST; ++ } ++ ++ p = sd_radv_route_prefix_ref(p); ++ ++ LIST_APPEND(prefix, ra->route_prefixes, p); ++ ra->n_route_prefixes++; ++ ++ cur = p; ++ if (!dynamic) { ++ log_radv("Added prefix %s/%u", strempty(pretty), p->opt.prefixlen); ++ return 0; ++ } ++ ++ update: ++ r = sd_event_now(ra->event, clock_boottime_or_monotonic(), &time_now); ++ if (r < 0) ++ return r; ++ ++ valid = be32toh(p->opt.lifetime) * USEC_PER_SEC; ++ valid_until = usec_add(valid, time_now); ++ if (valid_until == USEC_INFINITY) ++ return -EOVERFLOW; ++ ++ log_radv("%s route prefix %s/%u valid %s", ++ cur? "Updated": "Added", ++ strempty(pretty), p->opt.prefixlen, ++ format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, valid, USEC_PER_SEC)); ++ ++ return 0; ++} ++ + _public_ int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, + const struct in6_addr *dns, size_t n_dns) { + _cleanup_free_ struct sd_radv_opt_dns *opt_rdnss = NULL; +@@ -770,3 +845,54 @@ _public_ int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + + return 0; + } ++ ++_public_ int sd_radv_route_prefix_new(sd_radv_route_prefix **ret) { ++ sd_radv_route_prefix *p; ++ ++ assert_return(ret, -EINVAL); ++ ++ p = new(sd_radv_route_prefix, 1); ++ if (!p) ++ return -ENOMEM; ++ ++ *p = (sd_radv_route_prefix) { ++ .n_ref = 1, ++ ++ .opt.type = SD_RADV_OPT_ROUTE_INFORMATION, ++ .opt.length = DIV_ROUND_UP(sizeof(p->opt), 8), ++ .opt.prefixlen = 64, ++ ++ .opt.lifetime = htobe32(604800), ++ }; ++ ++ *ret = p; ++ return 0; ++} ++ ++DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(sd_radv_route_prefix, sd_radv_route_prefix, mfree); ++ ++_public_ int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, ++ unsigned char prefixlen) { ++ assert_return(p, -EINVAL); ++ assert_return(in6_addr, -EINVAL); ++ ++ if (prefixlen > 128) ++ return -EINVAL; ++ ++ if (prefixlen > 64) ++ /* unusual but allowed, log it */ ++ log_radv("Unusual prefix length %u greater than 64", prefixlen); ++ ++ p->opt.in6_addr = *in6_addr; ++ p->opt.prefixlen = prefixlen; ++ ++ return 0; ++} ++ ++_public_ int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime) { ++ assert_return(p, -EINVAL); ++ ++ p->opt.lifetime = htobe32(valid_lifetime); ++ ++ return 0; ++} +diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf +index d4d108ad25..43163a31ec 100644 +--- a/src/network/networkd-network-gperf.gperf ++++ b/src/network/networkd-network-gperf.gperf +@@ -223,6 +223,8 @@ IPv6Prefix.OnLink, config_parse_prefix_flags, + IPv6Prefix.AddressAutoconfiguration, config_parse_prefix_flags, 0, 0 + IPv6Prefix.ValidLifetimeSec, config_parse_prefix_lifetime, 0, 0 + IPv6Prefix.PreferredLifetimeSec, config_parse_prefix_lifetime, 0, 0 ++IPv6RoutePrefix.Route, config_parse_route_prefix, 0, 0 ++IPv6RoutePrefix.LifetimeSec, config_parse_route_prefix_lifetime, 0, 0 + CAN.BitRate, config_parse_si_size, 0, offsetof(Network, can_bitrate) + CAN.SamplePoint, config_parse_permille, 0, offsetof(Network, can_sample_point) + CAN.RestartSec, config_parse_sec, 0, offsetof(Network, can_restart_us) +diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c +index 70dbd31f50..0608219429 100644 +--- a/src/network/networkd-network.c ++++ b/src/network/networkd-network.c +@@ -458,6 +458,7 @@ int network_load_one(Manager *manager, const char *filename) { + "BridgeVLAN\0" + "IPv6PrefixDelegation\0" + "IPv6Prefix\0" ++ "IPv6RoutePrefix\0" + "CAN\0", + config_item_perf_lookup, network_network_gperf_lookup, + CONFIG_PARSE_WARN, network); +diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h +index bc760744e5..486b8c31a5 100644 +--- a/src/network/networkd-network.h ++++ b/src/network/networkd-network.h +@@ -221,6 +221,7 @@ struct Network { + LIST_HEAD(Neighbor, neighbors); + LIST_HEAD(AddressLabel, address_labels); + LIST_HEAD(Prefix, static_prefixes); ++ LIST_HEAD(Prefix, static_route_prefixes); + LIST_HEAD(RoutingPolicyRule, rules); + + unsigned n_static_addresses; +@@ -230,6 +231,7 @@ struct Network { + unsigned n_neighbors; + unsigned n_address_labels; + unsigned n_static_prefixes; ++ unsigned n_static_route_prefixes; + unsigned n_rules; + + Hashmap *addresses_by_section; +@@ -238,6 +240,7 @@ struct Network { + Hashmap *neighbors_by_section; + Hashmap *address_labels_by_section; + Hashmap *prefixes_by_section; ++ Hashmap *route_prefixes_by_section; + Hashmap *rules_by_section; + + /* All kinds of DNS configuration */ +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 25321aefed..8972c661ae 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -101,16 +101,100 @@ static int prefix_new_static(Network *network, const char *filename, + return 0; + } + ++int route_prefix_new(Prefix **ret) { ++ _cleanup_(prefix_freep) Prefix *prefix = NULL; ++ ++ prefix = new0(Prefix, 1); ++ if (!prefix) ++ return -ENOMEM; ++ ++ if (sd_radv_route_prefix_new(&prefix->radv_route_prefix) < 0) ++ return -ENOMEM; ++ ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++} ++ ++void route_prefix_free(Prefix *prefix) { ++ if (!prefix) ++ return; ++ ++ if (prefix->network) { ++ LIST_REMOVE(prefixes, prefix->network->static_route_prefixes, prefix); ++ assert(prefix->network->n_static_route_prefixes > 0); ++ prefix->network->n_static_route_prefixes--; ++ ++ if (prefix->section) ++ hashmap_remove(prefix->network->route_prefixes_by_section, ++ prefix->section); ++ } ++ ++ network_config_section_free(prefix->section); ++ ++ free(prefix); ++} ++ ++static int route_prefix_new_static(Network *network, const char *filename, ++ unsigned section_line, Prefix **ret) { ++ _cleanup_(network_config_section_freep) NetworkConfigSection *n = NULL; ++ _cleanup_(prefix_freep) Prefix *prefix = NULL; ++ int r; ++ ++ assert(network); ++ assert(ret); ++ assert(!!filename == (section_line > 0)); ++ ++ if (filename) { ++ r = network_config_section_new(filename, section_line, &n); ++ if (r < 0) ++ return r; ++ ++ if (section_line) { ++ prefix = hashmap_get(network->route_prefixes_by_section, n); ++ if (prefix) { ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++ } ++ } ++ } ++ ++ r = route_prefix_new(&prefix); ++ if (r < 0) ++ return r; ++ ++ prefix->network = network; ++ LIST_APPEND(prefixes, network->static_route_prefixes, prefix); ++ network->n_static_route_prefixes++; ++ ++ if (filename) { ++ prefix->section = TAKE_PTR(n); ++ ++ r = hashmap_ensure_allocated(&network->route_prefixes_by_section, &network_config_hash_ops); ++ if (r < 0) ++ return r; ++ ++ r = hashmap_put(network->route_prefixes_by_section, prefix->section, prefix); ++ if (r < 0) ++ return r; ++ } ++ ++ *ret = TAKE_PTR(prefix); ++ ++ return 0; ++} ++ + int config_parse_prefix(const char *unit, +- const char *filename, +- unsigned line, +- const char *section, +- unsigned section_line, +- const char *lvalue, +- int ltype, +- const char *rvalue, +- void *data, +- void *userdata) { ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { + + Network *network = userdata; + _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; +@@ -234,6 +318,90 @@ int config_parse_prefix_lifetime(const char *unit, + return 0; + } + ++int config_parse_route_prefix(const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ ++ Network *network = userdata; ++ _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ uint8_t prefixlen = 64; ++ union in_addr_union in6addr; ++ int r; ++ ++ assert(filename); ++ assert(section); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ r = route_prefix_new_static(network, filename, section_line, &p); ++ if (r < 0) ++ return r; ++ ++ r = in_addr_prefix_from_string(rvalue, AF_INET6, &in6addr, &prefixlen); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Route prefix is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ if (sd_radv_prefix_set_route_prefix(p->radv_route_prefix, &in6addr.in6, prefixlen) < 0) ++ return -EADDRNOTAVAIL; ++ ++ log_syntax(unit, LOG_INFO, filename, line, r, "Found route prefix %s", rvalue); ++ ++ p = NULL; ++ ++ return 0; ++} ++ ++int config_parse_route_prefix_lifetime(const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ Network *network = userdata; ++ _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ usec_t usec; ++ int r; ++ ++ assert(filename); ++ assert(section); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ r = route_prefix_new_static(network, filename, section_line, &p); ++ if (r < 0) ++ return r; ++ ++ r = parse_sec(rvalue, &usec); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Roure lifetime is invalid, ignoring assignment: %s", rvalue); ++ return 0; ++ } ++ ++ /* a value of 0xffffffff represents infinity */ ++ r = sd_radv_route_prefix_set_lifetime(p->radv_route_prefix, DIV_ROUND_UP(usec, USEC_PER_SEC)); ++ if (r < 0) ++ return r; ++ ++ p = NULL; ++ ++ return 0; ++} ++ + static int radv_get_ip6dns(Network *network, struct in6_addr **dns, + size_t *n_dns) { + _cleanup_free_ struct in6_addr *addresses = NULL; +@@ -438,6 +606,15 @@ int radv_configure(Link *link) { + if (r < 0) + return r; + } ++ ++ LIST_FOREACH(prefixes, p, link->network->static_route_prefixes) { ++ r = sd_radv_add_route_prefix(link->radv, p->radv_route_prefix, false); ++ if (r == -EEXIST) ++ continue; ++ if (r < 0) ++ return r; ++ } ++ + } + + return radv_emit_dns(link); +diff --git a/src/network/networkd-radv.h b/src/network/networkd-radv.h +index 45be083bfe..2f60b285ae 100644 +--- a/src/network/networkd-radv.h ++++ b/src/network/networkd-radv.h +@@ -26,8 +26,10 @@ struct Prefix { + NetworkConfigSection *section; + + sd_radv_prefix *radv_prefix; ++ sd_radv_route_prefix *radv_route_prefix; + + LIST_FIELDS(Prefix, prefixes); ++ LIST_FIELDS(Prefix, route_prefixes); + }; + + int prefix_new(Prefix **ret); +@@ -35,6 +37,11 @@ void prefix_free(Prefix *prefix); + + DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, prefix_free); + ++int route_prefix_new(Prefix **ret); ++void route_prefix_free(Prefix *prefix); ++ ++DEFINE_NETWORK_SECTION_FUNCTIONS(Prefix, route_prefix_free); ++ + int radv_emit_dns(Link *link); + int radv_configure(Link *link); + +@@ -48,3 +55,5 @@ CONFIG_PARSER_PROTOTYPE(config_parse_prefix_flags); + CONFIG_PARSER_PROTOTYPE(config_parse_prefix_lifetime); + CONFIG_PARSER_PROTOTYPE(config_parse_radv_dns); + CONFIG_PARSER_PROTOTYPE(config_parse_radv_search_domains); ++CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix); ++CONFIG_PARSER_PROTOTYPE(config_parse_route_prefix_lifetime); +diff --git a/src/systemd/sd-radv.h b/src/systemd/sd-radv.h +index 93861b9d24..f085231934 100644 +--- a/src/systemd/sd-radv.h ++++ b/src/systemd/sd-radv.h +@@ -37,6 +37,7 @@ _SD_BEGIN_DECLARATIONS; + + typedef struct sd_radv sd_radv; + typedef struct sd_radv_prefix sd_radv_prefix; ++typedef struct sd_radv_route_prefix sd_radv_route_prefix; + + /* Router Advertisement */ + int sd_radv_new(sd_radv **ret); +@@ -59,6 +60,7 @@ int sd_radv_set_managed_information(sd_radv *ra, int managed); + int sd_radv_set_other_information(sd_radv *ra, int other); + int sd_radv_set_preference(sd_radv *ra, unsigned preference); + int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic); ++int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int dynamic); + sd_radv_prefix *sd_radv_remove_prefix(sd_radv *ra, const struct in6_addr *prefix, + unsigned char prefixlen); + int sd_radv_set_rdnss(sd_radv *ra, uint32_t lifetime, +@@ -80,8 +82,16 @@ int sd_radv_prefix_set_valid_lifetime(sd_radv_prefix *p, + int sd_radv_prefix_set_preferred_lifetime(sd_radv_prefix *p, + uint32_t preferred_lifetime); + ++int sd_radv_route_prefix_new(sd_radv_route_prefix **ret); ++sd_radv_route_prefix *sd_radv_route_prefix_ref(sd_radv_route_prefix *ra); ++sd_radv_route_prefix *sd_radv_route_prefix_unref(sd_radv_route_prefix *ra); ++ ++int sd_radv_prefix_set_route_prefix(sd_radv_route_prefix *p, const struct in6_addr *in6_addr, unsigned char prefixlen); ++int sd_radv_route_prefix_set_lifetime(sd_radv_route_prefix *p, uint32_t valid_lifetime); ++ + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv, sd_radv_unref); + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_prefix, sd_radv_prefix_unref); ++_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_radv_route_prefix, sd_radv_route_prefix_unref); + + _SD_END_DECLARATIONS; + +diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network +index 848d4bd187..b688d37d08 100644 +--- a/test/fuzz/fuzz-network-parser/directives.network ++++ b/test/fuzz/fuzz-network-parser/directives.network +@@ -174,6 +174,9 @@ OnLink= + PreferredLifetimeSec= + AddressAutoconfiguration= + ValidLifetimeSec= ++[IPv6RoutePrefix] ++Route= ++LifetimeSec= + [BridgeVLAN] + EgressUntagged= + VLAN= +-- +2.23.0 + diff --git a/0048-network-fix-invalid-cleanup-function.patch b/0048-network-fix-invalid-cleanup-function.patch new file mode 100644 index 0000000000000000000000000000000000000000..0b7d423b6e00198ff2b791884899f61e45fc61f2 --- /dev/null +++ b/0048-network-fix-invalid-cleanup-function.patch @@ -0,0 +1,34 @@ +From e7825b2359d484c606bc1ff8ae3e5ab9aaf980c1 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 10:39:15 +0900 +Subject: [PATCH] network: fix invalid cleanup function + +--- + src/network/networkd-radv.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 8972c661ae..4e74756d17 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -330,7 +330,7 @@ int config_parse_route_prefix(const char *unit, + void *userdata) { + + Network *network = userdata; +- _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ _cleanup_(route_prefix_free_or_set_invalidp) Prefix *p = NULL; + uint8_t prefixlen = 64; + union in_addr_union in6addr; + int r; +@@ -372,7 +372,7 @@ int config_parse_route_prefix_lifetime(const char *unit, + void *data, + void *userdata) { + Network *network = userdata; +- _cleanup_(prefix_free_or_set_invalidp) Prefix *p = NULL; ++ _cleanup_(route_prefix_free_or_set_invalidp) Prefix *p = NULL; + usec_t usec; + int r; + +-- +2.23.0 + diff --git a/0049-network-fix-memleak-in-route_prefix_free.patch b/0049-network-fix-memleak-in-route_prefix_free.patch new file mode 100644 index 0000000000000000000000000000000000000000..a63765efbf884e3f1d25e78f0429390191f8f45f --- /dev/null +++ b/0049-network-fix-memleak-in-route_prefix_free.patch @@ -0,0 +1,33 @@ +From 471e126b254dccac66cb2987be3a5f58592d8932 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 10:46:44 +0900 +Subject: [PATCH] network: fix memleak in route_prefix_free() + +--- + src/network/networkd-radv.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/network/networkd-radv.c b/src/network/networkd-radv.c +index 8d933f1901..87db34d6cc 100644 +--- a/src/network/networkd-radv.c ++++ b/src/network/networkd-radv.c +@@ -31,7 +31,7 @@ void prefix_free(Prefix *prefix) { + } + + network_config_section_free(prefix->section); +- prefix->radv_prefix = sd_radv_prefix_unref(prefix->radv_prefix); ++ sd_radv_prefix_unref(prefix->radv_prefix); + + free(prefix); + } +@@ -131,6 +131,7 @@ void route_prefix_free(Prefix *prefix) { + } + + network_config_section_free(prefix->section); ++ sd_radv_route_prefix_unref(prefix->radv_route_prefix); + + free(prefix); + } +-- +2.23.0 + diff --git a/0050-sd-radv-fix-memleak.patch b/0050-sd-radv-fix-memleak.patch new file mode 100644 index 0000000000000000000000000000000000000000..78b131022a5362c82fc18350510bffa0bcfa5d1e --- /dev/null +++ b/0050-sd-radv-fix-memleak.patch @@ -0,0 +1,30 @@ +From 69d7eba1880095f4a9bf9350de777fe7d370c188 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 5 Nov 2019 13:30:00 +0900 +Subject: [PATCH] sd-radv: fix memleak + +--- + src/libsystemd-network/sd-radv.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/libsystemd-network/sd-radv.c b/src/libsystemd-network/sd-radv.c +index 5c7f727faa..873a2f40f8 100644 +--- a/src/libsystemd-network/sd-radv.c ++++ b/src/libsystemd-network/sd-radv.c +@@ -99,6 +99,13 @@ static sd_radv *radv_free(sd_radv *ra) { + sd_radv_prefix_unref(p); + } + ++ while (ra->route_prefixes) { ++ sd_radv_route_prefix *p = ra->route_prefixes; ++ ++ LIST_REMOVE(prefix, ra->route_prefixes, p); ++ sd_radv_route_prefix_unref(p); ++ } ++ + free(ra->rdnss); + free(ra->dnssl); + +-- +2.23.0 + diff --git a/0051-sd-bus-invalidate-connection-when-Hello-fails.patch b/0051-sd-bus-invalidate-connection-when-Hello-fails.patch new file mode 100644 index 0000000000000000000000000000000000000000..2b09b2512841356606e02d21a22485e5c165b8d2 --- /dev/null +++ b/0051-sd-bus-invalidate-connection-when-Hello-fails.patch @@ -0,0 +1,66 @@ +From 19fa17c7c4ac228924bd9b7499653a6018abf0b5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 15 Nov 2019 14:23:53 +0100 +Subject: [PATCH] sd-bus: invalidate connection when Hello() fails + +Fixes: #13969 +--- + src/libsystemd/sd-bus/sd-bus.c | 26 +++++++++++++++++++------- + 1 file changed, 19 insertions(+), 7 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index ebbfc588ca..058492a83e 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -537,29 +537,41 @@ static int hello_callback(sd_bus_message *reply, void *userdata, sd_bus_error *e + assert(IN_SET(bus->state, BUS_HELLO, BUS_CLOSING)); + + r = sd_bus_message_get_errno(reply); +- if (r > 0) +- return -r; ++ if (r > 0) { ++ r = -r; ++ goto fail; ++ } + + r = sd_bus_message_read(reply, "s", &s); + if (r < 0) +- return r; ++ goto fail; + +- if (!service_name_is_valid(s) || s[0] != ':') +- return -EBADMSG; ++ if (!service_name_is_valid(s) || s[0] != ':') { ++ r = -EBADMSG; ++ goto fail; ++ } + + r = free_and_strdup(&bus->unique_name, s); + if (r < 0) +- return r; ++ goto fail; + + if (bus->state == BUS_HELLO) { + bus_set_state(bus, BUS_RUNNING); + + r = synthesize_connected_signal(bus); + if (r < 0) +- return r; ++ goto fail; + } + + return 1; ++ ++fail: ++ /* When Hello() failed, let's propagate this in two ways: first we return the error immediately here, ++ * which is the propagated up towards the event loop. Let's also invalidate the connection, so that ++ * if the user then calls back into us again we won't wait any longer. */ ++ ++ bus_set_state(bus, BUS_CLOSING); ++ return r; + } + + static int bus_send_hello(sd_bus *bus) { +-- +2.23.0 + diff --git a/0052-shared-bus-util-Don-t-replace-exsting-strv.patch b/0052-shared-bus-util-Don-t-replace-exsting-strv.patch new file mode 100644 index 0000000000000000000000000000000000000000..6b6ae8ab09970abf4afd784b4dfb37ed7781a885 --- /dev/null +++ b/0052-shared-bus-util-Don-t-replace-exsting-strv.patch @@ -0,0 +1,33 @@ +From 411975ce63b28194b21b964268efaa04b19cbb37 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Tue, 10 Dec 2019 01:58:01 -0800 +Subject: [PATCH] shared/bus-util: Don't replace exsting strv + +Change the behavior of string arrays in a bus property map. Previously, +passing the same strv pointer to more than one map entry would result in +the old strv being freed and overwritten. With this change, an existing +strv pointer is appended to. + +This is important if we want to create one strv comprised of multiple +dependencies. This makes it so callers don't have to create one strv per +dependency and subsequently merge them into one strv. +--- + src/shared/bus-util.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index aea46d3119..10c05eba18 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -1127,7 +1127,7 @@ static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigne + if (r < 0) + return r; + +- return strv_free_and_replace(*p, l); ++ return strv_extend_strv(p, l, false); + } + + case SD_BUS_TYPE_BOOLEAN: { +-- +2.23.0 + diff --git a/0053-systemctl-Add-with-dependencies-flag.patch b/0053-systemctl-Add-with-dependencies-flag.patch new file mode 100644 index 0000000000000000000000000000000000000000..8fc4800efa828a9c75723260d956db7264c56f02 --- /dev/null +++ b/0053-systemctl-Add-with-dependencies-flag.patch @@ -0,0 +1,330 @@ +From e9c387c8293c57d1c773fc80d23239350eb3b370 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Sun, 8 Dec 2019 15:23:27 -0800 +Subject: [PATCH] systemctl: Add --with-dependencies flag + +Will print a unit and all of its dependencies. Works with cat, status, +list-units, and list-unit-files. This flag can also be used in conjunction +with --reverse, --before, and --after. + +We also vastly simplify the list_dependencies_get_dependencies logic. +Instead of using 5 strvs and merging them into one, use one strv and +have the bus append all the map values to it. + +Fixes #9273 +--- + src/systemctl/systemctl.c | 227 +++++++++++++++++++++++++------------- + 1 file changed, 148 insertions(+), 79 deletions(-) + +diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c +index 6a0e59a4d7..0873045173 100644 +--- a/src/systemctl/systemctl.c ++++ b/src/systemctl/systemctl.c +@@ -117,6 +117,7 @@ static bool arg_dry_run = false; + static bool arg_quiet = false; + static bool arg_full = false; + static bool arg_recursive = false; ++static bool arg_with_dependencies = false; + static bool arg_show_transaction = false; + static int arg_force = 0; + static bool arg_ask_password = false; +@@ -799,6 +800,107 @@ static int expand_names(sd_bus *bus, char **names, const char* suffix, char ***r + return c; + } + ++static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***ret) { ++ _cleanup_strv_free_ char **deps = NULL; ++ ++ static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = { ++ [DEPENDENCY_FORWARD] = { ++ { "Requires", "as", NULL, 0 }, ++ { "Requisite", "as", NULL, 0 }, ++ { "Wants", "as", NULL, 0 }, ++ { "ConsistsOf", "as", NULL, 0 }, ++ { "BindsTo", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_REVERSE] = { ++ { "RequiredBy", "as", NULL, 0 }, ++ { "RequisiteOf", "as", NULL, 0 }, ++ { "WantedBy", "as", NULL, 0 }, ++ { "PartOf", "as", NULL, 0 }, ++ { "BoundBy", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_AFTER] = { ++ { "After", "as", NULL, 0 }, ++ {} ++ }, ++ [DEPENDENCY_BEFORE] = { ++ { "Before", "as", NULL, 0 }, ++ {} ++ }, ++ }; ++ ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_free_ char *dbus_path = NULL; ++ int r; ++ ++ assert(bus); ++ assert(name); ++ assert(ret); ++ ++ dbus_path = unit_dbus_path_from_name(name); ++ if (!dbus_path) ++ return log_oom(); ++ ++ r = bus_map_all_properties(bus, ++ "org.freedesktop.systemd1", ++ dbus_path, ++ map[arg_dependency], ++ BUS_MAP_STRDUP, ++ &error, ++ NULL, ++ &deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); ++ ++ *ret = TAKE_PTR(deps); ++ ++ return 0; ++} ++ ++static int append_unit_dependencies(sd_bus *bus, char **names, char ***ret) { ++ _cleanup_strv_free_ char **with_deps = NULL; ++ char **name; ++ ++ assert(bus); ++ assert(ret); ++ ++ STRV_FOREACH(name, names) { ++ _cleanup_strv_free_ char **deps = NULL; ++ ++ if (strv_extend(&with_deps, *name) < 0) ++ return log_oom(); ++ ++ (void) list_dependencies_get_dependencies(bus, *name, &deps); ++ ++ if (strv_extend_strv(&with_deps, deps, true) < 0) ++ return log_oom(); ++ } ++ ++ *ret = TAKE_PTR(with_deps); ++ ++ return 0; ++} ++ ++static int maybe_extend_with_unit_dependencies(sd_bus *bus, char ***list) { ++ assert(bus); ++ assert(list); ++ ++ if (arg_with_dependencies) { ++ int r; ++ _cleanup_strv_free_ char **list_with_deps = NULL; ++ ++ r = append_unit_dependencies(bus, *list, &list_with_deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to append unit dependencies: %m"); ++ ++ strv_free(*list); ++ *list = TAKE_PTR(list_with_deps); ++ } ++ ++ return 0; ++} ++ + static int list_units(int argc, char *argv[], void *userdata) { + _cleanup_free_ UnitInfo *unit_infos = NULL; + _cleanup_(message_set_freep) Set *replies = NULL; +@@ -812,9 +914,21 @@ static int list_units(int argc, char *argv[], void *userdata) { + + (void) pager_open(arg_pager_flags); + +- r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); +- if (r < 0) +- return r; ++ if (arg_with_dependencies) { ++ _cleanup_strv_free_ char **names = NULL; ++ ++ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names); ++ if (r < 0) ++ return r; ++ ++ r = get_unit_list_recursive(bus, names, &unit_infos, &replies, &machines); ++ if (r < 0) ++ return r; ++ } else { ++ r = get_unit_list_recursive(bus, strv_skip(argv, 1), &unit_infos, &replies, &machines); ++ if (r < 0) ++ return r; ++ } + + typesafe_qsort(unit_infos, r, compare_unit_info); + return output_units_list(unit_infos, r); +@@ -1571,9 +1685,21 @@ static int list_unit_files(int argc, char *argv[], void *userdata) { + if (r < 0) + return bus_log_create_error(r); + +- r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); +- if (r < 0) +- return bus_log_create_error(r); ++ if (arg_with_dependencies) { ++ _cleanup_strv_free_ char **names_with_deps = NULL; ++ ++ r = append_unit_dependencies(bus, strv_skip(argv, 1), &names_with_deps); ++ if (r < 0) ++ return log_error_errno(r, "Failed to append unit dependencies: %m"); ++ ++ r = sd_bus_message_append_strv(m, names_with_deps); ++ if (r < 0) ++ return bus_log_create_error(r); ++ } else { ++ r = sd_bus_message_append_strv(m, strv_skip(argv, 1)); ++ if (r < 0) ++ return bus_log_create_error(r); ++ } + + r = sd_bus_call(bus, m, 0, &error, &reply); + if (r < 0 && sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) { +@@ -1677,79 +1803,6 @@ static int list_dependencies_print(const char *name, int level, unsigned branche + return 0; + } + +-static int list_dependencies_get_dependencies(sd_bus *bus, const char *name, char ***deps) { +- struct DependencyStatusInfo { +- char **dep[5]; +- } info = {}; +- +- static const struct bus_properties_map map[_DEPENDENCY_MAX][6] = { +- [DEPENDENCY_FORWARD] = { +- { "Requires", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- { "Requisite", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, +- { "Wants", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, +- { "ConsistsOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, +- { "BindsTo", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, +- {} +- }, +- [DEPENDENCY_REVERSE] = { +- { "RequiredBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- { "RequisiteOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[1]) }, +- { "WantedBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[2]) }, +- { "PartOf", "as", NULL, offsetof(struct DependencyStatusInfo, dep[3]) }, +- { "BoundBy", "as", NULL, offsetof(struct DependencyStatusInfo, dep[4]) }, +- {} +- }, +- [DEPENDENCY_AFTER] = { +- { "After", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- {} +- }, +- [DEPENDENCY_BEFORE] = { +- { "Before", "as", NULL, offsetof(struct DependencyStatusInfo, dep[0]) }, +- {} +- }, +- }; +- +- _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; +- _cleanup_strv_free_ char **ret = NULL; +- _cleanup_free_ char *dbus_path = NULL; +- int i, r; +- +- assert(bus); +- assert(name); +- assert(deps); +- +- dbus_path = unit_dbus_path_from_name(name); +- if (!dbus_path) +- return log_oom(); +- +- r = bus_map_all_properties(bus, +- "org.freedesktop.systemd1", +- dbus_path, +- map[arg_dependency], +- BUS_MAP_STRDUP, +- &error, +- NULL, +- &info); +- if (r < 0) +- return log_error_errno(r, "Failed to get properties of %s: %s", name, bus_error_message(&error, r)); +- +- if (IN_SET(arg_dependency, DEPENDENCY_AFTER, DEPENDENCY_BEFORE)) { +- *deps = info.dep[0]; +- return 0; +- } +- +- for (i = 0; i < 5; i++) { +- r = strv_extend_strv(&ret, info.dep[i], true); +- if (r < 0) +- return log_oom(); +- info.dep[i] = strv_free(info.dep[i]); +- } +- +- *deps = TAKE_PTR(ret); +- +- return 0; +-} +- + static int list_dependencies_compare(char * const *a, char * const *b) { + if (unit_name_to_type(*a) == UNIT_TARGET && unit_name_to_type(*b) != UNIT_TARGET) + return 1; +@@ -5909,6 +5962,10 @@ static int show(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + ++ r = maybe_extend_with_unit_dependencies(bus, &names); ++ if (r < 0) ++ return r; ++ + STRV_FOREACH(name, names) { + _cleanup_free_ char *path; + +@@ -5959,6 +6016,10 @@ static int cat(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "Failed to expand names: %m"); + ++ r = maybe_extend_with_unit_dependencies(bus, &names); ++ if (r < 0) ++ return r; ++ + (void) pager_open(arg_pager_flags); + + STRV_FOREACH(name, names) { +@@ -7945,6 +8006,9 @@ static int systemctl_help(void) { + " -l --full Don't ellipsize unit names on output\n" + " -r --recursive Show unit list of host and local containers\n" + " --reverse Show reverse dependencies with 'list-dependencies'\n" ++ " --with-dependencies\n" ++ " Show unit dependencies with 'status', 'cat',\n" ++ " 'list-units', and 'list-unit-files'.\n" + " --job-mode=MODE Specify how to deal with already queued jobs, when\n" + " queueing a new job\n" + " -T --show-transaction\n" +@@ -8235,6 +8298,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + ARG_BOOT_LOADER_ENTRY, + ARG_NOW, + ARG_MESSAGE, ++ ARG_WITH_DEPENDENCIES, + ARG_WAIT, + ARG_WHAT, + }; +@@ -8281,6 +8345,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + { "plain", no_argument, NULL, ARG_PLAIN }, + { "state", required_argument, NULL, ARG_STATE }, + { "recursive", no_argument, NULL, 'r' }, ++ { "with-dependencies", no_argument, NULL, ARG_WITH_DEPENDENCIES }, + { "preset-mode", required_argument, NULL, ARG_PRESET_MODE }, + { "firmware-setup", no_argument, NULL, ARG_FIRMWARE_SETUP }, + { "boot-loader-menu", required_argument, NULL, ARG_BOOT_LOADER_MENU }, +@@ -8641,6 +8706,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) { + arg_show_transaction = true; + break; + ++ case ARG_WITH_DEPENDENCIES: ++ arg_with_dependencies = true; ++ break; ++ + case ARG_WHAT: { + const char *p; + +-- +2.23.0 + diff --git a/0054-man-Document-systemctl-with-dependencies-switch.patch b/0054-man-Document-systemctl-with-dependencies-switch.patch new file mode 100644 index 0000000000000000000000000000000000000000..46d3314bff9ca1fd62ed3ca16655d4797b4a2abd --- /dev/null +++ b/0054-man-Document-systemctl-with-dependencies-switch.patch @@ -0,0 +1,39 @@ +From a602a0b44b9eb9af0027d054dd24e405a658e375 Mon Sep 17 00:00:00 2001 +From: Kevin Kuehler +Date: Mon, 9 Dec 2019 01:40:47 -0800 +Subject: [PATCH] man: Document systemctl --with-dependencies switch + +--- + man/systemctl.xml | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/man/systemctl.xml b/man/systemctl.xml +index 3d86f7dffa..5828477e8d 100644 +--- a/man/systemctl.xml ++++ b/man/systemctl.xml +@@ -1592,6 +1592,22 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err + + + ++ ++ ++ ++ ++ When used with status, ++ cat, list-units, and ++ list-unit-files, those commands print all ++ specified units and the dependencies of those units. ++ ++ Options , ++ , ++ may be used to change what types of dependencies ++ are shown. ++ ++ ++ + + + +-- +2.23.0 + diff --git a/0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch b/0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch new file mode 100644 index 0000000000000000000000000000000000000000..4baab93b7a3e5d7a1e49a9c36446e089dd913d61 --- /dev/null +++ b/0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch @@ -0,0 +1,42 @@ +From 6d9e0ca400133aeffa4a53c707db43b3e6c98c7b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:01:14 +0100 +Subject: [PATCH] core: expose swap priority value via dbus only if it is set + +--- + src/core/dbus-swap.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/src/core/dbus-swap.c b/src/core/dbus-swap.c +index 353fa20132..57c8c42091 100644 +--- a/src/core/dbus-swap.c ++++ b/src/core/dbus-swap.c +@@ -12,16 +12,23 @@ + #include "unit.h" + + static int swap_get_priority(Swap *s) { +- if (s->from_proc_swaps) ++ assert(s); ++ ++ if (s->from_proc_swaps && s->parameters_proc_swaps.priority_set) + return s->parameters_proc_swaps.priority; +- if (s->from_fragment) ++ ++ if (s->from_fragment && s->parameters_fragment.priority_set) + return s->parameters_fragment.priority; ++ + return -1; + } + + static const char *swap_get_options(Swap *s) { ++ assert(s); ++ + if (s->from_fragment) + return s->parameters_fragment.options; ++ + return NULL; + } + +-- +2.23.0 + diff --git a/0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch b/0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch new file mode 100644 index 0000000000000000000000000000000000000000..92beba286c2888cdb85aa69f9d46ac040f0c3d6b --- /dev/null +++ b/0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch @@ -0,0 +1,39 @@ +From 7e284b054ec599012f0dad6a745f6b52eba87853 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 17 Jan 2020 15:37:56 +0100 +Subject: [PATCH] tree-wide: we forgot to destroy some bus errors + +--- + src/libsystemd/sd-bus/test-bus-server.c | 2 +- + src/locale/localed.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/test-bus-server.c b/src/libsystemd/sd-bus/test-bus-server.c +index e38bcdcc76..82eb35e5b1 100644 +--- a/src/libsystemd/sd-bus/test-bus-server.c ++++ b/src/libsystemd/sd-bus/test-bus-server.c +@@ -108,7 +108,7 @@ fail: + static int client(struct context *c) { + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL; + _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; +- sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; + + assert_se(sd_bus_new(&bus) >= 0); +diff --git a/src/locale/localed.c b/src/locale/localed.c +index baf0bd102b..2031cd25ce 100644 +--- a/src/locale/localed.c ++++ b/src/locale/localed.c +@@ -33,7 +33,7 @@ static int locale_update_system_manager(Context *c, sd_bus *bus) { + _cleanup_free_ char **l_unset = NULL; + _cleanup_strv_free_ char **l_set = NULL; + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; +- sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + size_t c_set, c_unset; + LocaleVariable p; + int r; +-- +2.23.0 + diff --git a/0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch b/0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch new file mode 100644 index 0000000000000000000000000000000000000000..d937f86641662498eb05170366b7b73752134b15 --- /dev/null +++ b/0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch @@ -0,0 +1,25 @@ +From 58abbbcc6bcedc4eebd1f5c7733cd41518e1f2e3 Mon Sep 17 00:00:00 2001 +From: sangelovic +Date: Mon, 27 Jan 2020 21:40:37 +0100 +Subject: [PATCH] sd-bus: fix introspection bug in signal parameter names + +--- + src/libsystemd/sd-bus/bus-introspect.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/bus-introspect.c b/src/libsystemd/sd-bus/bus-introspect.c +index beab80687d..e8934489b5 100644 +--- a/src/libsystemd/sd-bus/bus-introspect.c ++++ b/src/libsystemd/sd-bus/bus-introspect.c +@@ -160,7 +160,7 @@ int introspect_write_interface(struct introspect *i, const sd_bus_vtable *v) { + case _SD_BUS_VTABLE_SIGNAL: + fprintf(i->f, " \n", v->x.signal.member); + if (bus_vtable_has_names(vtable)) +- names = strempty(v->x.method.names); ++ names = strempty(v->x.signal.names); + introspect_write_arguments(i, strempty(v->x.signal.signature), &names, NULL); + introspect_write_flags(i, v->type, v->flags); + fputs(" \n", i->f); +-- +2.23.0 + diff --git a/0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch b/0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch new file mode 100644 index 0000000000000000000000000000000000000000..3b6e1b5b20c428fc1b42132a5263b0746a8c5b62 --- /dev/null +++ b/0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch @@ -0,0 +1,54 @@ +From 72545ae05745f99e194eb83e3fa865f276601378 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Thu, 6 Feb 2020 15:34:17 -0800 +Subject: [PATCH] core: sync SeccompParseFlags between dbus-execute and + load-fragment + +9e486265716963439fb0fd7f2a97abf109f24f75 added some new syscalls to the +filter lists. However, on systems that do not yet support the new calls, +running systemd-run with the filter set results in error: + +``` +$ sudo systemd-run -t -r -p "SystemCallFilter=~@mount" /bin/true +Failed to start transient service unit: Invalid argument +``` + +Having the same properties in a unit file will start the service +without issue. This is because the load-fragment code will parse the +syscall filters in permissive mode: +https://github.com/systemd/systemd/blob/master/src/core/load-fragment.c#L2909 +whereas the dbus-execute equivalent of the code does not. + +Since the permissive mode appears to be the right setting to support +older kernels/libseccomp, this will update the dbus-execute parsing +to also be permissive. +--- + src/core/dbus-execute.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c +index 9ff3f157f5..d8ba3e5d92 100644 +--- a/src/core/dbus-execute.c ++++ b/src/core/dbus-execute.c +@@ -1587,6 +1587,7 @@ int bus_exec_context_set_transient_property( + r = seccomp_parse_syscall_filter("@default", + -1, + c->syscall_filter, ++ SECCOMP_PARSE_PERMISSIVE | + SECCOMP_PARSE_WHITELIST | invert_flag, + u->id, + NULL, 0); +@@ -1606,7 +1607,9 @@ int bus_exec_context_set_transient_property( + r = seccomp_parse_syscall_filter(n, + e, + c->syscall_filter, +- (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0) | invert_flag, ++ SECCOMP_PARSE_LOG | SECCOMP_PARSE_PERMISSIVE | ++ invert_flag | ++ (c->syscall_whitelist ? SECCOMP_PARSE_WHITELIST : 0), + u->id, + NULL, 0); + if (r < 0) +-- +2.23.0 + diff --git a/0059-core-swap-priority-can-be-negative.patch b/0059-core-swap-priority-can-be-negative.patch new file mode 100644 index 0000000000000000000000000000000000000000..b7f70891d84116dcd27ad0fe1c3bff8df1e88f08 --- /dev/null +++ b/0059-core-swap-priority-can-be-negative.patch @@ -0,0 +1,115 @@ +From 7477451b691d288dad67b4c8ce9e519e9b75770d Mon Sep 17 00:00:00 2001 +From: Topi Miettinen +Date: Tue, 3 Dec 2019 20:36:37 +0200 +Subject: [PATCH] core: swap priority can be negative + +Negative priorities are useful for swap targets which should be only used as +last resort. +--- + src/core/swap.c | 10 ++++++---- + src/core/swap.h | 1 + + src/shared/fstab-util.c | 10 +++------- + src/test/test-fstab-util.c | 3 +++ + 4 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index e4b018616d..03f443daec 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -117,7 +117,8 @@ static void swap_init(Unit *u) { + s->exec_context.std_output = u->manager->default_std_output; + s->exec_context.std_error = u->manager->default_std_error; + +- s->parameters_proc_swaps.priority = s->parameters_fragment.priority = -1; ++ s->parameters_proc_swaps.priority = s->parameters_fragment.priority = 0; ++ s->parameters_fragment.priority_set = false; + + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + +@@ -433,6 +434,7 @@ static int swap_setup_unit( + SWAP(u)->from_proc_swaps = true; + + p->priority = priority; ++ p->priority_set = true; + + unit_add_to_dbus_queue(u); + return 0; +@@ -766,15 +768,15 @@ static void swap_enter_activating(Swap *s) { + s->control_command = s->exec_command + SWAP_EXEC_ACTIVATE; + + if (s->from_fragment) { +- int priority = -1; ++ int priority = 0; + + r = fstab_find_pri(s->parameters_fragment.options, &priority); + if (r < 0) + log_warning_errno(r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); +- else if (r == 1 && s->parameters_fragment.priority >= 0) ++ else if (r == 1 && s->parameters_fragment.priority_set) + log_warning("Duplicate swap priority configuration by Priority and Options fields."); + +- if (r <= 0 && s->parameters_fragment.priority >= 0) { ++ if (r <= 0 && s->parameters_fragment.priority_set) { + if (s->parameters_fragment.options) + r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority); + else +diff --git a/src/core/swap.h b/src/core/swap.h +index 389faf584d..cb24cec7aa 100644 +--- a/src/core/swap.h ++++ b/src/core/swap.h +@@ -33,6 +33,7 @@ typedef struct SwapParameters { + char *what; + char *options; + int priority; ++ bool priority_set; + } SwapParameters; + + struct Swap { +diff --git a/src/shared/fstab-util.c b/src/shared/fstab-util.c +index f90501eb92..86a57e6b2c 100644 +--- a/src/shared/fstab-util.c ++++ b/src/shared/fstab-util.c +@@ -186,8 +186,7 @@ int fstab_extract_values(const char *opts, const char *name, char ***values) { + + int fstab_find_pri(const char *options, int *ret) { + _cleanup_free_ char *opt = NULL; +- int r; +- unsigned pri; ++ int r, pri; + + assert(ret); + +@@ -197,14 +196,11 @@ int fstab_find_pri(const char *options, int *ret) { + if (r == 0 || !opt) + return 0; + +- r = safe_atou(opt, &pri); ++ r = safe_atoi(opt, &pri); + if (r < 0) + return r; + +- if ((int) pri < 0) +- return -ERANGE; +- +- *ret = (int) pri; ++ *ret = pri; + return 1; + } + +diff --git a/src/test/test-fstab-util.c b/src/test/test-fstab-util.c +index 4cd504e45c..c1c7ec9114 100644 +--- a/src/test/test-fstab-util.c ++++ b/src/test/test-fstab-util.c +@@ -100,6 +100,9 @@ static void test_fstab_find_pri(void) { + assert_se(fstab_find_pri("pri=11", &pri) == 1); + assert_se(pri == 11); + ++ assert_se(fstab_find_pri("pri=-2", &pri) == 1); ++ assert_se(pri == -2); ++ + assert_se(fstab_find_pri("opt,pri=12,opt", &pri) == 1); + assert_se(pri == 12); + +-- +2.23.0 + diff --git a/0060-core-no-need-to-initialize-swap-structure-fields-if-.patch b/0060-core-no-need-to-initialize-swap-structure-fields-if-.patch new file mode 100644 index 0000000000000000000000000000000000000000..cdfab1a1021f5a53ba775c1b2f8e4e14fb04af51 --- /dev/null +++ b/0060-core-no-need-to-initialize-swap-structure-fields-if-.patch @@ -0,0 +1,35 @@ +From 6afc31615e63b7db941684be84da82a06373a778 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:01:46 +0100 +Subject: [PATCH] core: no need to initialize swap structure fields if all + zeroes anyway + +--- + src/core/swap.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index 03f443daec..6caf20ea66 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -63,7 +63,6 @@ static void swap_unset_proc_swaps(Swap *s) { + return; + + s->parameters_proc_swaps.what = mfree(s->parameters_proc_swaps.what); +- + s->from_proc_swaps = false; + } + +@@ -117,9 +116,6 @@ static void swap_init(Unit *u) { + s->exec_context.std_output = u->manager->default_std_output; + s->exec_context.std_error = u->manager->default_std_error; + +- s->parameters_proc_swaps.priority = s->parameters_fragment.priority = 0; +- s->parameters_fragment.priority_set = false; +- + s->control_command_id = _SWAP_EXEC_COMMAND_INVALID; + + u->ignore_on_isolate = true; +-- +2.23.0 + diff --git a/0061-core-initialize-priority_set-when-parsing-swap-unit-.patch b/0061-core-initialize-priority_set-when-parsing-swap-unit-.patch new file mode 100644 index 0000000000000000000000000000000000000000..134470ac76e8463990a8903f19d00ba7de8b69b9 --- /dev/null +++ b/0061-core-initialize-priority_set-when-parsing-swap-unit-.patch @@ -0,0 +1,99 @@ +From eb34a981d67165ec346c69aba53168facc556b64 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:02:56 +0100 +Subject: [PATCH] core: initialize priority_set when parsing swap unit files + +Fixes: #14524 +--- + src/core/load-fragment-gperf.gperf.m4 | 2 +- + src/core/load-fragment.c | 48 +++++++++++++++++++++++++++ + src/core/load-fragment.h | 1 + + 3 files changed, 50 insertions(+), 1 deletion(-) + +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index de08f7d067..c1f8ac7bb2 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -435,7 +435,7 @@ Automount.DirectoryMode, config_parse_mode, 0, + Automount.TimeoutIdleSec, config_parse_sec_fix_0, 0, offsetof(Automount, timeout_idle_usec) + m4_dnl + Swap.What, config_parse_unit_path_printf, 0, offsetof(Swap, parameters_fragment.what) +-Swap.Priority, config_parse_int, 0, offsetof(Swap, parameters_fragment.priority) ++Swap.Priority, config_parse_swap_priority, 0, 0 + Swap.Options, config_parse_unit_string_printf, 0, offsetof(Swap, parameters_fragment.options) + Swap.TimeoutSec, config_parse_sec_fix_0, 0, offsetof(Swap, timeout_usec) + EXEC_CONTEXT_CONFIG_ITEMS(Swap)m4_dnl +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index 1679e047dd..8f9a2f64db 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -5129,6 +5129,54 @@ int config_parse_crash_chvt( + return 0; + } + ++int config_parse_swap_priority( ++ const char *unit, ++ const char *filename, ++ unsigned line, ++ const char *section, ++ unsigned section_line, ++ const char *lvalue, ++ int ltype, ++ const char *rvalue, ++ void *data, ++ void *userdata) { ++ ++ Swap *s = userdata; ++ int r, priority; ++ ++ assert(s); ++ assert(filename); ++ assert(lvalue); ++ assert(rvalue); ++ assert(data); ++ ++ if (isempty(rvalue)) { ++ s->parameters_fragment.priority = -1; ++ s->parameters_fragment.priority_set = false; ++ return 0; ++ } ++ ++ r = safe_atoi(rvalue, &priority); ++ if (r < 0) { ++ log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap pririty '%s', ignoring.", rvalue); ++ return 0; ++ } ++ ++ if (priority < -1) { ++ log_syntax(unit, LOG_ERR, filename, line, 0, "Sorry, swap priorities smaller than -1 may only be assigned by the kernel itself, ignoring: %s", rvalue); ++ return 0; ++ } ++ ++ if (priority > 32767) { ++ log_syntax(unit, LOG_ERR, filename, line, 0, "Swap priority out of range, ignoring: %s", rvalue); ++ return 0; ++ } ++ ++ s->parameters_fragment.priority = priority; ++ s->parameters_fragment.priority_set = true; ++ return 0; ++} ++ + int config_parse_timeout_abort( + const char* unit, + const char *filename, +diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h +index b81887d510..28613ef5b3 100644 +--- a/src/core/load-fragment.h ++++ b/src/core/load-fragment.h +@@ -121,6 +121,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_status_unit_format); + CONFIG_PARSER_PROTOTYPE(config_parse_output_restricted); + CONFIG_PARSER_PROTOTYPE(config_parse_crash_chvt); + CONFIG_PARSER_PROTOTYPE(config_parse_timeout_abort); ++CONFIG_PARSER_PROTOTYPE(config_parse_swap_priority); + + /* gperf prototypes */ + const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length); +-- +2.23.0 + diff --git a/0062-core-use-unit-based-logging-instead-of-generic-loggi.patch b/0062-core-use-unit-based-logging-instead-of-generic-loggi.patch new file mode 100644 index 0000000000000000000000000000000000000000..045d60be4d7594a47270e3979d03d26a902ca6ce --- /dev/null +++ b/0062-core-use-unit-based-logging-instead-of-generic-loggi.patch @@ -0,0 +1,47 @@ +From af4454cb17da6727e490522afb7d4bddf8dae7fd Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:03:57 +0100 +Subject: [PATCH] core: use unit-based logging instead of generic logging where + appropriate + +--- + src/core/swap.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index 6caf20ea66..d4f6db6ddc 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -768,9 +768,9 @@ static void swap_enter_activating(Swap *s) { + + r = fstab_find_pri(s->parameters_fragment.options, &priority); + if (r < 0) +- log_warning_errno(r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); +- else if (r == 1 && s->parameters_fragment.priority_set) +- log_warning("Duplicate swap priority configuration by Priority and Options fields."); ++ log_unit_warning_errno(UNIT(s), r, "Failed to parse swap priority \"%s\", ignoring: %m", s->parameters_fragment.options); ++ else if (r > 0 && s->parameters_fragment.priority_set) ++ log_unit_warning(UNIT(s), "Duplicate swap priority configuration by Priority= and Options= fields."); + + if (r <= 0 && s->parameters_fragment.priority_set) { + if (s->parameters_fragment.options) +@@ -788,7 +788,7 @@ static void swap_enter_activating(Swap *s) { + + if (s->parameters_fragment.options || opts) { + r = exec_command_append(s->control_command, "-o", +- opts ? : s->parameters_fragment.options, NULL); ++ opts ?: s->parameters_fragment.options, NULL); + if (r < 0) + goto fail; + } +@@ -804,7 +804,6 @@ static void swap_enter_activating(Swap *s) { + goto fail; + + swap_set_state(s, SWAP_ACTIVATING); +- + return; + + fail: +-- +2.23.0 + diff --git a/0063-core-set-error-value-correctly.patch b/0063-core-set-error-value-correctly.patch new file mode 100644 index 0000000000000000000000000000000000000000..9a07379c8a815588d1f8dd911935c012379e6416 --- /dev/null +++ b/0063-core-set-error-value-correctly.patch @@ -0,0 +1,28 @@ +From 6fca66a7f125607864850ac9a4d6cc56a27594dd Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:04:25 +0100 +Subject: [PATCH] core: set error value correctly + +--- + src/core/swap.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/core/swap.c b/src/core/swap.c +index d4f6db6ddc..225488282e 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -777,8 +777,10 @@ static void swap_enter_activating(Swap *s) { + r = asprintf(&opts, "%s,pri=%i", s->parameters_fragment.options, s->parameters_fragment.priority); + else + r = asprintf(&opts, "pri=%i", s->parameters_fragment.priority); +- if (r < 0) ++ if (r < 0) { ++ r = -ENOMEM; + goto fail; ++ } + } + } + +-- +2.23.0 + diff --git a/0064-core-fix-re-realization-of-cgroup-siblings.patch b/0064-core-fix-re-realization-of-cgroup-siblings.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e5af6f54da1f50c8536b008112426686ca935a8 --- /dev/null +++ b/0064-core-fix-re-realization-of-cgroup-siblings.patch @@ -0,0 +1,59 @@ +From 65f6b6bdcb500c576674b5838e4cc4c35e18bfde Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 9 Jan 2020 17:30:31 +0100 +Subject: [PATCH] core: fix re-realization of cgroup siblings + +This is a fix-up for eef85c4a3f8054d29383a176f6cebd1ef3a15b9a which +broke this. + +Tracked down by @w-simon + +Fixes: #14453 +--- + src/core/cgroup.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/src/core/cgroup.c b/src/core/cgroup.c +index abcd057d6a..af2efd46fa 100644 +--- a/src/core/cgroup.c ++++ b/src/core/cgroup.c +@@ -2334,29 +2334,25 @@ unsigned manager_dispatch_cgroup_realize_queue(Manager *m) { + static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) { + Unit *slice; + +- /* This adds the siblings of the specified unit and the +- * siblings of all parent units to the cgroup queue. (But +- * neither the specified unit itself nor the parents.) */ ++ /* This adds the siblings of the specified unit and the siblings of all parent units to the cgroup ++ * queue. (But neither the specified unit itself nor the parents.) */ + + while ((slice = UNIT_DEREF(u->slice))) { + Iterator i; + Unit *m; + void *v; + +- HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) { +- /* Skip units that have a dependency on the slice +- * but aren't actually in it. */ ++ HASHMAP_FOREACH_KEY(v, m, slice->dependencies[UNIT_BEFORE], i) { ++ /* Skip units that have a dependency on the slice but aren't actually in it. */ + if (UNIT_DEREF(m->slice) != slice) + continue; + +- /* No point in doing cgroup application for units +- * without active processes. */ ++ /* No point in doing cgroup application for units without active processes. */ + if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m))) + continue; + +- /* If the unit doesn't need any new controllers +- * and has current ones realized, it doesn't need +- * any changes. */ ++ /* If the unit doesn't need any new controllers and has current ones realized, it ++ * doesn't need any changes. */ + if (unit_has_mask_realized(m, + unit_get_target_mask(m), + unit_get_enable_mask(m))) +-- +2.23.0 + diff --git a/0065-basic-string-table-avoid-crash-when-table-is-sparse.patch b/0065-basic-string-table-avoid-crash-when-table-is-sparse.patch new file mode 100644 index 0000000000000000000000000000000000000000..a41e0669e9698642c4c14f4a4ea5a14a8098bd27 --- /dev/null +++ b/0065-basic-string-table-avoid-crash-when-table-is-sparse.patch @@ -0,0 +1,27 @@ +From aa73f181e92ce991cff4e6890822764698befc90 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 27 Feb 2020 21:28:54 +0100 +Subject: [PATCH] basic/string-table: avoid crash when table is sparse + +Generated _from_string() would crash when invoked on a table with some +holes. +--- + src/basic/string-table.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/basic/string-table.h b/src/basic/string-table.h +index 2d3cf81435..96924778f5 100644 +--- a/src/basic/string-table.h ++++ b/src/basic/string-table.h +@@ -44,7 +44,7 @@ ssize_t string_table_lookup(const char * const *table, size_t len, const char *k + char *s; \ + if (i < 0 || i > max) \ + return -ERANGE; \ +- if (i < (type) ELEMENTSOF(name##_table)) { \ ++ if (i < (type) ELEMENTSOF(name##_table) && name##_table[i]) { \ + s = strdup(name##_table[i]); \ + if (!s) \ + return -ENOMEM; \ +-- +2.23.0 + diff --git a/0066-journal-fix-buffer-overrun-when-urlifying.patch b/0066-journal-fix-buffer-overrun-when-urlifying.patch new file mode 100644 index 0000000000000000000000000000000000000000..d46e191632902d06afedd7823b096fdbc616b14d --- /dev/null +++ b/0066-journal-fix-buffer-overrun-when-urlifying.patch @@ -0,0 +1,49 @@ +From 85fbebe61a1aec2f86e36fb464283b6b55d3d76d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 23 Jun 2020 20:51:13 +0200 +Subject: [PATCH] journal: fix buffer overrun when urlifying + +Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=21122. + +message is only valid until message_len, and we need to make sure we're not +reading pass that. Bug introduced in 2108b56749ebb8d17f06d08b6ada2f79ae4f0. +--- + src/shared/logs-show.c | 9 ++++++--- + test/fuzz/fuzz-journal-remote/oss-fuzz-21122 | Bin 0 -> 35798 bytes + 2 files changed, 6 insertions(+), 3 deletions(-) + create mode 100644 test/fuzz/fuzz-journal-remote/oss-fuzz-21122 + +diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c +index 570377dc76..fee6ccdf2a 100644 +--- a/src/shared/logs-show.c ++++ b/src/shared/logs-show.c +@@ -573,19 +573,22 @@ static int output_short( + if (config_file && + message_len >= config_file_len && + memcmp(message, config_file, config_file_len) == 0 && +- IN_SET(message[config_file_len], ':', ' ', '\0') && ++ (message_len == config_file_len || IN_SET(message[config_file_len], ':', ' ')) && + (!highlight || highlight_shifted[0] == 0 || highlight_shifted[0] > config_file_len)) { + + _cleanup_free_ char *t = NULL, *urlified = NULL; + + t = strndup(config_file, config_file_len); + if (t && terminal_urlify_path(t, NULL, &urlified) >= 0) { +- size_t shift = strlen(urlified) - config_file_len; ++ size_t urlified_len = strlen(urlified); ++ size_t shift = urlified_len - config_file_len; + char *joined; + +- joined = strjoin(urlified, message + config_file_len); ++ joined = realloc(urlified, message_len + shift); + if (joined) { ++ memcpy(joined + urlified_len, message + config_file_len, message_len - config_file_len); + free_and_replace(message, joined); ++ TAKE_PTR(urlified); + message_len += shift; + if (highlight) { + highlight_shifted[0] += shift; + +-- +2.23.0 + diff --git a/0071-backport-CVE-2018-21029-resolved-check-for-IP-in-certificate-when-using-DoT-.patch b/0071-backport-CVE-2018-21029-resolved-check-for-IP-in-certificate-when-using-DoT-.patch new file mode 100644 index 0000000000000000000000000000000000000000..74b9b80c14706d2abf9d0a7b328ec74bf11c80e6 --- /dev/null +++ b/0071-backport-CVE-2018-21029-resolved-check-for-IP-in-certificate-when-using-DoT-.patch @@ -0,0 +1,51 @@ +From 7f2f4faced3fda47e6b76ab73cde747cc20cf8b8 Mon Sep 17 00:00:00 2001 +From: Iwan Timmer +Date: Tue, 29 Oct 2019 20:32:18 +0100 +Subject: [PATCH] resolved: check for IP in certificate when using DoT with + GnuTLS + +Validate the IP address in the certificate for DNS-over-TLS in strict mode when GnuTLS is used. As this is not yet the case in contrast to the documentation. +--- + src/resolve/resolved-dnstls-gnutls.c | 13 +++++++++++-- + src/resolve/resolved-dnstls-gnutls.h | 1 + + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c +index ea276d2c20..9e5e60fcce 100644 +--- a/src/resolve/resolved-dnstls-gnutls.c ++++ b/src/resolve/resolved-dnstls-gnutls.c +@@ -55,8 +55,17 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + server->dnstls_data.session_data.size = 0; + } + +- if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) +- gnutls_session_set_verify_cert(gs, NULL, 0); ++ if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { ++ stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; ++ if (server->family == AF_INET) { ++ stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; ++ stream->dnstls_data.validation.size = 4; ++ } else { ++ stream->dnstls_data.validation.data = server->address.in6.s6_addr; ++ stream->dnstls_data.validation.size = 16; ++ } ++ gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); ++ } + + gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + +diff --git a/src/resolve/resolved-dnstls-gnutls.h b/src/resolve/resolved-dnstls-gnutls.h +index af52f04fdf..d4da2017c3 100644 +--- a/src/resolve/resolved-dnstls-gnutls.h ++++ b/src/resolve/resolved-dnstls-gnutls.h +@@ -18,6 +18,7 @@ struct DnsTlsServerData { + + struct DnsTlsStreamData { + gnutls_session_t session; ++ gnutls_typed_vdata_st validation; + int handshake; + bool shutdown; + }; +-- +2.26.2 + diff --git a/0072-backport-CVE-2018-21029-resolved-fix-connection-failures-with-TLS-1.3-and-Gn.patch b/0072-backport-CVE-2018-21029-resolved-fix-connection-failures-with-TLS-1.3-and-Gn.patch new file mode 100644 index 0000000000000000000000000000000000000000..38431f041ae1696c896569850b04226a923b2cad --- /dev/null +++ b/0072-backport-CVE-2018-21029-resolved-fix-connection-failures-with-TLS-1.3-and-Gn.patch @@ -0,0 +1,34 @@ +From 68805580209cfaa50b2400d1a2e6c66500001395 Mon Sep 17 00:00:00 2001 +From: Peter Wu +Date: Sun, 20 Oct 2019 18:10:31 +0100 +Subject: [PATCH] resolved: fix connection failures with TLS 1.3 and GnuTLS + +Prefer TLS 1.3 before TLS 1.2 for DNS-over-TLS support, otherwise +servers compliant with RFC 8446 might end up agreeing TLS 1.2 plus a +downgrade signal which is not expected by GnuTLS clients. This manifests +in the following error: + + Failed to invoke gnutls_handshake: An illegal parameter has been received. + +Fixes: #13528 +Fixes: v242-962-g9c0624dcdb ("resolved: support TLS 1.3 when using GnuTLS for DNS-over-TLS") +--- + src/resolve/resolved-dnstls-gnutls.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c +index 06d635fcc4..7ad9662073 100644 +--- a/src/resolve/resolved-dnstls-gnutls.c ++++ b/src/resolve/resolved-dnstls-gnutls.c +@@ -10,7 +10,7 @@ + #include "resolved-dnstls.h" + + #if GNUTLS_VERSION_NUMBER >= 0x030600 +-#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.2:+VERS-TLS1.3" ++#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2" + #else + #define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.2" + #endif +-- +2.26.2 + diff --git a/0073-backport-CVE-2018-21029-resolved-require-at-least-version-3.6.0-of-GnuTLS-fo.patch b/0073-backport-CVE-2018-21029-resolved-require-at-least-version-3.6.0-of-GnuTLS-fo.patch new file mode 100644 index 0000000000000000000000000000000000000000..32124be4ec2044415a759b81b4578924f3695679 --- /dev/null +++ b/0073-backport-CVE-2018-21029-resolved-require-at-least-version-3.6.0-of-GnuTLS-fo.patch @@ -0,0 +1,58 @@ +From 38e053c58fa139e0f546f327b5d8ce3db7cf1647 Mon Sep 17 00:00:00 2001 +From: Iwan Timmer +Date: Tue, 29 Oct 2019 20:26:05 +0100 +Subject: [PATCH] resolved: require at least version 3.6.0 of GnuTLS for + DNS-over-TLS + +Increase the required version to ensure TLS 1.3 is always supported when using GnuTLS for DNS-over-TLS and allow further changes to use recent API additions. +--- + README | 2 +- + meson.build | 2 +- + src/resolve/resolved-dnstls-gnutls.c | 4 ---- + 3 files changed, 2 insertions(+), 6 deletions(-) + +diff --git a/README b/README +index 8aa16fe8c9..8dbf94b49c 100644 +--- a/README ++++ b/README +@@ -155,7 +155,7 @@ REQUIREMENTS: + libmicrohttpd (optional) + libpython (optional) + libidn2 or libidn (optional) +- gnutls >= 3.1.4 (optional, >= 3.5.3 is required to support DNS-over-TLS with gnutls) ++ gnutls >= 3.1.4 (optional, >= 3.6.0 is required to support DNS-over-TLS with gnutls) + openssl >= 1.1.0 (optional, required to support DNS-over-TLS with openssl) + elfutils >= 158 (optional) + polkit (optional) +diff --git a/meson.build b/meson.build +index 0001504d53..a7a9222582 100644 +--- a/meson.build ++++ b/meson.build +@@ -1199,7 +1199,7 @@ if dns_over_tls != 'false' + if dns_over_tls == 'openssl' + have_gnutls = false + else +- have_gnutls = (conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.5.3')) ++ have_gnutls = (conf.get('HAVE_GNUTLS') == 1 and libgnutls.version().version_compare('>= 3.6.0')) + if dns_over_tls == 'gnutls' and not have_gnutls + error('DNS-over-TLS support was requested with gnutls, but dependencies are not available') + endif +diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c +index 7ad9662073..ea276d2c20 100644 +--- a/src/resolve/resolved-dnstls-gnutls.c ++++ b/src/resolve/resolved-dnstls-gnutls.c +@@ -9,11 +9,7 @@ + #include "resolved-dns-stream.h" + #include "resolved-dnstls.h" + +-#if GNUTLS_VERSION_NUMBER >= 0x030600 + #define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2" +-#else +-#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.2" +-#endif + DEFINE_TRIVIAL_CLEANUP_FUNC(gnutls_session_t, gnutls_deinit); + + static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *iov, int iovcnt) { +-- +2.26.2 + diff --git a/0074-backport-CVE-2018-21029-Be-more-specific-in-resolved.conf-man-page-with-rega.patch b/0074-backport-CVE-2018-21029-Be-more-specific-in-resolved.conf-man-page-with-rega.patch new file mode 100644 index 0000000000000000000000000000000000000000..95167a59cbdb962178b50aceed111aa642197ed7 --- /dev/null +++ b/0074-backport-CVE-2018-21029-Be-more-specific-in-resolved.conf-man-page-with-rega.patch @@ -0,0 +1,37 @@ +From 2f2b28ab35e80855042c69e324feaf7418636aa2 Mon Sep 17 00:00:00 2001 +From: Riccardo Schirone +Date: Wed, 13 Nov 2019 17:37:15 +0100 +Subject: [PATCH] Be more specific in resolved.conf man page with regard to + DNSOverTLS + +DNSOverTLS in strict mode (value yes) does check the server, as it is said in +the first few lines of the option documentation. The check is not performed in +"opportunistic" mode, however, as that is allowed by RFC 7858, section "4.1. +Opportunistic Privacy Profile". + +> With such a discovered DNS server, the client might or might not validate the +> resolver. These choices maximize availability and performance, but they leave +> the client vulnerable to on-path attacks that remove privacy. +--- + man/resolved.conf.xml | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml +index 213be1d7b2..818000145b 100644 +--- a/man/resolved.conf.xml ++++ b/man/resolved.conf.xml +@@ -210,8 +210,9 @@ + send for setting up an encrypted connection, and thus results + in a small DNS look-up time penalty. + +- Note as the resolver is not capable of authenticating +- the server, it is vulnerable for "man-in-the-middle" attacks. ++ Note that in opportunistic mode the ++ resolver is not capable of authenticating the server, so it is ++ vulnerable to "man-in-the-middle" attacks. + + In addition to this global DNSOverTLS setting + systemd-networkd.service8 +-- +2.26.2 + diff --git a/0075-backport-CVE-2018-21029-Implement-SNI-when-using-DNS-over-TLS.patch b/0075-backport-CVE-2018-21029-Implement-SNI-when-using-DNS-over-TLS.patch new file mode 100644 index 0000000000000000000000000000000000000000..a864bcaa71182019831406c1f62a1b44f0b0c560 --- /dev/null +++ b/0075-backport-CVE-2018-21029-Implement-SNI-when-using-DNS-over-TLS.patch @@ -0,0 +1,330 @@ +From 2e22a54f4e085496088b77085f38b66532da59fb Mon Sep 17 00:00:00 2001 +From: Guilhem Lettron +Date: Sat, 30 Nov 2019 03:51:40 +0100 +Subject: [PATCH] Implement SNI when using DNS-over-TLS + +Some DNS providers need SNI to identify client. + +This can be used by adding #name to a DNS. +Example: +[Resolve] +DNS=192.168.1.1#example.com +--- + man/resolved.conf.xml | 3 +++ + src/resolve/meson.build | 8 ++++++ + src/resolve/resolved-conf.c | 6 +++-- + src/resolve/resolved-dns-server.c | 12 ++++++++- + src/resolve/resolved-dns-server.h | 5 +++- + src/resolve/resolved-dnstls-gnutls.c | 6 +++++ + src/resolve/resolved-dnstls-openssl.c | 11 ++++++++ + src/resolve/resolved-link-bus.c | 2 +- + src/resolve/resolved-link.c | 2 +- + src/resolve/resolved-util.c | 36 +++++++++++++++++++++++++++ + src/resolve/resolved-util.h | 6 +++++ + src/resolve/test-resolved-util.c | 32 ++++++++++++++++++++++++ + 12 files changed, 123 insertions(+), 6 deletions(-) + create mode 100644 src/resolve/resolved-util.c + create mode 100644 src/resolve/resolved-util.h + create mode 100644 src/resolve/test-resolved-util.c + +diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml +index 818000145b..0f70ced5b5 100644 +--- a/man/resolved.conf.xml ++++ b/man/resolved.conf.xml +@@ -214,6 +214,9 @@ + resolver is not capable of authenticating the server, so it is + vulnerable to "man-in-the-middle" attacks. + ++ Server Name Indication (SNI) can be used when opening a TLS connection. ++ Entries in DNS= should be in format address#server_name. ++ + In addition to this global DNSOverTLS setting + systemd-networkd.service8 + also maintains per-link DNSOverTLS settings. For system DNS +diff --git a/src/resolve/meson.build b/src/resolve/meson.build +index 92b67b6333..c4d8d4e5d9 100644 +--- a/src/resolve/meson.build ++++ b/src/resolve/meson.build +@@ -64,6 +64,8 @@ systemd_resolved_sources = files(''' + resolved-etc-hosts.h + resolved-etc-hosts.c + resolved-dnstls.h ++ resolved-util.c ++ resolved-util.h + '''.split()) + + resolvectl_sources = files(''' +@@ -228,4 +230,10 @@ tests += [ + [], + [], + 'ENABLE_RESOLVE', 'manual'], ++ ++ [['src/resolve/test-resolved-util.c', ++ 'src/resolve/resolved-util.c', ++ 'src/resolve/resolved-util.h'], ++ [], ++ []], + ] +diff --git a/src/resolve/resolved-conf.c b/src/resolve/resolved-conf.c +index a46c45385b..ca5b8e7918 100644 +--- a/src/resolve/resolved-conf.c ++++ b/src/resolve/resolved-conf.c +@@ -8,6 +8,7 @@ + #include "parse-util.h" + #include "resolved-conf.h" + #include "resolved-dnssd.h" ++#include "resolved-util.h" + #include "specifier.h" + #include "string-table.h" + #include "string-util.h" +@@ -27,11 +28,12 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons + union in_addr_union address; + int family, r, ifindex = 0; + DnsServer *s; ++ _cleanup_free_ char *server_name = NULL; + + assert(m); + assert(word); + +- r = in_addr_ifindex_from_string_auto(word, &family, &address, &ifindex); ++ r = in_addr_ifindex_name_from_string_auto(word, &family, &address, &ifindex, &server_name); + if (r < 0) + return r; + +@@ -52,7 +54,7 @@ static int manager_add_dns_server_by_string(Manager *m, DnsServerType type, cons + return 0; + } + +- return dns_server_new(m, NULL, type, NULL, family, &address, ifindex); ++ return dns_server_new(m, NULL, type, NULL, family, &address, ifindex, server_name); + } + + int manager_parse_dns_server_string_and_warn(Manager *m, DnsServerType type, const char *string) { +diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c +index 9f2c97314f..4b0599ab9c 100644 +--- a/src/resolve/resolved-dns-server.c ++++ b/src/resolve/resolved-dns-server.c +@@ -25,8 +25,10 @@ int dns_server_new( + Link *l, + int family, + const union in_addr_union *in_addr, +- int ifindex) { ++ int ifindex, ++ const char *server_name) { + ++ _cleanup_free_ char *name = NULL; + DnsServer *s; + + assert(m); +@@ -44,6 +46,12 @@ int dns_server_new( + return -E2BIG; + } + ++ if (server_name) { ++ name = strdup(server_name); ++ if (!name) ++ return -ENOMEM; ++ } ++ + s = new(DnsServer, 1); + if (!s) + return -ENOMEM; +@@ -55,6 +63,7 @@ int dns_server_new( + .family = family, + .address = *in_addr, + .ifindex = ifindex, ++ .server_name = TAKE_PTR(name), + }; + + dns_server_reset_features(s); +@@ -107,6 +116,7 @@ static DnsServer* dns_server_free(DnsServer *s) { + #endif + + free(s->server_string); ++ free(s->server_name); + return mfree(s); + } + +diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h +index 54339355aa..889c80a205 100644 +--- a/src/resolve/resolved-dns-server.h ++++ b/src/resolve/resolved-dns-server.h +@@ -53,6 +53,8 @@ struct DnsServer { + + char *server_string; + ++ char *server_name; ++ + /* The long-lived stream towards this server. */ + DnsStream *stream; + +@@ -94,7 +96,8 @@ int dns_server_new( + Link *link, + int family, + const union in_addr_union *address, +- int ifindex); ++ int ifindex, ++ const char *server_string); + + DnsServer* dns_server_ref(DnsServer *s); + DnsServer* dns_server_unref(DnsServer *s); +diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c +index ed0a31e8bf..aad3bb4481 100644 +--- a/src/resolve/resolved-dnstls-gnutls.c ++++ b/src/resolve/resolved-dnstls-gnutls.c +@@ -67,6 +67,12 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); + } + ++ if (server->server_name) { ++ r = gnutls_server_name_set(gs, GNUTLS_NAME_DNS, server->server_name, strlen(server->server_name)); ++ if (r < 0) ++ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", gnutls_strerror(r)); ++ } ++ + gnutls_handshake_set_timeout(gs, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); + + gnutls_transport_set_ptr2(gs, (gnutls_transport_ptr_t) (long) stream->fd, stream); +diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c +index 85e202ff74..ce0a437371 100644 +--- a/src/resolve/resolved-dnstls-openssl.c ++++ b/src/resolve/resolved-dnstls-openssl.c +@@ -87,6 +87,17 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + return -ECONNREFUSED; + } + ++ if (server->server_name) { ++ r = SSL_set_tlsext_host_name(s, server->server_name); ++ if (r <= 0) { ++ char errbuf[256]; ++ ++ error = ERR_get_error(); ++ ERR_error_string_n(error, errbuf, sizeof(errbuf)); ++ return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to set server name: %s", errbuf); ++ } ++ } ++ + ERR_clear_error(); + stream->dnstls_data.handshake = SSL_do_handshake(s); + if (stream->dnstls_data.handshake <= 0) { +diff --git a/src/resolve/resolved-link-bus.c b/src/resolve/resolved-link-bus.c +index 8a2768b1e2..dae8435b45 100644 +--- a/src/resolve/resolved-link-bus.c ++++ b/src/resolve/resolved-link-bus.c +@@ -284,7 +284,7 @@ int bus_link_method_set_dns_servers(sd_bus_message *message, void *userdata, sd_ + if (s) + dns_server_move_back_and_unmark(s); + else { +- r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0); ++ r = dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, dns[i].family, &dns[i].address, 0, NULL); + if (r < 0) + goto clear; + } +diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c +index 96ebb4d23d..f19fc2f3aa 100644 +--- a/src/resolve/resolved-link.c ++++ b/src/resolve/resolved-link.c +@@ -269,7 +269,7 @@ static int link_update_dns_server_one(Link *l, const char *name) { + return 0; + } + +- return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0); ++ return dns_server_new(l->manager, NULL, DNS_SERVER_LINK, l, family, &a, 0, NULL); + } + + static int link_update_dns_servers(Link *l) { +diff --git a/src/resolve/resolved-util.c b/src/resolve/resolved-util.c +new file mode 100644 +index 0000000000..2f18f8c19d +--- /dev/null ++++ b/src/resolve/resolved-util.c +@@ -0,0 +1,36 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "alloc-util.h" ++#include "in-addr-util.h" ++#include "macro.h" ++#include "resolved-util.h" ++ ++int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name) { ++ _cleanup_free_ char *buf = NULL, *name = NULL; ++ const char *m; ++ int r; ++ ++ assert(s); ++ ++ m = strchr(s, '#'); ++ if (m) { ++ name = strdup(m+1); ++ if (!name) ++ return -ENOMEM; ++ ++ buf = strndup(s, m - s); ++ if (!buf) ++ return -ENOMEM; ++ ++ s = buf; ++ } ++ ++ r = in_addr_ifindex_from_string_auto(s, family, ret, ifindex); ++ if (r < 0) ++ return r; ++ ++ if (server_name) ++ *server_name = TAKE_PTR(name); ++ ++ return r; ++} +diff --git a/src/resolve/resolved-util.h b/src/resolve/resolved-util.h +new file mode 100644 +index 0000000000..10ebbc0874 +--- /dev/null ++++ b/src/resolve/resolved-util.h +@@ -0,0 +1,6 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++#pragma once ++ ++#include "in-addr-util.h" ++ ++int in_addr_ifindex_name_from_string_auto(const char *s, int *family, union in_addr_union *ret, int *ifindex, char **server_name); +diff --git a/src/resolve/test-resolved-util.c b/src/resolve/test-resolved-util.c +new file mode 100644 +index 0000000000..35bd73c4f6 +--- /dev/null ++++ b/src/resolve/test-resolved-util.c +@@ -0,0 +1,32 @@ ++/* SPDX-License-Identifier: LGPL-2.1+ */ ++ ++#include "log.h" ++#include "resolved-util.h" ++#include "string-util.h" ++#include "tests.h" ++ ++ ++static void test_in_addr_ifindex_name_from_string_auto_one(const char *a, const char *expected) { ++ int family, ifindex; ++ union in_addr_union ua; ++ _cleanup_free_ char *server_name = NULL; ++ ++ assert_se(in_addr_ifindex_name_from_string_auto(a, &family, &ua, &ifindex, &server_name) >= 0); ++ assert_se(streq_ptr(server_name, expected)); ++} ++ ++static void test_in_addr_ifindex_name_from_string_auto(void) { ++ log_info("/* %s */", __func__); ++ ++ test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1", NULL); ++ test_in_addr_ifindex_name_from_string_auto_one("192.168.0.1#test.com", "test.com"); ++ test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19", NULL); ++ test_in_addr_ifindex_name_from_string_auto_one("fe80::18%19#another.test.com", "another.test.com"); ++} ++ ++int main(int argc, char **argv) { ++ test_setup_logging(LOG_DEBUG); ++ ++ test_in_addr_ifindex_name_from_string_auto(); ++ return 0; ++} +-- +2.26.2 + diff --git a/0076-backport-CVE-2018-21029-resolve-error-handling-improvements.patch b/0076-backport-CVE-2018-21029-resolve-error-handling-improvements.patch new file mode 100644 index 0000000000000000000000000000000000000000..c04f6d60256bd1f4b1e6d305deb052843eaf1425 --- /dev/null +++ b/0076-backport-CVE-2018-21029-resolve-error-handling-improvements.patch @@ -0,0 +1,80 @@ +From df70539f9fe01a16d0f561ad9c6f5d7a955039c0 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 10 Feb 2020 14:50:03 +0900 +Subject: [PATCH] resolve: error handling improvements + +--- + src/resolve/resolved-dnstls-openssl.c | 27 ++++++++++++++++++--------- + 1 file changed, 18 insertions(+), 9 deletions(-) + +diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c +index ce0a437371..8f58efacbd 100644 +--- a/src/resolve/resolved-dnstls-openssl.c ++++ b/src/resolve/resolved-dnstls-openssl.c +@@ -73,7 +73,9 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + return -ENOMEM; + + SSL_set_connect_state(s); +- SSL_set_session(s, server->dnstls_data.session); ++ r = SSL_set_session(s, server->dnstls_data.session); ++ if (r == 0) ++ return -EIO; + SSL_set_bio(s, TAKE_PTR(rb), TAKE_PTR(wb)); + + if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { +@@ -83,7 +85,7 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + SSL_set_verify(s, SSL_VERIFY_PEER, NULL); + v = SSL_get0_param(s); + ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; +- if (!X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family))) ++ if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) + return -ECONNREFUSED; + } + +@@ -106,8 +108,8 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + char errbuf[256]; + + ERR_error_string_n(error, errbuf, sizeof(errbuf)); +- log_debug("Failed to invoke SSL_do_handshake: %s", errbuf); +- return -ECONNREFUSED; ++ return log_debug_errno(SYNTHETIC_ERRNO(ECONNREFUSED), ++ "Failed to invoke SSL_do_handshake: %s", errbuf); + } + } + +@@ -368,20 +370,27 @@ void dnstls_server_free(DnsServer *server) { + + int dnstls_manager_init(Manager *manager) { + int r; ++ + assert(manager); + + ERR_load_crypto_strings(); + SSL_load_error_strings(); +- manager->dnstls_data.ctx = SSL_CTX_new(TLS_client_method()); + ++ manager->dnstls_data.ctx = SSL_CTX_new(TLS_client_method()); + if (!manager->dnstls_data.ctx) + return -ENOMEM; + +- SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION); +- SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION); ++ r = SSL_CTX_set_min_proto_version(manager->dnstls_data.ctx, TLS1_2_VERSION); ++ if (r == 0) ++ return -EIO; ++ ++ (void) SSL_CTX_set_options(manager->dnstls_data.ctx, SSL_OP_NO_COMPRESSION); ++ + r = SSL_CTX_set_default_verify_paths(manager->dnstls_data.ctx); +- if (r < 0) +- log_warning("Failed to load system trust store: %s", ERR_error_string(ERR_get_error(), NULL)); ++ if (r == 0) ++ return log_warning_errno(SYNTHETIC_ERRNO(EIO), ++ "Failed to load system trust store: %s", ++ ERR_error_string(ERR_get_error(), NULL)); + + return 0; + } +-- +2.26.2 + diff --git a/0077-backport-CVE-2018-21029-systemd-resolved-use-hostname-for-certificate-valida.patch b/0077-backport-CVE-2018-21029-systemd-resolved-use-hostname-for-certificate-valida.patch new file mode 100644 index 0000000000000000000000000000000000000000..f69880f520fc956bff06b96656d188b6358df959 --- /dev/null +++ b/0077-backport-CVE-2018-21029-systemd-resolved-use-hostname-for-certificate-valida.patch @@ -0,0 +1,124 @@ +From eec394f10bbfcc3d2fc8504ad8ff5be44231abd5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= +Date: Tue, 3 Mar 2020 23:31:25 +0000 +Subject: [PATCH] systemd-resolved: use hostname for certificate validation in + DoT + +Widely accepted certificates for IP addresses are expensive and only +affordable for larger organizations. Therefore if the user provides +the hostname in the DNS= option, we should use it instead of the IP +address. +--- + man/resolved.conf.xml | 19 +++++++++++-------- + src/resolve/resolved-dnstls-gnutls.c | 20 ++++++++++++-------- + src/resolve/resolved-dnstls-openssl.c | 15 +++++++++++---- + 3 files changed, 34 insertions(+), 20 deletions(-) + +diff --git a/man/resolved.conf.xml b/man/resolved.conf.xml +index 0f70ced5b5..37161ebcbc 100644 +--- a/man/resolved.conf.xml ++++ b/man/resolved.conf.xml +@@ -193,11 +193,17 @@ + + DNSOverTLS= + +- Takes a boolean argument or opportunistic. +- If true all connections to the server will be encrypted. Note that +- this mode requires a DNS server that supports DNS-over-TLS and has +- a valid certificate for it's IP. If the DNS server does not support +- DNS-over-TLS all DNS requests will fail. When set to opportunistic ++ Takes a boolean argument or opportunistic. If ++ true all connections to the server will be encrypted. Note that this ++ mode requires a DNS server that supports DNS-over-TLS and has a valid ++ certificate. If the hostname was specified in DNS= ++ by using the format format address#server_name it ++ is used to validate its certificate and also to enable Server Name ++ Indication (SNI) when opening a TLS connection. Otherwise ++ the certificate is checked against the server's IP. ++ If the DNS server does not support DNS-over-TLS all DNS requests will fail. ++ ++ When set to opportunistic + DNS request are attempted to send encrypted with DNS-over-TLS. + If the DNS server does not support TLS, DNS-over-TLS is disabled. + Note that this mode makes DNS-over-TLS vulnerable to "downgrade" +@@ -214,9 +220,6 @@ + resolver is not capable of authenticating the server, so it is + vulnerable to "man-in-the-middle" attacks. + +- Server Name Indication (SNI) can be used when opening a TLS connection. +- Entries in DNS= should be in format address#server_name. +- + In addition to this global DNSOverTLS setting + systemd-networkd.service8 + also maintains per-link DNSOverTLS settings. For system DNS +diff --git a/src/resolve/resolved-dnstls-gnutls.c b/src/resolve/resolved-dnstls-gnutls.c +index aad3bb4481..ef90a7d5ae 100644 +--- a/src/resolve/resolved-dnstls-gnutls.c ++++ b/src/resolve/resolved-dnstls-gnutls.c +@@ -56,15 +56,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + } + + if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { +- stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; +- if (server->family == AF_INET) { +- stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; +- stream->dnstls_data.validation.size = 4; +- } else { +- stream->dnstls_data.validation.data = server->address.in6.s6_addr; +- stream->dnstls_data.validation.size = 16; ++ if (server->server_name) ++ gnutls_session_set_verify_cert(gs, server->server_name, 0); ++ else { ++ stream->dnstls_data.validation.type = GNUTLS_DT_IP_ADDRESS; ++ if (server->family == AF_INET) { ++ stream->dnstls_data.validation.data = (unsigned char*) &server->address.in.s_addr; ++ stream->dnstls_data.validation.size = 4; ++ } else { ++ stream->dnstls_data.validation.data = server->address.in6.s6_addr; ++ stream->dnstls_data.validation.size = 16; ++ } ++ gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); + } +- gnutls_session_set_verify_cert2(gs, &stream->dnstls_data.validation, 1, 0); + } + + if (server->server_name) { +diff --git a/src/resolve/resolved-dnstls-openssl.c b/src/resolve/resolved-dnstls-openssl.c +index 8f58efacbd..7763cbcb5a 100644 +--- a/src/resolve/resolved-dnstls-openssl.c ++++ b/src/resolve/resolved-dnstls-openssl.c +@@ -6,6 +6,7 @@ + + #include + #include ++#include + + #include "io-util.h" + #include "resolved-dns-stream.h" +@@ -80,13 +81,19 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) { + + if (server->manager->dns_over_tls_mode == DNS_OVER_TLS_YES) { + X509_VERIFY_PARAM *v; +- const unsigned char *ip; + + SSL_set_verify(s, SSL_VERIFY_PEER, NULL); + v = SSL_get0_param(s); +- ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; +- if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) +- return -ECONNREFUSED; ++ if (server->server_name) { ++ X509_VERIFY_PARAM_set_hostflags(v, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); ++ if (X509_VERIFY_PARAM_set1_host(v, server->server_name, 0) == 0) ++ return -ECONNREFUSED; ++ } else { ++ const unsigned char *ip; ++ ip = server->family == AF_INET ? (const unsigned char*) &server->address.in.s_addr : server->address.in6.s6_addr; ++ if (X509_VERIFY_PARAM_set1_ip(v, ip, FAMILY_ADDRESS_SIZE(server->family)) == 0) ++ return -ECONNREFUSED; ++ } + } + + if (server->server_name) { +-- +2.26.2 + diff --git a/0078-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch b/0078-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch new file mode 100644 index 0000000000000000000000000000000000000000..fd3e27c2a22ebaa8a98cd6d0554b13cd845567e7 --- /dev/null +++ b/0078-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch @@ -0,0 +1,84 @@ +From 9807fdc1da8e037ddedfa4e2c6d2728b6e60051e Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Wed, 20 Jan 2021 19:15:55 +0100 +Subject: [PATCH] varlink: make 'userdata' pointer inheritance from varlink + server to connection optional + +@keszybz's right on +https://github.com/systemd/systemd/pull/18248#issuecomment-760798473: +swapping out the userdata pointer of a live varlink connection is iffy. + +Let's fix this by making the userdata inheritance from VarlinkServer +object to the Varlink connection object optional: we want it for most +cases, but not all, i.e. all those cases where the calls implemented as +varlink methods are stateless and can be answered synchronously. For the +other cases (i.e. where we want per-connection objects that wrap the +asynchronous operation as it goes on) let's not do such inheritance but +initialize the userdata pointer only once we have it. THis means the +original manager object must be manually retrieved from the +VarlinkServer object, which in turn needs to be requested from the +Varlink connection object. + +The userdata inheritance is now controlled by the +VARLINK_INHERIT_USERDATA flag passed at VarlinkServer construction. + +Alternative-to: #18248 + +--- + src/journal/journald-server.c | 2 +- + src/shared/varlink.c | 4 +++- + src/shared/varlink.h | 9 +++++---- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index a0c2dcd..7f3c7a9 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1968,7 +1968,7 @@ static int server_open_varlink(Server *s) { + + assert(s); + +- r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY); ++ r = varlink_server_new(&s->varlink_server, VARLINK_SERVER_ROOT_ONLY|VARLINK_SERVER_INHERIT_USERDATA); + if (r < 0) + return r; + +diff --git a/src/shared/varlink.c b/src/shared/varlink.c +index 9934316..06fb0ab 100644 +--- a/src/shared/varlink.c ++++ b/src/shared/varlink.c +@@ -2035,7 +2035,9 @@ int varlink_server_add_connection(VarlinkServer *server, int fd, Varlink **ret) + return r; + + v->fd = fd; +- v->userdata = server->userdata; ++ if (server->flags & VARLINK_SERVER_INHERIT_USERDATA) ++ v->userdata = server->userdata; ++ + if (ucred_acquired) { + v->ucred = ucred; + v->ucred_acquired = true; +diff --git a/src/shared/varlink.h b/src/shared/varlink.h +index d96fa93..1284bc8 100644 +--- a/src/shared/varlink.h ++++ b/src/shared/varlink.h +@@ -41,11 +41,12 @@ typedef enum VarlinkMethodFlags { + } VarlinkMethodFlags; + + typedef enum VarlinkServerFlags { +- VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */ +- VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ +- VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ ++ VARLINK_SERVER_ROOT_ONLY = 1 << 0, /* Only accessible by root */ ++ VARLINK_SERVER_MYSELF_ONLY = 1 << 1, /* Only accessible by our own UID */ ++ VARLINK_SERVER_ACCOUNT_UID = 1 << 2, /* Do per user accounting */ ++ VARLINK_SERVER_INHERIT_USERDATA = 1 << 3, /* Initialize Varlink connection userdata from VarlinkServer userdata */ + +- _VARLINK_SERVER_FLAGS_ALL = (1 << 3) - 1, ++ _VARLINK_SERVER_FLAGS_ALL = (1 << 4) - 1, + } VarlinkServerFlags; + + typedef int (*VarlinkMethod)(Varlink *link, JsonVariant *parameters, VarlinkMethodFlags flags, void *userdata); +-- +2.23.0 + diff --git a/0079-backport-udev-net_id-parse-_SUN-ACPI-index-as-a-signed-intege.patch b/0079-backport-udev-net_id-parse-_SUN-ACPI-index-as-a-signed-intege.patch new file mode 100644 index 0000000000000000000000000000000000000000..98ef693531b3611b162d54b0175339c02af741b9 --- /dev/null +++ b/0079-backport-udev-net_id-parse-_SUN-ACPI-index-as-a-signed-intege.patch @@ -0,0 +1,46 @@ +From 3e545ae5abcf258791eacbee60c829c100a33274 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Mon, 19 Oct 2020 10:56:11 +0200 +Subject: [PATCH] udev/net_id: parse _SUN ACPI index as a signed integer + +Negative value means there is no match between a PCI device and any of +the slots. In the following commit we will extend this and value of 0 +will indicate that there is a match between some slot and PCI device, +but that device is a PCI bridge. +--- + src/udev/udev-builtin-net_id.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c +index b82fd88..99d44a2 100644 +--- a/src/udev/udev-builtin-net_id.c ++++ b/src/udev/udev-builtin-net_id.c +@@ -246,7 +246,8 @@ static bool is_pci_ari_enabled(sd_device *dev) { + + static int dev_pci_slot(sd_device *dev, struct netnames *names) { + unsigned long dev_port = 0; +- unsigned domain, bus, slot, func, hotplug_slot = 0; ++ unsigned domain, bus, slot, func; ++ int hotplug_slot = -1; + size_t l; + char *s; + const char *sysname, *attr, *port_name = NULL, *syspath; +@@ -327,13 +328,13 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) { + continue; + + FOREACH_DIRENT_ALL(dent, dir, break) { +- unsigned i; ++ int i; + char str[PATH_MAX]; + _cleanup_free_ char *address = NULL; + + if (dent->d_name[0] == '.') + continue; +- r = safe_atou_full(dent->d_name, 10, &i); ++ r = safe_atoi(dent->d_name, &i); + if (r < 0 || i <= 0) + continue; + +-- +2.23.0 + diff --git a/0080-backport-udev-net_id-don-t-generate-slot-based-names-if-multi.patch b/0080-backport-udev-net_id-don-t-generate-slot-based-names-if-multi.patch new file mode 100644 index 0000000000000000000000000000000000000000..81d22f5c9288d98c461ddac1a7cd979753d16558 --- /dev/null +++ b/0080-backport-udev-net_id-don-t-generate-slot-based-names-if-multi.patch @@ -0,0 +1,130 @@ +From 2c8ec0095e6fd2e72879d4915ff8a9e5c0664d0b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Mon, 19 Oct 2020 11:10:31 +0200 +Subject: [PATCH] udev/net_id: don't generate slot based names if multiple + devices might claim the same slot + +--- + man/systemd.net-naming-scheme.xml | 14 ++++++++++++++ + src/udev/net/naming-scheme.c | 1 + + src/udev/net/naming-scheme.h | 2 ++ + src/udev/udev-builtin-net_id.c | 29 ++++++++++++++++++++++++++++- + 4 files changed, 45 insertions(+), 1 deletion(-) + +diff --git a/man/systemd.net-naming-scheme.xml b/man/systemd.net-naming-scheme.xml +index 91ad57d..40d7e58 100644 +--- a/man/systemd.net-naming-scheme.xml ++++ b/man/systemd.net-naming-scheme.xml +@@ -182,6 +182,9 @@ + SR-IOV virtual devices are named based on the name of the parent interface, with a suffix of + v and the virtual device number, with any leading zeros removed. The bus + number is ignored. This device type is found in IBM PowerVMs. ++ ++ In some configurations a parent PCI bridge of a given network controller may be associated ++ with a slot. In such case we don't generate this device property to avoid possible naming conflicts. + + + +@@ -329,6 +332,17 @@ + Previously two-letter interface type prefix was prepended to + ID_NET_LABEL_ONBOARD=. This is not done anymore. + ++ ++ ++ v246 ++ ++ If the PCI slot is assocated with PCI bridge and that has multiple child network ++ controllers then all of them might derive the same value of ID_NET_NAME_SLOT ++ property. That could cause naming conflict if the property is selected as a device name. Now, we detect the ++ situation, slot - bridge relation, and we don't produce the ID_NET_NAME_SLOT property to ++ avoid possible naming conflict. ++ ++ + + + Note that latest may be used to denote the latest scheme known (to this +diff --git a/src/udev/net/naming-scheme.c b/src/udev/net/naming-scheme.c +index 0d7f413..ebab2ff 100644 +--- a/src/udev/net/naming-scheme.c ++++ b/src/udev/net/naming-scheme.c +@@ -10,6 +10,7 @@ static const NamingScheme naming_schemes[] = { + { "v240", NAMING_V240 }, + { "v241", NAMING_V241 }, + { "v243", NAMING_V243 }, ++ { "v246", NAMING_V246 }, + /* … add more schemes here, as the logic to name devices is updated … */ + }; + +diff --git a/src/udev/net/naming-scheme.h b/src/udev/net/naming-scheme.h +index 38dfa75..d744f3e 100644 +--- a/src/udev/net/naming-scheme.h ++++ b/src/udev/net/naming-scheme.h +@@ -30,6 +30,7 @@ typedef enum NamingSchemeFlags { + NAMING_STABLE_VIRTUAL_MACS = 1 << 5, /* Use device name to generate MAC, see 6d3646406560 */ + NAMING_NETDEVSIM = 1 << 6, /* Generate names for netdevsim devices, see eaa9d507d855 */ + NAMING_LABEL_NOPREFIX = 1 << 7, /* Don't prepend ID_NET_LABEL_ONBOARD with interface type prefix */ ++ NAMING_BRIDGE_NO_SLOT = 1 << 9, /* Don't use PCI hotplug slot information if the corresponding device is a PCI bridge */ + + /* And now the masks that combine the features above */ + NAMING_V238 = 0, +@@ -37,6 +38,7 @@ typedef enum NamingSchemeFlags { + NAMING_V240 = NAMING_V239 | NAMING_INFINIBAND | NAMING_ZERO_ACPI_INDEX | NAMING_ALLOW_RERENAMES, + NAMING_V241 = NAMING_V240 | NAMING_STABLE_VIRTUAL_MACS, + NAMING_V243 = NAMING_V241 | NAMING_NETDEVSIM | NAMING_LABEL_NOPREFIX, ++ NAMING_V246 = NAMING_V243 | NAMING_BRIDGE_NO_SLOT, + + _NAMING_SCHEME_FLAGS_INVALID = -1, + } NamingSchemeFlags; +diff --git a/src/udev/udev-builtin-net_id.c b/src/udev/udev-builtin-net_id.c +index 99d44a2..af0d2a7 100644 +--- a/src/udev/udev-builtin-net_id.c ++++ b/src/udev/udev-builtin-net_id.c +@@ -244,6 +244,25 @@ static bool is_pci_ari_enabled(sd_device *dev) { + return streq(a, "1"); + } + ++static bool is_pci_bridge(sd_device *dev) { ++ const char *v, *p; ++ ++ if (sd_device_get_sysattr_value(dev, "modalias", &v) < 0) ++ return false; ++ ++ if (!startswith(v, "pci:")) ++ return false; ++ ++ p = strrchr(v, 's'); ++ if (!p) ++ return false; ++ if (p[1] != 'c') ++ return false; ++ ++ /* PCI device subclass 04 corresponds to PCI bridge */ ++ return strneq(p + 2, "04", 2); ++} ++ + static int dev_pci_slot(sd_device *dev, struct netnames *names) { + unsigned long dev_port = 0; + unsigned domain, bus, slot, func; +@@ -343,10 +362,18 @@ static int dev_pci_slot(sd_device *dev, struct netnames *names) { + read_one_line_file(str, &address) >= 0 && + startswith(sysname, address)) { + hotplug_slot = i; ++ ++ /* We found the match between PCI device and slot. However, we won't use the ++ * slot index if the device is a PCI bridge, because it can have other child ++ * devices that will try to claim the same index and that would create name ++ * collision. */ ++ if (naming_scheme_has(NAMING_BRIDGE_NO_SLOT) && is_pci_bridge(hotplug_slot_dev)) ++ hotplug_slot = 0; ++ + break; + } + } +- if (hotplug_slot > 0) ++ if (hotplug_slot >= 0) + break; + if (sd_device_get_parent_with_subsystem_devtype(hotplug_slot_dev, "pci", NULL, &hotplug_slot_dev) < 0) + break; +-- +2.23.0 + diff --git a/0081-journal-refresh-cached-credentials-of-stdout-streams.patch b/0081-journal-refresh-cached-credentials-of-stdout-streams.patch new file mode 100644 index 0000000000000000000000000000000000000000..195dda4f1540bd9f7d1fbac24f32adc587bf56ac --- /dev/null +++ b/0081-journal-refresh-cached-credentials-of-stdout-streams.patch @@ -0,0 +1,148 @@ +From 09d0b46ab61bebafe5bdc1be95ee153dfb13d6bc Mon Sep 17 00:00:00 2001 +From: Lorenz Bauer +Date: Mon, 4 Nov 2019 16:35:46 +0000 +Subject: [PATCH] journal: refresh cached credentials of stdout streams + +journald assumes that getsockopt(SO_PEERCRED) correctly identifies the +process on the remote end of the socket. However, this is incorrect +according to man 7 socket: + +The returned credentials are those that were in effect at the + time of the call to connect(2) or socketpair(2). + +This becomes a problem when a new process inherits the stdout stream +from a parent. First, log messages from the child process will +be attributed to the parent. Second, the struct ucred used by journald +becomes invalid as soon as the parent exits. Further sendmsg calls then +fail with ENOENT. Logs for the child process then vanish from the journal. + +Fix this by using recvmsg on the stdout stream, and refreshing the cached +struct ucred if SCM_CREDENTIALS indicate a new process. + +Fixes #13708 +--- + src/journal/journald-stream.c | 49 ++++++++++++++++++++++++++++++++++-- + test/TEST-04-JOURNAL/test-journal.sh | 16 ++++++++++++ + 2 files changed, 63 insertions(+), 2 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index afebade..22a70ce 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -487,11 +487,22 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { + } + + static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { ++ uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + StdoutStream *s = userdata; ++ struct ucred *ucred = NULL; ++ struct cmsghdr *cmsg; ++ struct iovec iovec; + size_t limit; + ssize_t l; + int r; + ++ struct msghdr msghdr = { ++ .msg_iov = &iovec, ++ .msg_iovlen = 1, ++ .msg_control = buf, ++ .msg_controllen = sizeof(buf), ++ }; ++ + assert(s); + + if ((revents|EPOLLIN|EPOLLHUP) != (EPOLLIN|EPOLLHUP)) { +@@ -511,20 +522,50 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + * always leave room for a terminating NUL we might need to add. */ + limit = MIN(s->allocated - 1, s->server->line_max); + +- l = read(s->fd, s->buffer + s->length, limit - s->length); ++ iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); ++ ++ l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); + if (l < 0) { +- if (errno == EAGAIN) ++ if (IN_SET(errno, EINTR, EAGAIN)) + return 0; + + log_warning_errno(errno, "Failed to read from stream: %m"); + goto terminate; + } ++ cmsg_close_all(&msghdr); + + if (l == 0) { + stdout_stream_scan(s, true); + goto terminate; + } + ++ CMSG_FOREACH(cmsg, &msghdr) ++ if (cmsg->cmsg_level == SOL_SOCKET && ++ cmsg->cmsg_type == SCM_CREDENTIALS && ++ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) { ++ ucred = (struct ucred *)CMSG_DATA(cmsg); ++ break; ++ } ++ ++ /* Invalidate the context if the pid of the sender changed. ++ * This happens when a forked process inherits stdout / stderr ++ * from a parent. In this case getpeercred returns the ucred ++ * of the parent, which can be invalid if the parent has exited ++ * in the meantime. ++ */ ++ if (ucred && ucred->pid != s->ucred.pid) { ++ /* force out any previously half-written lines from a ++ * different process, before we switch to the new ucred ++ * structure for everything we just added */ ++ r = stdout_stream_scan(s, true); ++ if (r < 0) ++ goto terminate; ++ ++ s->ucred = *ucred; ++ client_context_release(s->server, s->context); ++ s->context = NULL; ++ } ++ + s->length += l; + r = stdout_stream_scan(s, false); + if (r < 0) +@@ -562,6 +603,10 @@ int stdout_stream_install(Server *s, int fd, StdoutStream **ret) { + if (r < 0) + return log_error_errno(r, "Failed to determine peer credentials: %m"); + ++ r = setsockopt_int(fd, SOL_SOCKET, SO_PASSCRED, true); ++ if (r < 0) ++ return log_error_errno(r, "SO_PASSCRED failed: %m"); ++ + if (mac_selinux_use()) { + r = getpeersec(fd, &stream->label); + if (r < 0 && r != -EOPNOTSUPP) +diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh +index 4e539aa..de27eb0 100755 +--- a/test/TEST-04-JOURNAL/test-journal.sh ++++ b/test/TEST-04-JOURNAL/test-journal.sh +@@ -74,6 +74,22 @@ cmp /expected /output + { journalctl -ball -b -m 2>&1 || :; } | head -1 > /output + cmp /expected /output + ++# https://github.com/systemd/systemd/issues/13708 ++ID=$(systemd-id128 new) ++systemd-cat -t "$ID" bash -c 'echo parent; (echo child) & wait' & ++PID=$! ++wait %% ++journalctl --sync ++# We can drop this grep when https://github.com/systemd/systemd/issues/13937 ++# has a fix. ++journalctl -b -o export -t "$ID" --output-fields=_PID | grep '^_PID=' >/output ++[[ `grep -c . /output` -eq 2 ]] ++grep -q "^_PID=$PID" /output ++grep -vq "^_PID=$PID" /output ++ ++# Add new tests before here, the journald restarts below ++# may make tests flappy. ++ + # Don't lose streams on restart + systemctl start forever-print-hola + sleep 3 +-- +1.8.3.1 + diff --git a/0082-journald-rework-end-of-line-marker-handling-to-use-a.patch b/0082-journald-rework-end-of-line-marker-handling-to-use-a.patch new file mode 100644 index 0000000000000000000000000000000000000000..c365959cee0d5d3ce3cf46991f0b0778a927e7e5 --- /dev/null +++ b/0082-journald-rework-end-of-line-marker-handling-to-use-a.patch @@ -0,0 +1,77 @@ +From 549b7379ba404c33fd448d2bca46a57f6529b00b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 12 May 2020 18:53:35 +0200 +Subject: [PATCH] journald: rework end of line marker handling to use a field + table + +--- + src/journal/journald-stream.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index 22a70ce..b86ed78 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -57,6 +57,8 @@ typedef enum LineBreak { + LINE_BREAK_NUL, + LINE_BREAK_LINE_MAX, + LINE_BREAK_EOF, ++ _LINE_BREAK_MAX, ++ _LINE_BREAK_INVALID = -1, + } LineBreak; + + struct StdoutStream { +@@ -236,7 +238,11 @@ fail: + return log_error_errno(r, "Failed to save stream data %s: %m", s->state_file); + } + +-static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_break) { ++static int stdout_stream_log( ++ StdoutStream *s, ++ const char *p, ++ LineBreak line_break) { ++ + struct iovec *iovec; + int priority; + char syslog_priority[] = "PRIORITY=\0"; +@@ -248,6 +254,9 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea + assert(s); + assert(p); + ++ assert(line_break >= 0); ++ assert(line_break < _LINE_BREAK_MAX); ++ + if (s->context) + (void) client_context_maybe_refresh(s->server, s->context, NULL, NULL, 0, NULL, USEC_INFINITY); + else if (pid_is_valid(s->ucred.pid)) { +@@ -299,17 +308,19 @@ static int stdout_stream_log(StdoutStream *s, const char *p, LineBreak line_brea + iovec[n++] = IOVEC_MAKE_STRING(syslog_identifier); + } + +- if (line_break != LINE_BREAK_NEWLINE) { +- const char *c; ++ static const char * const line_break_field_table[_LINE_BREAK_MAX] = { ++ [LINE_BREAK_NEWLINE] = NULL, /* Do not add field if traditional newline */ ++ [LINE_BREAK_NUL] = "_LINE_BREAK=nul", ++ [LINE_BREAK_LINE_MAX] = "_LINE_BREAK=line-max", ++ [LINE_BREAK_EOF] = "_LINE_BREAK=eof", ++ }; + +- /* If this log message was generated due to an uncommon line break then mention this in the log +- * entry */ ++ const char *c = line_break_field_table[line_break]; + +- c = line_break == LINE_BREAK_NUL ? "_LINE_BREAK=nul" : +- line_break == LINE_BREAK_LINE_MAX ? "_LINE_BREAK=line-max" : +- "_LINE_BREAK=eof"; ++ /* If this log message was generated due to an uncommon line break then mention this in the log ++ * entry */ ++ if (c) + iovec[n++] = IOVEC_MAKE_STRING(c); +- } + + message = strjoin("MESSAGE=", p); + if (message) +-- +1.8.3.1 + diff --git a/0083-journald-rework-pid-change-handling.patch b/0083-journald-rework-pid-change-handling.patch new file mode 100644 index 0000000000000000000000000000000000000000..b8edce42a7c41cad06b805e7873551596225f98c --- /dev/null +++ b/0083-journald-rework-pid-change-handling.patch @@ -0,0 +1,230 @@ +From 45ba1ea5e9264d385fa565328fe957ef1d78caa1 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 12 May 2020 18:56:34 +0200 +Subject: [PATCH] journald: rework pid change handling + +Let's introduce an explicit line ending marker for line endings due to +pid change. + +Let's also make sure we don't get confused with buffer management. + +Fixes: #15654 +--- + src/journal/journald-stream.c | 108 +++++++++++++++++++++++++++--------------- + 1 file changed, 69 insertions(+), 39 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index b86ed78..3219b14 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -57,6 +57,7 @@ typedef enum LineBreak { + LINE_BREAK_NUL, + LINE_BREAK_LINE_MAX, + LINE_BREAK_EOF, ++ LINE_BREAK_PID_CHANGE, + _LINE_BREAK_MAX, + _LINE_BREAK_INVALID = -1, + } LineBreak; +@@ -313,6 +314,7 @@ static int stdout_stream_log( + [LINE_BREAK_NUL] = "_LINE_BREAK=nul", + [LINE_BREAK_LINE_MAX] = "_LINE_BREAK=line-max", + [LINE_BREAK_EOF] = "_LINE_BREAK=eof", ++ [LINE_BREAK_PID_CHANGE] = "_LINE_BREAK=pid-change", + }; + + const char *c = line_break_field_table[line_break]; +@@ -434,21 +436,43 @@ static int stdout_stream_line(StdoutStream *s, char *p, LineBreak line_break) { + assert_not_reached("Unknown stream state"); + } + +-static int stdout_stream_scan(StdoutStream *s, bool force_flush) { +- char *p; +- size_t remaining; ++static int stdout_stream_found( ++ StdoutStream *s, ++ char *p, ++ size_t l, ++ LineBreak line_break) { ++ ++ char saved; + int r; + + assert(s); ++ assert(p); ++ ++ /* Let's NUL terminate the specified buffer for this call, and revert back afterwards */ ++ saved = p[l]; ++ p[l] = 0; ++ r = stdout_stream_line(s, p, line_break); ++ p[l] = saved; + +- p = s->buffer; +- remaining = s->length; ++ return r; ++} ++ ++static int stdout_stream_scan( ++ StdoutStream *s, ++ char *p, ++ size_t remaining, ++ LineBreak force_flush, ++ size_t *ret_consumed) { + +- /* XXX: This function does nothing if (s->length == 0) */ ++ size_t consumed = 0; ++ int r; ++ ++ assert(s); ++ assert(p); + + for (;;) { + LineBreak line_break; +- size_t skip; ++ size_t skip, found; + char *end1, *end2; + + end1 = memchr(p, '\n', remaining); +@@ -456,43 +480,40 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { + + if (end2) { + /* We found a NUL terminator */ +- skip = end2 - p + 1; ++ found = end2 - p; ++ skip = found + 1; + line_break = LINE_BREAK_NUL; + } else if (end1) { + /* We found a \n terminator */ +- *end1 = 0; +- skip = end1 - p + 1; ++ found = end1 - p; ++ skip = found + 1; + line_break = LINE_BREAK_NEWLINE; + } else if (remaining >= s->server->line_max) { + /* Force a line break after the maximum line length */ +- *(p + s->server->line_max) = 0; +- skip = remaining; ++ found = skip = s->server->line_max; + line_break = LINE_BREAK_LINE_MAX; + } else + break; + +- r = stdout_stream_line(s, p, line_break); ++ r = stdout_stream_found(s, p, found, line_break); + if (r < 0) + return r; + +- remaining -= skip; + p += skip; ++ consumed += skip; ++ remaining -= skip; + } + +- if (force_flush && remaining > 0) { +- p[remaining] = 0; +- r = stdout_stream_line(s, p, LINE_BREAK_EOF); ++ if (force_flush >= 0 && remaining > 0) { ++ r = stdout_stream_found(s, p, remaining, force_flush); + if (r < 0) + return r; + +- p += remaining; +- remaining = 0; ++ consumed += remaining; + } + +- if (p > s->buffer) { +- memmove(s->buffer, p, remaining); +- s->length = remaining; +- } ++ if (ret_consumed) ++ *ret_consumed = consumed; + + return 0; + } +@@ -500,11 +521,12 @@ static int stdout_stream_scan(StdoutStream *s, bool force_flush) { + static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, void *userdata) { + uint8_t buf[CMSG_SPACE(sizeof(struct ucred))]; + StdoutStream *s = userdata; ++ size_t limit, consumed; + struct ucred *ucred = NULL; + struct cmsghdr *cmsg; + struct iovec iovec; +- size_t limit; + ssize_t l; ++ char *p; + int r; + + struct msghdr msghdr = { +@@ -532,7 +554,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, + * always leave room for a terminating NUL we might need to add. */ + limit = MIN(s->allocated - 1, s->server->line_max); +- ++ assert(s->length <= limit); + iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); + + l = recvmsg(s->fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC); +@@ -546,7 +568,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + cmsg_close_all(&msghdr); + + if (l == 0) { +- stdout_stream_scan(s, true); ++ (void) stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_EOF, NULL); + goto terminate; + } + +@@ -558,30 +580,38 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + break; + } + +- /* Invalidate the context if the pid of the sender changed. +- * This happens when a forked process inherits stdout / stderr +- * from a parent. In this case getpeercred returns the ucred +- * of the parent, which can be invalid if the parent has exited +- * in the meantime. +- */ ++ /* Invalidate the context if the PID of the sender changed. This happens when a forked process ++ * inherits stdout/stderr from a parent. In this case getpeercred() returns the ucred of the parent, ++ * which can be invalid if the parent has exited in the meantime. */ + if (ucred && ucred->pid != s->ucred.pid) { +- /* force out any previously half-written lines from a ++ /* Force out any previously half-written lines from a + * different process, before we switch to the new ucred + * structure for everything we just added */ +- r = stdout_stream_scan(s, true); ++ r = stdout_stream_scan(s, s->buffer, s->length, /* force_flush = */ LINE_BREAK_PID_CHANGE, NULL); + if (r < 0) + goto terminate; + +- s->ucred = *ucred; +- client_context_release(s->server, s->context); +- s->context = NULL; ++ s->context = client_context_release(s->server, s->context); ++ ++ p = s->buffer + s->length; ++ } else { ++ p = s->buffer; ++ l += s->length; + } + +- s->length += l; +- r = stdout_stream_scan(s, false); ++ /* Always copy in the new credentials */ ++ if (ucred) ++ s->ucred = *ucred; ++ ++ r = stdout_stream_scan(s, p, l, _LINE_BREAK_INVALID, &consumed); + if (r < 0) + goto terminate; + ++ /* Move what wasn't consumed to the front of the buffer */ ++ assert(consumed <= (size_t) l); ++ s->length = l - consumed; ++ memmove(s->buffer, p + consumed, s->length); ++ + return 1; + + terminate: +-- +1.8.3.1 + diff --git a/0084-journald-enforce-longer-line-length-limit-during-set.patch b/0084-journald-enforce-longer-line-length-limit-during-set.patch new file mode 100644 index 0000000000000000000000000000000000000000..71aeae5198114534cfffe6642ff316eb6846ea07 --- /dev/null +++ b/0084-journald-enforce-longer-line-length-limit-during-set.patch @@ -0,0 +1,104 @@ +From 4e071b5240a29842bc8acd0d7eb0b797f2812b8b Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Fri, 21 May 2021 17:55:38 +0800 +Subject: [PATCH] change + +--- + src/journal/journald-stream.c | 35 ++++++++++++++++++++++++++++------- + 1 file changed, 28 insertions(+), 7 deletions(-) + +diff --git a/src/journal/journald-stream.c b/src/journal/journald-stream.c +index 3219b14..fda75fb 100644 +--- a/src/journal/journald-stream.c ++++ b/src/journal/journald-stream.c +@@ -38,6 +38,12 @@ + + #define STDOUT_STREAMS_MAX 4096 + ++/* During the "setup" protocol phase of the stream logic let's define a different maximum line length than ++ * during the actual operational phase. We want to allow users to specify very short line lengths after all, ++ * but the unit name we embed in the setup protocol might be longer than that. Hence, during the setup phase ++ * let's enforce a line length matching the maximum unit name length (255) */ ++#define STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX (UNIT_NAME_MAX-1U) ++ + typedef enum StdoutStreamState { + STDOUT_STREAM_IDENTIFIER, + STDOUT_STREAM_UNIT_ID, +@@ -46,7 +52,7 @@ typedef enum StdoutStreamState { + STDOUT_STREAM_FORWARD_TO_SYSLOG, + STDOUT_STREAM_FORWARD_TO_KMSG, + STDOUT_STREAM_FORWARD_TO_CONSOLE, +- STDOUT_STREAM_RUNNING ++ STDOUT_STREAM_RUNNING, + } StdoutStreamState; + + /* The different types of log record terminators: a real \n was read, a NUL character was read, the maximum line length +@@ -457,6 +463,18 @@ static int stdout_stream_found( + return r; + } + ++static size_t stdout_stream_line_max(StdoutStream *s) { ++ assert(s); ++ ++ /* During the "setup" phase of our protocol, let's ensure we use a line length where a full unit name ++ * can fit in */ ++ if (s->state != STDOUT_STREAM_RUNNING) ++ return STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX; ++ ++ /* After the protocol's "setup" phase is complete, let's use whatever the user configured */ ++ return s->server->line_max; ++} ++ + static int stdout_stream_scan( + StdoutStream *s, + char *p, +@@ -464,19 +482,22 @@ static int stdout_stream_scan( + LineBreak force_flush, + size_t *ret_consumed) { + +- size_t consumed = 0; ++ size_t consumed = 0, line_max; + int r; + + assert(s); + assert(p); + ++ line_max = stdout_stream_line_max(s); ++ + for (;;) { + LineBreak line_break; + size_t skip, found; + char *end1, *end2; ++ size_t tmp_remaining = MIN(remaining, line_max); + +- end1 = memchr(p, '\n', remaining); +- end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : remaining); ++ end1 = memchr(p, '\n', tmp_remaining); ++ end2 = memchr(p, 0, end1 ? (size_t) (end1 - p) : tmp_remaining); + + if (end2) { + /* We found a NUL terminator */ +@@ -488,9 +509,9 @@ static int stdout_stream_scan( + found = end1 - p; + skip = found + 1; + line_break = LINE_BREAK_NEWLINE; +- } else if (remaining >= s->server->line_max) { ++ } else if (remaining >= line_max) { + /* Force a line break after the maximum line length */ +- found = skip = s->server->line_max; ++ found = skip = line_max; + line_break = LINE_BREAK_LINE_MAX; + } else + break; +@@ -553,7 +574,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents, + + /* Try to make use of the allocated buffer in full, but never read more than the configured line size. Also, + * always leave room for a terminating NUL we might need to add. */ +- limit = MIN(s->allocated - 1, s->server->line_max); ++ limit = MIN(s->allocated - 1, MAX(s->server->line_max, STDOUT_STREAM_SETUP_PROTOCOL_LINE_MAX)); + assert(s->length <= limit); + iovec = IOVEC_MAKE(s->buffer + s->length, limit - s->length); + +-- +1.8.3.1 + diff --git a/0086-fix-CVE-2021-33910.patch b/0086-fix-CVE-2021-33910.patch new file mode 100644 index 0000000000000000000000000000000000000000..d4b7ed32d7be5c74699f5320f4ef4ad0973166ca --- /dev/null +++ b/0086-fix-CVE-2021-33910.patch @@ -0,0 +1,72 @@ +From 441e0115646d54f080e5c3bb0ba477c892861ab9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 23 Jun 2021 11:46:41 +0200 +Subject: [PATCH] basic/unit-name: do not use strdupa() on a path + +The path may have unbounded length, for example through a fuse mount. + +CVE-2021-33910: attacked controlled alloca() leads to crash in systemd +and +ultimately a kernel panic. Systemd parses the content of +/proc/self/mountinfo +and each mountpoint is passed to mount_setup_unit(), which calls +unit_name_path_escape() underneath. A local attacker who is able to +mount a +filesystem with a very long path can crash systemd and the whole system. + +https://bugzilla.redhat.com/show_bug.cgi?id=1970887 + +The resulting string length is bounded by UNIT_NAME_MAX, which is 256. +But we +can't easily check the length after simplification before doing the +simplification, which in turns uses a copy of the string we can write +to. +So we can't reject paths that are too long before doing the duplication. +Hence the most obvious solution is to switch back to strdup(), as before +7410616cd9dbbec97cf98d75324da5cda2b2f7a2. + +https://github.com/systemd/systemd/pull/20256/commits/441e0115646d54f080e5c3bb0ba477c892861ab9 + +--- + src/basic/unit-name.c | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/src/basic/unit-name.c b/src/basic/unit-name.c +index 4226f30..1b01af6 100644 +--- a/src/basic/unit-name.c ++++ b/src/basic/unit-name.c +@@ -370,12 +370,13 @@ int unit_name_unescape(const char *f, char **ret) { + } + + int unit_name_path_escape(const char *f, char **ret) { +- char *p, *s; ++ _cleanup_free_ char *p = NULL; ++ char *s; + + assert(f); + assert(ret); + +- p = strdupa(f); ++ p = strdup(f); + if (!p) + return -ENOMEM; + +@@ -387,13 +388,9 @@ int unit_name_path_escape(const char *f, char **ret) { + if (!path_is_normalized(p)) + return -EINVAL; + +- /* Truncate trailing slashes */ ++ /* Truncate trailing slashes and skip leading slashes */ + delete_trailing_chars(p, "/"); +- +- /* Truncate leading slashes */ +- p = skip_leading_chars(p, "/"); +- +- s = unit_name_escape(p); ++ s = unit_name_escape(skip_leading_chars(p, "/")); + } + if (!s) + return -ENOMEM; +-- +2.23.0 + diff --git a/0017-resolved-create-etc-resolv.conf-symlink-at-runtime.patch b/0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch similarity index 65% rename from 0017-resolved-create-etc-resolv.conf-symlink-at-runtime.patch rename to 0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch index 21ba7904cc4904cd665b22a552339607e2037f5e..aa238ee5db18d3147497938883c8637f80cf2a39 100644 --- a/0017-resolved-create-etc-resolv.conf-symlink-at-runtime.patch +++ b/0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch @@ -10,43 +10,39 @@ If it exists, do nothing. In particular, if it is a broken symlink, we cannot really know if the administator configured it to point to a location used by some service that hasn't started yet, so we don't touch it in that case either. - + https://bugzilla.redhat.com/show_bug.cgi?id=1313085 --- - src/resolve/resolved.c | 5 +++++ - tmpfiles.d/etc.conf.in | 3 --- - 2 files changed, 5 insertions(+), 3 deletions(-) + src/resolve/resolved.c | 4 ++++ + tmpfiles.d/etc.conf.m4 | 3 --- + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/resolve/resolved.c b/src/resolve/resolved.c -index 50989a6b0a..95a51a574a 100644 +index 2ca9fbdc72..3c8a9ff12a 100644 --- a/src/resolve/resolved.c +++ b/src/resolve/resolved.c -@@ -58,6 +58,11 @@ static int run(int argc, char *argv[]) { - if (r < 0) - return log_error_errno(r, "Could not create runtime directory: %m"); - +@@ -49,6 +49,10 @@ static int run(int argc, char *argv[]) { + /* Drop privileges, but only if we have been started as root. If we are not running as root we assume most + * privileges are already dropped. */ + if (getuid() == 0) { + r = symlink("../run/systemd/resolve/resolv.conf", "/etc/resolv.conf"); + if (r < 0 && errno != EEXIST) + log_warning_errno(errno, + "Could not create /etc/resolv.conf symlink: %m"); -+ - /* Drop privileges, but keep three caps. Note that we drop two of those too, later on (see below) */ + + /* Drop privileges, but keep three caps. Note that we drop those too, later on (see below) */ r = drop_privileges(uid, gid, - (UINT64_C(1) << CAP_NET_RAW)| /* needed for SO_BINDTODEVICE */ -diff --git a/tmpfiles.d/etc.conf.in b/tmpfiles.d/etc.conf.in +diff --git a/tmpfiles.d/etc.conf.m4 b/tmpfiles.d/etc.conf.m4 index f82e0b82ce..66a777bdb2 100644 ---- a/tmpfiles.d/etc.conf.in -+++ b/tmpfiles.d/etc.conf.in +--- a/tmpfiles.d/etc.conf.m4 ++++ b/tmpfiles.d/etc.conf.m4 @@ -12,9 +12,6 @@ L+ /etc/mtab - - - - ../proc/self/mounts - {% if HAVE_SMACK_RUN_LABEL %} + m4_ifdef(`HAVE_SMACK_RUN_LABEL', t /etc/mtab - - - - security.SMACK64=_ - {% endif %} --{% if ENABLE_RESOLVE %} + )m4_dnl +-m4_ifdef(`ENABLE_RESOLVE', -L! /etc/resolv.conf - - - - ../run/systemd/resolve/stub-resolv.conf --{% endif %} +-)m4_dnl C! /etc/nsswitch.conf - - - - - {% if HAVE_PAM %} + m4_ifdef(`HAVE_PAM', C! /etc/pam.d - - - - --- -2.23.0 - diff --git a/1509-fix-journal-file-descriptors-leak-problems.patch b/1509-fix-journal-file-descriptors-leak-problems.patch new file mode 100644 index 0000000000000000000000000000000000000000..8ea3a5cf2cc60ad3555190572099e3de55eea1ba --- /dev/null +++ b/1509-fix-journal-file-descriptors-leak-problems.patch @@ -0,0 +1,54 @@ +From 4f8cec1924bf00532f5350d9a4d7af8e853241fe Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Thu, 28 Jun 2018 20:23:45 +0800 +Subject: [PATCH] systemd-journald: Fix journal file descriptors leak problems. + +Journal files opened and then be removed by external programs(for example, the journal rotation +of systemd-journald will removed jounal files) before journal directory notify watching is added +will not be closed properly. This patch fix this problem by removing and closing these deleted journal files +after notify watching is added. +--- + src/journal/sd-journal.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/src/journal/sd-journal.c b/src/journal/sd-journal.c +index 004fe64..8be5481 100644 +--- a/src/journal/sd-journal.c ++++ b/src/journal/sd-journal.c +@@ -1436,6 +1436,18 @@ fail: + log_debug_errno(errno, "Failed to enumerate directory %s, ignoring: %m", m->path); + } + ++static void remove_nonexistent_journal_files(sd_journal *j) { ++ Iterator i; ++ JournalFile *f = NULL; ++ ORDERED_HASHMAP_FOREACH(f, j->files, i) { ++ if(f->path && access(f->path, F_OK) < 0) { ++ log_debug("Remove not-existed file from the journal map: %s", f->path); ++ /*Its OK to remove entry from the hashmap although we are iterating on it.*/ ++ remove_file_real(j, f); ++ } ++ } ++} ++ + static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) { + int r; + +@@ -1464,6 +1476,14 @@ static void directory_watch(sd_journal *j, Directory *m, int fd, uint32_t mask) + (void) inotify_rm_watch(j->inotify_fd, m->wd); + m->wd = -1; + } ++ ++ /* ++ * Before event watching, there were some files opened and if some of these opened files were ++ * deleted due to the journal rotation of systemd-jounald, they will become leaking files and will ++ * never be closed until the process exited. ++ * So here we remove these deleted files from the journal after event watching. ++ */ ++ remove_nonexistent_journal_files(j); + } + + static int add_directory(sd_journal *j, const char *prefix, const char *dirname) { +-- +1.8.3.1 + diff --git a/1602-activation-service-must-be-restarted-when-reactivated.patch b/1602-activation-service-must-be-restarted-when-reactivated.patch new file mode 100644 index 0000000000000000000000000000000000000000..a71eaa857c33af7dab199596c44a4fe2d848992f --- /dev/null +++ b/1602-activation-service-must-be-restarted-when-reactivated.patch @@ -0,0 +1,44 @@ +From 4acc8a3168e5f11b5308cf8558d68bf2a0503444 Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Mon, 7 Aug 2017 17:06:30 +0800 +Subject: [PATCH] systemd: Activation service must be restarted when it is already started and re-actived +by dbus + +When dbus-daemon service is killed, every activation service must be restarted +to reestblished dbus connection between dbus-daemon and the service. +Otherwise, there will be problem on the dbus connection. This patch fix this +problem by set JobType to JOB_RESTART when it is re-actived in signal_activation_request function. +--- + src/core/dbus.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/src/core/dbus.c b/src/core/dbus.c +index 29524d4..38940ef 100644 +--- a/src/core/dbus.c ++++ b/src/core/dbus.c +@@ -152,6 +152,8 @@ static int signal_activation_request(sd_bus_message *message, void *userdata, sd + const char *name; + Unit *u; + int r; ++ int jobtype; ++ Service *s = NULL; + + assert(message); + assert(m); +@@ -177,7 +179,13 @@ static int signal_activation_request(sd_bus_message *message, void *userdata, sd + goto failed; + } + +- r = manager_add_job(m, JOB_START, u, JOB_REPLACE, NULL, &error, NULL); ++ jobtype = JOB_START; ++ s = SERVICE(u); ++ if(s && s->state != SERVICE_DEAD) { ++ jobtype = JOB_RESTART; ++ log_unit_info(u, "Service '%s' will be restarted to activate the service. The current service state is %d.", u->id, s->state); ++ } ++ r = manager_add_job(m, jobtype, u, JOB_REPLACE, NULL, &error, NULL); + if (r < 0) + goto failed; + +-- +1.8.3.1 diff --git a/1605-systemd-core-fix-problem-of-dbus-service-can-not-be-started.patch b/1605-systemd-core-fix-problem-of-dbus-service-can-not-be-started.patch new file mode 100644 index 0000000000000000000000000000000000000000..5075453c38dba1b068dff70f09c0254bfaf09855 --- /dev/null +++ b/1605-systemd-core-fix-problem-of-dbus-service-can-not-be-started.patch @@ -0,0 +1,40 @@ +From bf589755bd5b084f1b5dd099ea3e4917ac9911fd Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Thu, 14 Sep 2017 12:54:01 +0800 +Subject: [PATCH] systemd-core: fix problem of dbus service can not be started + when dbus is dead and state of system dbus of systemd stay in + BUS_AUTHENTICATING. + +When systemd starts a dbus communication, it will first authenticate the bus by communicating with polkitd service, and then enter running state. +But if authenticating can not be establised within 25s(default timeout seconds) since authenticating starts +(maybe caused by polkitd service or dbus service can not be activated in time), the dbus state in systemd side will stays in BUS_AUTHENTICATING state, +and systemd will enter a mad state that it will handle authenticating(in bus_process_internal function) very frequently and will have no any change to +service for events of restarting services(by systemctl restart dbus.service --no-ask-password --no-block). So that the dbus service will never be restarted successfully. +systemd will enter such a state is caused by the timeout setting in sd_bus_get_timeout function. When in BUS_AUTHENTICATING state, the timeout is set +to a fix value of bus->auth_timeout(authenticating start time + 25s), if auth_timeout is an expired time, but not a furture time, systemd will always service +for the callback of function of dbus(time_callback) with no any delay when it got its chance, and leave no chance for events of restarting services. +This patch fix this problem by fixing the timeout to a furture time when bus->auth_timeout is expired. +--- + src/libsystemd/sd-bus/sd-bus.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index b0a3237..ca626d3 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -2267,7 +2267,11 @@ _public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) { + switch (bus->state) { + + case BUS_AUTHENTICATING: +- *timeout_usec = bus->auth_timeout; ++ //delay 1 second to ensure it is a furture time but not an expired time ++ if(bus->auth_timeout <= now(CLOCK_MONOTONIC)) ++ *timeout_usec = now(CLOCK_MONOTONIC) + USEC_PER_SEC; ++ else ++ *timeout_usec = bus->auth_timeout; + return 1; + + case BUS_RUNNING: +-- +1.8.3.1 + diff --git a/1610-add-new-rules-for-lower-priority-events-to-preempt.patch b/1610-add-new-rules-for-lower-priority-events-to-preempt.patch new file mode 100644 index 0000000000000000000000000000000000000000..8715946f1fc36d41d6ed338bdce9ce4b2765216b --- /dev/null +++ b/1610-add-new-rules-for-lower-priority-events-to-preempt.patch @@ -0,0 +1,222 @@ +From 49f6a75e648c113fa9985675f47f78a4cd57c084 Mon Sep 17 00:00:00 2001 +From: yangbin +Date: Fri, 26 Jul 2019 10:02:58 +0800 +Subject: [PATCH] systemd-core: Add new rules for lower priority events to + preempt over higher priority events + +1. When a high priority event happenes very frequent, and this event takes long time for execution,systemd will get into busy for handling this event only, and lower priority events will have no any change to dispatch and run. + +2. One example is the event for /proc/self/mountinfo, which have a very high priority with -10. +When there are many mountpoints in mountinfo(for example, there may be many netns mountpoints),this event will take long time to finish. +Then if now there are mountpoints in repeating mounting and unmounting(for example, /run/user/uid mountpoint will be mounted then unmounted when for one su command), +this event will take all time of systemd, and lower priority lower events will not be dispatched anyway. +This will case a very severity problem that zombie process will not be reaped, for the evnet for reaping zombies has a lower priority of -6. + +3. This patch fix this problem by add the following rules to allow lower priority events to preempt over higher priority events. +a) If a higher priority event has already been execute for a certain count in consecutive, it can be preempted by lower priority events. The default value for this count is 10, and can be configured through 'sd_event_source_set_preempt_dispatch_count'. +b) If a lower priority gets into pending for 10 times in consecutive, it can preempt over higher priority events. +c) If a lower priority is in pending, and is not dispatched over 50 iteration, it can preempt over higher priority events. +d) The above rules only works for events with priority equal or higher than 'SD_EVENT_PRIORITY_NORMAL' or evnets with type of SOURCE_DEFER, since SOURCE_DEFER events is used for job running queues. +--- + src/core/mount.c | 4 ++ + src/libsystemd/sd-event/sd-event.c | 87 ++++++++++++++++++++++++++++++ + src/systemd/sd-event.h | 1 + + 3 files changed, 92 insertions(+) + +diff --git a/src/core/mount.c b/src/core/mount.c +index 1b94ab4..78b6e30 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1742,6 +1742,10 @@ static void mount_enumerate(Manager *m) { + goto fail; + } + ++ r = sd_event_source_set_preempt_dispatch_count(m->mount_event_source, 5); ++ if (r < 0) ++ goto fail; ++ + (void) sd_event_source_set_description(m->mount_event_source, "mount-monitor-dispatch"); + } + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index d53b9a7..7e33061 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -26,6 +26,11 @@ + #include "time-util.h" + #include "util.h" + ++#define DEFAULT_PREEMPTED_ITERATION_COUNT (3) ++#define DEFAULT_PREEMPT_DISPATCH_COUNT (10) ++#define DEFAULT_PREEMPT_PENDING_COUNT (10) ++#define DEFAULT_PREEMPT_ITERATION_COUNT (30) ++ + #define DEFAULT_ACCURACY_USEC (250 * USEC_PER_MSEC) + + typedef enum EventSourceType { +@@ -103,6 +108,11 @@ struct sd_event_source { + uint64_t pending_iteration; + uint64_t prepare_iteration; + ++ uint64_t preempted_iteration; /*The iteration that dispatched_count is greater than preempt_dispatch_count*/ ++ unsigned pending_count; /*times of pending not dispatched*/ ++ unsigned dispatched_count; /*consecutive dispatched count*/ ++ unsigned preempt_dispatch_count; /*Will be preempted by lower priority if dispatched count reaches to this*/ ++ + sd_event_destroy_t destroy_callback; + + LIST_FIELDS(sd_event_source, sources); +@@ -301,6 +311,11 @@ struct sd_event { + + LIST_HEAD(sd_event_source, sources); + ++ /*last dispatched source, its type is sd_event_source, ++ * here use void to avoid accessing its members, ++ * for it may have been freed already.*/ ++ void *last_source; ++ + usec_t last_run, last_log; + unsigned delays[sizeof(usec_t) * 8]; + }; +@@ -314,8 +329,42 @@ static sd_event *event_resolve(sd_event *e) { + return e == SD_EVENT_DEFAULT ? default_event : e; + } + ++static int preempt_prioq_compare(const sd_event_source *x, const sd_event_source *y) { ++ if((x->priority > SD_EVENT_PRIORITY_NORMAL && x->type != SOURCE_DEFER) ++ || (y->priority > SD_EVENT_PRIORITY_NORMAL && y->type != SOURCE_DEFER)) { ++ return 0; /*only high priority evnets can preempt*/ ++ } ++ ++ if(x->priority <= y->priority) { ++ if(x->dispatched_count >= x->preempt_dispatch_count) ++ return 1; ++ if(y->type != SOURCE_DEFER) { /*pending state for defer event is always true*/ ++ /*y has lower priority, but its pending count is greater than x, so y wins*/ ++ if(y->pending_count >= (x->pending_count + DEFAULT_PREEMPT_PENDING_COUNT)) ++ return 1; ++ /*y has lower priority, but is in pending longer than x, so y wins*/ ++ if(x->pending_iteration >= (y->pending_iteration + DEFAULT_PREEMPT_ITERATION_COUNT)) ++ return 1; ++ } ++ } else { ++ if(y->dispatched_count >= y->preempt_dispatch_count) ++ return -1; ++ if(x->type != SOURCE_DEFER) { /*pending state for defer event is always true*/ ++ /*x has lower priority, but its pending count is greater than y, so x wins*/ ++ if(x->pending_count >= (y->pending_count + DEFAULT_PREEMPT_PENDING_COUNT)) ++ return -1; ++ /*x has lower priority, but is in pending longer than y, so x wins*/ ++ if(y->pending_iteration >= (x->pending_iteration + DEFAULT_PREEMPT_ITERATION_COUNT)) ++ return -1; ++ } ++ } ++ ++ return 0; ++} ++ + static int pending_prioq_compare(const void *a, const void *b) { + const sd_event_source *x = a, *y = b; ++ int r; + + assert(x->pending); + assert(y->pending); +@@ -326,6 +375,10 @@ static int pending_prioq_compare(const void *a, const void *b) { + if (x->enabled == SD_EVENT_OFF && y->enabled != SD_EVENT_OFF) + return 1; + ++ r = preempt_prioq_compare(a, b); ++ if(r) ++ return r; ++ + /* Lower priority values first */ + if (x->priority < y->priority) + return -1; +@@ -1030,6 +1083,17 @@ static int source_set_pending(sd_event_source *s, bool b) { + assert(s); + assert(s->type != SOURCE_EXIT); + ++ if (b && s->pending == b) ++ s->pending_count++; ++ else ++ s->pending_count = (b ? 1 : 0); ++ if (b && s->preempted_iteration && ++ (s->pending_count >= DEFAULT_PREEMPTED_ITERATION_COUNT || ++ s->event->iteration >= (s->preempted_iteration + DEFAULT_PREEMPTED_ITERATION_COUNT)) ) { ++ s->dispatched_count = 0; ++ s->preempted_iteration = 0; ++ } ++ + if (s->pending == b) + return 0; + +@@ -1097,6 +1161,7 @@ static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType t + .type = type, + .pending_index = PRIOQ_IDX_NULL, + .prepare_index = PRIOQ_IDX_NULL, ++ .preempt_dispatch_count = DEFAULT_PREEMPT_DISPATCH_COUNT, + }; + + if (!floating) +@@ -2263,6 +2328,7 @@ _public_ int sd_event_source_set_enabled(sd_event_source *s, int m) { + return r; + } + ++ s->pending_count = 0; + switch (s->type) { + + case SOURCE_IO: +@@ -3055,6 +3121,19 @@ static int process_inotify(sd_event *e) { + return done; + } + ++static void source_dispatch_pre(sd_event_source *s) { ++ if(s->event->last_source == s) { ++ s->dispatched_count++; ++ if(s->dispatched_count >= s->preempt_dispatch_count) ++ s->preempted_iteration = s->event->iteration; ++ } else { ++ s->preempted_iteration = 0; ++ s->dispatched_count = 0; ++ } ++ s->event->last_source = s; ++ s->pending_count = 0; ++} ++ + static int source_dispatch(sd_event_source *s) { + EventSourceType saved_type; + int r = 0; +@@ -3095,6 +3174,7 @@ static int source_dispatch(sd_event_source *s) { + return r; + } + ++ source_dispatch_pre(s); + s->dispatching = true; + + switch (s->type) { +@@ -3793,3 +3873,10 @@ _public_ int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_d + + return !!s->destroy_callback; + } ++ ++_public_ int sd_event_source_set_preempt_dispatch_count(sd_event_source *s, unsigned count) { ++ assert_return(s, -EINVAL); ++ ++ s->preempt_dispatch_count = count; ++ return 0; ++} +diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h +index 7fcae4a..fdf9108 100644 +--- a/src/systemd/sd-event.h ++++ b/src/systemd/sd-event.h +@@ -143,6 +143,7 @@ int sd_event_source_get_child_pid(sd_event_source *s, pid_t *pid); + int sd_event_source_get_inotify_mask(sd_event_source *s, uint32_t *ret); + int sd_event_source_set_destroy_callback(sd_event_source *s, sd_event_destroy_t callback); + int sd_event_source_get_destroy_callback(sd_event_source *s, sd_event_destroy_t *ret); ++int sd_event_source_set_preempt_dispatch_count(sd_event_source *s, unsigned count); + + /* Define helpers so that __attribute__((cleanup(sd_event_unrefp))) and similar may be used. */ + _SD_DEFINE_POINTER_CLEANUP_FUNC(sd_event, sd_event_unref); +-- +2.17.1 + diff --git a/1612-serialize-pids-for-scope-when-not-started.patch b/1612-serialize-pids-for-scope-when-not-started.patch new file mode 100644 index 0000000000000000000000000000000000000000..3d51aa655ef056e06273c59ba7cc9876b813160f --- /dev/null +++ b/1612-serialize-pids-for-scope-when-not-started.patch @@ -0,0 +1,89 @@ +From a5c08598384d44ad3bce24ff63ab320b3b3e5292 Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Wed, 31 Jan 2018 22:28:36 +0800 +Subject: [PATCH] systemd-core: Serialize pids for scope unit when it is not + started + +1. when a scope unit is initialized, and daemon-reload is performed before it is started, +pids (generally comes from dbus) belog to this scope will not be attached to the cgroup of this scope, +because these pids are not serialized and are lost during daemon-reload. +2. this patch fix this problem by serializing scope pids when the state of the scope is DEAD(the init state). +--- + src/core/scope.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/src/core/scope.c b/src/core/scope.c +index ae6614f..8d96ee1 100644 +--- a/src/core/scope.c ++++ b/src/core/scope.c +@@ -194,6 +194,8 @@ static int scope_load(Unit *u) { + + static int scope_coldplug(Unit *u) { + Scope *s = SCOPE(u); ++ Iterator i; ++ void *pidp = NULL; + int r; + + assert(s); +@@ -214,6 +216,12 @@ static int scope_coldplug(Unit *u) { + bus_scope_track_controller(s); + + scope_set_state(s, s->deserialized_state); ++ if (s->state == SCOPE_DEAD && !u->cgroup_path && !set_isempty(u->pids)) { ++ SET_FOREACH(pidp, u->pids, i) { ++ log_unit_info(u, "Rewatch pid from serialized pids. unit: %s, pid: %u", u->id, PTR_TO_UINT32(pidp)); ++ unit_watch_pid(u, PTR_TO_UINT32(pidp)); ++ } ++ } + return 0; + } + +@@ -396,6 +404,8 @@ static int scope_get_timeout(Unit *u, usec_t *timeout) { + } + + static int scope_serialize(Unit *u, FILE *f, FDSet *fds) { ++ Iterator i; ++ void *pidp = NULL; + Scope *s = SCOPE(u); + + assert(s); +@@ -408,6 +418,14 @@ static int scope_serialize(Unit *u, FILE *f, FDSet *fds) { + if (s->controller) + unit_serialize_item(u, f, "controller", s->controller); + ++ /*serialize pids when scope is not started*/ ++ if (s->state == SCOPE_DEAD && !u->cgroup_path && !set_isempty(u->pids)) { ++ SET_FOREACH(pidp, u->pids, i) { ++ log_unit_info(u, "scope is not started yet, pids are serialized. unit: %s, pid: %u", u->id, PTR_TO_UINT32(pidp)); ++ unit_serialize_item_format(u, f, "scope_pids", PID_FMT, PTR_TO_UINT32(pidp)); ++ } ++ } ++ + return 0; + } + +@@ -443,6 +461,21 @@ static int scope_deserialize_item(Unit *u, const char *key, const char *value, F + if (r < 0) + log_oom(); + ++ } else if (streq(key, "scope_pids")) { ++ pid_t pid; ++ ++ if (parse_pid(value, &pid) < 0) ++ log_unit_debug(u, "Failed to parse scope-pid value %s.", value); ++ else { ++ if(!u->pids) { ++ r = set_ensure_allocated(&u->pids, NULL); ++ if (r < 0) ++ return r; ++ } ++ r = set_put(u->pids, pid); ++ if (r < 0) ++ return r; ++ } + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + +-- +1.8.3.1 + diff --git a/1615-do-not-finish-job-during-daemon-reload-in-unit_notify.patch b/1615-do-not-finish-job-during-daemon-reload-in-unit_notify.patch new file mode 100644 index 0000000000000000000000000000000000000000..d29e083491253fe95c06e0b35e564736a1cff97b --- /dev/null +++ b/1615-do-not-finish-job-during-daemon-reload-in-unit_notify.patch @@ -0,0 +1,37 @@ +From 650352c713aeb3b47807c9699ceeb168f9f880b8 Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Tue, 13 Mar 2018 20:51:37 +0800 +Subject: [PATCH] systemd-core: Do not finish job during daemon reloading in + unit_notify. + +1. During daemon reload, a service unit will restore its state from dead to its deserialized state, +and unit_notify will be triggered to notify the state change. +Since JobRemove signal will not be sent during daemon-reload(see details of job_uninstall), +if one job is finished in unit_notify due to the deserialization of a service, the corresponding +job observers(such as systemctl) will not receive any JobRemove signals will hang forever. +2. The above problem will cause a systemctl command to hang forever by using the following steps to reproduce. +a) Ensuere a service(named A)is in running state. +b) execute "systemctl daemon-reload" and "systemctl start A" concurrently +c) the systemctl command will hang for it is in waiting for the JobRemoved signal, but not signals will come from systemd. +3. This patch fix this bug by not finishing job in unit_notify when it is in daemon reload. +--- + src/core/unit.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 9e5f1a8..2da6f61 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1831,7 +1831,8 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlag + + unit_update_on_console(u); + +- if (u->job) { ++ if (u->job && ++ !(m->n_reloading > 0 && u->job->state != JOB_RUNNING && os == UNIT_INACTIVE)) { /*do not finish job during daemon-reload*/ + unexpected = false; + + if (u->job->state == JOB_WAITING) +-- +1.8.3.1 + diff --git a/1619-delay-to-restart-when-a-service-can-not-be-auto-restarted.patch b/1619-delay-to-restart-when-a-service-can-not-be-auto-restarted.patch new file mode 100644 index 0000000000000000000000000000000000000000..f45745214ade529976fb4d061059f06533703ab1 --- /dev/null +++ b/1619-delay-to-restart-when-a-service-can-not-be-auto-restarted.patch @@ -0,0 +1,43 @@ +From 9315c29e4fdfa19c90bb483a364b017881f5cef7 Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Sat, 21 Apr 2018 17:18:19 +0800 +Subject: [PATCH] systemd-core: Delay to restart when a service can not be + auto-restarted when there is one STOP_JOB for the service + +When a service current has a STOP job has not scheduled yet, +and also if the service is already scheduled with an auto-restart +with restart-second configured as 0, the service will not be restarted successfully, +and systemd will go into an endless loop to restart the service. +This is because restart-second is 0 and timer task has higher priority than IO tasks when there priority +is same(both with 0), so the STOP job has no chance to be scheduled, and systemd will go into the endless loop +to handle the time task. +This patch fix this problem by delaying 1 second to restart the service to cause STOP job to be scheduled. +--- + src/core/service.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index ad9c028..8217447 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1716,14 +1716,15 @@ fail: + static void service_enter_restart(Service *s) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + int r; ++ int restart_usec; + + assert(s); + + if (UNIT(s)->job && UNIT(s)->job->type == JOB_STOP) { + /* Don't restart things if we are going down anyway */ + log_unit_info(UNIT(s), "Stop job pending for unit, delaying automatic restart."); +- +- r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec)); ++ restart_usec = (s->restart_usec == 0) ? 1*USEC_PER_SEC : s->restart_usec; ++ r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), restart_usec)); + if (r < 0) + goto fail; + +-- +1.8.3.1 + diff --git a/1620-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch b/1620-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch new file mode 100644 index 0000000000000000000000000000000000000000..05c9cf46404880e744ba65f88e5b390019a95321 --- /dev/null +++ b/1620-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch @@ -0,0 +1,46 @@ +From 07e13151c566588b5f679e2576d3dfc2125c6e7c Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Sun, 22 Apr 2018 18:49:19 +0800 +Subject: [PATCH] systemd-core: nop_job of a unit must also be coldpluged after + deserization. + +When a unit is not in-active, and systemctl try-restart is executed for this unit, +systemd will do nothing for it and just accept it as a nop_job for the unit. +When then nop-job is still in the running queue, then daemon-reload is performed, this nop job +will be dropped from the unit since it is not coldpluged in the unit_coldplug function. +After then, the systemctl try-restart command will hang forever since no JOB_DONE dbus signal will be sent +to it from systemd. +This patch fix this problem by do coldplug for the nop_job in unit_coldplug function. +--- + src/core/unit.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 2da6f61..a862b79 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3028,10 +3028,17 @@ int unit_coldplug(Unit *u) { + r = q; + } + +- if (u->job) { +- q = job_coldplug(u->job); +- if (q < 0 && r >= 0) +- r = q; ++ if (u->job || u->nop_job) { ++ if (u->job) { ++ q = job_coldplug(u->job); ++ if (q < 0 && r >= 0) ++ r = q; ++ } ++ if (u->nop_job) { ++ q = job_coldplug(u->nop_job); ++ if (q < 0 && r >= 0) ++ r = q; ++ } + } + + return r; +-- +1.8.3.1 + diff --git a/backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch b/backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch new file mode 100644 index 0000000000000000000000000000000000000000..b61423c49ef55eac6f1a4e4959862568f0b54c67 --- /dev/null +++ b/backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch @@ -0,0 +1,34 @@ +From a59b0a9f768f6e27b25f4f1bab6de08842e78d74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Thu, 5 Nov 2020 17:55:25 +0100 +Subject: [PATCH] basic/stat-util: make mtime check stricter and use entire + timestamp + +Note that st_mtime member of struct stat is defined as follows, + + #define st_mtime st_mtim.tv_sec + +Hence we omitted checking nanosecond part of the timestamp (struct +timespec) and possibly would miss modifications that happened within the +same second. +--- + src/basic/stat-util.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c +index 4595ba7..b44d75c 100644 +--- a/src/basic/stat-util.c ++++ b/src/basic/stat-util.c +@@ -394,7 +394,8 @@ bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { + return a && b && + (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */ + ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */ +- a->st_mtime == b->st_mtime && ++ a->st_mtim.tv_sec == b->st_mtim.tv_sec && ++ a->st_mtim.tv_nsec == b->st_mtim.tv_nsec && + (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */ + a->st_dev == b->st_dev && + a->st_ino == b->st_ino && +-- +2.23.0 + diff --git a/backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch b/backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch new file mode 100644 index 0000000000000000000000000000000000000000..ac60fbc5ec6993f4ef0ad4ea8bea3644c186060d --- /dev/null +++ b/backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch @@ -0,0 +1,52 @@ +From 578dc69f2a60d6282acc2d06ce8a3bf8a9d8ada0 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 6 Mar 2020 15:56:28 +0900 +Subject: [PATCH 0007/6858] execute: Fix migration from DynamicUser=yes to no + +Closes #12131. +Reference: https://github.com/systemd/systemd/pull/15033/commits/578dc69f2a60d6282acc2d06ce8a3bf8a9d8ada0 +Conflict: remove the last arguement "NULL" of function "chase_symlinks" +--- + src/core/execute.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index 4595bb12dc..46b5c99ada 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2247,7 +2247,7 @@ static int setup_exec_directory( + + if (type != EXEC_DIRECTORY_CONFIGURATION && + readlink_and_make_absolute(p, &target) >= 0) { +- _cleanup_free_ char *q = NULL; ++ _cleanup_free_ char *q = NULL, *q_resolved = NULL, *target_resolved = NULL; + + /* This already exists and is a symlink? Interesting. Maybe it's one created + * by DynamicUser=1 (see above)? +@@ -2256,13 +2256,22 @@ static int setup_exec_directory( + * since they all support the private/ symlink logic at least in some + * configurations, see above. */ + ++ r = chase_symlinks(target, NULL, 0, &target_resolved); ++ if (r < 0) ++ goto fail; ++ + q = path_join(params->prefix[type], "private", *rt); + if (!q) { + r = -ENOMEM; + goto fail; + } + +- if (path_equal(q, target)) { ++ /* /var/lib or friends may be symlinks. So, let's chase them also. */ ++ r = chase_symlinks(q, NULL, CHASE_NONEXISTENT, &q_resolved); ++ if (r < 0) ++ goto fail; ++ ++ if (path_equal(q_resolved, target_resolved)) { + + /* Hmm, apparently DynamicUser= was once turned on for this service, + * but is no longer. Let's move the directory back up. */ +-- +2.23.0 + diff --git a/backport-network-add-missing-link-network-checks.patch b/backport-network-add-missing-link-network-checks.patch new file mode 100644 index 0000000000000000000000000000000000000000..186596bb1cfebca35a442e6845ec82c63c34450e --- /dev/null +++ b/backport-network-add-missing-link-network-checks.patch @@ -0,0 +1,41 @@ +From b1b0b42e48303134731e017a108c6c334ef5f4c8 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Tue, 17 Sep 2019 21:29:23 +0900 +Subject: [PATCH] network: add missing link->network checks + +When the function is called, no network file may be assigned to the +link. +--- + src/network/networkd-link.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c +index f1aeb7287e34..46d55f64dc5b 100644 +--- a/src/network/networkd-link.c ++++ b/src/network/networkd-link.c +@@ -2393,9 +2393,9 @@ static int link_drop_foreign_config(Link *link) { + continue; + + if (link_address_is_dynamic(link, address)) { +- if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) ++ if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; +- } else if (FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) ++ } else if (link->network && FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + + if (link_is_static_address_configured(link, address)) { +@@ -2435,11 +2435,11 @@ static int link_drop_foreign_config(Link *link) { + in_addr_equal(AF_INET6, &route->dst, &(union in_addr_union) { .in6 = {{{ 0xff,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 }}} })) + continue; + +- if (route->protocol == RTPROT_STATIC && ++ if (route->protocol == RTPROT_STATIC && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_STATIC)) + continue; + +- if (route->protocol == RTPROT_DHCP && ++ if (route->protocol == RTPROT_DHCP && link->network && + FLAGS_SET(link->network->keep_configuration, KEEP_CONFIGURATION_DHCP)) + continue; + diff --git a/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch b/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch new file mode 100644 index 0000000000000000000000000000000000000000..17d4325f750a4dab215287e64ed46e0b9ee72689 --- /dev/null +++ b/backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch @@ -0,0 +1,317 @@ +From efd3be9de1dc07ec743912f3c166bbf17dbb20f5 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Mon, 8 Mar 2021 15:39:53 +0900 +Subject: [PATCH] sd-event: re-check new epoll events when a child event is + queued + +Previously, when a process outputs something and exit just after +epoll_wait() but before process_child(), then the IO event is ignored +even if the IO event has higher priority. See #18190. + +This can be solved by checking epoll event again after process_child(). + +However, there exists a possibility that another process outputs and +exits just after process_child() but before the second epoll_wait(). +When the IO event has lower priority than the child event, still IO +event is processed. + +So, this makes new epoll events and child events are checked in a loop +until no new event is detected. To prevent an infinite loop, the number +of maximum trial is set to 10. + +Fixes #18190. +--- + src/libsystemd/sd-event/sd-event.c | 150 +++++++++++++++++++++++++++---------- + 1 file changed, 110 insertions(+), 40 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 5d0e057..65db799 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -850,7 +850,7 @@ static int source_set_pending(sd_event_source *s, bool b) { + } + } + +- return 0; ++ return 1; + } + + static sd_event_source *source_new(sd_event *e, bool floating, EventSourceType type) { +@@ -2502,12 +2502,20 @@ static int process_timer( + return 0; + } + +-static int process_child(sd_event *e) { ++static int process_child(sd_event *e, int64_t threshold, int64_t *ret_min_priority) { ++ int64_t min_priority = threshold; ++ bool something_new = false; + sd_event_source *s; + Iterator i; + int r; + + assert(e); ++ assert(ret_min_priority); ++ ++ if (!e->need_process_child) { ++ *ret_min_priority = min_priority; ++ return 0; ++ } + + e->need_process_child = false; + +@@ -2532,6 +2540,9 @@ static int process_child(sd_event *e) { + HASHMAP_FOREACH(s, e->child_sources, i) { + assert(s->type == SOURCE_CHILD); + ++ if (s->priority > threshold) ++ continue; ++ + if (s->pending) + continue; + +@@ -2560,19 +2571,24 @@ static int process_child(sd_event *e) { + r = source_set_pending(s, true); + if (r < 0) + return r; ++ if (r > 0) { ++ something_new = true; ++ min_priority = MIN(min_priority, s->priority); ++ } + } + } + +- return 0; ++ *ret_min_priority = min_priority; ++ return something_new; + } + +-static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { +- bool read_one = false; ++static int process_signal(sd_event *e, struct signal_data *d, uint32_t events, int64_t *min_priority) { + int r; + + assert(e); + assert(d); + assert_return(events == EPOLLIN, -EIO); ++ assert(min_priority); + + /* If there's a signal queued on this priority and SIGCHLD is + on this priority too, then make sure to recheck the +@@ -2598,7 +2614,7 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + n = read(d->fd, &si, sizeof(si)); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) +- return read_one; ++ return 0; + + return -errno; + } +@@ -2608,8 +2624,6 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + + assert(SIGNAL_VALID(si.ssi_signo)); + +- read_one = true; +- + if (e->signal_sources) + s = e->signal_sources[si.ssi_signo]; + if (!s) +@@ -2623,12 +2637,16 @@ static int process_signal(sd_event *e, struct signal_data *d, uint32_t events) { + r = source_set_pending(s, true); + if (r < 0) + return r; ++ if (r > 0 && *min_priority >= s->priority) { ++ *min_priority = s->priority; ++ return 1; /* an event source with smaller priority is queued. */ ++ } + +- return 1; ++ return 0; + } + } + +-static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents) { ++static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t revents, int64_t threshold) { + ssize_t n; + + assert(e); +@@ -2644,6 +2662,9 @@ static int event_inotify_data_read(sd_event *e, struct inotify_data *d, uint32_t + if (d->buffer_filled > 0) + return 0; + ++ if (d->priority > threshold) ++ return 0; ++ + n = read(d->fd, &d->buffer, sizeof(d->buffer)); + if (n < 0) { + if (IN_SET(errno, EAGAIN, EINTR)) +@@ -3101,21 +3122,15 @@ pending: + return r; + } + +-_public_ int sd_event_wait(sd_event *e, uint64_t timeout) { ++static int process_epoll(sd_event *e, usec_t timeout, int64_t threshold, int64_t *ret_min_priority) { ++ int64_t min_priority = threshold; ++ bool something_new = false; + struct epoll_event *ev_queue; + unsigned ev_queue_max; + int r, m, i; + +- assert_return(e, -EINVAL); +- assert_return(e = event_resolve(e), -ENOPKG); +- assert_return(!event_pid_changed(e), -ECHILD); +- assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); +- assert_return(e->state == SD_EVENT_ARMED, -EBUSY); +- +- if (e->exit_requested) { +- e->state = SD_EVENT_PENDING; +- return 1; +- } ++ assert(e); ++ assert(ret_min_priority); + + ev_queue_max = MAX(e->n_sources, 1u); + ev_queue = newa(struct epoll_event, ev_queue_max); +@@ -3127,16 +3142,12 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + m = epoll_wait(e->epoll_fd, ev_queue, ev_queue_max, + timeout == (uint64_t) -1 ? -1 : (int) DIV_ROUND_UP(timeout, USEC_PER_MSEC)); + if (m < 0) { +- if (errno == EINTR) { +- e->state = SD_EVENT_PENDING; +- return 1; +- } +- +- r = -errno; +- goto finish; ++ return -errno; + } + +- triple_timestamp_get(&e->timestamp); ++ /* Set timestamp only when this is called first time. */ ++ if (threshold == INT64_MAX) ++ triple_timestamp_get(&e->timestamp); + + for (i = 0; i < m; i++) { + +@@ -3147,9 +3158,18 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + + switch (*t) { + +- case WAKEUP_EVENT_SOURCE: +- r = process_io(e, ev_queue[i].data.ptr, ev_queue[i].events); ++ case WAKEUP_EVENT_SOURCE: { ++ sd_event_source *s = ev_queue[i].data.ptr; ++ ++ if (s->priority > threshold) ++ continue; ++ ++ min_priority = MIN(min_priority, s->priority); ++ ++ r = process_io(e, s, ev_queue[i].events); ++ + break; ++ } + + case WAKEUP_CLOCK_DATA: { + struct clock_data *d = ev_queue[i].data.ptr; +@@ -3158,11 +3178,12 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + } + + case WAKEUP_SIGNAL_DATA: +- r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events); ++ r = process_signal(e, ev_queue[i].data.ptr, ev_queue[i].events, &min_priority); + break; + + case WAKEUP_INOTIFY_DATA: +- r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events); ++ r = event_inotify_data_read(e, ev_queue[i].data.ptr, ev_queue[i].events, threshold); ++ + break; + + default: +@@ -3170,7 +3191,63 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + } + } + if (r < 0) ++ return r; ++ if (r > 0) ++ something_new = true; ++ } ++ ++ *ret_min_priority = min_priority; ++ return something_new; ++} ++ ++_public_ int sd_event_wait(sd_event *e, uint64_t timeout) { ++ int r; ++ ++ assert_return(e, -EINVAL); ++ assert_return(e = event_resolve(e), -ENOPKG); ++ assert_return(!event_pid_changed(e), -ECHILD); ++ assert_return(e->state != SD_EVENT_FINISHED, -ESTALE); ++ assert_return(e->state == SD_EVENT_ARMED, -EBUSY); ++ ++ if (e->exit_requested) { ++ e->state = SD_EVENT_PENDING; ++ return 1; ++ } ++ ++ for (int64_t threshold = INT64_MAX; ; threshold--) { ++ int64_t epoll_min_priority, child_min_priority; ++ ++ /* There may be a possibility that new epoll (especially IO) and child events are ++ * triggered just after process_epoll() call but before process_child(), and the new IO ++ * events may have higher priority than the child events. To salvage these events, ++ * let's call epoll_wait() again, but accepts only events with higher priority than the ++ * previous. See issue https://github.com/systemd/systemd/issues/18190 and comments ++ * https://github.com/systemd/systemd/pull/18750#issuecomment-785801085 ++ * https://github.com/systemd/systemd/pull/18922#issuecomment-792825226 */ ++ ++ r = process_epoll(e, timeout, threshold, &epoll_min_priority); ++ if (r == -EINTR) { ++ e->state = SD_EVENT_PENDING; ++ return 1; ++ } ++ if (r < 0) + goto finish; ++ if (r == 0 && threshold < INT64_MAX) ++ /* No new epoll event. */ ++ break; ++ ++ r = process_child(e, threshold, &child_min_priority); ++ if (r < 0) ++ goto finish; ++ if (r == 0) ++ /* No new child event. */ ++ break; ++ ++ threshold = MIN(epoll_min_priority, child_min_priority); ++ if (threshold == INT64_MIN) ++ break; ++ ++ timeout = 0; + } + + r = process_watchdog(e); +@@ -3197,19 +3274,12 @@ _public_ int sd_event_wait(sd_event *e, uint64_t timeout) { + if (r < 0) + goto finish; + +- if (e->need_process_child) { +- r = process_child(e); +- if (r < 0) +- goto finish; +- } +- + r = process_inotify(e); + if (r < 0) + goto finish; + + if (event_next_pending(e)) { + e->state = SD_EVENT_PENDING; +- + return 1; + } + +-- +1.8.3.1 + diff --git a/backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch b/backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch new file mode 100644 index 0000000000000000000000000000000000000000..c9018442b941ef5e6d9258a86bd869e0174381dc --- /dev/null +++ b/backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch @@ -0,0 +1,53 @@ +From fee5c52ac260d021466c1062499f0ebd5241db5f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 28 Apr 2020 18:16:25 +0200 +Subject: [PATCH] stat-util: add stat_inode_unmodified() helper that checks if + an inode was modified + +--- + src/basic/stat-util.c | 21 +++++++++++++++++++++ + src/basic/stat-util.h | 2 ++ + 2 files changed, 23 insertions(+) + +diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c +index 2cd722c..4595ba7 100644 +--- a/src/basic/stat-util.c ++++ b/src/basic/stat-util.c +@@ -379,3 +379,24 @@ int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret + + return 0; + } ++ ++bool stat_inode_unmodified(const struct stat *a, const struct stat *b) { ++ ++ /* Returns if the specified stat structures reference the same, unmodified inode. This check tries to ++ * be reasonably careful when detecting changes: we check both inode and mtime, to cater for file ++ * systems where mtimes are fixed to 0 (think: ostree/nixos type installations). We also check file ++ * size, backing device, inode type and if this refers to a device not the major/minor. ++ * ++ * Note that we don't care if file attributes such as ownership or access mode change, this here is ++ * about contents of the file. The purpose here is to detect file contents changes, and nothing ++ * else. */ ++ ++ return a && b && ++ (a->st_mode & S_IFMT) != 0 && /* We use the check for .st_mode if the structure was ever initialized */ ++ ((a->st_mode ^ b->st_mode) & S_IFMT) == 0 && /* same inode type */ ++ a->st_mtime == b->st_mtime && ++ (!S_ISREG(a->st_mode) || a->st_size == b->st_size) && /* if regular file, compare file size */ ++ a->st_dev == b->st_dev && ++ a->st_ino == b->st_ino && ++ (!(S_ISCHR(a->st_mode) || S_ISBLK(a->st_mode)) || a->st_rdev == b->st_rdev); /* if device node, also compare major/minor, because we can */ ++} +diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h +index 7824af3..3665059 100644 +--- a/src/basic/stat-util.h ++++ b/src/basic/stat-util.h +@@ -87,3 +87,5 @@ int fd_verify_directory(int fd); + int device_path_make_major_minor(mode_t mode, dev_t devno, char **ret); + int device_path_make_canonical(mode_t mode, dev_t devno, char **ret); + int device_path_parse_major_minor(const char *path, mode_t *ret_mode, dev_t *ret_devno); ++ ++bool stat_inode_unmodified(const struct stat *a, const struct stat *b); +-- +2.23.0 + diff --git a/backport-tentatively-ignore-FORCERENEW-command.patch b/backport-tentatively-ignore-FORCERENEW-command.patch new file mode 100644 index 0000000000000000000000000000000000000000..2623fa2aeae361b88cbe146587b7dbf3e67f198d --- /dev/null +++ b/backport-tentatively-ignore-FORCERENEW-command.patch @@ -0,0 +1,38 @@ +From 38e980a6a5a3442c2f48b1f827284388096d8ca5 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 24 Jun 2021 01:22:07 +0900 +Subject: [PATCH] sd-dhcp-client: tentatively ignore FORCERENEW command + +This makes DHCP client ignore FORCERENEW requests, as unauthenticated +FORCERENEW requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). + +Let's re-enable this after RFC3118 (Authentication for DHCP Messages) +and/or RFC6704 (Forcerenew Nonce Authentication) are implemented. + +Fixes #16774. +--- + src/libsystemd-network/sd-dhcp-client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c +index 67a5a03eba6a..dc8ff19d1a24 100644 +--- a/src/libsystemd-network/sd-dhcp-client.c ++++ b/src/libsystemd-network/sd-dhcp-client.c +@@ -1380,9 +1380,17 @@ static int client_handle_forcerenew(sd_dhcp_client *client, DHCPMessage *force, + if (r != DHCP_FORCERENEW) + return -ENOMSG; + ++#if 0 + log_dhcp_client(client, "FORCERENEW"); + + return 0; ++#else ++ /* FIXME: Ignore FORCERENEW requests until we implement RFC3118 (Authentication for DHCP ++ * Messages) and/or RFC6704 (Forcerenew Nonce Authentication), as unauthenticated FORCERENEW ++ * requests causes a security issue (TALOS-2020-1142, CVE-2020-13529). */ ++ log_dhcp_client(client, "Received FORCERENEW, ignoring."); ++ return -ENOMSG; ++#endif + } + + static bool lease_equal(const sd_dhcp_lease *a, const sd_dhcp_lease *b) { diff --git a/backport-test-adapt-to-the-new-capsh-format.patch b/backport-test-adapt-to-the-new-capsh-format.patch new file mode 100644 index 0000000000000000000000000000000000000000..d2726c0a97714a6ec1087b3290998fe3c7d81895 --- /dev/null +++ b/backport-test-adapt-to-the-new-capsh-format.patch @@ -0,0 +1,107 @@ +From 9569e385036c05c0bf9fbccdbf3d131161398e2e Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Tue, 4 Feb 2020 13:49:01 +0100 +Subject: [PATCH] test: adapt to the new capsh format + +Since libcap v2.29 the format of cap_to_text() has been changed which +makes certain `test-execute` subtest fail. Let's remove the offending +part of the output (dropped capabilities) to make it compatible with +both the old and the new libcap. +--- + test/test-execute/exec-capabilityboundingset-invert.service | 3 ++- + .../exec-privatedevices-no-capability-mknod.service | 3 ++- + .../exec-privatedevices-no-capability-sys-rawio.service | 3 ++- + .../exec-privatedevices-yes-capability-mknod.service | 3 ++- + .../exec-privatedevices-yes-capability-sys-rawio.service | 3 ++- + .../exec-protectkernelmodules-no-capabilities.service | 3 ++- + .../exec-protectkernelmodules-yes-capabilities.service | 3 ++- + 9 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/test/test-execute/exec-capabilityboundingset-invert.service b/test/test-execute/exec-capabilityboundingset-invert.service +index 1abe390601..5f37427603 100644 +--- a/test/test-execute/exec-capabilityboundingset-invert.service ++++ b/test/test-execute/exec-capabilityboundingset-invert.service +@@ -2,6 +2,7 @@ + Description=Test for CapabilityBoundingSet + + [Service] +-ExecStart=/bin/sh -x -c '! capsh --print | grep "^Bounding set .*cap_chown"' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep "^Bounding set .*cap_chown"' + Type=oneshot + CapabilityBoundingSet=~CAP_CHOWN +diff --git a/test/test-execute/exec-privatedevices-no-capability-mknod.service b/test/test-execute/exec-privatedevices-no-capability-mknod.service +index 6d39469da8..4d61d9ffaa 100644 +--- a/test/test-execute/exec-privatedevices-no-capability-mknod.service ++++ b/test/test-execute/exec-privatedevices-no-capability-mknod.service +@@ -3,5 +3,6 @@ Description=Test CAP_MKNOD capability for PrivateDevices=no + + [Service] + PrivateDevices=no +-ExecStart=/bin/sh -x -c 'capsh --print | grep cap_mknod' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod' + Type=oneshot +diff --git a/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service +index e7f529c44c..f7f7a16736 100644 +--- a/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service ++++ b/test/test-execute/exec-privatedevices-no-capability-sys-rawio.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_RAWIO capability for PrivateDevices=no + + [Service] + PrivateDevices=no +-ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_rawio' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio' + Type=oneshot +diff --git a/test/test-execute/exec-privatedevices-yes-capability-mknod.service b/test/test-execute/exec-privatedevices-yes-capability-mknod.service +index fb1fc2875a..5bcace0845 100644 +--- a/test/test-execute/exec-privatedevices-yes-capability-mknod.service ++++ b/test/test-execute/exec-privatedevices-yes-capability-mknod.service +@@ -3,5 +3,6 @@ Description=Test CAP_MKNOD capability for PrivateDevices=yes + + [Service] + PrivateDevices=yes +-ExecStart=/bin/sh -x -c '! capsh --print | grep cap_mknod' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_mknod' + Type=oneshot +diff --git a/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service +index cebc493a7a..a246f950c1 100644 +--- a/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service ++++ b/test/test-execute/exec-privatedevices-yes-capability-sys-rawio.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_RAWIO capability for PrivateDevices=yes + + [Service] + PrivateDevices=yes +-ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_rawio' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_rawio' + Type=oneshot +diff --git a/test/test-execute/exec-protectkernelmodules-no-capabilities.service b/test/test-execute/exec-protectkernelmodules-no-capabilities.service +index b2f2cd6b8a..8d7e2b52d4 100644 +--- a/test/test-execute/exec-protectkernelmodules-no-capabilities.service ++++ b/test/test-execute/exec-protectkernelmodules-no-capabilities.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_MODULE ProtectKernelModules=no + + [Service] + ProtectKernelModules=no +-ExecStart=/bin/sh -x -c 'capsh --print | grep cap_sys_module' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c 'capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module' + Type=oneshot +diff --git a/test/test-execute/exec-protectkernelmodules-yes-capabilities.service b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service +index 84bf39be56..fe2ae208dd 100644 +--- a/test/test-execute/exec-protectkernelmodules-yes-capabilities.service ++++ b/test/test-execute/exec-protectkernelmodules-yes-capabilities.service +@@ -3,5 +3,6 @@ Description=Test CAP_SYS_MODULE for ProtectKernelModules=yes + + [Service] + ProtectKernelModules=yes +-ExecStart=/bin/sh -x -c '! capsh --print | grep cap_sys_module' ++# sed: remove dropped capabilities (cap_xxx-[epi]) from the output ++ExecStart=/bin/sh -x -c '! capsh --print | sed -r "s/[^ ]+?\-[epi]+//g" | grep cap_sys_module' + Type=oneshot +-- +2.23.0 + diff --git a/backport-udev-make-algorithm-that-selects-highest-priority-de.patch b/backport-udev-make-algorithm-that-selects-highest-priority-de.patch new file mode 100644 index 0000000000000000000000000000000000000000..139d3e3a373c9b93f390c6985b9f603cab32e8c5 --- /dev/null +++ b/backport-udev-make-algorithm-that-selects-highest-priority-de.patch @@ -0,0 +1,174 @@ +From 30f6dce62cb3a738b20253f2192270607c31b55b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Sekleta=CC=81r?= +Date: Fri, 23 Oct 2020 16:30:23 +0200 +Subject: [PATCH] udev: make algorithm that selects highest priority devlink + less susceptible to race conditions + +Previously it was very likely, when multiple contenders for the symlink +appear in parallel, that algorithm would select wrong symlink (i.e. one +with lower-priority). + +Now the algorithm is much more defensive and when we detect change in +set of contenders for the symlink we reevaluate the selection. Same +happens when new symlink replaces already existing symlink that points +to different device node. +--- + src/udev/udev-event.c | 7 ++++ + src/udev/udev-node.c | 75 ++++++++++++++++++++++++++++++++++--------- + 2 files changed, 67 insertions(+), 15 deletions(-) + +diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c +index ae78aef..1a8becb 100644 +--- a/src/udev/udev-event.c ++++ b/src/udev/udev-event.c +@@ -1017,6 +1017,13 @@ int udev_event_execute_rules(UdevEvent *event, + if (r < 0) + return log_device_debug_errno(dev, r, "Failed to update database under /run/udev/data/: %m"); + ++ /* Yes, we run update_devnode() twice, because in the first invocation, that is before update of udev database, ++ * it could happen that two contenders are replacing each other's symlink. Hence we run it again to make sure ++ * symlinks point to devices that claim them with the highest priority. */ ++ r = update_devnode(event); ++ if (r < 0) ++ return r; ++ + device_set_is_initialized(dev); + + event->dev_db_clone = sd_device_unref(event->dev_db_clone); +diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c +index ce95e20..2694185 100644 +--- a/src/udev/udev-node.c ++++ b/src/udev/udev-node.c +@@ -22,12 +22,15 @@ + #include "path-util.h" + #include "selinux-util.h" + #include "smack-util.h" ++#include "stat-util.h" + #include "stdio-util.h" + #include "string-util.h" + #include "strxcpyx.h" + #include "udev-node.h" + #include "user-util.h" + ++#define LINK_UPDATE_MAX_RETRIES 128 ++ + static int node_symlink(sd_device *dev, const char *node, const char *slink) { + _cleanup_free_ char *slink_dirname = NULL, *target = NULL; + const char *id_filename, *slink_tmp; +@@ -101,7 +104,9 @@ static int node_symlink(sd_device *dev, const char *node, const char *slink) { + if (rename(slink_tmp, slink) < 0) { + r = log_device_error_errno(dev, errno, "Failed to rename '%s' to '%s': %m", slink_tmp, slink); + (void) unlink(slink_tmp); +- } ++ } else ++ /* Tell caller that we replaced already existing symlink. */ ++ r = 1; + + return r; + } +@@ -194,7 +199,7 @@ static int link_update(sd_device *dev, const char *slink, bool add) { + _cleanup_free_ char *target = NULL, *filename = NULL, *dirname = NULL; + char name_enc[PATH_MAX]; + const char *id_filename; +- int r; ++ int i, r, retries; + + assert(dev); + assert(slink); +@@ -214,14 +219,6 @@ static int link_update(sd_device *dev, const char *slink, bool add) { + if (!add && unlink(filename) == 0) + (void) rmdir(dirname); + +- r = link_find_prioritized(dev, add, dirname, &target); +- if (r < 0) { +- log_device_debug(dev, "No reference left, removing '%s'", slink); +- if (unlink(slink) == 0) +- (void) rmdir_parents(slink, "/"); +- } else +- (void) node_symlink(dev, target, slink); +- + if (add) + do { + _cleanup_close_ int fd = -1; +@@ -234,7 +231,49 @@ static int link_update(sd_device *dev, const char *slink, bool add) { + r = -errno; + } while (r == -ENOENT); + +- return r; ++ /* If the database entry is not written yet we will just do one iteration and possibly wrong symlink ++ * will be fixed in the second invocation. */ ++ retries = sd_device_get_is_initialized(dev) > 0 ? LINK_UPDATE_MAX_RETRIES : 1; ++ ++ for (i = 0; i < retries; i++) { ++ struct stat st1 = {}, st2 = {}; ++ ++ r = stat(dirname, &st1); ++ if (r < 0 && errno != ENOENT) ++ return -errno; ++ ++ r = link_find_prioritized(dev, add, dirname, &target); ++ if (r == -ENOENT) { ++ log_device_debug(dev, "No reference left, removing '%s'", slink); ++ if (unlink(slink) == 0) ++ (void) rmdir_parents(slink, "/"); ++ ++ break; ++ } else if (r < 0) ++ return log_device_error_errno(dev, r, "Failed to determine highest priority symlink: %m"); ++ ++ r = node_symlink(dev, target, slink); ++ if (r < 0) { ++ (void) unlink(filename); ++ break; ++ } else if (r == 1) ++ /* We have replaced already existing symlink, possibly there is some other device trying ++ * to claim the same symlink. Let's do one more iteration to give us a chance to fix ++ * the error if other device actually claims the symlink with higher priority. */ ++ continue; ++ ++ /* Skip the second stat() if the first failed, stat_inode_unmodified() would return false regardless. */ ++ if ((st1.st_mode & S_IFMT) != 0) { ++ r = stat(dirname, &st2); ++ if (r < 0 && errno != ENOENT) ++ return -errno; ++ ++ if (stat_inode_unmodified(&st1, &st2)) ++ break; ++ } ++ } ++ ++ return i < LINK_UPDATE_MAX_RETRIES ? 0 : -ELOOP; + } + + int udev_node_update_old_links(sd_device *dev, sd_device *dev_old) { +@@ -442,8 +481,11 @@ int udev_node_add(sd_device *dev, bool apply, + (void) node_symlink(dev, devnode, filename); + + /* create/update symlinks, add symlinks to name index */ +- FOREACH_DEVICE_DEVLINK(dev, devlink) +- (void) link_update(dev, devlink, true); ++ FOREACH_DEVICE_DEVLINK(dev, devlink) { ++ r = link_update(dev, devlink, true); ++ if (r < 0) ++ log_device_info_errno(dev, r, "Failed to update device symlinks: %m"); ++ } + + return 0; + } +@@ -456,8 +498,11 @@ int udev_node_remove(sd_device *dev) { + assert(dev); + + /* remove/update symlinks, remove symlinks from name index */ +- FOREACH_DEVICE_DEVLINK(dev, devlink) +- (void) link_update(dev, devlink, false); ++ FOREACH_DEVICE_DEVLINK(dev, devlink) { ++ r = link_update(dev, devlink, false); ++ if (r < 0) ++ log_device_info_errno(dev, r, "Failed to update device symlinks: %m"); ++ } + + r = xsprintf_dev_num_path_from_sd_device(dev, &filename); + if (r < 0) +-- +2.23.0 + diff --git a/backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch b/backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch new file mode 100644 index 0000000000000000000000000000000000000000..518e8704f1c0d67ad919b2dae9467563bdb1a38b --- /dev/null +++ b/backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch @@ -0,0 +1,104 @@ +From f257a8fc13b2a617d845132eb61aefde47921198 Mon Sep 17 00:00:00 2001 +From: gaoyi +Date: Fri, 19 Mar 2021 15:16:56 +0800 +Subject: [PATCH] udevd: don't kill worker in manager_kill_workers when it's + running + +If worker is running, kill worker may lead uevent unprocessed. +--- + src/udev/udevd.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +diff --git a/src/udev/udevd.c b/src/udev/udevd.c +index cb51230..215f020 100644 +--- a/src/udev/udevd.c ++++ b/src/udev/udevd.c +@@ -134,6 +134,7 @@ enum worker_state { + WORKER_RUNNING, + WORKER_IDLE, + WORKER_KILLED, ++ WORKER_KILLING, + }; + + struct worker { +@@ -654,7 +655,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) { + return 0; + } + +-static void manager_kill_workers(Manager *manager) { ++static void manager_kill_workers(Manager *manager, bool force) { + struct worker *worker; + Iterator i; + +@@ -664,6 +665,11 @@ static void manager_kill_workers(Manager *manager) { + if (worker->state == WORKER_KILLED) + continue; + ++ if (worker->state == WORKER_RUNNING && !force) { ++ worker->state = WORKER_KILLING; ++ continue; ++ } ++ + worker->state = WORKER_KILLED; + (void) kill(worker->pid, SIGTERM); + } +@@ -810,7 +816,7 @@ static void manager_exit(Manager *manager) { + + /* discard queued events and kill workers */ + event_queue_cleanup(manager, EVENT_QUEUED); +- manager_kill_workers(manager); ++ manager_kill_workers(manager, true); + + assert_se(sd_event_now(manager->event, CLOCK_MONOTONIC, &usec) >= 0); + +@@ -829,7 +835,7 @@ static void manager_reload(Manager *manager) { + "RELOADING=1\n" + "STATUS=Flushing configuration..."); + +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + manager->rules = udev_rules_free(manager->rules); + udev_builtin_exit(); + +@@ -844,7 +850,7 @@ static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userda + assert(manager); + + log_debug("Cleanup idle workers"); +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + + return 1; + } +@@ -966,7 +972,10 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat + continue; + } + +- if (worker->state != WORKER_KILLED) ++ if (worker->state == WORKER_KILLING) { ++ worker->state = WORKER_KILLED; ++ (void) kill(worker->pid, SIGTERM); ++ } else if (worker->state != WORKER_KILLED) + worker->state = WORKER_IDLE; + + /* worker returned */ +@@ -1012,7 +1021,7 @@ static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, co + log_debug("Received udev control message (SET_LOG_LEVEL), setting log_priority=%i", value->intval); + log_set_max_level_realm(LOG_REALM_UDEV, value->intval); + log_set_max_level_realm(LOG_REALM_SYSTEMD, value->intval); +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + break; + case UDEV_CTRL_STOP_EXEC_QUEUE: + log_debug("Received udev control message (STOP_EXEC_QUEUE)"); +@@ -1077,7 +1086,7 @@ static int on_ctrl_msg(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, co + } + + key = val = NULL; +- manager_kill_workers(manager); ++ manager_kill_workers(manager, false); + break; + } + case UDEV_CTRL_SET_CHILDREN_MAX: +-- +1.8.3.1 + diff --git a/backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch b/backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch new file mode 100644 index 0000000000000000000000000000000000000000..72db99fca041e8ab29b21a37a443fc76185644b5 --- /dev/null +++ b/backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch @@ -0,0 +1,30 @@ +From 9fd32ff7d363945fbf8fdae0128702b995127558 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Thu, 5 Mar 2020 07:11:09 +0100 +Subject: [PATCH] units: restore RemainAfterExit=yes in + systemd-vconsole-setup.service + +This reverts the second part of 8125e8d38e3aa099c7dce8b0161997b8842aebdc. +The first part was reverted in 750e550eba362096d56a35104c6a32631aa67b8e. +The problem starts when s-v-s.s is pulled in by something that is then pulled +in by sysinit.target. Every time a unit is started, systemd recursively checks +all dependencies, and since sysinit.target is pull in by almost anything, we'll +start s-v-s.s over and over. In particular, plymouth-start.service currently +has Wants=s-v-s.s and After=s-v-s.s. +--- + units/systemd-vconsole-setup.service.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in +index f4178f495a..9042521c9d 100644 +--- a/units/systemd-vconsole-setup.service.in ++++ b/units/systemd-vconsole-setup.service.in +@@ -16,4 +16,5 @@ ConditionPathExists=/dev/tty0 + + [Service] + Type=oneshot ++RemainAfterExit=yes + ExecStart=@rootlibexecdir@/systemd-vconsole-setup +-- +2.23.0 + diff --git a/core-bugfix-call-malloc_trim-to-return-memory-to-OS-immediately.patch b/core-bugfix-call-malloc_trim-to-return-memory-to-OS-immediately.patch new file mode 100644 index 0000000000000000000000000000000000000000..c9a66d93967a5e3eb91971146a77cc2860afab65 --- /dev/null +++ b/core-bugfix-call-malloc_trim-to-return-memory-to-OS-immediately.patch @@ -0,0 +1,67 @@ +From 95100aa8fa3182f3b066bdc5927b0a78c37550aa Mon Sep 17 00:00:00 2001 +From: huangkaibin +Date: Mon, 23 Jul 2018 17:58:18 +0800 +Subject: [PATCH] systemd-udevd: Call malloc_trim to return memory to OS + immediately in forked children. + +hen there are many events from kernel, memory used to store these events(in event_list) +will be large, may be up to 100M. The forked child process will have a copy of these events and +release them using free. But since glibc will release memory to OS immediately, and if this child process +is stuck due I/O waiting(in D state), these memory will never be released until it is recoveried from D-state. +When there are so many such child processes, it will eat up much memory from system. +This patch fix this problem by invoking glibc's malloc_trim to release memory immediately when the child is forked. +--- + meson.build | 6 ++++++ + src/udev/udevd.c | 12 ++++++++++++ + 2 files changed, 18 insertions(+) + +diff --git a/meson.build b/meson.build +index c14540a..5ee2fa7 100644 +--- a/meson.build ++++ b/meson.build +@@ -518,6 +518,12 @@ else + conf.set10('HAVE_GETRANDOM', have) + endif + ++if cc.has_function('malloc_trim', prefix : '''#include ''') ++ conf.set10('HAVE_MALLOC_TRIM', true) ++else ++ conf.set10('HAVE_MALLOC_TRIM', false) ++endif ++ + ##################################################################### + + sed = find_program('sed') +diff --git a/src/udev/udevd.c b/src/udev/udevd.c +index c1119c3..62f1c44 100644 +--- a/src/udev/udevd.c ++++ b/src/udev/udevd.c +@@ -27,6 +27,9 @@ + #include + #include + #include ++#ifdef HAVE_MALLOC_TRIM ++#include ++#endif + + #include "sd-daemon.h" + #include "sd-event.h" +@@ -233,6 +236,15 @@ static void worker_spawn(Manager *manager, struct event *event) { + + manager->event = sd_event_unref(manager->event); + ++#ifdef HAVE_MALLOC_TRIM ++ /* unused memory inherits from parent has been freed, but it will ++ * not release to OS immediately. We do the optimization by invoking ++ * glibc's malloc_trim to force these unused memory to return to OS immediately. ++ * Otherwise when there are many forked process, it will eat up system's memory, ++ * and will cause OOM problem. ++ */ ++ malloc_trim(0); ++#endif + sigfillset(&mask); + fd_signal = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC); + if (fd_signal < 0) { +-- +1.8.3.1 + diff --git a/disable-systemd-timesyncd-networkd-resolved-by-defau.patch b/disable-systemd-timesyncd-networkd-resolved-by-defau.patch new file mode 100644 index 0000000000000000000000000000000000000000..18e1f491ed519008880910f0fa36e34385acc2ee --- /dev/null +++ b/disable-systemd-timesyncd-networkd-resolved-by-defau.patch @@ -0,0 +1,33 @@ +From 8324f588b88566e077aae9b5814a4ee721f8368c Mon Sep 17 00:00:00 2001 +From: licunlong +Date: Wed, 1 Dec 2021 17:04:40 +0800 +Subject: [PATCH] disable systemd-{timesyncd, networkd, resolved} by default + +--- + presets/90-systemd.preset | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/presets/90-systemd.preset b/presets/90-systemd.preset +index 11960e5..b16164a 100644 +--- a/presets/90-systemd.preset ++++ b/presets/90-systemd.preset +@@ -15,9 +15,6 @@ enable remote-cryptsetup.target + enable machines.target + + enable getty@.service +-enable systemd-timesyncd.service +-enable systemd-networkd.service +-enable systemd-resolved.service + + disable console-getty.service + disable debug-shell.service +@@ -34,3 +31,6 @@ disable syslog.socket + disable systemd-journal-gatewayd.* + disable systemd-journal-remote.* + disable systemd-journal-upload.* ++disable systemd-timesyncd.service ++disable systemd-networkd.service ++disable systemd-resolved.service +-- +2.23.0 + diff --git a/0016-fix-capsh-drop-but-ping-success.patch b/fix-capsh-drop-but-ping-success.patch similarity index 89% rename from 0016-fix-capsh-drop-but-ping-success.patch rename to fix-capsh-drop-but-ping-success.patch index eb82ea43707ed6cd23083aaae6272d37314e487f..b112369900750f67226fc8e0e4d00164069a3254 100644 --- a/0016-fix-capsh-drop-but-ping-success.patch +++ b/fix-capsh-drop-but-ping-success.patch @@ -18,12 +18,12 @@ index 41bd1f9..4d9bef8 100644 @@ -36,7 +36,7 @@ net.ipv4.conf.all.promote_secondaries = 1 # #define GID_T_MAX (((gid_t)~0U) >> 1) # That's not so bad because values between 2^31 and 2^32-1 are reserved on - # systemd-based systems anyway: https://systemd.io/UIDS-GIDS#summary + # systemd-based systems anyway: https://systemd.io/UIDS-GIDS.html#summary --net.ipv4.ping_group_range = 0 2147483647 +net.ipv4.ping_group_range = 1 0 # Fair Queue CoDel packet scheduler to fight bufferbloat - -net.core.default_qdisc = fq_codel + net.core.default_qdisc = fq_codel -- 1.8.3.1 diff --git a/set-kernel-core_pipe_limit-to-16.patch b/set-kernel-core_pipe_limit-to-16.patch new file mode 100644 index 0000000000000000000000000000000000000000..e2415049575bac09632e581a957aaa8e610c953f --- /dev/null +++ b/set-kernel-core_pipe_limit-to-16.patch @@ -0,0 +1,33 @@ +From 283ff70372cddb8b06ca3b2c5e7b8287f81207a9 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Fri, 30 Jul 2021 12:38:27 +0800 +Subject: [PATCH] set kernel.core_pipe_limit=16 + +https://github.com/poettering/systemd/commit/8444f245b56d085cdcfa788e9b9c7799fc58a46b + +--- + sysctl.d/50-coredump.conf.in | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/sysctl.d/50-coredump.conf.in b/sysctl.d/50-coredump.conf.in +index 47bf847..327863d 100644 +--- a/sysctl.d/50-coredump.conf.in ++++ b/sysctl.d/50-coredump.conf.in +@@ -10,3 +10,14 @@ + # setting below. + + kernel.core_pattern=|@rootlibexecdir@/systemd-coredump %P %u %g %s %t %c %h ++ ++# Allow that 16 coredumps are dispatched in parallel by the kernel. We want to ++# be able to collect process metadata from /proc/%P/ while processing ++# coredumps, and thus need to make sure the crashed processes are not reaped ++# until we finished collecting what we need. The kernel default for this sysctl ++# is "0" which means the kernel doesn't wait for userspace processes to finish ++# processing before reaping the crashed processes — by setting this higher the ++# kernel will delay reaping until we are done, but only for the specified ++# number of crashes in parallel. The value of 16 is chosen to match ++# systemd-coredump.socket's MaxConnections= value. ++kernel.core_pipe_limit=16 +-- +2.27.0 + diff --git a/systemd-249.tar.gz b/systemd-243.tar.gz similarity index 47% rename from systemd-249.tar.gz rename to systemd-243.tar.gz index 7d0d938cbff08c53ec81b1068eff3afb5d76da0d..9fab5204916001a54480524525e74ecc103caea9 100644 Binary files a/systemd-249.tar.gz and b/systemd-243.tar.gz differ diff --git a/0015-systemd-change-time-log-level.patch b/systemd-change-time-log-level.patch similarity index 100% rename from 0015-systemd-change-time-log-level.patch rename to systemd-change-time-log-level.patch diff --git a/systemd-core-Close-and-free-dbus-when-bus-authentica.patch b/systemd-core-Close-and-free-dbus-when-bus-authentica.patch new file mode 100644 index 0000000000000000000000000000000000000000..114f5413a70fdad0afb793d6b2c156557ace87aa --- /dev/null +++ b/systemd-core-Close-and-free-dbus-when-bus-authentica.patch @@ -0,0 +1,40 @@ +From 1245ae05c6e2ca7a2af055f9c44f19a0db2971a5 Mon Sep 17 00:00:00 2001 +From: yangbin +Date: Thu, 15 Aug 2019 15:24:03 +0800 +Subject: [PATCH 3/3] systemd-core: Close and free dbus when bus authenticating + timedout + +1. when timedout happened on authenticating a private dbus(can be established by systemctl command), +this dbus will never be freed and closed, and will left on systemd permanently even through the client +(for example, systemctl command) has closed the connection. This is because when timedout happend, +the event and also the timer to watch dbus actions is disabled by sd_event_source_set_enabled +from source_dispatch function, and systemd can do nothing on it since this dbus will not be activated again. +2. If a private dbus staying on authenticating state, and when systemd sends a signal message, it will also +add this message to the message write queue of this bus and will never send it out because the dbus is not in running. +systemd does this for it believe that the bus will change from authenticating to running sometime, but actually it will not. +3. When many private dbuses are left as authenticating and many signal messages are sent from dbus, it will eat up our memory +to hold these dbuses and messages, and memory usage of systemd will grow very fast. +4. This patch fix this problem by closing and freeing the dbus when authenticating timedout. +--- + src/libsystemd/sd-bus/sd-bus.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 05cb4c3..65cf449 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -2946,6 +2946,11 @@ static int bus_process_internal(sd_bus *bus, bool hint_priority, int64_t priorit + if (IN_SET(r, -ENOTCONN, -ECONNRESET, -EPIPE, -ESHUTDOWN)) { + bus_enter_closing(bus); + r = 1; ++ } else if(r == -ETIMEDOUT && !bus->is_system) { ++ /*close dbus directly when timedout happened and it is a private dbus*/ ++ log_info("Private bus is closed due authentication timedout."); ++ bus_enter_closing(bus); ++ r = 1; + } else if (r < 0) + return r; + +-- +2.17.1 + diff --git a/systemd.spec b/systemd.spec index 53c8222df2eae40e3b8b8bf241c4faada78f916a..2f51660553f88072c05acafec06ef5ade821f20a 100644 --- a/systemd.spec +++ b/systemd.spec @@ -13,21 +13,19 @@ %global efi_arch x64 %endif -%ifarch %{ix86} x86_64 aarch64 -%global have_gnu_efi 1 -%endif - Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd -Version: 249 -Release: 1 +Version: 243 +Release: 52 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager Source0: https://github.com/systemd/systemd/archive/v%{version}/%{name}-%{version}.tar.gz Source3: purge-nobody-user + Source4: yum-protect-systemd.conf + Source5: inittab Source6: sysctl.conf.README Source7: systemd-journal-remote.xml @@ -37,32 +35,128 @@ Source11: 20-grubby.install Source12: systemd-user Source13: rc.local -Source100: udev-40-openEuler.rules -Source101: udev-55-persistent-net-generator.rules -Source102: udev-56-net-sriov-names.rules -Source103: udev-61-openeuler-persistent-storage.rules -Source104: net-set-sriov-names -Source105: rule_generator.functions -Source106: write_net_rules -Source107: detect_virt - -Patch0001: 0001-update-rtc-with-system-clock-when-shutdown.patch -Patch0002: 0002-udev-add-actions-while-rename-netif-failed.patch -Patch0003: 0003-fix-two-VF-virtual-machines-have-same-mac-address.patch -Patch0004: 0004-logind-set-RemoveIPC-to-false-by-default.patch -Patch0005: 0005-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch -Patch0006: 0006-unit-don-t-add-Requires-for-tmp.mount.patch -Patch0007: 0007-rules-add-elevator-kernel-command-line-parameter.patch -Patch0008: 0008-rules-add-the-rule-that-adds-elevator-kernel-command.patch -Patch0009: 0009-units-add-Install-section-to-tmp.mount.patch -Patch0010: 0010-Make-systemd-udevd.service-start-after-systemd-remou.patch -Patch0011: 0011-udev-virsh-shutdown-vm.patch -Patch0012: 0012-sd-bus-properly-initialize-containers.patch -Patch0013: 0013-Revert-core-one-step-back-again-for-nspawn-we-actual.patch -Patch0014: 0014-journal-don-t-enable-systemd-journald-audit.socket-b.patch -Patch0015: 0015-systemd-change-time-log-level.patch -Patch0016: 0016-fix-capsh-drop-but-ping-success.patch -Patch0017: 0017-resolved-create-etc-resolv.conf-symlink-at-runtime.patch +Source100: udev-40-openEuler.rules +Source101: udev-55-persistent-net-generator.rules +Source102: udev-56-net-sriov-names.rules +Source103: udev-61-openeuler-persistent-storage.rules +Source104: net-set-sriov-names +Source105: rule_generator.functions +Source106: write_net_rules +Source107: detect_virt + +Patch0002: 0002-0001-udev-ignore-error-caused-by-device-disconnection.patch +Patch0003: 0003-0001-core-dont-check-error-parameter-of-get_name_owner_handler.patch +Patch0004: 0004-0001-core-dont-check-potentially-NULL-error.patch +Patch0005: 0005-0001-core-shorten-code-a-bit.patch +Patch0006: 0006-0001-core-no-need-to-eat-up-error.patch +Patch0007: 0007-0001-core-create-or-remove-unit-bus-name-slots-always-together.patch +Patch0008: 0008-0001-core-drop-initial-ListNames-bus-call-from-PID1.patch +Patch0009: 0009-1605-update-rtc-with-system-clock-when-shutdown.patch +Patch0010: 0010-1603-udev-add-actions-while-rename-netif-failed.patch +Patch0011: 0011-CVE-2020-1712-1.patch +Patch0012: 0012-CVE-2020-1712-2.patch +Patch0013: 0013-CVE-2020-1712-3.patch +Patch0014: 0014-CVE-2020-1712-4.patch +Patch0015: 0015-CVE-2020-1712-5.patch +Patch0016: 0016-sd-journal-close-journal-files-that-were-deleted-by-.patch +Patch0017: 0017-pid1-bump-DefaultTasksMax-to-80-of-the-kernel-pid.ma.patch +Patch0018: 0018-fix-two-VF-virtual-machines-have-same-mac-address.patch +Patch0019: 0019-logind-set-RemoveIPC-to-false-by-default.patch +Patch0020: 0020-rules-add-rule-for-naming-Dell-iDRAC-USB-Virtual-NIC.patch +Patch0021: 0021-unit-don-t-add-Requires-for-tmp.mount.patch +Patch0022: 0022-Revert-sysctl.d-switch-net.ipv4.conf.all.rp_filter-f.patch +Patch0023: 0023-rules-add-elevator-kernel-command-line-parameter.patch +Patch0024: 0024-rules-add-the-rule-that-adds-elevator-kernel-command.patch +Patch0025: 0025-units-add-Install-section-to-tmp.mount.patch +Patch0026: 0026-Make-systemd-udevd.service-start-after-systemd-remou.patch +Patch0027: 0027-udev-virsh-shutdown-vm.patch +Patch0028: 0028-fix-fd-leak-in-no-memory-condition.patch +Patch0029: 0029-dbus-execute-avoid-extra-strdup.patch +Patch0030: 0030-Avoid-tmp-being-mounted-as-tmpfs-without-the-user-s-.patch +Patch0031: 0031-sd-bus-properly-initialize-containers.patch +Patch0032: 0032-Revert-core-one-step-back-again-for-nspawn-we-actual.patch +Patch0033: 0033-journal-don-t-enable-systemd-journald-audit.socket-b.patch + +# The patch of 0026~0029 resolve the pid1 memory leaks +Patch0034: 0034-revert-pid1-drop-unit-caches-only-based-on-mtime.patch +Patch0035: 0035-revert-analyze-add-unit-files-to-dump-the-unit-fragm.patch +Patch0036: 0036-revert-pid1-use-a-cache-for-all-unit-aliases.patch +Patch0037: 0037-revert-shared-unit-file-add-a-function-to-validate-u.patch + +Patch0038: 0038-systemd-Fix-busctl-crash-on-aarch64-when-setting-out.patch +Patch0039: 0039-seccomp-more-comprehensive-protection-against-libsec.patch +Patch0040: 0040-network-fix-double-free-in-macsec_receive_channel_fr.patch +Patch0041: 0041-network-L2TP-fix-crash.patch + +Patch0042: 0042-systemctl-fix-memleak-caused-by-wrong-cleanup-func.patch +Patch0043: 0043-analyze-fix-minor-memleak.patch +Patch0044: 0044-network-add-one-more-section-validty-check.patch +Patch0045: 0045-network-use-fix-invalid-free-function.patch +Patch0046: 0046-network-fix-memleak.patch +Patch0047: 0047-network-Add-support-to-advertie-ipv6-route.patch +Patch0048: 0048-network-fix-invalid-cleanup-function.patch +Patch0049: 0049-network-fix-memleak-in-route_prefix_free.patch +Patch0050: 0050-sd-radv-fix-memleak.patch +Patch0051: 0051-sd-bus-invalidate-connection-when-Hello-fails.patch +Patch0052: 0052-shared-bus-util-Don-t-replace-exsting-strv.patch +Patch0053: 0053-systemctl-Add-with-dependencies-flag.patch +Patch0054: 0054-man-Document-systemctl-with-dependencies-switch.patch +Patch0055: 0055-core-expose-swap-priority-value-via-dbus-only-if-it-.patch +Patch0056: 0056-tree-wide-we-forgot-to-destroy-some-bus-errors.patch +Patch0057: 0057-sd-bus-fix-introspection-bug-in-signal-parameter-nam.patch +Patch0058: 0058-core-sync-SeccompParseFlags-between-dbus-execute-and.patch +Patch0059: 0059-core-swap-priority-can-be-negative.patch +Patch0060: 0060-core-no-need-to-initialize-swap-structure-fields-if-.patch +Patch0061: 0061-core-initialize-priority_set-when-parsing-swap-unit-.patch +Patch0062: 0062-core-use-unit-based-logging-instead-of-generic-loggi.patch +Patch0063: 0063-core-set-error-value-correctly.patch +Patch0064: 0064-core-fix-re-realization-of-cgroup-siblings.patch +Patch0065: 0065-basic-string-table-avoid-crash-when-table-is-sparse.patch +Patch0066: 0066-journal-fix-buffer-overrun-when-urlifying.patch + +Patch0071: 0071-backport-CVE-2018-21029-resolved-check-for-IP-in-certificate-when-using-DoT-.patch +Patch0072: 0072-backport-CVE-2018-21029-resolved-fix-connection-failures-with-TLS-1.3-and-Gn.patch +Patch0073: 0073-backport-CVE-2018-21029-resolved-require-at-least-version-3.6.0-of-GnuTLS-fo.patch +Patch0074: 0074-backport-CVE-2018-21029-Be-more-specific-in-resolved.conf-man-page-with-rega.patch +Patch0075: 0075-backport-CVE-2018-21029-Implement-SNI-when-using-DNS-over-TLS.patch +Patch0076: 0076-backport-CVE-2018-21029-resolve-error-handling-improvements.patch +Patch0077: 0077-backport-CVE-2018-21029-systemd-resolved-use-hostname-for-certificate-valida.patch +Patch0078: 0078-backport-varlink-make-userdata-pointer-inheritance-from-varli.patch +Patch0079: 0079-backport-udev-net_id-parse-_SUN-ACPI-index-as-a-signed-intege.patch +Patch0080: 0080-backport-udev-net_id-don-t-generate-slot-based-names-if-multi.patch + +Patch0081: 0081-journal-refresh-cached-credentials-of-stdout-streams.patch +Patch0082: 0082-journald-rework-end-of-line-marker-handling-to-use-a.patch +Patch0083: 0083-journald-rework-pid-change-handling.patch +Patch0084: 0084-journald-enforce-longer-line-length-limit-during-set.patch +Patch0085: backport-execute-Fix-migration-from-DynamicUser-yes-to-no.patch +Patch0086: 0086-fix-CVE-2021-33910.patch +Patch0087: backport-units-restore-RemainAfterExit-yes-in-systemd-vconsol.patch +Patch0088: backport-udevd-don-t-kill-worker-in-manager_kill_workers-when.patch +Patch0089: backport-stat-util-add-stat_inode_unmodified-helper-that-chec.patch +Patch0090: backport-basic-stat-util-make-mtime-check-stricter-and-use-en.patch +Patch0091: backport-udev-make-algorithm-that-selects-highest-priority-de.patch +Patch0092: backport-tentatively-ignore-FORCERENEW-command.patch +Patch0093: backport-network-add-missing-link-network-checks.patch +Patch0094: backport-core-fix-free-undefined-pointer-when-strdup-failed-i.patch +Patch0095: backport-test-adapt-to-the-new-capsh-format.patch +Patch0096: backport-sd-event-re-check-new-epoll-events-when-a-child-even.patch + +#openEuler +Patch9002: 1509-fix-journal-file-descriptors-leak-problems.patch +Patch9003: 1602-activation-service-must-be-restarted-when-reactivated.patch +Patch9004: 1605-systemd-core-fix-problem-of-dbus-service-can-not-be-started.patch +#Patch9004: 1612-serialize-pids-for-scope-when-not-started.patch +#Patch9005: 1615-do-not-finish-job-during-daemon-reload-in-unit_notify.patch +Patch9007: 1619-delay-to-restart-when-a-service-can-not-be-auto-restarted.patch +Patch9008: 1620-nop_job-of-a-unit-must-also-be-coldpluged-after-deserization.patch +#Patch9006: core-bugfix-call-malloc_trim-to-return-memory-to-OS-immediately.patch +#Patch9009: systemd-core-Close-and-free-dbus-when-bus-authentica.patch +Patch9009: systemd-change-time-log-level.patch +Patch9010: fix-capsh-drop-but-ping-success.patch +Patch9011: 0998-resolved-create-etc-resolv.conf-symlink-at-runtime.patch +Patch9012: set-kernel-core_pipe_limit-to-16.patch +Patch9013: disable-systemd-timesyncd-networkd-resolved-by-defau.patch BuildRequires: gcc, gcc-c++ BuildRequires: libcap-devel, libmount-devel, pam-devel, libselinux-devel @@ -74,16 +168,8 @@ BuildRequires: gnutls-devel, qrencode-devel, libmicrohttpd-devel, libxkbcommon- BuildRequires: iptables-devel, docbook-style-xsl, pkgconfig, libxslt, gperf BuildRequires: gawk, tree, hostname, git, meson >= 0.43, gettext, dbus >= 1.9.18 BuildRequires: python3-devel, python3-lxml, firewalld-filesystem, libseccomp-devel -BuildRequires: python3-jinja2 -%if 0%{?have_gnu_efi} BuildRequires: gnu-efi gnu-efi-devel -%endif - -%ifarch %{valgrind_arches} -BuildRequires: valgrind-devel -%endif -BuildRequires: util-linux -BuildRequires: chrpath +BuildRequires: valgrind-devel, util-linux Requires: %{name}-libs = %{version}-%{release} Requires(post): coreutils @@ -108,10 +194,8 @@ Provides: systemd-sysv = 206 Conflicts: initscripts < 9.56.1 Recommends: %{name}-help -Provides: %{name}-pam -Provides: %{name}-rpm-config -Obsoletes: %{name}-pam < 243 -Obsoletes: %{name}-rpm-config < 243 +Provides: %{name}-rpm-config = %{version}-%{release} +Obsoletes: %{name}-rpm-config <= %{version}-%{release} %description systemd is a system and service manager that runs as PID 1 and starts @@ -213,132 +297,6 @@ systemd-udev-compat is a set of udev rules which conflict with NetworkManager. If users choose to use the network-scripts to manager the network, the package can be used to do somethings when down or up nics or disk. -%package oomd -Summary: Systemd oomd feature -Requires: %{name} = %{version}-%{release} -License: LGPLv2+ -Requires(pre): /usr/bin/getent -Requires(post): systemd -Requires(preun): systemd -Requires(postun): systemd - -%description oomd -Systemd-oomd.service, systemd-oomd - A userspace out-of-memory (OOM) killer - -%package resolved -Summary: Network Name Resolution manager -License: LGPLv2+ -Requires: %{name}%{?_isa} = %{version}-%{release} -Requires(post): systemd -Requires(preun):systemd -Requires(postun):systemd -Requires(pre): /usr/bin/getent - -%description resolved -systemd-resolve is a system service that provides network name resolution to -local applications. It implements a caching and validating DNS/DNSSEC stub -resolver, as well as an LLMNR and MulticastDNS resolver and responder. - -%package nspawn -Summary: Spawn a command or OS in a light-weight container -License: LGPLv2+ -Requires: %{name}%{?_isa} = %{version}-%{release} - -%description nspawn -systemd-nspawn may be used to run a command or OS in a light-weight namespace -container. In many ways it is similar to chroot, but more powerful since it -fully virtualizes the file system hierarchy, as well as the process tree, the -various IPC subsystems and the host and domain name. - -%package networkd -Summary: System daemon that manages network configurations -Requires: %{name}%{?_isa} = %{version}-%{release} -License: LGPLv2+ -Requires(pre): /usr/bin/getent -Requires(post): systemd -Requires(preun):systemd -Requires(postun):systemd - -%description networkd -systemd-networkd is a system service that manages networks. It detects -and configures network devices as they appear, as well as creating virtual -network devices. - -%package timesyncd -Summary: Network Time Synchronization -License: LGPLv2+ -Requires: %{name}%{?_isa} = %{version}-%{release} -Requires(post): systemd -Requires(preun):systemd -Requires(postun):systemd -Requires(pre): /usr/bin/getent - -%description timesyncd -systemd-timesyncd is a system service that may be used to synchronize -the local system clock with a remote Network Time Protocol (NTP) server. -It also saves the local time to disk every time the clock has been -synchronized and uses this to possibly advance the system realtime clock -on subsequent reboots to ensure it (roughly) monotonically advances even -if the system lacks a battery-buffered RTC chip. - -%package pam -Summary: systemd PAM module -Requires: %{name} = %{version}-%{release} - -%description pam -Systemd PAM module registers the session with systemd-logind. - -%package coredump -Summary: Systemd tools for coredump management -License: LGPLv2+ -Requires: %{name} = %{version}-%{release} -%systemd_requires -Provides: systemd:%{_bindir}/coredumpctl - -%description coredump -Systemd tools to store and manage coredumps. - -This package contains systemd-coredump, coredumpctl. - -%package portable -Summary: Systemd tools for portable services -License: LGPLv2+ -Requires: %{name} = %{version}-%{release} -%systemd_requires - -%description portable -Systemd tools to manage portable services. The feature is still -considered experimental so the package might change or vanish. -Use at own risk. - -More information can be found online: - -http://0pointer.net/blog/walkthrough-for-portable-services.html -https://systemd.io/PORTABLE_SERVICES - -%package userdbd -Summary: Systemd tools for userdbd services -License: LGPLv2+ -Requires: %{name} = %{version}-%{release} -%systemd_requires - -%description userdbd -systemd-userdbd is a system service that multiplexes user/group lookups to -all local services that provide JSON user/group record definitions to the system. -Most of systemd-userdbd's functionality is accessible through the userdbctl(1) command. - -%package pstore -Summary: Systemd tools for pstore services -License: LGPLv2+ -Requires: %{name} = %{version}-%{release} -%systemd_requires - -%description pstore -systemd-pstore.service is a system service that archives the contents -of the Linux persistent storage filesystem, pstore, to other storage, -thus preserving the existing information contained in the pstore, -and clearing pstore storage for future error events. - %package_help %prep @@ -377,9 +335,7 @@ CONFIGURE_OPTS=( -Dlibiptc=true -Dlibcurl=true -Defi=true -%if 0%{?have_gnu_efi} -Dgnu-efi=true -%endif -Dtpm=true -Dhwdb=true -Dsysusers=true @@ -396,13 +352,7 @@ CONFIGURE_OPTS=( -Db_ndebug=false -Dman=true -Dversion-tag=v%{version}-%{release} - -Ddefault-hierarchy=legacy - -Ddefault-dnssec=no - # https://bugzilla.redhat.com/show_bug.cgi?id=1867830 - -Ddefault-mdns=no - -Ddefault-llmnr=resolve - -Doomd=true - -Dhtml=false + -Ddefault-hierarchy=legacy ) %meson "${CONFIGURE_OPTS[@]}" @@ -513,19 +463,6 @@ install -m 0755 %{SOURCE105} %{buildroot}/usr/lib/udev install -m 0755 %{SOURCE106} %{buildroot}/usr/lib/udev install -m 0755 %{SOURCE107} %{buildroot}/usr/lib/udev -# remove rpath info -for file in $(find %{buildroot}/ -executable -type f -exec file {} ';' | grep "\" | awk -F ':' '{print $1}') -do - if [ ! -u "$file" ]; then - if [ -w "$file" ]; then - chrpath -d $file - fi - fi -done -# add rpath path /usr/lib/systemd in ld.so.conf.d -mkdir -p %{buildroot}%{_sysconfdir}/ld.so.conf.d -echo "/usr/lib/systemd" > %{buildroot}%{_sysconfdir}/ld.so.conf.d/%{name}-%{_arch}.conf - %check %ninja_test -C %{_vpath_builddir} @@ -652,26 +589,21 @@ getent group kvm &>/dev/null || groupadd -r -g 36 kvm &>/dev/null || : getent group render &>/dev/null || groupadd -r render &>/dev/null || : getent group systemd-journal &>/dev/null || groupadd -r -g 190 systemd-journal 2>&1 || : -%pre coredump getent group systemd-coredump &>/dev/null || groupadd -r systemd-coredump 2>&1 || : getent passwd systemd-coredump &>/dev/null || useradd -r -l -g systemd-coredump -d / -s /sbin/nologin -c "systemd Core Dumper" systemd-coredump &>/dev/null || : -%pre networkd getent group systemd-network &>/dev/null || groupadd -r -g 192 systemd-network 2>&1 || : getent passwd systemd-network &>/dev/null || useradd -r -u 192 -l -g systemd-network -d / -s /sbin/nologin -c "systemd Network Management" systemd-network &>/dev/null || : -%pre resolved getent group systemd-resolve &>/dev/null || groupadd -r -g 193 systemd-resolve 2>&1 || : getent passwd systemd-resolve &>/dev/null || useradd -r -u 193 -l -g systemd-resolve -d / -s /sbin/nologin -c "systemd Resolver" systemd-resolve &>/dev/null || : %post -/sbin/ldconfig systemd-machine-id-setup &>/dev/null || : systemctl daemon-reexec &>/dev/null || : journalctl --update-catalog &>/dev/null || : systemd-tmpfiles --create &>/dev/null || : - # Make sure new journal files will be owned by the "systemd-journal" group machine_id=$(cat /etc/machine-id 2>/dev/null) chgrp systemd-journal /{run,var}/log/journal/{,${machine_id}} &>/dev/null || : @@ -686,13 +618,9 @@ setfacl -Rnm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal/ &>/de # before systemd due to rpm ordering problems: # https://bugzilla.redhat.com/show_bug.cgi?id=1647172 if [ $1 -eq 1 ] ; then - echo "DefaultTasksMax=80%" >> /etc/systemd/system.conf systemctl preset-all &>/dev/null || : fi -%postun -/sbin/ldconfig - %post libs %{?ldconfig} @@ -753,32 +681,20 @@ if [ $1 -eq 0 ] ; then serial-getty@.service \ console-getty.service \ debug-shell.service \ - >/dev/null || : -fi - - -%preun resolved -if [ $1 -eq 0 ] ; then - systemctl disable --quiet \ - systemd-resolved.service \ - >/dev/null || : -fi - -%preun networkd -if [ $1 -eq 0 ] ; then - systemctl disable --quiet \ systemd-networkd.service \ systemd-networkd-wait-online.service \ + systemd-resolved.service \ >/dev/null || : fi -%pre timesyncd +%pre udev getent group systemd-timesync &>/dev/null || groupadd -r systemd-timesync 2>&1 || : getent passwd systemd-timesync &>/dev/null || useradd -r -l -g systemd-timesync -d / -s /sbin/nologin -c "systemd Time Synchronization" systemd-timesync &>/dev/null || : -%post timesyncd +%post udev # Move old stuff around in /var/lib mv %{_localstatedir}/lib/random-seed %{_localstatedir}/lib/systemd/random-seed &>/dev/null +mv %{_localstatedir}/lib/backlight %{_localstatedir}/lib/systemd/backlight &>/dev/null if [ -L %{_localstatedir}/lib/systemd/timesync ]; then rm %{_localstatedir}/lib/systemd/timesync mv %{_localstatedir}/lib/private/systemd/timesync %{_localstatedir}/lib/systemd/timesync @@ -787,12 +703,6 @@ if [ -f %{_localstatedir}/lib/systemd/clock ] ; then mkdir -p %{_localstatedir}/lib/systemd/timesync mv %{_localstatedir}/lib/systemd/clock %{_localstatedir}/lib/systemd/timesync/. fi -# devided from post and preun stage of udev that included in macro udev_services -%systemd_post systemd-timesyncd.service - -%post udev -# Move old stuff around in /var/lib -mv %{_localstatedir}/lib/backlight %{_localstatedir}/lib/systemd/backlight &>/dev/null udevadm hwdb --update &>/dev/null %systemd_post %udev_services @@ -808,9 +718,6 @@ if [ -f "/usr/lib/udev/rules.d/50-udev-default.rules" ]; then fi %{_bindir}/systemctl daemon-reload &>/dev/null || : -%preun timesyncd -%systemd_preun systemd-timesyncd.service - %preun udev %systemd_preun %udev_services @@ -847,15 +754,6 @@ fi %systemd_postun_with_restart systemd-journal-upload.service %firewalld_reload -%preun portable -%systemd_preun systemd-portabled.service - -%preun userdbd -%systemd_preun systemd-userdbd.service systemd-userdbd.socket - -%preun pstore -%systemd_preun systemd-pstore.service - %files -f %{name}.lang %doc %{_pkgdocdir} %exclude %{_pkgdocdir}/LICENSE.* @@ -887,12 +785,14 @@ fi %ghost %attr(0700,root,root) %dir /var/lib/private %dir /var/lib/systemd %dir /var/lib/systemd/catalog +%ghost %dir /var/lib/systemd/coredump %ghost %dir /var/lib/systemd/linger %ghost /var/lib/systemd/catalog/database %ghost %dir /var/lib/private/systemd /usr/sbin/reboot /usr/sbin/halt /usr/sbin/telinit +/usr/sbin/resolvconf /usr/sbin/init /usr/sbin/runlevel /usr/sbin/poweroff @@ -912,9 +812,12 @@ fi /usr/share/bash-completion/completions/portablectl /usr/share/bash-completion/completions/systemd-run /usr/share/bash-completion/completions/systemd-cat +/usr/share/bash-completion/completions/resolvectl /usr/share/bash-completion/completions/coredumpctl /usr/share/bash-completion/completions/systemd-delta /usr/share/bash-completion/completions/systemd-cgls +/usr/share/bash-completion/completions/systemd-resolve +/usr/share/bash-completion/completions/networkctl /usr/share/bash-completion/completions/systemd-detect-virt /usr/share/bash-completion/completions/hostnamectl /usr/share/bash-completion/completions/systemd-cgtop @@ -929,12 +832,14 @@ fi /usr/share/zsh/site-functions/_journalctl /usr/share/zsh/site-functions/_systemd-delta /usr/share/zsh/site-functions/_systemd-tmpfiles +/usr/share/zsh/site-functions/_resolvectl /usr/share/zsh/site-functions/_systemctl /usr/share/zsh/site-functions/_systemd-run /usr/share/zsh/site-functions/_sd_outputmodes /usr/share/zsh/site-functions/_sd_unit_files /usr/share/zsh/site-functions/_sd_machines /usr/share/zsh/site-functions/_coredumpctl +/usr/share/zsh/site-functions/_networkctl /usr/share/zsh/site-functions/_timedatectl /usr/share/zsh/site-functions/_busctl /usr/share/zsh/site-functions/_systemd @@ -945,25 +850,33 @@ fi /usr/share/dbus-1/system-services/org.freedesktop.portable1.service /usr/share/dbus-1/system-services/org.freedesktop.login1.service /usr/share/dbus-1/system-services/org.freedesktop.locale1.service +/usr/share/dbus-1/system-services/org.freedesktop.resolve1.service /usr/share/dbus-1/system-services/org.freedesktop.hostname1.service +/usr/share/dbus-1/system-services/org.freedesktop.network1.service /usr/share/dbus-1/system-services/org.freedesktop.timedate1.service +/usr/share/dbus-1/system.d/org.freedesktop.resolve1.conf /usr/share/dbus-1/system.d/org.freedesktop.timedate1.conf /usr/share/dbus-1/system.d/org.freedesktop.hostname1.conf /usr/share/dbus-1/system.d/org.freedesktop.login1.conf /usr/share/dbus-1/system.d/org.freedesktop.systemd1.conf /usr/share/dbus-1/system.d/org.freedesktop.locale1.conf /usr/share/dbus-1/system.d/org.freedesktop.portable1.conf +/usr/share/dbus-1/system.d/org.freedesktop.network1.conf /usr/share/pkgconfig/systemd.pc /usr/share/pkgconfig/udev.pc /usr/share/polkit-1/actions/org.freedesktop.hostname1.policy /usr/share/polkit-1/actions/org.freedesktop.portable1.policy /usr/share/polkit-1/actions/org.freedesktop.timedate1.policy +/usr/share/polkit-1/actions/org.freedesktop.resolve1.policy /usr/share/polkit-1/actions/org.freedesktop.systemd1.policy /usr/share/polkit-1/actions/org.freedesktop.login1.policy +/usr/share/polkit-1/actions/org.freedesktop.network1.policy /usr/share/polkit-1/actions/org.freedesktop.locale1.policy +/usr/share/polkit-1/rules.d/systemd-networkd.rules /usr/bin/systemd-machine-id-setup /usr/bin/localectl /usr/bin/systemd-path +/usr/bin/portablectl /usr/bin/systemd-run /usr/bin/systemd-firstboot /usr/bin/systemd-escape @@ -971,9 +884,13 @@ fi /usr/bin/systemd-cat /usr/bin/systemd-inhibit /usr/bin/systemd-ask-password +/usr/bin/resolvectl /usr/bin/systemd-notify +/usr/bin/coredumpctl /usr/bin/systemd-delta /usr/bin/systemd-cgls +/usr/bin/systemd-resolve +/usr/bin/networkctl /usr/bin/systemd-stdio-bridge /usr/bin/systemd-detect-virt /usr/bin/systemd-socket-activate @@ -985,7 +902,6 @@ fi /usr/bin/systemctl /usr/bin/journalctl /usr/bin/systemd-analyze -/usr/bin/systemd-dissect /usr/bin/loginctl /usr/bin/timedatectl /usr/bin/systemd-sysusers @@ -997,11 +913,9 @@ fi %dir /usr/lib/sysctl.d %dir /usr/lib/systemd %dir /usr/lib/sysusers.d -/usr/lib/pam.d/systemd-user /usr/lib/sysusers.d/systemd.conf /usr/lib/sysusers.d/basic.conf /usr/lib/systemd/system/hwclock-save.service -/usr/lib/systemd/system/initrd-usr-fs.target /usr/lib/systemd/system/sysinit.target.wants/hwclock-save.service %{_systemddir}/systemd-update-done %{_systemddir}/systemd-update-utmp @@ -1013,8 +927,10 @@ fi %{_systemddir}/systemd-cgroups-agent %{_systemddir}/systemd-sulogin-shell %{_systemddir}/systemd-boot-check-no-failures +%dir %{_systemddir}/ntp-units.d %{_systemddir}/systemd-user-sessions %{_systemddir}/systemd-sysctl +%{_systemddir}/systemd-networkd-wait-online %{_systemddir}/systemd-socket-proxyd %{_systemddir}/systemd-ac-power %{_systemddir}/systemd-hostnamed @@ -1025,10 +941,12 @@ fi %{_systemddir}/systemd-journald %{_systemddir}/systemd-user-runtime-dir %{_systemddir}/systemd-logind +%{_systemddir}/systemd-networkd %dir %{_systemddir}/system-preset %dir %{_systemddir}/user-environment-generators %{_systemddir}/systemd-shutdown -%{_systemddir}/libsystemd-shared*.so +%{_systemddir}/systemd-portabled +%{_systemddir}/libsystemd-shared-243.so %{_systemddir}/systemd-reply-password %dir %{_systemddir}/system-generators %dir %{_systemddir}/system @@ -1036,18 +954,36 @@ fi %{_systemddir}/systemd-fsck %{_systemddir}/systemd-timedated %dir %{_systemddir}/user-generators +%dir %{_systemddir}/portable %{_systemddir}/systemd %dir %{_systemddir}/user-preset +%{_systemddir}/systemd-coredump +%{_systemddir}/resolv.conf +%{_systemddir}/systemd-dissect %{_systemddir}/systemd-veritysetup %{_systemddir}/systemd-network-generator +%{_systemddir}/systemd-time-wait-sync +%{_systemddir}/systemd-pstore +%{_systemddir}/systemd-resolved %{_systemddir}/systemd-binfmt %{_systemddir}/user-preset/90-systemd.preset +%dir %{_systemddir}/portable/profile +%dir %{_systemddir}/portable/profile/strict +%dir %{_systemddir}/portable/profile/nonetwork +%dir %{_systemddir}/portable/profile/trusted +%dir %{_systemddir}/portable/profile/default +%{_systemddir}/portable/profile/default/service.conf +%{_systemddir}/portable/profile/trusted/service.conf +%{_systemddir}/portable/profile/nonetwork/service.conf +%{_systemddir}/portable/profile/strict/service.conf %{_unitdir}/systemd-networkd.socket %{_unitdir}/systemd-binfmt.service %{_unitdir}/systemd-machine-id-commit.service %dir %{_unitdir}/basic.target.wants +%{_unitdir}/systemd-coredump.socket %{_unitdir}/ctrl-alt-del.target %{_unitdir}/systemd-tmpfiles-setup.service +%{_unitdir}/systemd-time-wait-sync.service %{_unitdir}/rpcbind.target %{_unitdir}/systemd-update-done.service %{_unitdir}/dev-hugepages.mount @@ -1061,6 +997,7 @@ fi %{_unitdir}/syslog.socket %{_unitdir}/systemd-localed.service %{_unitdir}/systemd-ask-password-console.service +%{_unitdir}/systemd-pstore.service %{_unitdir}/exit.target %{_unitdir}/systemd-ask-password-console.path %{_unitdir}/systemd-logind.service @@ -1110,6 +1047,7 @@ fi %{_unitdir}/systemd-update-utmp.service %dir %{_unitdir}/rescue.target.wants %{_unitdir}/bluetooth.target +%{_unitdir}/systemd-networkd-wait-online.service %{_unitdir}/systemd-ask-password-wall.path %{_unitdir}/emergency.service %{_unitdir}/network-pre.target @@ -1129,6 +1067,7 @@ fi %{_unitdir}/systemd-update-utmp-runlevel.service %{_unitdir}/network-online.target %{_unitdir}/systemd-initctl.socket +%{_unitdir}/systemd-coredump@.service %{_unitdir}/time-sync.target %{_unitdir}/runlevel5.target %{_unitdir}/paths.target @@ -1151,19 +1090,23 @@ fi %{_unitdir}/runlevel4.target %{_unitdir}/serial-getty@.service %{_unitdir}/sysinit.target +%{_unitdir}/dbus-org.freedesktop.portable1.service %{_unitdir}/rc-local.service %{_unitdir}/debug-shell.service %{_unitdir}/dev-mqueue.mount %{_unitdir}/emergency.target +%{_unitdir}/systemd-portabled.service %{_unitdir}/dbus-org.freedesktop.timedate1.service %{_unitdir}/runlevel1.target %dir %{_unitdir}/remote-fs.target.wants %{_unitdir}/dbus-org.freedesktop.hostname1.service +%{_unitdir}/systemd-networkd.service %{_unitdir}/runlevel0.target %{_unitdir}/user.slice %{_unitdir}/systemd-journal-catalog-update.service %{_unitdir}/local-fs-pre.target %{_unitdir}/systemd-halt.service +%{_unitdir}/systemd-resolved.service %{_unitdir}/container-getty@.service %{_unitdir}/slices.target %{_unitdir}/systemd-network-generator.service @@ -1218,18 +1161,11 @@ fi %{_unitdir}/multi-user.target.wants/systemd-ask-password-wall.path %{_unitdir}/multi-user.target.wants/systemd-update-utmp-runlevel.service %{_unitdir}/systemd-hostnamed.service.d/disable-privatedevices.conf +%{_unitdir}/sockets.target.wants/systemd-coredump.socket +%{_unitdir}/sockets.target.wants/systemd-journald-audit.socket %{_unitdir}/sockets.target.wants/systemd-journald-dev-log.socket %{_unitdir}/sockets.target.wants/systemd-journald.socket %{_unitdir}/sockets.target.wants/systemd-initctl.socket -%{_unitdir}/blockdev@.target -%{_unitdir}/sys-kernel-tracing.mount -%{_unitdir}/sysinit.target.wants/sys-kernel-tracing.mount -%{_unitdir}/system-systemd\x2dcryptsetup.slice -%{_unitdir}/systemd-journald-varlink@.socket -%{_unitdir}/systemd-journald@.service -%{_unitdir}/systemd-journald@.socket -%{_unitdir}/usb-gadget.target -%{_unitdir}/modprobe@.service %{_systemddir}/system-generators/systemd-fstab-generator %{_systemddir}/system-generators/systemd-sysv-generator %{_systemddir}/system-generators/systemd-rc-local-generator @@ -1258,9 +1194,7 @@ fi %{_userunitdir}/systemd-tmpfiles-clean.timer %{_userunitdir}/sockets.target %{_userunitdir}/smartcard.target -%{_systemddir}/network/80-wifi-adhoc.network -%{_systemddir}/network/80-wifi-ap.network.example -%{_systemddir}/network/80-wifi-station.network.example +%{_systemddir}/network/80-container-host0.network %{_systemddir}/catalog/systemd.fr.catalog %{_systemddir}/catalog/systemd.be.catalog %{_systemddir}/catalog/systemd.bg.catalog @@ -1273,15 +1207,14 @@ fi %{_systemddir}/catalog/systemd.zh_TW.catalog %{_systemddir}/catalog/systemd.ru.catalog %{_systemddir}/catalog/systemd.catalog -%{_systemddir}/systemd-xdg-autostart-condition -%{_systemddir}/user-generators/systemd-xdg-autostart-generator -%{_systemddir}/user/xdg-desktop-autostart.target +/usr/lib/sysctl.d/50-coredump.conf /usr/lib/sysctl.d/50-default.conf /usr/lib/sysctl.d/50-pid-max.conf /usr/lib/tmpfiles.d/systemd-tmp.conf /usr/lib/tmpfiles.d/systemd-nologin.conf /usr/lib/tmpfiles.d/systemd.conf /usr/lib/tmpfiles.d/journal-nocow.conf +/usr/lib/tmpfiles.d/portables.conf /usr/lib/tmpfiles.d/x11.conf /usr/lib/tmpfiles.d/tmp.conf /usr/lib/tmpfiles.d/home.conf @@ -1303,10 +1236,15 @@ fi %ghost %config(noreplace) /etc/machine-info %ghost %config(noreplace) /etc/machine-id %ghost %config(noreplace) /etc/hostname +%dir /etc/systemd/network %config(noreplace) /etc/systemd/user.conf +%config(noreplace) /etc/systemd/coredump.conf %dir /etc/systemd/user %config(noreplace) /etc/systemd/logind.conf +%config(noreplace) /etc/systemd/networkd.conf +%config(noreplace) /etc/systemd/resolved.conf %config(noreplace) /etc/systemd/journald.conf +%config(noreplace) /etc/systemd/pstore.conf %dir /etc/systemd/system %config(noreplace) /etc/systemd/system.conf %ghost %config(noreplace) /etc/X11/xorg.conf.d/00-keyboard.conf @@ -1320,44 +1258,18 @@ fi %config(noreplace) /etc/rc.d/init.d/README %dir /etc/xdg/systemd %config(noreplace) /etc/xdg/systemd/user -%{_sysconfdir}/ld.so.conf.d/%{name}-%{_arch}.conf +/usr/lib64/security/pam_systemd.so /usr/lib/rpm/macros.d/macros.systemd -/usr/bin/systemd-cryptenroll -/usr/bin/systemd-sysext -/usr/lib/modprobe.d/README -/usr/lib/sysctl.d/README -/usr/lib/systemd/system/first-boot-complete.target -/usr/lib/systemd/system/initrd-root-device.target.wants/remote-cryptsetup.target -/usr/lib/systemd/system/initrd-root-device.target.wants/remote-veritysetup.target -/usr/lib/systemd/system/remote-veritysetup.target -/usr/lib/systemd/system/sysinit.target.wants/veritysetup.target -/usr/lib/systemd/system/systemd-sysext.service -/usr/lib/systemd/system/veritysetup-pre.target -/usr/lib/systemd/system/veritysetup.target -/usr/lib/systemd/user/app.slice -/usr/lib/systemd/user/background.slice -/usr/lib/systemd/user/session.slice -/usr/lib/sysusers.d/README -/usr/lib/tmpfiles.d/README -/usr/lib/udev/dmi_memory_id -/usr/lib/udev/hwdb.d/20-dmi-id.hwdb -/usr/lib/udev/hwdb.d/60-autosuspend-fingerprint-reader.hwdb -/usr/lib/udev/hwdb.d/README -/usr/lib/udev/hwdb.d/60-seat.hwdb -/usr/lib/udev/hwdb.d/80-ieee1394-unit-function.hwdb -/usr/lib/udev/rules.d/81-net-dhcp.rules -/usr/lib/udev/rules.d/70-memory.rules -/usr/lib/udev/rules.d/README -/usr/share/bash-completion/completions/systemd-id128 -/usr/share/zsh/site-functions/_systemd-path - %files libs -%{_libdir}/libnss_systemd.so.2 -%{_libdir}/libnss_myhostname.so.2 -%{_libdir}/libsystemd.so.* -%{_libdir}/libudev.so.* +/usr/lib64/libnss_systemd.so.2 +/usr/lib64/libnss_resolve.so.2 +/usr/lib64/libnss_myhostname.so.2 +/usr/lib64/libsystemd.so.0 +/usr/lib64/libsystemd.so.0.27.0 +/usr/lib64/libudev.so.1 +/usr/lib64/libudev.so.1.6.15 %files devel /usr/share/man/man3/* @@ -1375,16 +1287,17 @@ fi /usr/include/systemd/sd-id128.h /usr/include/systemd/sd-bus.h /usr/include/systemd/sd-login.h -/usr/include/systemd/sd-path.h -%{_libdir}/libudev.so -%{_libdir}/libsystemd.so -%{_libdir}/pkgconfig/libsystemd.pc -%{_libdir}/pkgconfig/libudev.pc +/usr/lib64/libudev.so +/usr/lib64/libsystemd.so +/usr/lib64/pkgconfig/libsystemd.pc +/usr/lib64/pkgconfig/libudev.pc %files udev %ghost %dir /var/lib/systemd/backlight +%ghost %dir /var/lib/systemd/timesync %ghost %dir /var/lib/systemd/rfkill %ghost /var/lib/systemd/random-seed +%ghost /var/lib/systemd/timesync/clock /usr/sbin/udevadm /usr/share/bash-completion/completions/udevadm /usr/share/bash-completion/completions/bootctl @@ -1392,6 +1305,8 @@ fi /usr/share/zsh/site-functions/_bootctl /usr/share/zsh/site-functions/_udevadm /usr/share/zsh/site-functions/_kernel-install +/usr/share/dbus-1/system-services/org.freedesktop.timesync1.service +/usr/share/dbus-1/system.d/org.freedesktop.timesync1.conf /usr/bin/systemd-hwdb /usr/bin/udevadm /usr/bin/bootctl @@ -1400,6 +1315,8 @@ fi %dir /usr/lib/udev %dir /usr/lib/kernel %dir /usr/lib/modules-load.d +%dir %{_systemddir}/boot +%{_systemddir}/systemd-timesyncd %{_systemddir}/systemd-growfs %{_systemddir}/systemd-modules-load %dir %{_systemddir}/system-sleep @@ -1427,6 +1344,7 @@ fi %dir %{_unitdir}/systemd-udev-trigger.service.d %{_unitdir}/systemd-random-seed.service %{_unitdir}/systemd-quotacheck.service +%{_unitdir}/systemd-timesyncd.service %{_unitdir}/systemd-udevd-control.socket %{_unitdir}/hibernate.target %{_unitdir}/systemd-remount-fs.service @@ -1460,13 +1378,10 @@ fi %{_systemddir}/system-generators/systemd-cryptsetup-generator %{_systemddir}/system-generators/systemd-hibernate-resume-generator %{_systemddir}/system-generators/systemd-gpt-auto-generator -%if 0%{?have_gnu_efi} -%dir %{_systemddir}/boot +%{_systemddir}/ntp-units.d/80-systemd-timesync.list %dir %{_systemddir}/boot/efi %{_systemddir}/boot/efi/systemd-boot%{efi_arch}.efi %{_systemddir}/boot/efi/linux%{efi_arch}.efi.stub -%{_systemddir}/boot/efi/linux%{efi_arch}.elf.stub -%endif %{_systemddir}/network/99-default.link %dir /usr/lib/kernel/install.d /usr/lib/kernel/install.d/20-grubby.install @@ -1479,7 +1394,6 @@ fi /usr/lib/udev/cdrom_id /usr/lib/udev/mtd_probe /usr/lib/udev/scsi_id -/usr/lib/udev/fido_id %dir /usr/lib/udev/hwdb.d %{_udevhwdbdir}/20-bluetooth-vendor-product.hwdb %{_udevhwdbdir}/70-touchpad.hwdb @@ -1499,10 +1413,6 @@ fi %{_udevhwdbdir}/70-joystick.hwdb %{_udevhwdbdir}/60-sensor.hwdb %{_udevhwdbdir}/70-mouse.hwdb -%{_udevhwdbdir}/60-input-id.hwdb -%{_udevhwdbdir}/60-autosuspend-chromiumos.hwdb -%{_udevhwdbdir}/60-autosuspend.hwdb -%{_udevrulesdir}/60-autosuspend.rules %{_udevrulesdir}/40-openEuler.rules %{_udevrulesdir}/40-elevator.rules %{_udevrulesdir}/73-idrac.rules @@ -1534,12 +1444,12 @@ fi %{_udevrulesdir}/99-systemd.rules %{_udevrulesdir}/60-persistent-storage-tape.rules %{_udevrulesdir}/50-udev-default.rules -%{_udevrulesdir}/60-fido-id.rules /usr/lib/modprobe.d/systemd.conf %ghost %config(noreplace) /etc/vconsole.conf %dir /etc/udev %dir /etc/kernel %dir /etc/modules-load.d +%config(noreplace) /etc/systemd/timesyncd.conf %config(noreplace) /etc/systemd/sleep.conf %dir /etc/kernel/install.d %ghost /etc/udev/hwdb.bin @@ -1549,17 +1459,18 @@ fi %files container /usr/share/bash-completion/completions/machinectl +/usr/share/bash-completion/completions/systemd-nspawn /usr/share/zsh/site-functions/_machinectl +/usr/share/zsh/site-functions/_systemd-nspawn /usr/share/dbus-1/system-services/org.freedesktop.import1.service /usr/share/dbus-1/system-services/org.freedesktop.machine1.service -/usr/share/dbus-1/services/org.freedesktop.systemd1.service -/usr/share/dbus-1/system-services/org.freedesktop.systemd1.service /usr/share/dbus-1/system.d/org.freedesktop.import1.conf /usr/share/dbus-1/system.d/org.freedesktop.machine1.conf /usr/share/polkit-1/actions/org.freedesktop.import1.policy /usr/share/polkit-1/actions/org.freedesktop.machine1.policy -%{_libdir}/libnss_mymachines.so.2 +/usr/lib64/libnss_mymachines.so.2 /usr/bin/machinectl +/usr/bin/systemd-nspawn %{_systemddir}/systemd-import %{_systemddir}/systemd-machined %{_systemddir}/systemd-importd @@ -1574,9 +1485,12 @@ fi %{_unitdir}/machine.slice %{_unitdir}/machines.target %dir %{_unitdir}/machines.target.wants +%{_unitdir}/systemd-nspawn@.service %{_unitdir}/machines.target.wants/var-lib-machines.mount %{_unitdir}/remote-fs.target.wants/var-lib-machines.mount -%{_systemddir}/network/80-vm-vt.network +%{_systemddir}/network/80-container-vz.network +%{_systemddir}/network/80-container-ve.network +/usr/lib/tmpfiles.d/systemd-nspawn.conf %files journal-remote %ghost %dir /var/log/journal/remote @@ -1608,243 +1522,149 @@ fi /usr/lib/udev/net-set-sriov-names /usr/lib/udev/detect_virt -%files oomd -/etc/systemd/oomd.conf -/usr/bin/oomctl -/usr/lib/systemd/system/systemd-oomd.service -/usr/lib/systemd/system/dbus-org.freedesktop.oom1.service -/usr/lib/systemd/systemd-oomd -/usr/share/dbus-1/system-services/org.freedesktop.oom1.service -/usr/share/dbus-1/system.d/org.freedesktop.oom1.conf - %files help /usr/share/man/*/* %exclude /usr/share/man/man3/* -%files resolved -/usr/sbin/resolvconf -/usr/bin/resolvectl -/usr/share/bash-completion/completions/resolvectl -/usr/share/zsh/site-functions/_resolvectl -/usr/share/bash-completion/completions/systemd-resolve -/usr/share/dbus-1/system-services/org.freedesktop.resolve1.service -/usr/share/dbus-1/system.d/org.freedesktop.resolve1.conf -/usr/share/polkit-1/actions/org.freedesktop.resolve1.policy -/usr/bin/systemd-resolve -%{_systemddir}/resolv.conf -%{_systemddir}/systemd-resolved -%config(noreplace) /etc/systemd/resolved.conf -%{_libdir}/libnss_resolve.so.2 -%{_unitdir}/systemd-resolved.service - -%files nspawn -/usr/share/bash-completion/completions/systemd-nspawn -/usr/share/zsh/site-functions/_systemd-nspawn -/usr/bin/systemd-nspawn -%{_unitdir}/systemd-nspawn@.service -/usr/lib/tmpfiles.d/systemd-nspawn.conf - -%files networkd -/usr/share/bash-completion/completions/networkctl -/usr/share/zsh/site-functions/_networkctl -/usr/share/dbus-1/system-services/org.freedesktop.network1.service -/usr/share/dbus-1/system.d/org.freedesktop.network1.conf -/usr/share/polkit-1/actions/org.freedesktop.network1.policy -/usr/share/polkit-1/rules.d/systemd-networkd.rules -/usr/bin/networkctl -%{_systemddir}/systemd-networkd-wait-online -%{_systemddir}/systemd-networkd -%{_unitdir}/systemd-networkd.socket -%{_unitdir}/systemd-networkd-wait-online.service -%{_unitdir}/systemd-networkd.service -%{_systemddir}/network/80-container-host0.network -%dir /etc/systemd/network -%config(noreplace) /etc/systemd/networkd.conf -%{_systemddir}/network/80-container-vz.network -%{_systemddir}/network/80-container-ve.network - -%files timesyncd -%dir %{_systemddir}/ntp-units.d -%{_systemddir}/systemd-time-wait-sync -%{_unitdir}/systemd-time-wait-sync.service -%ghost %dir /var/lib/systemd/timesync -%ghost /var/lib/systemd/timesync/clock -/usr/share/dbus-1/system-services/org.freedesktop.timesync1.service -/usr/share/dbus-1/system.d/org.freedesktop.timesync1.conf -%{_systemddir}/systemd-timesyncd -%{_unitdir}/systemd-timesyncd.service -%{_systemddir}/ntp-units.d/80-systemd-timesync.list -%config(noreplace) /etc/systemd/timesyncd.conf - -%files pam -%{_libdir}/security/pam_systemd.so - -%files coredump -%defattr(-,root,root) -%{_bindir}/coredumpctl -%{_prefix}/lib/systemd/systemd-coredump -%{_unitdir}/systemd-coredump* -%{_unitdir}/sockets.target.wants/systemd-coredump.socket -%{_sysctldir}/50-coredump.conf -%config(noreplace) %{_sysconfdir}/systemd/coredump.conf -%dir %{_localstatedir}/lib/systemd/coredump - -%files portable -%defattr(-,root,root) -%{_bindir}/portablectl -%{_prefix}/lib/systemd/systemd-portabled -%{_prefix}/lib/systemd/portable -%{_unitdir}/systemd-portabled.service -%{_unitdir}/dbus-org.freedesktop.portable1.service -%{_tmpfilesdir}/portables.conf - -%files pstore -%defattr(-,root,root) -%config(noreplace) %{_sysconfdir}/systemd/pstore.conf -%{_prefix}/lib/systemd/systemd-pstore -%{_unitdir}/systemd-pstore.service -%{_tmpfilesdir}/systemd-pstore.conf - -%files userdbd -%defattr(-,root,root) -%{_bindir}/userdbctl -%{_prefix}/lib/systemd/systemd-userwork -%{_prefix}/lib/systemd/systemd-userdbd -%{_unitdir}/systemd-userdbd.service -%{_unitdir}/systemd-userdbd.socket - %changelog -* Wed Dec 8 2021 yangmingtai - 249-1 -- systemd update to v249 +* Tue Dec 27 2021 yangmingtai - 243-52 +- delete useless Provides and Obsoletes -* Thu Sep 16 2021 ExtinctFire - 248-13 -- core: fix free undefined pointer when strdup failed in the first loop - -* Mon Sep 6 2021 yangmingtai - 248-12 -- move postun to correct position - -* Sat Sep 4 2021 yangmingtai - 248-11 -- systemd delete rpath - -* Mon Aug 30 2021 yangmingtai - 248-10 -- enable some patches and delete unused patches - -* Thu Aug 26 2021 xujing - 248-9 -- enable some patches to fix bugs - -* Mon Aug 16 2021 yangmingtai - 248-8 -- udev: exec daemon-reload after installation - -* Thu Jun 03 2021 yangmingtai - 248-7 -- fix CVE-2021-33910 +* Tue Dec 21 2021 yangmingtai - 243-51 +- 22.03-LTS-NEXT systemd switch to 20.03-LTS-SP3 version -* Thu Jul 22 2021 shenyangyang - 248-6 -- change requires to openssl-libs as post scripts systemctl requires libssl.so.1.1 +* Fri Dec 3 2021 yangmingtai - 243-50 +- re-check new epoll events when a child event is queued -* Mon May 31 2021 hexiaowen - 248-5 -- fix typo +* Wed Dec 01 2021 licunlong - 243-49 +- disable systemd-{timesyncd, networkd, resolved} by default -* Wed May 19 2021 fangxiuning - 248-4 -- journald: enforce longer line length limit during "setup" phase of stream protocol +* Thu Sep 28 2021 shenyangyang - 243-48 +- adapt to the new capsh format for test -* Fri Apr 30 2021 hexiaowen - 248-3 -- delete unused rebase-patch +* Thu Sep 16 2021 ExtinctFire - 243-47 +- core: fix free undefined pointer when strdup failed in the first loop -* Fri Apr 30 2021 hexiaowen - 248-2 -- delete unused patches +* Thu Sep 9 2021 yangmingtai - 243-46 +- fix network coredump after install cloud-init -* Fri Apr 30 2021 hexiaowen - 248-1 -- Rebase to version 248 +* Mon Aug 16 2021 yangmingtai - 243-45 +- Type:CVE +- ID:CVE-2020-13529 +- SUG:NA +- DESC:fix CVE-2020-13529 -* Wed Mar 31 2021 fangxiuning - 246-15 +* Tue Aug 10 2021 yangmingtai - 243-44 - Type:bugfix - ID:NA - SUG:NA -- DESC:fix userdata double free +- DESC:udevd: exec daemon-reload after installation -* Wed Mar 3 2021 shenyangyang - 246-14 +* Tue Aug 03 2021 yangmingtai - 243-43 - Type:bugfix - ID:NA - SUG:NA -- DESC:fix Failed to migrate controller cgroups from *: Permission denied +- DESC:udevd: fix broken symbolic links when same link for different devices -* Sat Feb 27 2021 shenyangyang - 246-13 +* Mon Aug 02 2021 fangxiuning - 243-42 - Type:bugfix - ID:NA - SUG:NA -- DESC:xdg autostart Lower most info messages to debug level +- DESC:udevd: don't kill worker in manager_kill_worker when it's running + +* Mon Aug 02 2021 jiazhenyuan - 243-41 +- set kernel.core_pipe_limit=16 + +* Mon Jul 26 2021 extinctfire - 243-40 +- restore RemainAfterExit=yes in systemd-vconsole-setup.service + +* Thu Jul 22 2021 yangmingtai - 243-39 +- fix CVE-2021-33910 -* Sat Feb 27 2021 gaoyi - 246-12 +* Thu Jun 3 2021 extinctfire - 243-38 +- fix migration from DynamicUser=yes to no. + +* Mon May 31 2021 overweight - 243-37 +- fix journald: enforce longer line length limit during "setup" phase of stream protocol + +* Mon May 31 2021 overweight - 243-36 +- fix patches name and patches num + +* Thu May 27 2021 shenyangyang - 243-35 - Type:bugfix - ID:NA - SUG:NA -- DESC:just configure DefaultTasksMax when install +- DESC:change requires to openssl-libs as post scripts systemctl requires libssl.so.1.1 -* Tue Jan 26 2021 extinctfire - 246-11 +* Mon May 10 2021 shenyangyang - 243-34 - Type:bugfix - ID:NA - SUG:NA -- DESC:fix login timeout 2 minutes +- DESC:backport from upstream to solve the problem when devices claim the same slot -* Fri Dec 18 2020 overweight - 246-10 +* Fri Apr 02 2021 fangxiuning - 243-33 - Type:bugfix - ID:NA - SUG:NA -- DESC: fix 40-openEuler.rules for memory offline +- DESC:fix userdate double free -* Wed Dec 16 2020 shenyangyang - 246-9 -- Type:enhancement -- ID:NA +* Fri Jan 29 2021 overweight - 243-32 +- Type:cve +- ID:CVE-2018-21029 - SUG:NA -- DESC:do not create /var/log/journal on initial installation +- DESC:fix cve-2018-21029 -* Wed Nov 25 2020 shenyangyang - 246-8 -- Type:enhancement +* Fri Dec 18 2020 overweight - 243-31 +- Type:bugfix - ID:NA - SUG:NA -- DESC:don't enable systemd-journald-audit.socket by default +- DESC: fix 40-openEuler.rules for memory offline -* Thu Sep 17 2020 openEuler Buildteam - 246-7 +* Wed Dec 16 2020 shenyangyang - 243-30 - Type:enhancement - ID:NA - SUG:NA -- DESC:delete unneed patches and rebase to bded6f +- DESC:do not create /var/log/journal on initial installation -* Fri Sep 11 2020 openEuler Buildteam - 246-6 +* Mon Dec 14 2020 shenyangyang - 243-29 - Type:enhancement - ID:NA - SUG:NA -- DESC:delete unneed patches +- DESC:revert don't enable systemd-journald-audit.socket by default + that may cause reboot problem if update systemd with out dracut -f + from LTS-20.03 -* Wed Sep 9 2020 openEuler Buildteam - 246-5 +* Wed Nov 25 2020 shenyangyang - 243-28 - Type:enhancement - ID:NA - SUG:NA -- DESC:set default tasks max to 85% +- DESC:don't enable systemd-journald-audit.socket by default -* Wed Sep 9 2020 openEuler Buildteam - 246-4 +* Mon Nov 23 2020 openEuler Buildteam - 243-27 - Type:enhancement - ID:NA - SUG:NA -- DESC:fix error handling on readv +- DESC:add elevator= kernel command line parameter and don't enable bfq + by default -* Mon Aug 01 2020 openEuler Buildteam - 246-3 +* Tue Jul 7 2020 openEuler Buildteam - 243-26 - Type:enhancement - ID:NA - SUG:NA -- DESC:Update to real release 246 +- DESC:fix buffer overrun when urlifying -* Tue Jul 7 2020 openEuler Buildteam - 246-2 +* Thu Jun 18 2020 openEuler Buildteam - 243-25 - Type:enhancement - ID:NA - SUG:NA -- DESC:fix buffer overrun when urlifying. +- DESC:dbus commissioning enhancement -* Fri Jun 12 2020 openEuler Buildteam - 246-1 +* Thu May 28 2020 openEuler Buildteam - 243-24 - Type:enhancement - ID:NA - SUG:NA -- DESC:Update to release 246 +- DESC:fix double free in macsec_receive_channel_free() and + fix crash in network L2TP * Thu May 28 2020 openEuler Buildteam - 243-23 - Type:enhancement @@ -1893,7 +1713,7 @@ fi - Type:enhancement - ID:NA - SUG:NA -- DESC:add 1603-udev-add-actions-while-rename-netif-failed.patch +- DESC:add 0010-1603-udev-add-actions-while-rename-netif-failed.patch * Sat Feb 29 2020 openEuler Buildteam - 243-15 - Type:enhancement