label: plumb label_context through LabelOps
SELinux labeling with --root/--image needs per-call context to carry an alternate policy database and root prefix. The current LabelOps interface has no way to pass this, forcing any solution to rely on global state. Add a LabelContext *label_context to the label_ops callbacks and all intermediate layers. Generic filesystem functions that most callers use (xopenat_full, write_string_file_full, etc.) get a _label variant carrying the extra parameter, with inline wrappers preserving the original signatures so the vast majority of call sites remain untouched. Signed-off-by: Simon de Vlieger <cmdr@supakeen.com>
This commit is contained in:
+22
-21
@@ -25,16 +25,17 @@ int mkdirat_safe_internal(
|
||||
uid_t uid,
|
||||
gid_t gid,
|
||||
MkdirFlags flags,
|
||||
mkdirat_func_t _mkdirat) {
|
||||
mkdirat_func_t _mkdirat,
|
||||
LabelContext *label_context) {
|
||||
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(mode != MODE_INVALID);
|
||||
assert(_mkdirat && _mkdirat != mkdirat);
|
||||
assert(_mkdirat);
|
||||
|
||||
r = _mkdirat(dir_fd, path, mode);
|
||||
r = _mkdirat(dir_fd, path, mode, label_context);
|
||||
if (r >= 0)
|
||||
return chmod_and_chown_at(dir_fd, path, mode, uid, gid);
|
||||
if (r != -EEXIST)
|
||||
@@ -52,7 +53,7 @@ int mkdirat_safe_internal(
|
||||
if (r == 0)
|
||||
return mkdirat_safe_internal(dir_fd, p, mode, uid, gid,
|
||||
flags & ~MKDIR_FOLLOW_SYMLINK,
|
||||
_mkdirat);
|
||||
_mkdirat, label_context);
|
||||
|
||||
if (fstatat(dir_fd, p, &st, AT_SYMLINK_NOFOLLOW) < 0)
|
||||
return -errno;
|
||||
@@ -80,20 +81,20 @@ int mkdirat_safe_internal(
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode) {
|
||||
int mkdirat_errno_wrapper(int dirfd, const char *pathname, mode_t mode, LabelContext *label_context) {
|
||||
return RET_NERRNO(mkdirat(dirfd, pathname, mode));
|
||||
}
|
||||
|
||||
int mkdirat_safe(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
|
||||
return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
|
||||
return mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags, mkdirat_errno_wrapper, /* label_context= */ NULL);
|
||||
}
|
||||
|
||||
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
|
||||
int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat, LabelContext *label_context) {
|
||||
const char *e = NULL;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
assert(_mkdirat != mkdirat);
|
||||
assert(_mkdirat);
|
||||
|
||||
if (isempty(path))
|
||||
return 0;
|
||||
@@ -134,7 +135,7 @@ int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t ui
|
||||
|
||||
s[n] = '\0';
|
||||
|
||||
r = mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat);
|
||||
r = mkdirat_safe_internal(dir_fd, path, mode, uid, gid, flags | MKDIR_IGNORE_EXISTING, _mkdirat, label_context);
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return r;
|
||||
|
||||
@@ -142,12 +143,12 @@ int mkdirat_parents_internal(int dir_fd, const char *path, mode_t mode, uid_t ui
|
||||
}
|
||||
}
|
||||
|
||||
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
|
||||
int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat, LabelContext *label_context) {
|
||||
_cleanup_close_ int fd = AT_FDCWD;
|
||||
const char *p;
|
||||
|
||||
assert(path);
|
||||
assert(_mkdirat != mkdirat);
|
||||
assert(_mkdirat);
|
||||
|
||||
if (prefix) {
|
||||
p = path_startswith_full(path, prefix, PATH_STARTSWITH_REFUSE_DOT_DOT);
|
||||
@@ -160,34 +161,34 @@ int mkdir_parents_internal(const char *prefix, const char *path, mode_t mode, ui
|
||||
} else
|
||||
p = path;
|
||||
|
||||
return mkdirat_parents_internal(fd, p, mode, uid, gid, flags, _mkdirat);
|
||||
return mkdirat_parents_internal(fd, p, mode, uid, gid, flags, _mkdirat, label_context);
|
||||
}
|
||||
|
||||
int mkdirat_parents(int dir_fd, const char *path, mode_t mode) {
|
||||
return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
|
||||
return mkdirat_parents_internal(dir_fd, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper, /* label_context= */ NULL);
|
||||
}
|
||||
|
||||
int mkdir_parents_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
|
||||
return mkdir_parents_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
|
||||
return mkdir_parents_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper, /* label_context= */ NULL);
|
||||
}
|
||||
|
||||
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat) {
|
||||
int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags, mkdirat_func_t _mkdirat, LabelContext *label_context) {
|
||||
int r;
|
||||
|
||||
/* Like mkdir -p */
|
||||
|
||||
assert(_mkdirat != mkdirat);
|
||||
assert(_mkdirat);
|
||||
|
||||
r = mkdir_parents_internal(prefix, path, mode, uid, gid, flags | MKDIR_FOLLOW_SYMLINK, _mkdirat);
|
||||
r = mkdir_parents_internal(prefix, path, mode, uid, gid, flags | MKDIR_FOLLOW_SYMLINK, _mkdirat, label_context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!uid_is_valid(uid) && !gid_is_valid(gid) && flags == 0) {
|
||||
r = _mkdirat(AT_FDCWD, path, mode);
|
||||
r = _mkdirat(AT_FDCWD, path, mode, label_context);
|
||||
if (r < 0 && (r != -EEXIST || is_dir(path, true) <= 0))
|
||||
return r;
|
||||
} else {
|
||||
r = mkdir_safe_internal(path, mode, uid, gid, flags, _mkdirat);
|
||||
r = mkdir_safe_internal(path, mode, uid, gid, flags, _mkdirat, label_context);
|
||||
if (r < 0 && r != -EEXIST)
|
||||
return r;
|
||||
}
|
||||
@@ -196,11 +197,11 @@ int mkdir_p_internal(const char *prefix, const char *path, mode_t mode, uid_t ui
|
||||
}
|
||||
|
||||
int mkdir_p(const char *path, mode_t mode) {
|
||||
return mkdir_p_internal(NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper);
|
||||
return mkdir_p_internal(/* prefix= */ NULL, path, mode, UID_INVALID, UID_INVALID, 0, mkdirat_errno_wrapper, /* label_context= */ NULL);
|
||||
}
|
||||
|
||||
int mkdir_p_safe(const char *prefix, const char *path, mode_t mode, uid_t uid, gid_t gid, MkdirFlags flags) {
|
||||
return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper);
|
||||
return mkdir_p_internal(prefix, path, mode, uid, gid, flags, mkdirat_errno_wrapper, /* label_context= */ NULL);
|
||||
}
|
||||
|
||||
int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mode_t m, usec_t ts, Hashmap *subvolumes) {
|
||||
|
||||
Reference in New Issue
Block a user