diff --git a/TODO b/TODO index 4f77391f62..68b3ab48d2 100644 --- a/TODO +++ b/TODO @@ -120,6 +120,10 @@ Deprecations and removals: Features: +* replace symlink_label(), mknodat_label(), btrfs_subvol_make_label(), + mkdir_label() and related calls by flags-based calls that use + label_ops_pre()/label_ops_post(). + * maybe reconsider whether virtualization consoles (hvc1) are considered local or remote. i.e. are they more like an ssh login, or more like a /dev/tty1 login? Lennart used to believe the former, but maybe the latter is more diff --git a/src/basic/env-file.c b/src/basic/env-file.c index bc23e94d18..f9d63aefed 100644 --- a/src/basic/env-file.c +++ b/src/basic/env-file.c @@ -5,10 +5,12 @@ #include "alloc-util.h" #include "env-file.h" #include "env-util.h" +#include "errno-util.h" #include "escape.h" #include "fd-util.h" #include "fileio.h" #include "fs-util.h" +#include "label.h" #include "log.h" #include "string-util.h" #include "strv.h" @@ -629,7 +631,7 @@ static void write_env_var(FILE *f, const char *v) { fputc_unlocked('\n', f); } -int write_env_file(int dir_fd, const char *fname, char **headers, char **l) { +int write_env_file(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags) { _cleanup_fclose_ FILE *f = NULL; _cleanup_free_ char *p = NULL; int r; @@ -637,7 +639,18 @@ int write_env_file(int dir_fd, const char *fname, char **headers, char **l) { assert(dir_fd >= 0 || dir_fd == AT_FDCWD); assert(fname); + bool call_label_ops_post = false; + if (FLAGS_SET(flags, WRITE_ENV_FILE_LABEL)) { + r = label_ops_pre(dir_fd, fname, S_IFREG); + if (r < 0) + return r; + + call_label_ops_post = true; + } + r = fopen_tmpfile_linkable_at(dir_fd, fname, O_WRONLY|O_CLOEXEC, &p, &f); + if (call_label_ops_post) + RET_GATHER(r, label_ops_post(f ? fileno(f) : dir_fd, f ? NULL : fname, /* created= */ !!f)); if (r < 0) return r; @@ -672,5 +685,5 @@ int write_vconsole_conf(int dir_fd, const char *fname, char **l) { "# Written by systemd-localed(8) or systemd-firstboot(1), read by systemd-localed", "# and systemd-vconsole-setup(8). Use localectl(1) to update this file."); - return write_env_file(dir_fd, fname, headers, l); + return write_env_file(dir_fd, fname, headers, l, WRITE_ENV_FILE_LABEL); } diff --git a/src/basic/env-file.h b/src/basic/env-file.h index b44651fe1e..b17a1804cf 100644 --- a/src/basic/env-file.h +++ b/src/basic/env-file.h @@ -15,7 +15,11 @@ int load_env_file_pairs_fd(int fd, const char *fname, char ***ret); int merge_env_file(char ***env, FILE *f, const char *fname); -int write_env_file(int dir_fd, const char *fname, char **headers, char **l); +typedef enum WriteEnvFileFlags { + WRITE_ENV_FILE_LABEL = 1 << 0, +} WriteEnvFileFlags; + +int write_env_file(int dir_fd, const char *fname, char **headers, char **l, WriteEnvFileFlags flags); int write_vconsole_conf(int dir_fd, const char *fname, char **l); diff --git a/src/basic/fs-util.c b/src/basic/fs-util.c index 04f7290cc2..3dd32ccac6 100644 --- a/src/basic/fs-util.c +++ b/src/basic/fs-util.c @@ -459,14 +459,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; @@ -474,12 +474,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 59dbb1ce0e..1150f914be 100644 --- a/src/basic/fs-util.h +++ b/src/basic/fs-util.h @@ -48,9 +48,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 19d0898f9b..1f46b96ad9 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -5677,7 +5677,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 6ba7d4ba92..a7654ca615 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -28,6 +28,8 @@ #include "hostname-util.h" #include "image-policy.h" #include "kbd-util.h" +#include "label.h" +#include "label-util.h" #include "libcrypt-util.h" #include "locale-util.h" #include "lock-util.h" @@ -447,7 +449,12 @@ static int process_locale(int rfd) { locales[i] = NULL; - r = write_env_file(pfd, f, NULL, locales); + r = write_env_file( + pfd, + f, + /* headers= */ NULL, + locales, + WRITE_ENV_FILE_LABEL); if (r < 0) return log_error_errno(r, "Failed to write /etc/locale.conf: %m"); @@ -640,7 +647,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"); @@ -658,7 +665,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"); @@ -725,7 +732,7 @@ static int process_hostname(int rfd) { return 0; r = write_string_file_at(pfd, f, arg_hostname, - WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC); + WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL); if (r < 0) return log_error_errno(r, "Failed to write /etc/hostname: %m"); @@ -758,7 +765,7 @@ static int process_machine_id(int rfd) { } r = write_string_file_at(pfd, "machine-id", SD_ID128_TO_STRING(arg_machine_id), - WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC); + WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL); if (r < 0) return log_error_errno(r, "Failed to write /etc/machine-id: %m"); @@ -1184,7 +1191,7 @@ static int process_kernel_cmdline(int rfd) { } r = write_string_file_at(pfd, "cmdline", arg_kernel_cmdline, - WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC); + WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_SYNC|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL); if (r < 0) return log_error_errno(r, "Failed to write /etc/kernel/cmdline: %m"); @@ -1679,6 +1686,10 @@ static int run(int argc, char *argv[]) { } } + r = mac_init(); + if (r < 0) + return r; + if (arg_image) { assert(!arg_root); diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index e194381ce1..789ab2be78 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -21,7 +21,6 @@ #include "daemon-util.h" #include "device-private.h" #include "env-file.h" -#include "env-file-label.h" #include "env-util.h" #include "extract-word.h" #include "fileio.h" @@ -860,7 +859,12 @@ static int context_write_data_machine_info(Context *c) { return 0; } - r = write_env_file_label(AT_FDCWD, "/etc/machine-info", NULL, l); + r = write_env_file( + AT_FDCWD, + "/etc/machine-info", + /* headers= */ NULL, + l, + WRITE_ENV_FILE_LABEL); if (r < 0) return r; diff --git a/src/locale/localed-util.c b/src/locale/localed-util.c index 9e990443e4..0a96e7a3c9 100644 --- a/src/locale/localed-util.c +++ b/src/locale/localed-util.c @@ -8,7 +8,6 @@ #include "alloc-util.h" #include "copy.h" #include "env-file.h" -#include "env-file-label.h" #include "errno-util.h" #include "extract-word.h" #include "fd-util.h" @@ -315,7 +314,7 @@ int vconsole_write_data(Context *c) { return 0; } - r = write_vconsole_conf_label(l); + r = write_vconsole_conf(AT_FDCWD, "/etc/vconsole.conf", l); if (r < 0) return r; diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 0064adb948..d0b5d7340d 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -377,7 +377,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/env-file-label.c b/src/shared/env-file-label.c deleted file mode 100644 index 7609250605..0000000000 --- a/src/shared/env-file-label.c +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include - -#include "env-file.h" -#include "env-file-label.h" -#include "selinux-util.h" - -int write_env_file_label(int dir_fd, const char *fname, char **headers, char **l) { - int r; - - r = mac_selinux_create_file_prepare(fname, S_IFREG); - if (r < 0) - return r; - - r = write_env_file(dir_fd, fname, headers, l); - - mac_selinux_create_file_clear(); - - return r; -} - -int write_vconsole_conf_label(char **l) { - int r; - - r = mac_selinux_create_file_prepare("/etc/vconsole.conf", S_IFREG); - if (r < 0) - return r; - - r = write_vconsole_conf(AT_FDCWD, "/etc/vconsole.conf", l); - - mac_selinux_create_file_clear(); - - return r; -} diff --git a/src/shared/env-file-label.h b/src/shared/env-file-label.h deleted file mode 100644 index 5309eabff4..0000000000 --- a/src/shared/env-file-label.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "forward.h" - -/* These functions are split out of fileio.h (and not for example just flags to the functions they wrap) in order to - * optimize linking: This way, -lselinux is needed only for the callers of these functions that need selinux, but not - * for all */ - -int write_env_file_label(int dir_fd, const char *fname, char **headers, char **l); - -int write_vconsole_conf_label(char **l); diff --git a/src/shared/label-util.c b/src/shared/label-util.c index b4d5d4505a..78d5501c9f 100644 --- a/src/shared/label-util.c +++ b/src/shared/label-util.c @@ -60,25 +60,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 b135c0f1ab..b1586dd81e 100644 --- a/src/shared/label-util.h +++ b/src/shared/label-util.h @@ -16,10 +16,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/shared/locale-setup.c b/src/shared/locale-setup.c index c23f1c4078..c59bbe2abc 100644 --- a/src/shared/locale-setup.c +++ b/src/shared/locale-setup.c @@ -6,7 +6,6 @@ #include "alloc-util.h" #include "env-file.h" -#include "env-file-label.h" #include "env-util.h" #include "errno-util.h" #include "fd-util.h" @@ -212,7 +211,12 @@ int locale_context_save(LocaleContext *c, char ***ret_set, char ***ret_unset) { return 0; } - r = write_env_file_label(AT_FDCWD, "/etc/locale.conf", NULL, set); + r = write_env_file( + AT_FDCWD, + "/etc/locale.conf", + /* headers= */ NULL, + set, + WRITE_ENV_FILE_LABEL); if (r < 0) return r; diff --git a/src/shared/meson.build b/src/shared/meson.build index 33c550e5ba..38dd3b498d 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -68,7 +68,6 @@ shared_sources = files( 'efi-loader.c', 'elf-util.c', 'enable-mempool.c', - 'env-file-label.c', 'ethtool-util.c', 'exec-util.c', 'exit-status.c', diff --git a/src/test/test-env-file.c b/src/test/test-env-file.c index 69c8e48daa..812c0cb762 100644 --- a/src/test/test-env-file.c +++ b/src/test/test-env-file.c @@ -171,7 +171,7 @@ TEST(write_and_load_env_file) { assert_se(tempfn_random_child(NULL, NULL, &p) >= 0); assert_se(j = strjoin("TEST=", v)); - assert_se(write_env_file(AT_FDCWD, p, STRV_MAKE("# header 1", "", "# header 2"), STRV_MAKE(j)) >= 0); + assert_se(write_env_file(AT_FDCWD, p, STRV_MAKE("# header 1", "", "# header 2"), STRV_MAKE(j), /* flags= */ 0) >= 0); assert_se(cmd = strjoin(". ", p, " && /bin/echo -n \"$TEST\"")); assert_se(f = popen(cmd, "re")); diff --git a/src/test/test-fileio.c b/src/test/test-fileio.c index aa68155fe6..e0ae30bbb9 100644 --- a/src/test/test-fileio.c +++ b/src/test/test-fileio.c @@ -143,7 +143,7 @@ TEST(parse_env_file) { assert_se(fd >= 0); } - r = write_env_file(AT_FDCWD, p, NULL, a); + r = write_env_file(AT_FDCWD, p, /* headers= */ NULL, a, /* flags= */ 0); assert_se(r >= 0); r = load_env_file(NULL, p, &b); @@ -206,7 +206,7 @@ TEST(parse_multiline_env_file) { assert_se(fd >= 0); } - r = write_env_file(AT_FDCWD, p, NULL, a); + r = write_env_file(AT_FDCWD, p, /* headers= */ NULL, a, /* flags= */ 0); assert_se(r >= 0); r = load_env_file(NULL, p, &b); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index a11a90b93b..16e2742fc1 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -2471,17 +2471,13 @@ 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) return log_error_errno(r, "rm -rf %s failed: %m", i->path); - mac_selinux_create_file_prepare(i->path, S_IFLNK); - r = RET_NERRNO(symlinkat(i->argument, pfd, i->path)); - mac_selinux_create_file_clear(); + r = symlinkat_atomic_full(i->argument, pfd, bn, SYMLINK_LABEL); } if (r < 0) return log_error_errno(r, "symlink(%s, %s) failed: %m", i->argument, i->path); diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c index 5f165b5107..a48061a1ea 100644 --- a/src/udev/udev-node.c +++ b/src/udev/udev-node.c @@ -70,7 +70,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);