systemd: fix some issues in systemd v252.4

After PR-60270, systemd update to v252.4.
In this version, there are some problems that will affect gBMC.

refs:
https://github.com/systemd/systemd/commit/2cbb171d20a07ec0a25296f167b0385de102d74e
https://github.com/systemd/systemd/commit/782418a166e46a5862562479217e3ff98f81feb7

Google-Bug-Id: 267573639
Google-Bug-Id: 273819300
Google-Bug-Id: 273818953
Change-Id: I4f708c26e4265ccc82deb8f3a5706fe007adf4bf
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/recipes-core/systemd/systemd/0001-busctl-fix-introspecting-DBus-properties.patch b/recipes-core/systemd/systemd/0001-busctl-fix-introspecting-DBus-properties.patch
new file mode 100644
index 0000000..8c06589
--- /dev/null
+++ b/recipes-core/systemd/systemd/0001-busctl-fix-introspecting-DBus-properties.patch
@@ -0,0 +1,69 @@
+From 2cbb171d20a07ec0a25296f167b0385de102d74e Mon Sep 17 00:00:00 2001
+From: Yu Watanabe <watanabe.yu+github@gmail.com>
+Date: Fri, 13 Jan 2023 14:12:31 +0900
+Subject: [PATCH] busctl: fix introspecting DBus properties
+
+Follow-up for f2f7785d7a47ffa48ac929648794e1288509ddd8.
+
+Fixes #26033.
+
+Patch Tracking Bug: b/273819300
+Upstream info / review:
+https://github.com/systemd/systemd/commit/2cbb171d20a07ec0a25296f167b0385de102d74e
+Upstream-Status: Accepted
+Justification: bugfix busctrl introspect
+---
+ src/busctl/busctl.c | 21 +++++++++++++++++++--
+ 1 file changed, 19 insertions(+), 2 deletions(-)
+
+diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c
+index 32c6ed7cac..2b5552889b 100644
+--- a/src/busctl/busctl.c
++++ b/src/busctl/busctl.c
+@@ -1022,10 +1022,11 @@ static int introspect(int argc, char **argv, void *userdata) {
+ 
+                 for (;;) {
+                         Member *z;
+-                        _cleanup_free_ char *buf = NULL;
++                        _cleanup_free_ char *buf = NULL, *signature = NULL;
+                         _cleanup_fclose_ FILE *mf = NULL;
+                         size_t sz = 0;
+-                        const char *name;
++                        const char *name, *contents;
++                        char type;
+ 
+                         r = sd_bus_message_enter_container(reply, 'e', "sv");
+                         if (r < 0)
+@@ -1042,6 +1043,21 @@ static int introspect(int argc, char **argv, void *userdata) {
+                         if (r < 0)
+                                 return bus_log_parse_error(r);
+ 
++                        r = sd_bus_message_peek_type(reply, &type, &contents);
++                        if (r <= 0)
++                                return bus_log_parse_error(r == 0 ? EINVAL : r);
++
++                        if (type == SD_BUS_TYPE_STRUCT_BEGIN)
++                                signature = strjoin(CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END));
++                        else if (type == SD_BUS_TYPE_DICT_ENTRY_BEGIN)
++                                signature = strjoin(CHAR_TO_STR(SD_BUS_TYPE_DICT_ENTRY_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_DICT_ENTRY_END));
++                        else if (contents)
++                                signature = strjoin(CHAR_TO_STR(type), contents);
++                        else
++                                signature = strdup(CHAR_TO_STR(type));
++                        if (!signature)
++                                return log_oom();
++
+                         mf = open_memstream_unlocked(&buf, &sz);
+                         if (!mf)
+                                 return log_oom();
+@@ -1055,6 +1071,7 @@ static int introspect(int argc, char **argv, void *userdata) {
+                         z = set_get(members, &((Member) {
+                                                 .type = "property",
+                                                 .interface = m->interface,
++                                                .signature = signature,
+                                                 .name = (char*) name }));
+                         if (z)
+                                 free_and_replace(z->value, buf);
+-- 
+2.25.1
+
diff --git a/recipes-core/systemd/systemd/0001-shutdown-move-busy-mounts-to-not-block-parent-mounts.patch b/recipes-core/systemd/systemd/0001-shutdown-move-busy-mounts-to-not-block-parent-mounts.patch
new file mode 100644
index 0000000..5227bb0
--- /dev/null
+++ b/recipes-core/systemd/systemd/0001-shutdown-move-busy-mounts-to-not-block-parent-mounts.patch
@@ -0,0 +1,205 @@
+From 204bf0ffe18c66c5b78224cd6ab53960cbb4e98f Mon Sep 17 00:00:00 2001
+From: Harvey Wu <Harvey.Wu@quantatw.com>
+Date: Tue, 31 Jan 2023 10:48:52 +0800
+Subject: [PATCH] shutdown: move busy mounts to not block parent mounts
+
+copy from: https://github.com/systemd/systemd/commit/782418a166e46a5862562479217e3ff98f81feb7
+
+Patch Tracking Bug: b/273818953
+Upstream info / review:
+https://github.com/systemd/systemd/commit/782418a166e46a5862562479217e3ff98f81feb7
+Upstream-Status: Accepted
+Justification:  bugfix busctl introspect
+---
+ src/shared/libmount-util.h | 19 +++++++++++
+ src/shutdown/shutdown.c    |  5 +++
+ src/shutdown/umount.c      | 68 ++++++++++++++++++++++++++++++++++++--
+ src/shutdown/umount.h      |  5 +--
+ 4 files changed, 93 insertions(+), 4 deletions(-)
+
+diff --git a/src/shared/libmount-util.h b/src/shared/libmount-util.h
+index cf19c56ed1..c407159d8d 100644
+--- a/src/shared/libmount-util.h
++++ b/src/shared/libmount-util.h
+@@ -45,3 +45,22 @@ static inline int libmount_parse(
+         *ret_iter = TAKE_PTR(iter);
+         return 0;
+ }
++
++static inline int libmount_is_leaf(
++                struct libmnt_table *table,
++                struct libmnt_fs *fs) {
++        int r;
++
++        _cleanup_(mnt_free_iterp) struct libmnt_iter *iter_children = NULL;
++        iter_children = mnt_new_iter(MNT_ITER_FORWARD);
++        if (!iter_children)
++                return log_oom();
++
++        /* We care only whether it exists, it is unused */
++        _unused_ struct libmnt_fs *child;
++        r = mnt_table_next_child_fs(table, iter_children, fs, &child);
++        if (r < 0)
++                return r;
++
++        return r == 1;
++}
+diff --git a/src/shutdown/shutdown.c b/src/shutdown/shutdown.c
+index dcee0f9006..309107ec35 100644
+--- a/src/shutdown/shutdown.c
++++ b/src/shutdown/shutdown.c
+@@ -399,6 +399,11 @@ int main(int argc, char *argv[]) {
+         /* Lock us into memory */
+         (void) mlockall(MCL_CURRENT|MCL_FUTURE);
+ 
++        /* We need to make mounts private so that we can MS_MOVE in unmount_all(). Kernel does not allow
++         * MS_MOVE when parent mountpoints have shared propagation. */
++        if (mount(NULL, "/", NULL, MS_REC|MS_PRIVATE, NULL) < 0)
++                log_warning_errno(errno, "Failed to make mounts private, ignoring: %m");
++
+         /* Synchronize everything that is not written to disk yet at this point already. This is a good idea so that
+          * slow IO is processed here already and the final process killing spree is not impacted by processes
+          * desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will
+diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c
+index e650b82170..8b4b379802 100644
+--- a/src/shutdown/umount.c
++++ b/src/shutdown/umount.c
+@@ -23,6 +23,7 @@
+ 
+ #include "alloc-util.h"
+ #include "blockdev-util.h"
++#include "chase-symlinks.h"
+ #include "def.h"
+ #include "device-util.h"
+ #include "dirent-util.h"
+@@ -32,13 +33,16 @@
+ #include "fs-util.h"
+ #include "fstab-util.h"
+ #include "libmount-util.h"
++#include "mkdir.h"
+ #include "mount-setup.h"
+ #include "mount-util.h"
+ #include "mountpoint-util.h"
+ #include "parse-util.h"
+ #include "path-util.h"
+ #include "process-util.h"
++#include "random-util.h"
+ #include "signal-util.h"
++#include "stat-util.h"
+ #include "string-util.h"
+ #include "strv.h"
+ #include "sync-util.h"
+@@ -156,6 +160,11 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
+                 if (!m)
+                         return log_oom();
+ 
++                r = libmount_is_leaf(table, fs);
++                if (r < 0)
++                        return log_error_errno(r, "Failed to get children mounts for %s from %s: %m", path, mountinfo ?: "/proc/self/mountinfo");
++                bool leaf = r;
++
+                 *m = (MountPoint) {
+                         .remount_options = remount_options,
+                         .remount_flags = remount_flags,
+@@ -164,6 +173,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) {
+                         /* Unmount sysfs/procfs/… lazily, since syncing doesn't matter there, and it's OK if
+                          * something keeps an fd open to it. */
+                         .umount_lazily = is_api_vfs,
++                        .leaf = leaf,
+                 };
+ 
+                 m->path = strdup(path);
+@@ -682,7 +692,8 @@ static int umount_with_timeout(MountPoint *m, bool last_try) {
+ /* This includes remounting readonly, which changes the kernel mount options.  Therefore the list passed to
+  * this function is invalidated, and should not be reused. */
+ static int mount_points_list_umount(MountPoint **head, bool *changed, bool last_try) {
+-        int n_failed = 0;
++        int n_failed = 0, r;
++        _cleanup_free_ char *resolved_mounts_path = NULL;
+ 
+         assert(head);
+         assert(changed);
+@@ -717,10 +728,63 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool last_
+                         continue;
+ 
+                 /* Trying to umount */
+-                if (umount_with_timeout(m, last_try) < 0)
++                r = umount_with_timeout(m, last_try);
++                if (r < 0)
+                         n_failed++;
+                 else
+                         *changed = true;
++
++                /* If a mount is busy, we move it to not keep parent mount points busy.
++                 * If a mount point is not a leaf, moving it would invalidate our mount table.
++                 * More moving will occur in next iteration with a fresh mount table.
++                 */
++                if (r != -EBUSY || !m->leaf)
++                        continue;
++
++                _cleanup_free_ char *dirname = NULL;
++
++                r = path_extract_directory(m->path, &dirname);
++                if (r < 0) {
++                        n_failed++;
++                        log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Cannot find directory for %s: %m", m->path);
++                        continue;
++                }
++
++                /* We need to canonicalize /run/shutdown/mounts. We cannot compare inodes, since /run
++                 * might be bind mounted somewhere we want to unmount. And we need to move all mounts in
++                 * /run/shutdown/mounts from there.
++                 */
++                if (!resolved_mounts_path)
++                        (void) chase_symlinks("/run/shutdown/mounts", NULL, 0, &resolved_mounts_path, NULL);
++                if (!path_equal(dirname, resolved_mounts_path)) {
++                        char newpath[STRLEN("/run/shutdown/mounts/") + 16 + 1];
++
++                        xsprintf(newpath, "/run/shutdown/mounts/%016" PRIx64, random_u64());
++
++                        /* on error of is_dir, assume directory */
++                        if (is_dir(m->path, true) != 0) {
++                                r = mkdir_p(newpath, 0000);
++                                if (r < 0) {
++                                        log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Could not create directory %s: %m", newpath);
++                                        continue;
++                                }
++                        } else {
++                                r = touch_file(newpath, /* parents= */ true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0700);
++                                if (r < 0) {
++                                        log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Could not create file %s: %m", newpath);
++                                        continue;
++                                }
++                        }
++
++                        log_info("Moving mount %s to %s.", m->path, newpath);
++
++                        r = RET_NERRNO(mount(m->path, newpath, NULL, MS_MOVE, NULL));
++                        if (r < 0) {
++                                n_failed++;
++                                log_full_errno(last_try ? LOG_ERR : LOG_INFO, r, "Could not move %s to %s: %m", m->path, newpath);
++                        } else
++                                *changed = true;
++                }
+         }
+ 
+         return n_failed;
+diff --git a/src/shutdown/umount.h b/src/shutdown/umount.h
+index a4154c9099..a742ac0af5 100644
+--- a/src/shutdown/umount.h
++++ b/src/shutdown/umount.h
+@@ -18,8 +18,9 @@ typedef struct MountPoint {
+         char *path;
+         char *remount_options;
+         unsigned long remount_flags;
+-        bool try_remount_ro:1;
+-        bool umount_lazily:1;
++        bool try_remount_ro;
++        bool umount_lazily;
++        bool leaf;
+         dev_t devnum;
+         LIST_FIELDS(struct MountPoint, mount_point);
+ } MountPoint;
+-- 
+2.25.1
+
diff --git a/recipes-core/systemd/systemd_%.bbappend b/recipes-core/systemd/systemd_%.bbappend
index 44051a2..e9ae742 100644
--- a/recipes-core/systemd/systemd_%.bbappend
+++ b/recipes-core/systemd/systemd_%.bbappend
@@ -1,2 +1,6 @@
 FILESEXTRAPATHS:prepend:gbmc := "${THISDIR}/systemd:"
-SRC_URI:append:gbmc = " file://0001-radv-Hardcode-shorter-RA-interval.patch"
+SRC_URI:append:gbmc = " \
+  file://0001-radv-Hardcode-shorter-RA-interval.patch \
+  file://0001-busctl-fix-introspecting-DBus-properties.patch \
+  file://0001-shutdown-move-busy-mounts-to-not-block-parent-mounts.patch \
+"