]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chattr-util: add helpers to read and set project IDs
authorAndres Beltran <abeltran@microsoft.com>
Mon, 16 Jun 2025 23:38:25 +0000 (23:38 +0000)
committerAndres Beltran <abeltran@microsoft.com>
Mon, 7 Jul 2025 17:28:47 +0000 (17:28 +0000)
src/basic/chattr-util.c
src/basic/chattr-util.h

index 70a0210f72b8d5601b4dceb3a7a5285a0365a2b1..8e15b56ea39f98f56bad9b98ac1033365a92e57c 100644 (file)
@@ -10,6 +10,7 @@
 #include "fd-util.h"
 #include "fs-util.h"
 #include "log.h"
+#include "recurse-dir.h"
 #include "string-util.h"
 
 int chattr_full(
@@ -169,3 +170,81 @@ int read_attr_at(int dir_fd, const char *path, unsigned *ret) {
 
         return read_attr_fd(fd, ret);
 }
+
+int read_fs_xattr_fd(int fd, uint32_t *ret_xflags, uint32_t *ret_projid) {
+        struct fsxattr attrs;
+        _cleanup_close_ int fd_reopened = -EBADF;
+
+        assert(fd >= 0);
+
+        fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_reopened);
+        if (fd < 0)
+                return fd;
+
+        if (ioctl(fd, FS_IOC_FSGETXATTR, &attrs) < 0)
+                return -errno;
+
+        if (ret_xflags)
+                *ret_xflags = attrs.fsx_xflags;
+
+        if (ret_projid)
+                *ret_projid = attrs.fsx_projid;
+
+        return 0;
+}
+
+int set_proj_id(int fd, uint32_t proj_id) {
+        struct fsxattr attrs;
+        _cleanup_close_ int fd_reopened = -EBADF;
+
+        assert(fd >= 0);
+
+        fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_reopened);
+        if (fd < 0)
+                return fd;
+
+        if (ioctl(fd, FS_IOC_FSGETXATTR, &attrs) < 0)
+                return -errno;
+
+        struct stat statbuf;
+        if (fstat(fd, &statbuf) < 0)
+                return -errno;
+
+        if (attrs.fsx_projid == proj_id && (!S_ISDIR(statbuf.st_mode) || FLAGS_SET(attrs.fsx_xflags, FS_XFLAG_PROJINHERIT)))
+                return 0;
+
+        attrs.fsx_projid = proj_id;
+        if (S_ISDIR(statbuf.st_mode))
+                attrs.fsx_xflags |= FS_XFLAG_PROJINHERIT;
+
+        return RET_NERRNO(ioctl(fd, FS_IOC_FSSETXATTR, &attrs));
+}
+
+static int set_proj_id_cb(
+                RecurseDirEvent event,
+                const char *path,
+                int dir_fd,
+                int inode_fd,
+                const struct dirent *de,
+                const struct statx *sx,
+                void *userdata) {
+
+        if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY))
+                return RECURSE_DIR_CONTINUE;
+
+        if (de && !IN_SET(de->d_type, DT_DIR, DT_REG))
+                return RECURSE_DIR_CONTINUE;
+
+        return set_proj_id(inode_fd, PTR_TO_UINT32(userdata));
+}
+
+int set_proj_id_recursive(int fd, uint32_t proj_id) {
+        return recurse_dir_at(
+                        fd,
+                        /* path = */ NULL,
+                        /* statx_mask = */ 0,
+                        /* n_depth_max = */ UINT_MAX,
+                        RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_TOPLEVEL|RECURSE_DIR_INODE_FD,
+                        set_proj_id_cb,
+                        UINT32_TO_PTR(proj_id));
+}
index ab57239b0883c2ed62e2fc8fb961460e490d0f9f..50f97971f9cf8ac890cb2bc1c27f34bf6f355f12 100644 (file)
@@ -50,6 +50,10 @@ static inline int chattr_path(const char *path, unsigned value, unsigned mask) {
 
 int read_attr_fd(int fd, unsigned *ret);
 int read_attr_at(int dir_fd, const char *path, unsigned *ret);
+int read_fs_xattr_fd(int fd, uint32_t *ret_xflags, uint32_t *ret_projid);
+
+int set_proj_id(int fd, uint32_t proj_id);
+int set_proj_id_recursive(int fd, uint32_t proj_id);
 
 /* Combination of chattr flags, that should be appropriate for secrets stored on disk: Secure Remove +
  * Exclusion from Dumping + Synchronous Writing (i.e. not caching in memory) + In-Place Updating (i.e. not