#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"
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);
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;
safe_close(i->fd);
free(i->source);
free(i->image_path);
+ free(i->selinux_label);
return mfree(i);
}
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);
}
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;
}
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);
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;
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);
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;
_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);