mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
basic/namespace-util: obtain uid and gid before unsharing user namespace
Getting user and group after unsharing user namespace is too late because without any mapping, i.e. just after unshare(), we are mapped to nobody.
This commit is contained in:
committed by
Yu Watanabe
parent
278d5bfd7e
commit
8b5e3be88e
@@ -412,6 +412,8 @@ int detach_mount_namespace(void) {
|
||||
}
|
||||
|
||||
int detach_mount_namespace_harder(uid_t target_uid, gid_t target_gid) {
|
||||
uid_t from_uid;
|
||||
gid_t from_gid;
|
||||
int r;
|
||||
|
||||
/* Tried detach_mount_namespace() first. If that doesn't work due to permissions, opens up an
|
||||
@@ -439,11 +441,14 @@ int detach_mount_namespace_harder(uid_t target_uid, gid_t target_gid) {
|
||||
if (r != -EPERM)
|
||||
return r;
|
||||
|
||||
from_uid = getuid();
|
||||
from_gid = getgid();
|
||||
|
||||
if (unshare(CLONE_NEWUSER) < 0)
|
||||
return log_debug_errno(errno, "Failed to acquire user namespace: %m");
|
||||
|
||||
r = write_string_filef("/proc/self/uid_map", 0,
|
||||
UID_FMT " " UID_FMT " 1\n", target_uid, getuid());
|
||||
UID_FMT " " UID_FMT " 1\n", target_uid, from_uid);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to write uid map: %m");
|
||||
|
||||
@@ -452,7 +457,7 @@ int detach_mount_namespace_harder(uid_t target_uid, gid_t target_gid) {
|
||||
return log_debug_errno(r, "Failed to write setgroups file: %m");
|
||||
|
||||
r = write_string_filef("/proc/self/gid_map", 0,
|
||||
GID_FMT " " GID_FMT " 1\n", target_gid, getgid());
|
||||
GID_FMT " " GID_FMT " 1\n", target_gid, from_gid);
|
||||
if (r < 0)
|
||||
return log_debug_errno(r, "Failed to write gid map: %m");
|
||||
|
||||
|
||||
@@ -414,6 +414,32 @@ TEST(namespace_get_leader) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(detach_mount_namespace_harder) {
|
||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||
_cleanup_close_pair_ int p[2] = EBADF_PAIR;
|
||||
char x = 0;
|
||||
int r;
|
||||
|
||||
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC));
|
||||
|
||||
ASSERT_OK(r = pidref_safe_fork("(child)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_LOG, &pid));
|
||||
if (r == 0) {
|
||||
p[0] = safe_close(p[0]);
|
||||
|
||||
ASSERT_OK(detach_mount_namespace_harder(0, 0));
|
||||
|
||||
ASSERT_OK_EQ_ERRNO(write(p[1], &(const char[]) { 'x' }, 1), 1);
|
||||
freeze();
|
||||
}
|
||||
|
||||
p[1] = safe_close(p[1]);
|
||||
ASSERT_OK_EQ_ERRNO(read(p[0], &x, 1), 1);
|
||||
ASSERT_EQ(x, 'x');
|
||||
|
||||
ASSERT_OK_POSITIVE(pidref_in_same_namespace(NULL, &pid, NAMESPACE_USER));
|
||||
ASSERT_OK_ZERO(pidref_in_same_namespace(NULL, &pid, NAMESPACE_MOUNT));
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
if (!have_namespaces())
|
||||
return log_tests_skipped("Don't have namespace support or lacking privileges");
|
||||
|
||||
Reference in New Issue
Block a user