]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sysext: set SELinux context for hierarchies and workdir
authorgerblesh <101901964+gerblesh@users.noreply.github.com>
Thu, 14 Nov 2024 19:12:40 +0000 (19:12 +0000)
committerLuca Boccassi <luca.boccassi@gmail.com>
Tue, 26 Nov 2024 17:47:32 +0000 (17:47 +0000)
src/basic/fileio.c
src/basic/fileio.h
src/sysext/sysext.c
src/update-done/update-done.c

index aa1657c118d84d28f9b9401e762f70261f44a274..52a29e2f7bd2a1381860a158da0f05e186120dc8 100644 (file)
@@ -289,7 +289,8 @@ int write_string_file_full(
                 const char *fn,
                 const char *line,
                 WriteStringFileFlags flags,
-                const struct timespec *ts) {
+                const struct timespec *ts,
+                const char *label_fn) {
 
         bool call_label_ops_post = false, made_file = false;
         _cleanup_fclose_ FILE *f = NULL;
@@ -321,7 +322,8 @@ int write_string_file_full(
         mode_t mode = write_string_file_flags_to_mode(flags);
 
         if (FLAGS_SET(flags, WRITE_STRING_FILE_LABEL|WRITE_STRING_FILE_CREATE)) {
-                r = label_ops_pre(dir_fd, fn, mode);
+                const char *lookup = label_fn ? label_fn : fn;
+                r = label_ops_pre(dir_fd, lookup, mode);
                 if (r < 0)
                         goto fail;
 
index 8f54491c12c512bdf5a35ca459f2b618fa5a2c9f..08017f8270450c3d3eab7333a1563b965adb891f 100644 (file)
@@ -51,12 +51,13 @@ int write_string_stream_full(FILE *f, const char *line, WriteStringFileFlags fla
 static inline int write_string_stream(FILE *f, const char *line, WriteStringFileFlags flags) {
         return write_string_stream_full(f, line, flags, /* ts= */ NULL);
 }
-int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts);
+
+int write_string_file_full(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags, const struct timespec *ts, const char *label_fn);
 static inline int write_string_file(const char *fn, const char *line, WriteStringFileFlags flags) {
-        return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL);
+        return write_string_file_full(AT_FDCWD, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL);
 }
 static inline int write_string_file_at(int dir_fd, const char *fn, const char *line, WriteStringFileFlags flags) {
-        return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL);
+        return write_string_file_full(dir_fd, fn, line, flags, /* ts= */ NULL, /*label_fn=*/ NULL);
 }
 int write_string_filef(const char *fn, WriteStringFileFlags flags, const char *format, ...) _printf_(3, 4);
 
index 0adfab253cbd5f43a7d2d5979129f1f8c6c4d103..aab1f972a4a3d179624248701a675cb74a57cab2 100644 (file)
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
+#include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
 #include <linux/loop.h>
@@ -45,6 +46,7 @@
 #include "process-util.h"
 #include "rm-rf.h"
 #include "sort-util.h"
+#include "selinux-util.h"
 #include "string-table.h"
 #include "string-util.h"
 #include "terminal-util.h"
@@ -899,6 +901,7 @@ static int resolve_mutable_directory(
         _cleanup_free_ char *path = NULL, *resolved_path = NULL, *dir_name = NULL;
         const char *root = arg_root, *base = MUTABLE_EXTENSIONS_BASE_DIR;
         int r;
+        _cleanup_close_ int atfd = -EBADF;
 
         assert(hierarchy);
         assert(ret_resolved_mutable_directory);
@@ -943,6 +946,14 @@ static int resolve_mutable_directory(
                 r = mkdir_p(path_in_root, 0700);
                 if (r < 0)
                         return log_error_errno(r, "Failed to create a directory '%s': %m", path_in_root);
+
+                atfd = open(path_in_root, O_DIRECTORY|O_CLOEXEC);
+                if (atfd < 0)
+                        return log_error_errno(errno, "Failed to open directory '%s': %m", path_in_root);
+
+                r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", path_in_root);
         }
 
         r = chase(path, root, CHASE_PREFIX_ROOT, &resolved_path, NULL);
@@ -1289,6 +1300,7 @@ static int mount_overlayfs_with_op(
 
         int r;
         const char *top_layer = NULL;
+        _cleanup_close_ int atfd = -EBADF;
 
         assert(op);
         assert(overlay_path);
@@ -1301,10 +1313,28 @@ static int mount_overlayfs_with_op(
         if (r < 0)
                 return log_error_errno(r, "Failed to make directory '%s': %m", meta_path);
 
+        atfd = open(meta_path, O_DIRECTORY|O_CLOEXEC);
+        if (atfd < 0)
+                return log_error_errno(errno, "Failed to open directory '%s': %m", meta_path);
+
+        r = mac_selinux_fix_full(atfd, NULL, op->hierarchy, 0);
+        if (r < 0)
+                return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", meta_path);
+
         if (op->upper_dir && op->work_dir) {
                 r = mkdir_p(op->work_dir, 0700);
                 if (r < 0)
                         return log_error_errno(r, "Failed to make directory '%s': %m", op->work_dir);
+                _cleanup_close_ int dfd = -EBADF;
+
+                dfd = open(op->work_dir, O_DIRECTORY|O_CLOEXEC);
+                if (dfd < 0)
+                        return log_error_errno(errno, "Failed to open directory '%s': %m", op->work_dir);
+
+                r = mac_selinux_fix_full(dfd, NULL, op->hierarchy, 0);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", op->work_dir);
+
                 top_layer = op->upper_dir;
         } else {
                 assert(!strv_isempty(op->lower_dirs));
@@ -1325,7 +1355,7 @@ static int mount_overlayfs_with_op(
         return 0;
 }
 
-static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path) {
+static int write_extensions_file(ImageClass image_class, char **extensions, const char *meta_path, const char *hierarchy) {
         _cleanup_free_ char *f = NULL, *buf = NULL;
         int r;
 
@@ -1343,14 +1373,15 @@ static int write_extensions_file(ImageClass image_class, char **extensions, cons
         if (!buf)
                 return log_oom();
 
-        r = write_string_file(f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755);
+        const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
+        r = write_string_file_full(AT_FDCWD,f, buf, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_MKDIR_0755|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
         if (r < 0)
                 return log_error_errno(r, "Failed to write extension meta file '%s': %m", f);
 
         return 0;
 }
 
-static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path) {
+static int write_dev_file(ImageClass image_class, const char *meta_path, const char *overlay_path, const char *hierarchy) {
         _cleanup_free_ char *f = NULL;
         struct stat st;
         int r;
@@ -1372,14 +1403,15 @@ static int write_dev_file(ImageClass image_class, const char *meta_path, const c
         /* Modifying the underlying layers while the overlayfs is mounted is technically undefined, but at
          * least it won't crash or deadlock, as per the kernel docs about overlayfs:
          * https://www.kernel.org/doc/html/latest/filesystems/overlayfs.html#changes-to-underlying-filesystems */
-        r = write_string_file(f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE);
+        const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, image_class_info[image_class].short_identifier_plural);
+        r = write_string_file_full(AT_FDCWD, f, FORMAT_DEVNUM(st.st_dev), WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
         if (r < 0)
                 return log_error_errno(r, "Failed to write '%s': %m", f);
 
         return 0;
 }
 
-static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir) {
+static int write_work_dir_file(ImageClass image_class, const char *meta_path, const char *work_dir, const char* hierarchy) {
         _cleanup_free_ char *escaped_work_dir_in_root = NULL, *f = NULL;
         char *work_dir_in_root = NULL;
         int r;
@@ -1406,7 +1438,8 @@ static int write_work_dir_file(ImageClass image_class, const char *meta_path, co
         escaped_work_dir_in_root = cescape(work_dir_in_root);
         if (!escaped_work_dir_in_root)
                 return log_oom();
-        r = write_string_file(f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE);
+        const char *hierarchy_path = path_join(hierarchy, image_class_info[image_class].dot_directory_name, "work_dir");
+        r = write_string_file_full(AT_FDCWD, f, escaped_work_dir_in_root, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_LABEL, NULL, hierarchy_path);
         if (r < 0)
                 return log_error_errno(r, "Failed to write '%s': %m", f);
 
@@ -1418,8 +1451,10 @@ static int store_info_in_meta(
                 char **extensions,
                 const char *meta_path,
                 const char *overlay_path,
-                const char *work_dir) {
-
+                const char *work_dir,
+                const char *hierarchy) {
+        _cleanup_free_ char *f = NULL;
+        _cleanup_close_ int atfd = -EBADF;
         int r;
 
         assert(extensions);
@@ -1427,15 +1462,32 @@ static int store_info_in_meta(
         assert(overlay_path);
         /* work_dir may be NULL */
 
-        r = write_extensions_file(image_class, extensions, meta_path);
+        f = path_join(meta_path, image_class_info[image_class].dot_directory_name);
+        if (!f)
+                return log_oom();
+
+        r = mkdir_p(f, 0755);
+        if (r < 0)
+                return r;
+
+        atfd = open(f, O_DIRECTORY|O_CLOEXEC);
+        if (atfd < 0)
+                return log_error_errno(errno, "Failed to open directory '%s': %m", f);
+
+        r = mac_selinux_fix_full(atfd, NULL, hierarchy, 0);
+
+        if (r < 0)
+                return log_error_errno(r, "Failed to fix SELinux label for '%s': %m", hierarchy);
+
+        r = write_extensions_file(image_class, extensions, meta_path, hierarchy);
         if (r < 0)
                 return r;
 
-        r = write_dev_file(image_class, meta_path, overlay_path);
+        r = write_dev_file(image_class, meta_path, overlay_path, hierarchy);
         if (r < 0)
                 return r;
 
-        r = write_work_dir_file(image_class, meta_path, work_dir);
+        r = write_work_dir_file(image_class, meta_path, work_dir, hierarchy);
         if (r < 0)
                 return r;
 
@@ -1501,6 +1553,8 @@ static int merge_hierarchy(
         assert(overlay_path);
         assert(workspace_path);
 
+        mac_selinux_init();
+
         r = determine_used_extensions(hierarchy, paths, &used_paths, &extensions_used);
         if (r < 0)
                 return r;
@@ -1528,7 +1582,7 @@ static int merge_hierarchy(
         if (r < 0)
                 return r;
 
-        r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir);
+        r = store_info_in_meta(image_class, extensions, meta_path, overlay_path, op->work_dir, op->hierarchy);
         if (r < 0)
                 return r;
 
index 277d2860b9a05f45b40ab105e8796528a6cfd9bc..fdfbb7b52e24d66140c67df94fcb754f056586c0 100644 (file)
@@ -29,7 +29,7 @@ static int apply_timestamp(const char *path, struct timespec *ts) {
                      timespec_load_nsec(ts)) < 0)
                 return log_oom();
 
-        r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts);
+        r = write_string_file_full(AT_FDCWD, path, message, WRITE_STRING_FILE_CREATE|WRITE_STRING_FILE_ATOMIC|WRITE_STRING_FILE_LABEL, ts, NULL);
         if (r == -EROFS)
                 log_debug_errno(r, "Cannot create \"%s\", file system is read-only.", path);
         else if (r < 0)