From: Andres Beltran Date: Mon, 16 Jun 2025 23:38:25 +0000 (+0000) Subject: chattr-util: add helpers to read and set project IDs X-Git-Tag: v258-rc1~144^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=652ba6e0dc6a2dd227f983d0ca93c3a39e9c2c93;p=thirdparty%2Fsystemd.git chattr-util: add helpers to read and set project IDs --- diff --git a/src/basic/chattr-util.c b/src/basic/chattr-util.c index 70a0210f72b..8e15b56ea39 100644 --- a/src/basic/chattr-util.c +++ b/src/basic/chattr-util.c @@ -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)); +} diff --git a/src/basic/chattr-util.h b/src/basic/chattr-util.h index ab57239b088..50f97971f9c 100644 --- a/src/basic/chattr-util.h +++ b/src/basic/chattr-util.h @@ -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