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 setregid() when executed by a non-root user. 10 */ 11 12 #include <pwd.h> 13 14 #include "tst_test.h" 15 #include "compat_tst_16.h" 16 17 static int fail = -1; 18 static int pass; 19 static gid_t neg_one = -1; 20 21 struct group nobody_gr, daemon_gr, root_gr, bin_gr; 22 struct passwd nobody; 23 24 struct tcase { 25 gid_t *real_gid; 26 gid_t *eff_gid; 27 int *exp_ret; 28 struct group *exp_real_usr; 29 struct group *exp_eff_usr; 30 char *test_msg; 31 } tcases[] = { 32 { 33 &daemon_gr.gr_gid, &bin_gr.gr_gid, &pass, &daemon_gr, &bin_gr, 34 "After setregid(daemon, bin),"}, { 35 &neg_one, &daemon_gr.gr_gid, &pass, &daemon_gr, &daemon_gr, 36 "After setregid(-1, daemon)"}, { 37 &neg_one, &bin_gr.gr_gid, &pass, &daemon_gr, &bin_gr, 38 "After setregid(-1, bin),"}, { 39 &bin_gr.gr_gid, &neg_one, &pass, &bin_gr, &bin_gr, 40 "After setregid(bin, -1),"}, { 41 &neg_one, &neg_one, &pass, &bin_gr, &bin_gr, 42 "After setregid(-1, -1),"}, { 43 &neg_one, &bin_gr.gr_gid, &pass, &bin_gr, &bin_gr, 44 "After setregid(-1, bin),"}, { 45 &bin_gr.gr_gid, &neg_one, &pass, &bin_gr, &bin_gr, 46 "After setregid(bin, -1),"}, { 47 &bin_gr.gr_gid, &bin_gr.gr_gid, &pass, &bin_gr, &bin_gr, 48 "After setregid(bin, bin),"}, { 49 &daemon_gr.gr_gid, &neg_one, &fail, &bin_gr, &bin_gr, 50 "After setregid(daemon, -1)"}, { 51 &neg_one, &daemon_gr.gr_gid, &fail, &bin_gr, &bin_gr, 52 "After setregid(-1, daemon)"}, { 53 &daemon_gr.gr_gid, &daemon_gr.gr_gid, &fail, &bin_gr, &bin_gr, 54 "After setregid(daemon, daemon)"},}; 55 56 57 static struct group get_group_fallback(const char *gr1, const char *gr2) 58 { 59 struct group *junk; 60 61 junk = SAFE_GETGRNAM_FALLBACK(gr1, gr2); 62 GID16_CHECK(junk->gr_gid, setregid); 63 return *junk; 64 } 65 66 static struct group get_group(const char *group) 67 { 68 struct group *junk; 69 70 junk = SAFE_GETGRNAM(group); 71 GID16_CHECK(junk->gr_gid, setregid); 72 return *junk; 73 } 74 75 static void setup(void) 76 { 77 nobody = *SAFE_GETPWNAM("nobody"); 78 79 nobody_gr = get_group_fallback("nobody", "nogroup"); 80 daemon_gr = get_group("daemon"); 81 bin_gr = get_group("bin"); 82 83 /* set the appropriate ownership values */ 84 SAFE_SETREGID(daemon_gr.gr_gid, bin_gr.gr_gid); 85 SAFE_SETEUID(nobody.pw_uid); 86 } 87 88 static void test_success(struct tcase *tc) 89 { 90 if (TST_RET != 0) 91 tst_res(TFAIL | TTERRNO, "setregid(%d, %d) failed unexpectedly", 92 *tc->real_gid, *tc->eff_gid); 93 else 94 tst_res(TPASS, "setregid(%d, %d) succeeded as expected", 95 *tc->real_gid, *tc->eff_gid); 96 } 97 98 static void test_failure(struct tcase *tc) 99 { 100 if (TST_RET == 0) 101 tst_res(TFAIL, "setregid(%d, %d) succeeded unexpectedly", 102 *tc->real_gid, *tc->eff_gid); 103 else if (TST_ERR == EPERM) 104 tst_res(TPASS, "setregid(%d, %d) failed as expected", 105 *tc->real_gid, *tc->eff_gid); 106 else 107 tst_res(TFAIL | TTERRNO, 108 "setregid(%d, %d) did not set errno value as expected", 109 *tc->real_gid, *tc->eff_gid); 110 } 111 112 static void gid_verify(struct group *rg, struct group *eg, char *when) 113 { 114 if ((getgid() != rg->gr_gid) || (getegid() != eg->gr_gid)) { 115 tst_res(TFAIL, "ERROR: %s real gid = %d; effective gid = %d", 116 when, getgid(), getegid()); 117 tst_res(TINFO, "Expected: real gid = %d; effective gid = %d", 118 rg->gr_gid, eg->gr_gid); 119 } else { 120 tst_res(TPASS, 121 "real or effective gid was modified as expected"); 122 } 123 } 124 125 static void run(unsigned int i) 126 { 127 struct tcase *tc = &tcases[i]; 128 129 /* Set the real or effective group id */ 130 TEST(SETREGID(*tc->real_gid, *tc->eff_gid)); 131 132 if (*tc->exp_ret == 0) 133 test_success(tc); 134 else 135 test_failure(tc); 136 137 gid_verify(tc->exp_real_usr, tc->exp_eff_usr, tc->test_msg); 138 } 139 140 void run_all(void) 141 { 142 unsigned int i; 143 144 if (!SAFE_FORK()) { 145 for (i = 0; i < ARRAY_SIZE(tcases); i++) 146 run(i); 147 } 148 } 149 150 static struct tst_test test = { 151 .needs_root = 1, 152 .forks_child = 1, 153 .test_all = run_all, 154 .setup = setup, 155 }; 156