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