1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 4f08c3bdfSopenharmony_ci * 5f08c3bdfSopenharmony_ci * Ported by John George 6f08c3bdfSopenharmony_ci */ 7f08c3bdfSopenharmony_ci 8f08c3bdfSopenharmony_ci/* 9f08c3bdfSopenharmony_ci * Test setregid() when executed by a non-root user. 10f08c3bdfSopenharmony_ci */ 11f08c3bdfSopenharmony_ci 12f08c3bdfSopenharmony_ci#include <pwd.h> 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include "tst_test.h" 15f08c3bdfSopenharmony_ci#include "tst_uid.h" 16f08c3bdfSopenharmony_ci#include "compat_tst_16.h" 17f08c3bdfSopenharmony_ci 18f08c3bdfSopenharmony_cistatic int fail = -1; 19f08c3bdfSopenharmony_cistatic int pass; 20f08c3bdfSopenharmony_cistatic gid_t primary_gid, secondary_gid, neg_one = -1; 21f08c3bdfSopenharmony_ci 22f08c3bdfSopenharmony_cistruct tcase { 23f08c3bdfSopenharmony_ci gid_t *real_gid; 24f08c3bdfSopenharmony_ci gid_t *eff_gid; 25f08c3bdfSopenharmony_ci int *exp_ret; 26f08c3bdfSopenharmony_ci gid_t *exp_real_usr; 27f08c3bdfSopenharmony_ci gid_t *exp_eff_usr; 28f08c3bdfSopenharmony_ci char *test_msg; 29f08c3bdfSopenharmony_ci} tcases[] = { 30f08c3bdfSopenharmony_ci { 31f08c3bdfSopenharmony_ci &primary_gid, &secondary_gid, &pass, &primary_gid, &secondary_gid, 32f08c3bdfSopenharmony_ci "After setregid(primary, secondary),"}, { 33f08c3bdfSopenharmony_ci &neg_one, &primary_gid, &pass, &primary_gid, &primary_gid, 34f08c3bdfSopenharmony_ci "After setregid(-1, primary)"}, { 35f08c3bdfSopenharmony_ci &neg_one, &secondary_gid, &pass, &primary_gid, &secondary_gid, 36f08c3bdfSopenharmony_ci "After setregid(-1, secondary),"}, { 37f08c3bdfSopenharmony_ci &secondary_gid, &neg_one, &pass, &secondary_gid, &secondary_gid, 38f08c3bdfSopenharmony_ci "After setregid(secondary, -1),"}, { 39f08c3bdfSopenharmony_ci &neg_one, &neg_one, &pass, &secondary_gid, &secondary_gid, 40f08c3bdfSopenharmony_ci "After setregid(-1, -1),"}, { 41f08c3bdfSopenharmony_ci &neg_one, &secondary_gid, &pass, &secondary_gid, &secondary_gid, 42f08c3bdfSopenharmony_ci "After setregid(-1, secondary),"}, { 43f08c3bdfSopenharmony_ci &secondary_gid, &neg_one, &pass, &secondary_gid, &secondary_gid, 44f08c3bdfSopenharmony_ci "After setregid(secondary, -1),"}, { 45f08c3bdfSopenharmony_ci &secondary_gid, &secondary_gid, &pass, &secondary_gid, &secondary_gid, 46f08c3bdfSopenharmony_ci "After setregid(secondary, secondary),"}, { 47f08c3bdfSopenharmony_ci &primary_gid, &neg_one, &fail, &secondary_gid, &secondary_gid, 48f08c3bdfSopenharmony_ci "After setregid(primary, -1)"}, { 49f08c3bdfSopenharmony_ci &neg_one, &primary_gid, &fail, &secondary_gid, &secondary_gid, 50f08c3bdfSopenharmony_ci "After setregid(-1, primary)"}, { 51f08c3bdfSopenharmony_ci &primary_gid, &primary_gid, &fail, &secondary_gid, &secondary_gid, 52f08c3bdfSopenharmony_ci "After setregid(primary, primary)"},}; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistatic void setup(void) 55f08c3bdfSopenharmony_ci{ 56f08c3bdfSopenharmony_ci struct passwd *nobody; 57f08c3bdfSopenharmony_ci gid_t test_groups[2]; 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci nobody = SAFE_GETPWNAM("nobody"); 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci tst_get_gids(test_groups, 0, 2); 62f08c3bdfSopenharmony_ci primary_gid = test_groups[0]; 63f08c3bdfSopenharmony_ci secondary_gid = test_groups[1]; 64f08c3bdfSopenharmony_ci GID16_CHECK(primary_gid, setregid); 65f08c3bdfSopenharmony_ci GID16_CHECK(secondary_gid, setregid); 66f08c3bdfSopenharmony_ci 67f08c3bdfSopenharmony_ci /* set the appropriate ownership values */ 68f08c3bdfSopenharmony_ci SAFE_SETREGID(primary_gid, secondary_gid); 69f08c3bdfSopenharmony_ci SAFE_SETEUID(nobody->pw_uid); 70f08c3bdfSopenharmony_ci} 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_cistatic void test_success(struct tcase *tc) 73f08c3bdfSopenharmony_ci{ 74f08c3bdfSopenharmony_ci if (TST_RET != 0) 75f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, "setregid(%d, %d) failed unexpectedly", 76f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid); 77f08c3bdfSopenharmony_ci else 78f08c3bdfSopenharmony_ci tst_res(TPASS, "setregid(%d, %d) succeeded as expected", 79f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid); 80f08c3bdfSopenharmony_ci} 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_cistatic void test_failure(struct tcase *tc) 83f08c3bdfSopenharmony_ci{ 84f08c3bdfSopenharmony_ci if (TST_RET == 0) 85f08c3bdfSopenharmony_ci tst_res(TFAIL, "setregid(%d, %d) succeeded unexpectedly", 86f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid); 87f08c3bdfSopenharmony_ci else if (TST_ERR == EPERM) 88f08c3bdfSopenharmony_ci tst_res(TPASS, "setregid(%d, %d) failed as expected", 89f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid); 90f08c3bdfSopenharmony_ci else 91f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 92f08c3bdfSopenharmony_ci "setregid(%d, %d) did not set errno value as expected", 93f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid); 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_cistatic void gid_verify(gid_t rg, gid_t eg, char *when) 97f08c3bdfSopenharmony_ci{ 98f08c3bdfSopenharmony_ci if ((getgid() != rg) || (getegid() != eg)) { 99f08c3bdfSopenharmony_ci tst_res(TFAIL, "ERROR: %s real gid = %d; effective gid = %d", 100f08c3bdfSopenharmony_ci when, getgid(), getegid()); 101f08c3bdfSopenharmony_ci tst_res(TINFO, "Expected: real gid = %d; effective gid = %d", 102f08c3bdfSopenharmony_ci rg, eg); 103f08c3bdfSopenharmony_ci } else { 104f08c3bdfSopenharmony_ci tst_res(TPASS, 105f08c3bdfSopenharmony_ci "real or effective gid was modified as expected"); 106f08c3bdfSopenharmony_ci } 107f08c3bdfSopenharmony_ci} 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_cistatic void run(unsigned int i) 110f08c3bdfSopenharmony_ci{ 111f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[i]; 112f08c3bdfSopenharmony_ci 113f08c3bdfSopenharmony_ci /* Set the real or effective group id */ 114f08c3bdfSopenharmony_ci TEST(SETREGID(*tc->real_gid, *tc->eff_gid)); 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci if (*tc->exp_ret == 0) 117f08c3bdfSopenharmony_ci test_success(tc); 118f08c3bdfSopenharmony_ci else 119f08c3bdfSopenharmony_ci test_failure(tc); 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_ci gid_verify(*tc->exp_real_usr, *tc->exp_eff_usr, tc->test_msg); 122f08c3bdfSopenharmony_ci} 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_civoid run_all(void) 125f08c3bdfSopenharmony_ci{ 126f08c3bdfSopenharmony_ci unsigned int i; 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci if (!SAFE_FORK()) { 129f08c3bdfSopenharmony_ci for (i = 0; i < ARRAY_SIZE(tcases); i++) 130f08c3bdfSopenharmony_ci run(i); 131f08c3bdfSopenharmony_ci } 132f08c3bdfSopenharmony_ci} 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_cistatic struct tst_test test = { 135f08c3bdfSopenharmony_ci .needs_root = 1, 136f08c3bdfSopenharmony_ci .forks_child = 1, 137f08c3bdfSopenharmony_ci .test_all = run_all, 138f08c3bdfSopenharmony_ci .setup = setup, 139f08c3bdfSopenharmony_ci}; 140