From aeec5efab58adb2c8fe02ab4f6f8864b07905e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Thu, 28 Nov 2019 12:17:48 +0100 Subject: [PATCH] copy: add flag COPY_MAC_CREATE to create with correct label Useful for MAC aware file creation like in systemd-tmpfiles. --- src/basic/copy.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++-- src/basic/copy.h | 1 + 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/src/basic/copy.c b/src/basic/copy.c index 9028868f69..97d566c5b9 100644 --- a/src/basic/copy.c +++ b/src/basic/copy.c @@ -21,6 +21,7 @@ #include "missing_syscall.h" #include "mountpoint-util.h" #include "nulstr-util.h" +#include "selinux-util.h" #include "stat-util.h" #include "string-util.h" #include "strv.h" @@ -372,7 +373,15 @@ static int fd_copy_symlink( if (r < 0) return r; - if (symlinkat(target, dt, to) < 0) + if (copy_flags & COPY_MAC_CREATE) { + r = mac_selinux_create_file_prepare_at(dt, to, S_IFLNK); + if (r < 0) + return r; + } + r = symlinkat(target, dt, to); + if (copy_flags & COPY_MAC_CREATE) + mac_selinux_create_file_clear(); + if (r < 0) return -errno; if (fchownat(dt, to, @@ -408,7 +417,14 @@ static int fd_copy_regular( if (fdf < 0) return -errno; + if (copy_flags & COPY_MAC_CREATE) { + r = mac_selinux_create_file_prepare_at(dt, to, S_IFREG); + if (r < 0) + return r; + } fdt = openat(dt, to, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW, st->st_mode & 07777); + if (copy_flags & COPY_MAC_CREATE) + mac_selinux_create_file_clear(); if (fdt < 0) return -errno; @@ -457,7 +473,14 @@ static int fd_copy_fifo( assert(st); assert(to); + if (copy_flags & COPY_MAC_CREATE) { + r = mac_selinux_create_file_prepare_at(dt, to, S_IFIFO); + if (r < 0) + return r; + } r = mkfifoat(dt, to, st->st_mode & 07777); + if (copy_flags & COPY_MAC_CREATE) + mac_selinux_create_file_clear(); if (r < 0) return -errno; @@ -488,7 +511,14 @@ static int fd_copy_node( assert(st); assert(to); + if (copy_flags & COPY_MAC_CREATE) { + r = mac_selinux_create_file_prepare_at(dt, to, st->st_mode & S_IFMT); + if (r < 0) + return r; + } r = mknodat(dt, to, st->st_mode, st->st_rdev); + if (copy_flags & COPY_MAC_CREATE) + mac_selinux_create_file_clear(); if (r < 0) return -errno; @@ -556,7 +586,10 @@ static int fd_copy_directory( if (exists) created = false; else { - r = mkdirat(dt, to, st->st_mode & 07777); + if (copy_flags & COPY_MAC_CREATE) + r = mkdirat_label(dt, to, st->st_mode & 07777); + else + r = mkdirat(dt, to, st->st_mode & 07777); if (r >= 0) created = true; else if (errno == EEXIST && (copy_flags & COPY_MERGE)) @@ -796,7 +829,14 @@ int copy_file_full( assert(to); RUN_WITH_UMASK(0000) { + if (copy_flags & COPY_MAC_CREATE) { + r = mac_selinux_create_file_prepare(to, S_IFREG); + if (r < 0) + return r; + } fdt = open(to, flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY, mode); + if (copy_flags & COPY_MAC_CREATE) + mac_selinux_create_file_clear(); if (fdt < 0) return -errno; } @@ -850,13 +890,29 @@ int copy_file_atomic_full( if (r < 0) return r; + if (copy_flags & COPY_MAC_CREATE) { + r = mac_selinux_create_file_prepare(to, S_IFREG); + if (r < 0) { + t = mfree(t); + return r; + } + } fdt = open(t, O_CREAT|O_EXCL|O_NOFOLLOW|O_NOCTTY|O_WRONLY|O_CLOEXEC, 0600); + if (copy_flags & COPY_MAC_CREATE) + mac_selinux_create_file_clear(); if (fdt < 0) { t = mfree(t); return -errno; } } else { + if (copy_flags & COPY_MAC_CREATE) { + r = mac_selinux_create_file_prepare(to, S_IFREG); + if (r < 0) + return r; + } fdt = open_tmpfile_linkable(to, O_WRONLY|O_CLOEXEC, &t); + if (copy_flags & COPY_MAC_CREATE) + mac_selinux_create_file_clear(); if (fdt < 0) return fdt; } diff --git a/src/basic/copy.h b/src/basic/copy.h index 906c6f70ae..af8e88af04 100644 --- a/src/basic/copy.h +++ b/src/basic/copy.h @@ -16,6 +16,7 @@ typedef enum CopyFlags { COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */ COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */ COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */ + COPY_MAC_CREATE = 1 << 7, /* Create files with the correct MAC label (currently SELinux only) */ } CopyFlags; typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata);