namespace-util: add process_is_owned_by_uid() helper
This commit is contained in:
@@ -7,10 +7,12 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "namespace.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "tests.h"
|
||||
#include "uid-range.h"
|
||||
#include "user-util.h"
|
||||
#include "virt.h"
|
||||
|
||||
@@ -276,6 +278,93 @@ TEST(userns_get_base_uid) {
|
||||
ASSERT_ERROR(userns_get_base_uid(fd, &base_uid, &base_gid), ENOMSG);
|
||||
}
|
||||
|
||||
TEST(process_is_owned_by_uid) {
|
||||
int r;
|
||||
|
||||
/* Test our own PID */
|
||||
_cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
|
||||
ASSERT_OK(pidref_set_self(&pid));
|
||||
ASSERT_OK_POSITIVE(process_is_owned_by_uid(&pid, getuid()));
|
||||
pidref_done(&pid);
|
||||
|
||||
if (getuid() != 0)
|
||||
return (void) log_tests_skipped("lacking userns privileges");
|
||||
|
||||
_cleanup_(uid_range_freep) UIDRange *range = NULL;
|
||||
ASSERT_OK(uid_range_load_userns(/* path= */ NULL, UID_RANGE_USERNS_INSIDE, &range));
|
||||
if (!uid_range_contains(range, 1))
|
||||
return (void) log_tests_skipped("UID 1 not included in userns UID delegation, skipping test");
|
||||
|
||||
/* Test a child that runs as uid 1 */
|
||||
_cleanup_close_pair_ int p[2] = EBADF_PAIR;
|
||||
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC));
|
||||
|
||||
r = pidref_safe_fork("(child)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL, &pid);
|
||||
ASSERT_OK(r);
|
||||
if (r == 0) {
|
||||
p[0] = safe_close(p[0]);
|
||||
ASSERT_OK(fully_set_uid_gid(1, 1, NULL, 0));
|
||||
ASSERT_OK_EQ_ERRNO(write(p[1], &(const char[]) { 'x' }, 1), 1);
|
||||
p[1] = safe_close(p[1]);
|
||||
freeze();
|
||||
}
|
||||
|
||||
p[1] = safe_close(p[1]);
|
||||
char x = 0;
|
||||
ASSERT_OK_EQ_ERRNO(read(p[0], &x, 1), 1);
|
||||
ASSERT_EQ(x, 'x');
|
||||
p[0] = safe_close(p[0]);
|
||||
|
||||
ASSERT_OK_ZERO(process_is_owned_by_uid(&pid, getuid()));
|
||||
|
||||
ASSERT_OK(pidref_kill(&pid, SIGKILL));
|
||||
ASSERT_OK(pidref_wait_for_terminate(&pid, /* ret= */ NULL));
|
||||
|
||||
/* Test a child that runs in a userns as uid 1, but the userns is owned by us */
|
||||
ASSERT_OK_ERRNO(pipe2(p, O_CLOEXEC));
|
||||
|
||||
_cleanup_close_pair_ int pp[2] = EBADF_PAIR;
|
||||
ASSERT_OK_ERRNO(pipe2(pp, O_CLOEXEC));
|
||||
|
||||
r = pidref_safe_fork("(child)", FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL|FORK_NEW_USERNS, &pid);
|
||||
ASSERT_OK(r);
|
||||
if (r == 0) {
|
||||
p[0] = safe_close(p[0]);
|
||||
pp[1] = safe_close(pp[1]);
|
||||
|
||||
x = 0;
|
||||
ASSERT_OK_EQ_ERRNO(read(pp[0], &x, 1), 1);
|
||||
ASSERT_EQ(x, 'x');
|
||||
pp[0] = safe_close(pp[0]);
|
||||
|
||||
ASSERT_OK(reset_uid_gid());
|
||||
|
||||
ASSERT_OK_EQ_ERRNO(write(p[1], &(const char[]) { 'x' }, 1), 1);
|
||||
p[1] = safe_close(p[1]);
|
||||
freeze();
|
||||
}
|
||||
|
||||
p[1] = safe_close(p[1]);
|
||||
pp[0] = safe_close(pp[0]);
|
||||
|
||||
ASSERT_OK(write_string_file(procfs_file_alloca(pid.pid, "uid_map"), "0 1 1\n", 0));
|
||||
ASSERT_OK(write_string_file(procfs_file_alloca(pid.pid, "setgroups"), "deny", 0));
|
||||
ASSERT_OK(write_string_file(procfs_file_alloca(pid.pid, "gid_map"), "0 1 1\n", 0));
|
||||
|
||||
ASSERT_OK_EQ_ERRNO(write(pp[1], &(const char[]) { 'x' }, 1), 1);
|
||||
pp[1] = safe_close(pp[1]);
|
||||
|
||||
x = 0;
|
||||
ASSERT_OK_EQ_ERRNO(read(p[0], &x, 1), 1);
|
||||
ASSERT_EQ(x, 'x');
|
||||
p[0] = safe_close(p[0]);
|
||||
|
||||
ASSERT_OK_POSITIVE(process_is_owned_by_uid(&pid, getuid()));
|
||||
|
||||
ASSERT_OK(pidref_kill(&pid, SIGKILL));
|
||||
ASSERT_OK(pidref_wait_for_terminate(&pid, /* ret= */ NULL));
|
||||
}
|
||||
|
||||
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