• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_group_fallback(const char * gr1,const char * gr2)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 
get_group(const char * group)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 
setup(void)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 
test_success(struct tcase * tc)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 
test_failure(struct tcase * tc)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 
gid_verify(struct group * rg,struct group * eg,char * when)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 
run(unsigned int i)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 
run_all(void)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