1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) Wipro Technologies Ltd, 2002.  All Rights Reserved.
4f08c3bdfSopenharmony_ci *    AUTHOR: Madhu T L <madhu.tarikere@wipro.com>
5f08c3bdfSopenharmony_ci * Copyright (C) 2021 SUSE LLC <mdoucha@suse.cz>
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*\
9f08c3bdfSopenharmony_ci * [Description]
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * Verify that setresgid() fails with EPERM if unprivileged user tries to set
12f08c3bdfSopenharmony_ci * process group ID which requires higher permissions.
13f08c3bdfSopenharmony_ci */
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_ci#include <sys/types.h>
16f08c3bdfSopenharmony_ci#include <pwd.h>
17f08c3bdfSopenharmony_ci
18f08c3bdfSopenharmony_ci#include "tst_test.h"
19f08c3bdfSopenharmony_ci#include "tst_uid.h"
20f08c3bdfSopenharmony_ci#include "compat_tst_16.h"
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_cistruct test_case_t {
23f08c3bdfSopenharmony_ci	gid_t *rgid;
24f08c3bdfSopenharmony_ci	gid_t *egid;
25f08c3bdfSopenharmony_ci	gid_t *sgid;
26f08c3bdfSopenharmony_ci	gid_t *exp_rgid;
27f08c3bdfSopenharmony_ci	gid_t *exp_egid;
28f08c3bdfSopenharmony_ci	gid_t *exp_sgid;
29f08c3bdfSopenharmony_ci	char *desc;
30f08c3bdfSopenharmony_ci};
31f08c3bdfSopenharmony_ci
32f08c3bdfSopenharmony_cistatic gid_t nobody_gid, other_gid, neg = -1;
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_cistatic struct test_case_t test_cases[] = {
35f08c3bdfSopenharmony_ci	{&neg, &neg, &other_gid, &nobody_gid, &nobody_gid, &nobody_gid,
36f08c3bdfSopenharmony_ci		"setresgid(-1, -1, other)"},
37f08c3bdfSopenharmony_ci	{&neg, &other_gid, &neg, &nobody_gid, &nobody_gid, &nobody_gid,
38f08c3bdfSopenharmony_ci		"setresgid(-1, other, -1)"},
39f08c3bdfSopenharmony_ci	{&other_gid, &neg, &neg, &nobody_gid, &nobody_gid, &nobody_gid,
40f08c3bdfSopenharmony_ci		"setresgid(other, -1, -1)"},
41f08c3bdfSopenharmony_ci	{&other_gid, &other_gid, &other_gid, &nobody_gid, &nobody_gid,
42f08c3bdfSopenharmony_ci		&nobody_gid, "setresgid(other, other, other)"},
43f08c3bdfSopenharmony_ci};
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_cistatic void setup(void)
46f08c3bdfSopenharmony_ci{
47f08c3bdfSopenharmony_ci	gid_t test_groups[2];
48f08c3bdfSopenharmony_ci	struct passwd *pw = SAFE_GETPWNAM("nobody");
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci	nobody_gid = test_groups[0] = pw->pw_gid;
51f08c3bdfSopenharmony_ci	tst_get_gids(test_groups, 1, 2);
52f08c3bdfSopenharmony_ci	other_gid = test_groups[1];
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ci	GID16_CHECK(nobody_gid, setresgid);
55f08c3bdfSopenharmony_ci	GID16_CHECK(other_gid, setresgid);
56f08c3bdfSopenharmony_ci
57f08c3bdfSopenharmony_ci	/* Set real/effective/saved gid to nobody */
58f08c3bdfSopenharmony_ci	SAFE_SETRESGID(nobody_gid, nobody_gid, nobody_gid);
59f08c3bdfSopenharmony_ci	SAFE_SETUID(pw->pw_uid);
60f08c3bdfSopenharmony_ci}
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_cistatic void run(unsigned int n)
63f08c3bdfSopenharmony_ci{
64f08c3bdfSopenharmony_ci	const struct test_case_t *tc = test_cases + n;
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci	TST_EXP_FAIL(SETRESGID(*tc->rgid, *tc->egid, *tc->sgid), EPERM, "%s",
67f08c3bdfSopenharmony_ci		tc->desc);
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_ci	if (!TST_PASS)
70f08c3bdfSopenharmony_ci		return;
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ci	tst_check_resgid(tc->desc, *tc->exp_rgid, *tc->exp_egid,
73f08c3bdfSopenharmony_ci		*tc->exp_sgid);
74f08c3bdfSopenharmony_ci}
75f08c3bdfSopenharmony_ci
76f08c3bdfSopenharmony_cistatic struct tst_test test = {
77f08c3bdfSopenharmony_ci	.test = run,
78f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(test_cases),
79f08c3bdfSopenharmony_ci	.setup = setup,
80f08c3bdfSopenharmony_ci	.needs_root = 1,
81f08c3bdfSopenharmony_ci};
82