]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
fs-util: Add XOpenFlags with XO_LABEL flag to have xopenat() MAC label files/dirs 26969/head
authorDaan De Meyer <daan.j.demeyer@gmail.com>
Sun, 26 Mar 2023 17:48:57 +0000 (19:48 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 31 May 2023 11:15:56 +0000 (13:15 +0200)
src/basic/chase.c
src/basic/fs-util.c
src/basic/fs-util.h
src/basic/lock-util.c
src/basic/stat-util.c
src/libsystemd/sd-id128/id128-util.c
src/shared/btrfs-util.c
src/shared/loop-util.c
src/test/test-fs-util.c
src/tmpfiles/tmpfiles.c

index 373252b64526f28c5f2e8acc2befc8569347022b..983901f71416d70c9a4f4e86b41350a7d425dd77 100644 (file)
@@ -325,7 +325,11 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
                                 return r;
 
                         if (FLAGS_SET(flags, CHASE_MKDIR_0755) && !isempty(todo)) {
-                                child = xopenat(fd, first, O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0755);
+                                child = xopenat(fd,
+                                                first,
+                                                O_DIRECTORY|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC,
+                                                /* xopen_flags = */ 0,
+                                                0755);
                                 if (child < 0)
                                         return child;
                         } else if (FLAGS_SET(flags, CHASE_PARENT) && isempty(todo)) {
@@ -628,6 +632,7 @@ int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, i
                 /* Shortcut this call if none of the special features of this call are requested */
                 return RET_NERRNO(xopenat(AT_FDCWD, path,
                                           open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
+                                          /* xopen_flags = */ 0,
                                           mode));
 
         r = chase(path, root, CHASE_PARENT|chase_flags, &p, &path_fd);
@@ -645,7 +650,7 @@ int chase_and_open(const char *path, const char *root, ChaseFlags chase_flags, i
                         return r;
         }
 
-        r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, mode);
+        r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
         if (r < 0)
                 return r;
 
@@ -834,6 +839,7 @@ int chase_and_openat(int dir_fd, const char *path, ChaseFlags chase_flags, int o
                 /* Shortcut this call if none of the special features of this call are requested */
                 return RET_NERRNO(xopenat(dir_fd, path,
                                           open_flags | (FLAGS_SET(chase_flags, CHASE_NOFOLLOW) ? O_NOFOLLOW : 0),
+                                          /* xopen_flags = */ 0,
                                           mode));
 
         r = chaseat(dir_fd, path, chase_flags|CHASE_PARENT, &p, &path_fd);
@@ -846,7 +852,7 @@ int chase_and_openat(int dir_fd, const char *path, ChaseFlags chase_flags, int o
                         return r;
         }
 
-        r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, mode);
+        r = xopenat(path_fd, strempty(fname), open_flags|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
         if (r < 0)
                 return r;
 
index 1e1413dc80eca339ace82b939030f4e2b8569a4d..04a6531dcbd362c1f1cea94a1fe0a5e451b39052 100644 (file)
@@ -14,6 +14,7 @@
 #include "fileio.h"
 #include "fs-util.h"
 #include "hostname-util.h"
+#include "label.h"
 #include "lock-util.h"
 #include "log.h"
 #include "macro.h"
@@ -1034,7 +1035,7 @@ int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode) {
                 path = fname;
         }
 
-        fd = xopenat(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, mode);
+        fd = xopenat(dirfd, path, flags|O_CREAT|O_DIRECTORY|O_NOFOLLOW, /* xopen_flags = */ 0, mode);
         if (IN_SET(fd, -ELOOP, -ENOTDIR))
                 return -EEXIST;
         if (fd < 0)
@@ -1090,7 +1091,7 @@ int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, b
         }
 }
 
-int xopenat(int dir_fd, const char *path, int flags, mode_t mode) {
+int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode) {
         _cleanup_close_ int fd = -EBADF;
         bool made = false;
         int r;
@@ -1099,14 +1100,20 @@ int xopenat(int dir_fd, const char *path, int flags, mode_t mode) {
         assert(path);
 
         if (isempty(path)) {
-                assert(!FLAGS_SET(flags, O_CREAT|O_EXCL));
-                return fd_reopen(dir_fd, flags & ~O_NOFOLLOW);
+                assert(!FLAGS_SET(open_flags, O_CREAT|O_EXCL));
+                return fd_reopen(dir_fd, open_flags & ~O_NOFOLLOW);
         }
 
-        if (FLAGS_SET(flags, O_DIRECTORY|O_CREAT)) {
+        if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) {
+                r = label_ops_pre(dir_fd, path, FLAGS_SET(open_flags, O_DIRECTORY) ? S_IFDIR : S_IFREG);
+                if (r < 0)
+                        return r;
+        }
+
+        if (FLAGS_SET(open_flags, O_DIRECTORY|O_CREAT)) {
                 r = RET_NERRNO(mkdirat(dir_fd, path, mode));
                 if (r == -EEXIST) {
-                        if (FLAGS_SET(flags, O_EXCL))
+                        if (FLAGS_SET(open_flags, O_EXCL))
                                 return -EEXIST;
 
                         made = false;
@@ -1115,10 +1122,17 @@ int xopenat(int dir_fd, const char *path, int flags, mode_t mode) {
                 else
                         made = true;
 
-                flags &= ~(O_EXCL|O_CREAT);
+                if (FLAGS_SET(xopen_flags, XO_LABEL)) {
+                        r = label_ops_post(dir_fd, path);
+                        if (r < 0)
+                                return r;
+                }
+
+                open_flags &= ~(O_EXCL|O_CREAT);
+                xopen_flags &= ~XO_LABEL;
         }
 
-        fd = RET_NERRNO(openat(dir_fd, path, flags, mode));
+        fd = RET_NERRNO(openat(dir_fd, path, open_flags, mode));
         if (fd < 0) {
                 if (IN_SET(fd,
                            /* We got ENOENT? then someone else immediately removed it after we
@@ -1137,10 +1151,24 @@ int xopenat(int dir_fd, const char *path, int flags, mode_t mode) {
                 return fd;
         }
 
+        if (FLAGS_SET(open_flags, O_CREAT) && FLAGS_SET(xopen_flags, XO_LABEL)) {
+                r = label_ops_post(dir_fd, path);
+                if (r < 0)
+                        return r;
+        }
+
         return TAKE_FD(fd);
 }
 
-int xopenat_lock(int dir_fd, const char *path, int flags, mode_t mode, LockType locktype, int operation) {
+int xopenat_lock(
+                int dir_fd,
+                const char *path,
+                int open_flags,
+                XOpenFlags xopen_flags,
+                mode_t mode,
+                LockType locktype,
+                int operation) {
+
         _cleanup_close_ int fd = -EBADF;
         int r;
 
@@ -1150,13 +1178,13 @@ int xopenat_lock(int dir_fd, const char *path, int flags, mode_t mode, LockType
 
         /* POSIX/UNPOSIX locks don't work on directories (errno is set to -EBADF so let's return early with
          * the same error here). */
-        if (FLAGS_SET(flags, O_DIRECTORY) && locktype != LOCK_BSD)
+        if (FLAGS_SET(open_flags, O_DIRECTORY) && locktype != LOCK_BSD)
                 return -EBADF;
 
         for (;;) {
                 struct stat st;
 
-                fd = xopenat(dir_fd, path, flags, mode);
+                fd = xopenat(dir_fd, path, open_flags, xopen_flags, mode);
                 if (fd < 0)
                         return fd;
 
index cf381dfc266d1ca7fbf1c30e9e37a60d2b5a15c4..a19836d13892b15b00ccd05e3e2118f0f10da98f 100644 (file)
@@ -132,6 +132,10 @@ int open_mkdir_at(int dirfd, const char *path, int flags, mode_t mode);
 
 int openat_report_new(int dirfd, const char *pathname, int flags, mode_t mode, bool *ret_newly_created);
 
-int xopenat(int dir_fd, const char *path, int flags, mode_t mode);
+typedef enum XOpenFlags {
+        XO_LABEL = 1 << 0,
+} XOpenFlags;
 
-int xopenat_lock(int dir_fd, const char *path, int flags, mode_t mode, LockType locktype, int operation);
+int xopenat(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode);
+
+int xopenat_lock(int dir_fd, const char *path, int open_flags, XOpenFlags xopen_flags, mode_t mode, LockType locktype, int operation);
index 8ca30a50f0b70a11c9847e14f3a0c34d3a8753ff..3614fbe37cba9994cd206d30bf63c97a449e8ad5 100644 (file)
@@ -37,7 +37,13 @@ int make_lock_file_at(int dir_fd, const char *p, int operation, LockFile *ret) {
         if (!t)
                 return -ENOMEM;
 
-        fd = xopenat_lock(dfd, p, O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY, 0600, LOCK_UNPOSIX, operation);
+        fd = xopenat_lock(dfd,
+                          p,
+                          O_CREAT|O_RDWR|O_NOFOLLOW|O_CLOEXEC|O_NOCTTY,
+                          /* xopen_flags = */ 0,
+                          0600,
+                          LOCK_UNPOSIX,
+                          operation);
         if (fd < 0)
                 return fd == -EAGAIN ? -EBUSY : fd;
 
index 843cc025dc8468831a71f400252d8ded3b770356..633d9479dd2a6aa5ac9fbbd9907c60fcc44c21a4 100644 (file)
@@ -464,7 +464,7 @@ int xstatfsat(int dir_fd, const char *path, struct statfs *ret) {
         assert(path);
         assert(ret);
 
-        fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY, 0);
+        fd = xopenat(dir_fd, path, O_PATH|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
         if (fd < 0)
                 return fd;
 
index 76c9d1c051a3b4c273273b7b0dfcc18c874f4fdf..edadd86eaa0828b9c84694c0a1ee312bf20522ea 100644 (file)
@@ -119,7 +119,7 @@ int id128_read_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t *ret) {
         assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
         assert(path);
 
-        fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY, 0);
+        fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
         if (fd < 0)
                 return fd;
 
@@ -165,7 +165,7 @@ int id128_write_at(int dir_fd, const char *path, Id128Flag f, sd_id128_t id) {
         assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
         assert(path);
 
-        fd = xopenat(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444);
+        fd = xopenat(dir_fd, path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, /* xopen_flags = */ 0, 0444);
         if (fd < 0)
                 return fd;
 
index 7909184f2dc7eca25fe1d35e258e7ff062efe909..16295a582377cc7db3aeb21a7f5abbe6464f6eea 100644 (file)
@@ -223,7 +223,7 @@ int btrfs_get_block_device_at(int dir_fd, const char *path, dev_t *ret) {
         assert(path);
         assert(ret);
 
-        fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, 0);
+        fd = xopenat(dir_fd, path, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY, /* xopen_flags = */ 0, /* mode = */ 0);
         if (fd < 0)
                 return fd;
 
index 5418871093def6ebff8088a6b5fb5e58d8409c01..3ac9a3a6ae0e19bdc14af791b105949b7dfc9624 100644 (file)
@@ -677,9 +677,9 @@ int loop_device_make_by_path_at(
         direct_flags = FLAGS_SET(loop_flags, LO_FLAGS_DIRECT_IO) ? O_DIRECT : 0;
         rdwr_flags = open_flags >= 0 ? open_flags : O_RDWR;
 
-        fd = xopenat(dir_fd, path, basic_flags|direct_flags|rdwr_flags, 0);
+        fd = xopenat(dir_fd, path, basic_flags|direct_flags|rdwr_flags, /* xopen_flags = */ 0, /* mode = */ 0);
         if (fd < 0 && direct_flags != 0) /* If we had O_DIRECT on, and things failed with that, let's immediately try again without */
-                fd = xopenat(dir_fd, path, basic_flags|rdwr_flags, 0);
+                fd = xopenat(dir_fd, path, basic_flags|rdwr_flags, /* xopen_flags = */ 0, /* mode = */ 0);
         else
                 direct = direct_flags != 0;
         if (fd < 0) {
@@ -689,9 +689,9 @@ int loop_device_make_by_path_at(
                 if (open_flags >= 0 || !(ERRNO_IS_PRIVILEGE(r) || r == -EROFS))
                         return r;
 
-                fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY, 0);
+                fd = xopenat(dir_fd, path, basic_flags|direct_flags|O_RDONLY, /* xopen_flags = */ 0, /* mode = */ 0);
                 if (fd < 0 && direct_flags != 0) /* as above */
-                        fd = xopenat(dir_fd, path, basic_flags|O_RDONLY, 0);
+                        fd = xopenat(dir_fd, path, basic_flags|O_RDONLY, /* xopen_flags = */ 0, /* mode = */ 0);
                 else
                         direct = direct_flags != 0;
                 if (fd < 0)
index fa33b807b28689eacc2c3e6890a0d705adb8ae53..873052e24d4a3be6d9ed859315f0f2969255dc42 100644 (file)
@@ -680,26 +680,26 @@ TEST(xopenat) {
 
         /* Test that xopenat() creates directories if O_DIRECTORY is specified. */
 
-        assert_se((fd = xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0755)) >= 0);
+        assert_se((fd = xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0, 0755)) >= 0);
         assert_se((fd_verify_directory(fd) >= 0));
         fd = safe_close(fd);
 
-        assert_se(xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0755) == -EEXIST);
+        assert_se(xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_EXCL|O_CLOEXEC, 0, 0755) == -EEXIST);
 
-        assert_se((fd = xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_CLOEXEC, 0755)) >= 0);
+        assert_se((fd = xopenat(tfd, "abc", O_DIRECTORY|O_CREAT|O_CLOEXEC, 0, 0755)) >= 0);
         assert_se((fd_verify_directory(fd) >= 0));
         fd = safe_close(fd);
 
         /* Test that xopenat() creates regular files if O_DIRECTORY is not specified. */
 
-        assert_se((fd = xopenat(tfd, "def", O_CREAT|O_EXCL|O_CLOEXEC, 0644)) >= 0);
+        assert_se((fd = xopenat(tfd, "def", O_CREAT|O_EXCL|O_CLOEXEC, 0, 0644)) >= 0);
         assert_se(fd_verify_regular(fd) >= 0);
         fd = safe_close(fd);
 
         /* Test that we can reopen an existing fd with xopenat() by specifying an empty path. */
 
-        assert_se((fd = xopenat(tfd, "def", O_PATH|O_CLOEXEC, 0)) >= 0);
-        assert_se((fd2 = xopenat(fd, "", O_RDWR|O_CLOEXEC, 0644)) >= 0);
+        assert_se((fd = xopenat(tfd, "def", O_PATH|O_CLOEXEC, 0, 0)) >= 0);
+        assert_se((fd2 = xopenat(fd, "", O_RDWR|O_CLOEXEC, 0, 0644)) >= 0);
 }
 
 TEST(xopenat_lock) {
@@ -713,11 +713,11 @@ TEST(xopenat_lock) {
          * and close the file descriptor and still properly create the directory and acquire the lock in
          * another process.  */
 
-        fd = xopenat_lock(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0755, LOCK_BSD, LOCK_EX);
+        fd = xopenat_lock(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
         assert_se(fd >= 0);
         assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
         assert_se(fd_verify_directory(fd) >= 0);
-        assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
+        assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
 
         pid_t pid = fork();
         assert_se(pid >= 0);
@@ -725,11 +725,11 @@ TEST(xopenat_lock) {
         if (pid == 0) {
                 safe_close(fd);
 
-                fd = xopenat_lock(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0755, LOCK_BSD, LOCK_EX);
+                fd = xopenat_lock(tfd, "abc", O_CREAT|O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX);
                 assert_se(fd >= 0);
                 assert_se(faccessat(tfd, "abc", F_OK, 0) >= 0);
                 assert_se(fd_verify_directory(fd) >= 0);
-                assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
+                assert_se(xopenat_lock(tfd, "abc", O_DIRECTORY|O_CLOEXEC, 0, 0755, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
 
                 _exit(EXIT_SUCCESS);
         }
@@ -748,8 +748,8 @@ TEST(xopenat_lock) {
         assert_se(wait_for_terminate(pid, &si) >= 0);
         assert_se(si.si_code == CLD_EXITED);
 
-        assert_se(xopenat_lock(tfd, "abc", 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
-        assert_se(xopenat_lock(tfd, "def", O_DIRECTORY, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
+        assert_se(xopenat_lock(tfd, "abc", 0, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
+        assert_se(xopenat_lock(tfd, "def", O_DIRECTORY, 0, 0755, LOCK_POSIX, LOCK_EX) == -EBADF);
 }
 
 static int intro(void) {
index b58c595e6b0cbcb5cb2051edb2d7bd838ae686b3..1cb8f06b3e9005c06b433d24d7c346236438d820 100644 (file)
@@ -800,7 +800,11 @@ static int dir_cleanup(
                                            cutoff_nsec, sub_path, age_by_file, false))
                                 continue;
 
-                        fd = xopenat(dirfd(d), de->d_name, O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME, 0);
+                        fd = xopenat(dirfd(d),
+                                     de->d_name,
+                                     O_RDONLY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME,
+                                     /* xopen_flags = */ 0,
+                                     /* mode = */ 0);
                         if (fd < 0 && fd != -ENOENT)
                                 log_warning_errno(fd, "Opening file \"%s\" failed, ignoring: %m", sub_path);
                         if (fd >= 0 && flock(fd, LOCK_EX|LOCK_NB) < 0 && errno == EAGAIN) {