]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
copy: add flag COPY_MAC_CREATE to create with correct label
authorChristian Göttsche <cgzones@googlemail.com>
Thu, 28 Nov 2019 11:17:48 +0000 (12:17 +0100)
committerChristian Göttsche <cgzones@googlemail.com>
Thu, 28 Nov 2019 11:17:56 +0000 (12:17 +0100)
Useful for MAC aware file creation like in systemd-tmpfiles.

src/basic/copy.c
src/basic/copy.h

index 9028868f696d892e9de8eef7a3183d704f35cf18..97d566c5b936b250c0bc7693f58d567de982c95d 100644 (file)
@@ -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;
         }
index 906c6f70aec2dcbe5965a402b05e032a952fe644..af8e88af04815546a11ec2ad62cd7cfed4bf95aa 100644 (file)
@@ -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);