chattr-util: add helpers to read and set project IDs

This commit is contained in:
Andres Beltran
2025-06-16 23:38:25 +00:00
parent a2123bf9d4
commit 652ba6e0dc
2 changed files with 83 additions and 0 deletions

View 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));
}

View 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