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 that setregid() fails and sets the proper errno values when a 10f08c3bdfSopenharmony_ci * non-root user attemps to change the real or effective group id to a 11f08c3bdfSopenharmony_ci * value other than the current gid or the current effective gid. 12f08c3bdfSopenharmony_ci */ 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci#include <errno.h> 15f08c3bdfSopenharmony_ci#include <pwd.h> 16f08c3bdfSopenharmony_ci#include <grp.h> 17f08c3bdfSopenharmony_ci#include <stdlib.h> 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci#include "tst_test.h" 20f08c3bdfSopenharmony_ci#include "tst_uid.h" 21f08c3bdfSopenharmony_ci#include "compat_tst_16.h" 22f08c3bdfSopenharmony_ci 23f08c3bdfSopenharmony_cistatic gid_t root_gid, nobody_gid, other_gid, neg_one = -1; 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_cistatic struct passwd *ltpuser; 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci/* 28f08c3bdfSopenharmony_ci * The following structure contains all test data. Each structure in the array 29f08c3bdfSopenharmony_ci * is used for a separate test. The tests are executed in the for loop below. 30f08c3bdfSopenharmony_ci */ 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_cistatic struct tcase { 33f08c3bdfSopenharmony_ci gid_t *real_gid; 34f08c3bdfSopenharmony_ci gid_t *eff_gid; 35f08c3bdfSopenharmony_ci int exp_errno; 36f08c3bdfSopenharmony_ci gid_t *exp_real_usr; 37f08c3bdfSopenharmony_ci gid_t *exp_eff_usr; 38f08c3bdfSopenharmony_ci char *test_msg; 39f08c3bdfSopenharmony_ci} tcases[] = { 40f08c3bdfSopenharmony_ci { 41f08c3bdfSopenharmony_ci &neg_one, &root_gid, EPERM, &nobody_gid, &nobody_gid, 42f08c3bdfSopenharmony_ci "After setregid(-1, root),"}, { 43f08c3bdfSopenharmony_ci &neg_one, &other_gid, EPERM, &nobody_gid, &nobody_gid, 44f08c3bdfSopenharmony_ci "After setregid(-1, other)"}, { 45f08c3bdfSopenharmony_ci &root_gid, &neg_one, EPERM, &nobody_gid, &nobody_gid, 46f08c3bdfSopenharmony_ci "After setregid(root,-1),"}, { 47f08c3bdfSopenharmony_ci &other_gid, &neg_one, EPERM, &nobody_gid, &nobody_gid, 48f08c3bdfSopenharmony_ci "After setregid(other, -1),"}, { 49f08c3bdfSopenharmony_ci &root_gid, &other_gid, EPERM, &nobody_gid, &nobody_gid, 50f08c3bdfSopenharmony_ci "After setregid(root, other)"}, { 51f08c3bdfSopenharmony_ci &other_gid, &root_gid, EPERM, &nobody_gid, &nobody_gid, 52f08c3bdfSopenharmony_ci "After setregid(other, root),"} 53f08c3bdfSopenharmony_ci}; 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_civoid gid_verify(gid_t rg, gid_t eg, char *when) 56f08c3bdfSopenharmony_ci{ 57f08c3bdfSopenharmony_ci if ((getgid() != rg) || (getegid() != eg)) { 58f08c3bdfSopenharmony_ci tst_res(TFAIL, "ERROR: %s real gid = %d; effective gid = %d", 59f08c3bdfSopenharmony_ci when, getgid(), getegid()); 60f08c3bdfSopenharmony_ci tst_res(TINFO, "Expected: real gid = %d; effective gid = %d", 61f08c3bdfSopenharmony_ci rg, eg); 62f08c3bdfSopenharmony_ci return; 63f08c3bdfSopenharmony_ci } 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_ci tst_res(TPASS, "real or effective gid wasn't modified as expected"); 66f08c3bdfSopenharmony_ci} 67f08c3bdfSopenharmony_ci 68f08c3bdfSopenharmony_cistatic void run(unsigned int n) 69f08c3bdfSopenharmony_ci{ 70f08c3bdfSopenharmony_ci struct tcase *tc = &tcases[n]; 71f08c3bdfSopenharmony_ci 72f08c3bdfSopenharmony_ci /* Set the real or effective group id */ 73f08c3bdfSopenharmony_ci TEST(SETREGID(*tc->real_gid, *tc->eff_gid)); 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci if (TST_RET == -1) { 76f08c3bdfSopenharmony_ci if (tc->exp_errno == TST_ERR) { 77f08c3bdfSopenharmony_ci tst_res(TPASS | TTERRNO, 78f08c3bdfSopenharmony_ci "setregid(%d, %d) failed as expected", 79f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid); 80f08c3bdfSopenharmony_ci } else { 81f08c3bdfSopenharmony_ci tst_res(TFAIL | TTERRNO, 82f08c3bdfSopenharmony_ci "setregid(%d, %d) failed unexpectedly, expected %s", 83f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid, 84f08c3bdfSopenharmony_ci tst_strerrno(tc->exp_errno)); 85f08c3bdfSopenharmony_ci } 86f08c3bdfSopenharmony_ci } else { 87f08c3bdfSopenharmony_ci tst_res(TFAIL, 88f08c3bdfSopenharmony_ci "setregid(%d, %d) did not fail (ret: %ld) as expected (ret: -1).", 89f08c3bdfSopenharmony_ci *tc->real_gid, *tc->eff_gid, TST_RET); 90f08c3bdfSopenharmony_ci } 91f08c3bdfSopenharmony_ci gid_verify(*tc->exp_real_usr, *tc->exp_eff_usr, tc->test_msg); 92f08c3bdfSopenharmony_ci} 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_cistatic void setup(void) 95f08c3bdfSopenharmony_ci{ 96f08c3bdfSopenharmony_ci gid_t test_groups[3]; 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci ltpuser = SAFE_GETPWNAM("nobody"); 99f08c3bdfSopenharmony_ci nobody_gid = test_groups[0] = ltpuser->pw_gid; 100f08c3bdfSopenharmony_ci root_gid = test_groups[1] = getgid(); 101f08c3bdfSopenharmony_ci tst_get_gids(test_groups, 2, 3); 102f08c3bdfSopenharmony_ci other_gid = test_groups[2]; 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci GID16_CHECK(root_gid, setregid); 105f08c3bdfSopenharmony_ci GID16_CHECK(nobody_gid, setregid); 106f08c3bdfSopenharmony_ci GID16_CHECK(other_gid, setregid); 107f08c3bdfSopenharmony_ci 108f08c3bdfSopenharmony_ci SAFE_SETGID(ltpuser->pw_gid); 109f08c3bdfSopenharmony_ci SAFE_SETUID(ltpuser->pw_uid); 110f08c3bdfSopenharmony_ci} 111f08c3bdfSopenharmony_ci 112f08c3bdfSopenharmony_cistatic struct tst_test test = { 113f08c3bdfSopenharmony_ci .tcnt = ARRAY_SIZE(tcases), 114f08c3bdfSopenharmony_ci .needs_root = 1, 115f08c3bdfSopenharmony_ci .test = run, 116f08c3bdfSopenharmony_ci .setup = setup, 117f08c3bdfSopenharmony_ci}; 118