File 0001-fs-util-replace-symlink_atomic_full_label-by-a-flag-.patch of Package systemd

From 63a9bb0a8db8960b6df919ebf97d06a1439d052a Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 18 Jun 2025 10:14:09 +0200
Subject: [PATCH 1/4] fs-util: replace symlink_atomic_full_label() by a flag to
 symlinkat_atomic_full()

More porting work to label_ops_pre()/label_ops_post()

This also enables labelling of the /etc/localtime symlink in
systemd-firstboot, which should address one small facet of #37857
---
 src/basic/fs-util.c                | 23 ++++++++++++++++++-----
 src/basic/fs-util.h                |  9 +++++++--
 src/core/unit.c                    |  2 +-
 src/firstboot/firstboot.c          |  5 +++--
 src/resolve/resolved-resolv-conf.c |  2 +-
 src/shared/label-util.c            | 19 -------------------
 src/shared/label-util.h            |  4 ----
 src/tmpfiles/tmpfiles.c            |  4 +---
 src/udev/udev-node.c               |  2 +-
 9 files changed, 32 insertions(+), 38 deletions(-)

diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c
index 4ede324c34..b77fd1a9d9 100644
--- a/src/basic/fs-util.c
+++ b/src/basic/fs-util.c
@@ -454,14 +454,14 @@ int symlinkat_idempotent(const char *from, int atfd, const char *to, bool make_r
         return 0;
 }
 
-int symlinkat_atomic_full(const char *from, int atfd, const char *to, bool make_relative) {
-        _cleanup_free_ char *relpath = NULL, *t = NULL;
+int symlinkat_atomic_full(const char *from, int atfd, const char *to, SymlinkFlags flags) {
         int r;
 
         assert(from);
         assert(to);
 
-        if (make_relative) {
+        _cleanup_free_ char *relpath = NULL;
+        if (FLAGS_SET(flags, SYMLINK_MAKE_RELATIVE)) {
                 r = path_make_relative_parent(to, from, &relpath);
                 if (r < 0)
                         return r;
@@ -469,12 +469,25 @@ int symlinkat_atomic_full(const char *from, int atfd, const char *to, bool make_
                 from = relpath;
         }
 
+        _cleanup_free_ char *t = NULL;
         r = tempfn_random(to, NULL, &t);
         if (r < 0)
                 return r;
 
-        if (symlinkat(from, atfd, t) < 0)
-                return -errno;
+        bool call_label_ops_post = false;
+        if (FLAGS_SET(flags, SYMLINK_LABEL)) {
+                r = label_ops_pre(atfd, to, S_IFLNK);
+                if (r < 0)
+                        return r;
+
+                call_label_ops_post = true;
+        }
+
+        r = RET_NERRNO(symlinkat(from, atfd, t));
+        if (call_label_ops_post)
+                RET_GATHER(r, label_ops_post(atfd, t, /* created= */ r >= 0));
+        if (r < 0)
+                return r;
 
         r = RET_NERRNO(renameat(atfd, t, atfd, to));
         if (r < 0) {
diff --git a/src/basic/fs-util.h b/src/basic/fs-util.h
index 028c86a3b2..fa225bad68 100644
--- a/src/basic/fs-util.h
+++ b/src/basic/fs-util.h
@@ -67,9 +67,14 @@ static inline int symlink_idempotent(const char *from, const char *to, bool make
         return symlinkat_idempotent(from, AT_FDCWD, to, make_relative);
 }
 
-int symlinkat_atomic_full(const char *from, int atfd, const char *to, bool make_relative);
+typedef enum SymlinkFlags {
+        SYMLINK_MAKE_RELATIVE = 1 << 0,
+        SYMLINK_LABEL         = 1 << 1,
+} SymlinkFlags;
+
+int symlinkat_atomic_full(const char *from, int atfd, const char *to, SymlinkFlags flags);
 static inline int symlink_atomic(const char *from, const char *to) {
-        return symlinkat_atomic_full(from, AT_FDCWD, to, false);
+        return symlinkat_atomic_full(from, AT_FDCWD, to, 0);
 }
 
 int mknodat_atomic(int atfd, const char *path, mode_t mode, dev_t dev);
diff --git a/src/core/unit.c b/src/core/unit.c
index 0d88f4f641..c786366e94 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -5614,7 +5614,7 @@ static int unit_export_invocation_id(Unit *u) {
         if (r < 0)
                 return log_unit_debug_errno(u, r, "Failed to get invocation path: %m");
 
-        r = symlink_atomic_label(u->invocation_id_string, p);
+        r = symlinkat_atomic_full(u->invocation_id_string, AT_FDCWD, p, SYMLINK_LABEL);
         if (r < 0)
                 return log_unit_debug_errno(u, r, "Failed to create invocation ID symlink %s: %m", p);
 
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index a389eeae10..3c8644b39f 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -27,6 +27,7 @@
 #include "glyph-util.h"
 #include "hostname-util.h"
 #include "kbd-util.h"
+#include "label.h"
 #include "libcrypt-util.h"
 #include "locale-util.h"
 #include "lock-util.h"
@@ -582,7 +583,7 @@ static int process_timezone(int rfd) {
                         if (r < 0)
                                 return log_error_errno(r, "Failed to read host's /etc/localtime: %m");
 
-                        r = symlinkat_atomic_full(s, pfd, f, /* make_relative= */ false);
+                        r = symlinkat_atomic_full(s, pfd, f, SYMLINK_LABEL);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to create /etc/localtime symlink: %m");
 
@@ -600,7 +601,7 @@ static int process_timezone(int rfd) {
 
         e = strjoina("../usr/share/zoneinfo/", arg_timezone);
 
-        r = symlinkat_atomic_full(e, pfd, f, /* make_relative= */ false);
+        r = symlinkat_atomic_full(e, pfd, f, SYMLINK_LABEL);
         if (r < 0)
                 return log_error_errno(r, "Failed to create /etc/localtime symlink: %m");
 
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c
index 2071e0810c..5b0d2e13c0 100644
--- a/src/resolve/resolved-resolv-conf.c
+++ b/src/resolve/resolved-resolv-conf.c
@@ -375,7 +375,7 @@ int manager_write_resolv_conf(Manager *m) {
                 if (r < 0)
                         return log_warning_errno(r, "Failed to extract filename from path '" PRIVATE_UPLINK_RESOLV_CONF "', ignoring: %m");
 
-                r = symlink_atomic_label(fname, PRIVATE_STUB_RESOLV_CONF);
+                r = symlinkat_atomic_full(fname, AT_FDCWD, PRIVATE_STUB_RESOLV_CONF, SYMLINK_LABEL);
                 if (r < 0)
                         log_warning_errno(r, "Failed to symlink %s, ignoring: %m", PRIVATE_STUB_RESOLV_CONF);
         }
diff --git a/src/shared/label-util.c b/src/shared/label-util.c
index 2c482daaf6..6011ab60a1 100644
--- a/src/shared/label-util.c
+++ b/src/shared/label-util.c
@@ -62,25 +62,6 @@ int symlink_label(const char *old_path, const char *new_path) {
         return mac_smack_fix(new_path, 0);
 }
 
-int symlink_atomic_full_label(const char *from, const char *to, bool make_relative) {
-        int r;
-
-        assert(from);
-        assert(to);
-
-        r = mac_selinux_create_file_prepare(to, S_IFLNK);
-        if (r < 0)
-                return r;
-
-        r = symlinkat_atomic_full(from, AT_FDCWD, to, make_relative);
-        mac_selinux_create_file_clear();
-
-        if (r < 0)
-                return r;
-
-        return mac_smack_fix(to, 0);
-}
-
 int mknodat_label(int dirfd, const char *pathname, mode_t mode, dev_t dev) {
         int r;
 
diff --git a/src/shared/label-util.h b/src/shared/label-util.h
index 5a19a4cd43..c8dce55dc2 100644
--- a/src/shared/label-util.h
+++ b/src/shared/label-util.h
@@ -17,10 +17,6 @@ static inline int label_fix(const char *path, LabelFixFlags flags) {
 }
 
 int symlink_label(const char *old_path, const char *new_path);
-int symlink_atomic_full_label(const char *from, const char *to, bool make_relative);
-static inline int symlink_atomic_label(const char *from, const char *to) {
-        return symlink_atomic_full_label(from, to, false);
-}
 
 int mknodat_label(int dirfd, const char *pathname, mode_t mode, dev_t dev);
 static inline int mknod_label(const char *pathname, mode_t mode, dev_t dev) {
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 0e40896ec6..b14fda7d57 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -2469,9 +2469,7 @@ static int create_symlink(Context *c, Item *i) {
 
                 fd = safe_close(fd);
 
-                mac_selinux_create_file_prepare(i->path, S_IFLNK);
-                r = symlinkat_atomic_full(i->argument, pfd, bn, /* make_relative= */ false);
-                mac_selinux_create_file_clear();
+                r = symlinkat_atomic_full(i->argument, pfd, bn, SYMLINK_LABEL);
                 if (IN_SET(r, -EISDIR, -EEXIST, -ENOTEMPTY)) {
                         r = rm_rf_child(pfd, bn, REMOVE_PHYSICAL);
                         if (r < 0)
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 673f723ff2..a3eca076bb 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -65,7 +65,7 @@ static int node_create_symlink(sd_device *dev, const char *devnode, const char *
                 return log_device_debug_errno(dev, r, "Failed to create parent directory of '%s': %m", slink);
 
         /* use relative link */
-        r = symlink_atomic_full_label(devnode, slink, /* make_relative = */ true);
+        r = symlinkat_atomic_full(devnode, AT_FDCWD, slink, SYMLINK_MAKE_RELATIVE|SYMLINK_LABEL);
         if (r < 0)
                 return log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink, devnode);
 
-- 
2.43.0

openSUSE Build Service is sponsored by