test: Gracefully handle running within user namespace with single user

Unprivileged users often make themselves root by unsharing a user namespace
and then mapping their current user to root which does not require privileges.
Let's make sure our tests don't fail in such an environment by adding checks
where required to see if we're not running in a user namespace with only a
single user.
This commit is contained in:
Daan De Meyer
2024-08-18 21:53:52 +02:00
parent d098b8df6e
commit ef31767ed7
10 changed files with 43 additions and 10 deletions
+1 -1
View File
@@ -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)
+5 -2
View File
@@ -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);
+2 -2
View File
@@ -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));
+2 -2
View File
@@ -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;
}
+7
View File
@@ -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);
+2 -2
View File
@@ -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);
+3
View File
@@ -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 */
+1 -1
View File
@@ -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;