mirror of
https://github.com/systemd/systemd.git
synced 2025-01-20 18:04:03 +03:00
Merge pull request #34026 from DaanDeMeyer/tests
Handle unprivileged user namespaces gracefully in tests
This commit is contained in:
commit
c4e809b6ad
@ -92,18 +92,24 @@ TEST(message_address) {
|
||||
struct in_addr in_data;
|
||||
struct ifa_cacheinfo cache;
|
||||
const char *label;
|
||||
int r;
|
||||
|
||||
assert_se(sd_netlink_open(&rtnl) >= 0);
|
||||
ifindex = (int) if_nametoindex("lo");
|
||||
|
||||
assert_se(sd_rtnl_message_new_addr(rtnl, &message, RTM_GETADDR, ifindex, AF_INET) >= 0);
|
||||
assert_se(sd_netlink_message_set_request_dump(message, true) >= 0);
|
||||
assert_se(sd_netlink_call(rtnl, message, 0, &reply) == 1);
|
||||
|
||||
assert_se(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data) >= 0);
|
||||
assert_se(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data) >= 0);
|
||||
assert_se(sd_netlink_message_read_string(reply, IFA_LABEL, &label) >= 0);
|
||||
assert_se(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache) == 0);
|
||||
r = sd_netlink_call(rtnl, message, 0, &reply);
|
||||
assert_se(r >= 0);
|
||||
|
||||
/* If the loopback device is down we won't get any results. */
|
||||
if (r > 0) {
|
||||
assert_se(sd_netlink_message_read_in_addr(reply, IFA_LOCAL, &in_data) >= 0);
|
||||
assert_se(sd_netlink_message_read_in_addr(reply, IFA_ADDRESS, &in_data) >= 0);
|
||||
assert_se(sd_netlink_message_read_string(reply, IFA_LABEL, &label) >= 0);
|
||||
assert_se(sd_netlink_message_read_cache_info(reply, IFA_CACHEINFO, &cache) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(message_route) {
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "uid-range.h"
|
||||
|
||||
char* setup_fake_runtime_dir(void) {
|
||||
char t[] = "/tmp/fake-xdg-runtime-XXXXXX", *p;
|
||||
@ -166,6 +167,24 @@ bool have_namespaces(void) {
|
||||
assert_not_reached();
|
||||
}
|
||||
|
||||
bool userns_has_single_user(void) {
|
||||
_cleanup_(uid_range_freep) UIDRange *uidrange = NULL, *gidrange = NULL;
|
||||
|
||||
/* Check if we're in a user namespace with only a single user mapped in. We special case this
|
||||
* scenario in a few tests because it's the only kind of namespace that can be created unprivileged
|
||||
* and as such happens more often than not, so we make sure to deal with it so that all tests pass
|
||||
* in such environments. */
|
||||
|
||||
if (uid_range_load_userns(NULL, UID_RANGE_USERNS_INSIDE, &uidrange) < 0)
|
||||
return false;
|
||||
|
||||
if (uid_range_load_userns(NULL, GID_RANGE_USERNS_INSIDE, &gidrange) < 0)
|
||||
return false;
|
||||
|
||||
return uidrange->n_entries == 1 && uidrange->entries[0].nr == 1 &&
|
||||
gidrange->n_entries == 1 && gidrange->entries[0].nr == 1;
|
||||
}
|
||||
|
||||
bool can_memlock(void) {
|
||||
/* Let's see if we can mlock() a larger blob of memory. BPF programs are charged against
|
||||
* RLIMIT_MEMLOCK, hence let's first make sure we can lock memory at all, and skip the test if we
|
||||
|
@ -76,6 +76,7 @@ void test_setup_logging(int level);
|
||||
int write_tmpfile(char *pattern, const char *contents);
|
||||
|
||||
bool have_namespaces(void);
|
||||
bool userns_has_single_user(void);
|
||||
|
||||
/* We use the small but non-trivial limit here */
|
||||
#define CAN_MEMLOCK_SIZE (512 * 1024U)
|
||||
|
@ -41,7 +41,7 @@ TEST_RET(add_acls_for_user) {
|
||||
cmd = strjoina("getfacl -p ", fn);
|
||||
assert_se(system(cmd) == 0);
|
||||
|
||||
if (getuid() == 0) {
|
||||
if (getuid() == 0 && !userns_has_single_user()) {
|
||||
const char *nobody = NOBODY_USER_NAME;
|
||||
r = get_user_creds(&nobody, &uid, NULL, NULL, NULL, 0);
|
||||
if (r < 0)
|
||||
|
@ -318,10 +318,13 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
show_capabilities();
|
||||
|
||||
test_drop_privileges();
|
||||
if (!userns_has_single_user())
|
||||
test_drop_privileges();
|
||||
|
||||
test_update_inherited_set();
|
||||
|
||||
fork_test(test_have_effective_cap);
|
||||
if (!userns_has_single_user())
|
||||
fork_test(test_have_effective_cap);
|
||||
|
||||
if (run_ambient)
|
||||
fork_test(test_apply_ambient_caps);
|
||||
|
@ -183,7 +183,7 @@ TEST(chase) {
|
||||
|
||||
/* Paths underneath the "root" with different UIDs while using CHASE_SAFE */
|
||||
|
||||
if (geteuid() == 0) {
|
||||
if (geteuid() == 0 && !userns_has_single_user()) {
|
||||
p = strjoina(temp, "/user");
|
||||
ASSERT_OK(mkdir(p, 0755));
|
||||
ASSERT_OK(chown(p, UID_NOBODY, GID_NOBODY));
|
||||
@ -313,7 +313,7 @@ TEST(chase) {
|
||||
r = chase(p, NULL, 0, &result, NULL);
|
||||
assert_se(r == -ENOENT);
|
||||
|
||||
if (geteuid() == 0) {
|
||||
if (geteuid() == 0 && !userns_has_single_user()) {
|
||||
p = strjoina(temp, "/priv1");
|
||||
ASSERT_OK(mkdir(p, 0755));
|
||||
|
||||
|
@ -153,8 +153,8 @@ TEST(chown_recursive) {
|
||||
}
|
||||
|
||||
static int intro(void) {
|
||||
if (geteuid() != 0)
|
||||
return log_tests_skipped("not running as root");
|
||||
if (geteuid() != 0 || userns_has_single_user())
|
||||
return log_tests_skipped("not running as root or in userns with single user");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -1003,6 +1003,13 @@ TEST(condition_test_group) {
|
||||
condition_free(condition);
|
||||
free(gid);
|
||||
|
||||
/* In an unprivileged user namespace with the current user mapped to root, all the auxiliary groups
|
||||
* of the user will be mapped to the nobody group, which means the user in the user namespace is in
|
||||
* both the root and the nobody group, meaning the next test can't work, so let's skip it in that
|
||||
* case. */
|
||||
if (in_group(NOBODY_GROUP_NAME) && in_group("root"))
|
||||
return (void) log_tests_skipped("user is in both root and nobody group");
|
||||
|
||||
groupname = (char*)(getegid() == 0 ? NOBODY_GROUP_NAME : "root");
|
||||
condition = condition_new(CONDITION_GROUP, groupname, false, false);
|
||||
assert_se(condition);
|
||||
|
@ -368,8 +368,8 @@ TEST(chmod_and_chown) {
|
||||
struct stat st;
|
||||
const char *p;
|
||||
|
||||
if (geteuid() != 0)
|
||||
return;
|
||||
if (geteuid() != 0 || userns_has_single_user())
|
||||
return (void) log_tests_skipped("not running as root or in userns with single user");
|
||||
|
||||
BLOCK_WITH_UMASK(0000);
|
||||
|
||||
|
@ -89,6 +89,9 @@ static void test_rm_rf_chmod_inner(void) {
|
||||
TEST(rm_rf_chmod) {
|
||||
int r;
|
||||
|
||||
if (getuid() == 0 && userns_has_single_user())
|
||||
return (void) log_tests_skipped("running as root or in userns with single user");
|
||||
|
||||
if (getuid() == 0) {
|
||||
/* This test only works unpriv (as only then the access mask for the owning user matters),
|
||||
* hence drop privs here */
|
||||
|
@ -170,7 +170,7 @@ TEST(getpeercred_getpeergroups) {
|
||||
struct ucred ucred;
|
||||
int pair[2] = EBADF_PAIR;
|
||||
|
||||
if (geteuid() == 0) {
|
||||
if (geteuid() == 0 && !userns_has_single_user()) {
|
||||
test_uid = 1;
|
||||
test_gid = 2;
|
||||
test_gids = (gid_t*) gids;
|
||||
|
Loading…
x
Reference in New Issue
Block a user