summaryrefslogtreecommitdiff
path: root/src/portable
diff options
context:
space:
mode:
Diffstat (limited to 'src/portable')
-rw-r--r--src/portable/portable.c46
-rw-r--r--src/portable/portable.h1
2 files changed, 42 insertions, 5 deletions
diff --git a/src/portable/portable.c b/src/portable/portable.c
index 8af7fe2aef..4daafea3d3 100644
--- a/src/portable/portable.c
+++ b/src/portable/portable.c
@@ -28,6 +28,7 @@
#include "path-lookup.h"
#include "portable.h"
#include "process-util.h"
+#include "selinux-util.h"
#include "set.h"
#include "signal-util.h"
#include "socket-util.h"
@@ -78,7 +79,7 @@ static bool unit_match(const char *unit, char **matches) {
return false;
}
-static PortableMetadata *portable_metadata_new(const char *name, const char *path, int fd) {
+static PortableMetadata *portable_metadata_new(const char *name, const char *path, const char *selinux_label, int fd) {
PortableMetadata *m;
m = malloc0(offsetof(PortableMetadata, name) + strlen(name) + 1);
@@ -92,6 +93,15 @@ static PortableMetadata *portable_metadata_new(const char *name, const char *pat
return mfree(m);
}
+ /* The metadata file might have SELinux labels, we need to carry them and reapply them */
+ if (!isempty(selinux_label)) {
+ m->selinux_label = strdup(selinux_label);
+ if (!m->selinux_label) {
+ free(m->image_path);
+ return mfree(m);
+ }
+ }
+
strcpy(m->name, name);
m->fd = fd;
@@ -105,6 +115,7 @@ PortableMetadata *portable_metadata_unref(PortableMetadata *i) {
safe_close(i->fd);
free(i->source);
free(i->image_path);
+ free(i->selinux_label);
return mfree(i);
}
@@ -201,6 +212,7 @@ static int extract_now(
if (socket_fd >= 0) {
struct iovec iov[] = {
IOVEC_MAKE_STRING(os_release_id),
+ IOVEC_MAKE((char *)"\0", sizeof(char)),
};
r = send_one_fd_iov_with_data_fd(socket_fd, iov, ELEMENTSOF(iov), os_release_fd);
@@ -209,7 +221,7 @@ static int extract_now(
}
if (ret_os_release) {
- os_release = portable_metadata_new(os_release_id, NULL, os_release_fd);
+ os_release = portable_metadata_new(os_release_id, NULL, NULL, os_release_fd);
if (!os_release)
return -ENOMEM;
@@ -264,8 +276,19 @@ static int extract_now(
}
if (socket_fd >= 0) {
+ _cleanup_(mac_selinux_freep) char *con = NULL;
+#if HAVE_SELINUX
+ /* The units will be copied on the host's filesystem, so if they had a SELinux label
+ * we have to preserve it. Copy it out so that it can be applied later. */
+
+ r = fgetfilecon_raw(fd, &con);
+ if (r < 0 && errno != ENODATA)
+ log_debug_errno(errno, "Failed to get SELinux file context from '%s', ignoring: %m", de->d_name);
+#endif
struct iovec iov[] = {
IOVEC_MAKE_STRING(de->d_name),
+ IOVEC_MAKE((char *)"\0", sizeof(char)),
+ IOVEC_MAKE_STRING(strempty(con)),
};
r = send_one_fd_iov_with_data_fd(socket_fd, iov, ELEMENTSOF(iov), fd);
@@ -273,7 +296,7 @@ static int extract_now(
return log_debug_errno(r, "Failed to send unit metadata to parent: %m");
}
- m = portable_metadata_new(de->d_name, NULL, fd);
+ m = portable_metadata_new(de->d_name, NULL, NULL, fd);
if (!m)
return -ENOMEM;
fd = -1;
@@ -401,7 +424,11 @@ static int portable_extract_by_path(
for (;;) {
_cleanup_(portable_metadata_unrefp) PortableMetadata *add = NULL;
_cleanup_close_ int fd = -1;
- char iov_buffer[PATH_MAX + 2];
+ /* We use NAME_MAX space for the SELinux label here. The kernel currently enforces no limit, but
+ * according to suggestions from the SELinux people this will change and it will probably be
+ * identical to NAME_MAX. For now we use that, but this should be updated one day when the final
+ * limit is known. */
+ char iov_buffer[PATH_MAX + NAME_MAX + 2];
struct iovec iov = IOVEC_INIT(iov_buffer, sizeof(iov_buffer));
ssize_t n = receive_one_fd_iov(seq[0], &iov, 1, 0, &fd);
@@ -420,7 +447,13 @@ static int portable_extract_by_path(
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid item sent from child.");
- add = portable_metadata_new(iov_buffer, path, fd);
+ /* Given recvmsg cannot be used with multiple io vectors if you don't know the size in advance,
+ * use a marker to separate the name and the optional SELinux context. */
+ char *selinux_label = memchr(iov_buffer, 0, n);
+ assert(selinux_label);
+ selinux_label++;
+
+ add = portable_metadata_new(iov_buffer, path, selinux_label, fd);
if (!add)
return -ENOMEM;
fd = -1;
@@ -1065,7 +1098,10 @@ static int attach_unit_file(
_cleanup_(unlink_and_freep) char *tmp = NULL;
_cleanup_close_ int fd = -1;
+ (void) mac_selinux_create_file_prepare_label(path, m->selinux_label);
+
fd = open_tmpfile_linkable(path, O_WRONLY|O_CLOEXEC, &tmp);
+ mac_selinux_create_file_clear(); /* Clear immediately in case of errors */
if (fd < 0)
return log_debug_errno(fd, "Failed to create unit file '%s': %m", path);
diff --git a/src/portable/portable.h b/src/portable/portable.h
index 94144287ae..077ab3333f 100644
--- a/src/portable/portable.h
+++ b/src/portable/portable.h
@@ -12,6 +12,7 @@ typedef struct PortableMetadata {
int fd;
char *source;
char *image_path;
+ char *selinux_label;
char name[];
} PortableMetadata;