#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"
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|
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)
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;
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())
return -EOVERFLOW;
}
+ if (isempty(fname))
+ flags |= AT_EMPTY_PATH;
+
return RET_NERRNO(fchownat(fd, strempty(fname), uid, gid, flags));
}
#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);