Submitted By:            Douglas R. Reno <renodr at linuxfromscratch dot org>
Date:                    2020-12-02
Initial Package Version: 247
Origin:                  Upstream + PR #17809
Upstream Status:         Applied (and undergoing review)
Description:             Fixes a few regressions discovered in systemd-247.
                         The first regression causes segmentation faults when
                         shutting down or rebooting. This appears to crash
                         PID1, which will result in a kernel panic.
                         The next regression causes systems on networks that
                         have an IPv4 prefix length of 32 or higher to not be
                         able to get a route assigned when working over DHCP.
                         Note: This primarily impacts users of Comcast as an ISP.

diff -Naurp systemd-247.orig/src/core/scope.c systemd-247/src/core/scope.c
--- systemd-247.orig/src/core/scope.c	2020-11-26 12:00:50.000000000 -0600
+++ systemd-247/src/core/scope.c	2020-12-02 18:30:39.826650593 -0600
@@ -377,10 +377,6 @@ static int scope_start(Unit *u) {
                 return r;
         }
 
-        /* Now u->pids have been moved into the scope cgroup, it's not needed
-         * anymore. */
-        u->pids = set_free(u->pids);
-
         s->result = SCOPE_SUCCESS;
 
         scope_set_state(s, SCOPE_RUNNING);
@@ -388,7 +384,13 @@ static int scope_start(Unit *u) {
         /* Set the maximum runtime timeout. */
         scope_arm_timer(s, usec_add(UNIT(s)->active_enter_timestamp.monotonic, s->runtime_max_usec));
 
-        /* Start watching the PIDs currently in the scope */
+        /* On unified we use proper notifications, hence we can unwatch the PIDs
+         * we just attached to the scope. This can also be done on legacy as
+         * we're going to update the list of the processes we watch with the
+         * PIDs currently in the scope anyway. */
+        unit_unwatch_all_pids(u);
+
+        /* Start watching the PIDs currently in the scope (legacy hierarchy only) */
         (void) unit_enqueue_rewatch_pids(u);
         return 1;
 }
diff -Naurp systemd-247.orig/src/libsystemd/sd-event/sd-event.c systemd-247/src/libsystemd/sd-event/sd-event.c
--- systemd-247.orig/src/libsystemd/sd-event/sd-event.c	2020-11-26 12:00:50.000000000 -0600
+++ systemd-247/src/libsystemd/sd-event/sd-event.c	2020-12-02 18:28:32.268651998 -0600
@@ -3725,7 +3725,7 @@ _public_ int sd_event_run(sd_event *e, u
                 this_run = now(CLOCK_MONOTONIC);
 
                 l = u64log2(this_run - e->last_run);
-                assert(l < sizeof(e->delays));
+                assert(l < ELEMENTSOF(e->delays));
                 e->delays[l]++;
 
                 if (this_run - e->last_log >= 5*USEC_PER_SEC) {
diff -Naurp systemd-247.orig/src/network/networkd-address.c systemd-247/src/network/networkd-address.c
--- systemd-247.orig/src/network/networkd-address.c	2020-11-26 12:00:50.000000000 -0600
+++ systemd-247/src/network/networkd-address.c	2020-12-02 18:36:58.081646426 -0600
@@ -1863,10 +1863,12 @@ static int address_section_verify(Addres
                                          address->section->filename, address->section->line);
         }
 
-        if (address->family == AF_INET && in_addr_is_null(address->family, &address->in_addr_peer) &&
-            address->broadcast.s_addr == 0 && address->prefixlen <= 30)
-                address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen);
-        else if (address->broadcast.s_addr != 0) {
+        if (address->family == AF_INET &&
+              in_addr_is_null(address->family, &address->in_addr_peer) &&
+              address->prefixlen <= 30) {
+           if (address->broadcast.s_addr == 0)
+              address->broadcast.s_addr = address->in_addr.in.s_addr | htobe32(0xfffffffflu >> address->prefixlen);
+        } else if (address->broadcast.s_addr != 0) {
                 log_warning("%s: broadcast address is set for IPv6 address or IPv4 address with prefixlength larger than 30. "
                             "Ignoring Broadcast= setting in the [Address] section from line %u.",
                             address->section->filename, address->section->line);
diff -Naurp systemd-247.orig/src/network/networkd-dhcp4.c systemd-247/src/network/networkd-dhcp4.c
--- systemd-247.orig/src/network/networkd-dhcp4.c	2020-11-26 12:00:50.000000000 -0600
+++ systemd-247/src/network/networkd-dhcp4.c	2020-12-02 18:37:58.247645763 -0600
@@ -861,7 +861,8 @@ static int dhcp4_update_address(Link *li
         addr->cinfo.ifa_prefered = lifetime;
         addr->cinfo.ifa_valid = lifetime;
         addr->prefixlen = prefixlen;
-        addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
+        if (prefixlen <= 30)
+           addr->broadcast.s_addr = address.s_addr | ~netmask.s_addr;
         SET_FLAG(addr->flags, IFA_F_NOPREFIXROUTE, !link_prefixroute(link));
 
         /* allow reusing an existing address and simply update its lifetime
diff -Naurp systemd-247.orig/src/network/test-networkd-conf.c systemd-247/src/network/test-networkd-conf.c
--- systemd-247.orig/src/network/test-networkd-conf.c	2020-11-26 12:00:50.000000000 -0600
+++ systemd-247/src/network/test-networkd-conf.c	2020-12-02 18:27:55.637652401 -0600
@@ -224,7 +224,7 @@ static void test_config_parse_match_ifna
         assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "!baz", &names, NULL) == 0);
         assert_se(config_parse_match_ifnames("network", "filename", 1, "section", 1, "Name", 0, "aaa bbb ccc", &names, NULL) == 0);
 
-        strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "aaa", "bbb", "ccc"));
+        assert_se(strv_equal(names, STRV_MAKE("!hoge", "!hogehoge", "!foo", "!baz", "aaa", "bbb", "ccc")));
 }
 
 static void test_config_parse_match_strv(void) {
