nspawn-bind-user: Write membership records

This commit is contained in:
Daan De Meyer
2025-10-30 22:20:59 +01:00
parent 3fbf4ac24b
commit b430f2bc94
3 changed files with 55 additions and 1 deletions

View File

@@ -5,12 +5,16 @@
#include "sd-json.h"
#include "alloc-util.h"
#include "chase.h"
#include "fd-util.h"
#include "fileio.h"
#include "format-util.h"
#include "io-util.h"
#include "log.h"
#include "nspawn.h"
#include "machine-bind-user.h"
#include "nspawn-bind-user.h"
#include "strv.h"
#include "user-record.h"
#include "group-record.h"
#include "path-util.h"
@@ -67,6 +71,40 @@ static int write_and_symlink(
return 0;
}
static int write_membership(const char *root, const char *user, const char *group) {
int r;
assert(user);
assert(group);
_cleanup_free_ char *membership = strjoin(user, ":", group, ".membership");
if (!membership)
return log_oom();
_cleanup_free_ char *p = path_join("/run/host/userdb/", membership);
if (!p)
return log_oom();
_cleanup_close_ int fd = chase_and_open(
p,
root,
CHASE_PREFIX_ROOT|CHASE_NO_AUTOFS,
O_WRONLY|O_CREAT|O_CLOEXEC,
/* ret_path= */ NULL);
if (fd < 0)
return log_error_errno(errno, "Failed to create %s: %m", p);
r = userns_chown_at(fd, /* fname= */ NULL, /* uid= */ 0, /* gid= */ 0, /* flags= */ 0);
if (r < 0)
return log_error_errno(r, "Failed to adjust access mode of '%s': %m", p);
r = loop_write(fd, "{}\n", SIZE_MAX);
if (r < 0)
return log_error_errno(r, "Failed to write empty JSON object into %s: %m", p);
return 0;
}
int bind_user_setup(const MachineBindUserContext *c, const char *root) {
static const UserRecordLoadFlags strip_flags = /* Removes privileged info */
USER_RECORD_LOAD_MASK_PRIVILEGED|
@@ -130,6 +168,12 @@ int bind_user_setup(const MachineBindUserContext *c, const char *root) {
if (r < 0)
return r;
STRV_FOREACH(u, stripped_group->members) {
r = write_membership(root, *u, stripped_group->group_name);
if (r < 0)
return r;
}
/* Third, write out user shadow data. i.e. extract privileged info from user record */
r = user_record_clone(d->payload_user, shadow_flags, &shadow_user);
if (r < 0)
@@ -161,6 +205,12 @@ int bind_user_setup(const MachineBindUserContext *c, const char *root) {
0);
if (r < 0)
return r;
STRV_FOREACH(g, stripped_user->member_of) {
r = write_membership(root, stripped_user->user_name, *g);
if (r < 0)
return r;
}
}
return 1;

View File

@@ -1733,7 +1733,7 @@ static int in_child_chown(void) {
return IN_SET(arg_userns_mode, USER_NAMESPACE_PICK, USER_NAMESPACE_FIXED);
}
static int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int flags) {
int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int flags) {
assert(fd >= 0 || fd == AT_FDCWD);
if (!in_child_chown())
@@ -1756,6 +1756,9 @@ static int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int
return -EOVERFLOW;
}
if (isempty(fname))
flags |= AT_EMPTY_PATH;
return RET_NERRNO(fchownat(fd, strempty(fname), uid, gid, flags));
}

View File

@@ -3,6 +3,7 @@
#include "shared-forward.h"
int userns_chown_at(int fd, const char *fname, uid_t uid, gid_t gid, int flags);
int userns_lchown(const char *p, uid_t uid, gid_t gid);
int userns_mkdir(const char *root, const char *path, mode_t mode, uid_t uid, gid_t gid);
int make_run_host(const char *root);