1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2016 Linux Test Project.
4f08c3bdfSopenharmony_ci */
5f08c3bdfSopenharmony_ci
6f08c3bdfSopenharmony_ci/*
7f08c3bdfSopenharmony_ci * A regression test for can_nice call usage in sched_setscheduler,
8f08c3bdfSopenharmony_ci * introduced by kernel commit:
9f08c3bdfSopenharmony_ci *    d50dde5a (sched: Add new scheduler syscalls to support
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * This was fixed by below commit:
12f08c3bdfSopenharmony_ci *    eaad4513 (sched: Fix __sched_setscheduler() nice test
13f08c3bdfSopenharmony_ci *
14f08c3bdfSopenharmony_ci */
15f08c3bdfSopenharmony_ci
16f08c3bdfSopenharmony_ci#define _GNU_SOURCE
17f08c3bdfSopenharmony_ci#include <stdio.h>
18f08c3bdfSopenharmony_ci#include <errno.h>
19f08c3bdfSopenharmony_ci#include <pwd.h>
20f08c3bdfSopenharmony_ci#include <sys/time.h>
21f08c3bdfSopenharmony_ci#include <sys/resource.h>
22f08c3bdfSopenharmony_ci#include <sys/wait.h>
23f08c3bdfSopenharmony_ci#include <stdlib.h>
24f08c3bdfSopenharmony_ci
25f08c3bdfSopenharmony_ci#include "tst_test.h"
26f08c3bdfSopenharmony_ci#include "tst_sched.h"
27f08c3bdfSopenharmony_ci
28f08c3bdfSopenharmony_ci#define RLIMIT_NICE_NORMAL 20
29f08c3bdfSopenharmony_ci
30f08c3bdfSopenharmony_cistatic pid_t zero_pid;
31f08c3bdfSopenharmony_cistatic struct sched_param param[1] = { {0} };
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_cistruct test_case_t {
34f08c3bdfSopenharmony_ci	pid_t *pid;
35f08c3bdfSopenharmony_ci	int policy;
36f08c3bdfSopenharmony_ci	struct sched_param *sched_param;
37f08c3bdfSopenharmony_ci	int error;
38f08c3bdfSopenharmony_ci};
39f08c3bdfSopenharmony_ci
40f08c3bdfSopenharmony_cistruct test_case_t cases[] = {
41f08c3bdfSopenharmony_ci	{
42f08c3bdfSopenharmony_ci		.pid = &zero_pid,
43f08c3bdfSopenharmony_ci		.policy = SCHED_OTHER,
44f08c3bdfSopenharmony_ci		.sched_param = &param[0]
45f08c3bdfSopenharmony_ci	},
46f08c3bdfSopenharmony_ci	{
47f08c3bdfSopenharmony_ci		.pid = &zero_pid,
48f08c3bdfSopenharmony_ci		.policy = SCHED_BATCH,
49f08c3bdfSopenharmony_ci		.sched_param = &param[0]
50f08c3bdfSopenharmony_ci	},
51f08c3bdfSopenharmony_ci#ifdef SCHED_IDLE
52f08c3bdfSopenharmony_ci	{
53f08c3bdfSopenharmony_ci		.pid = &zero_pid,
54f08c3bdfSopenharmony_ci		.policy = SCHED_IDLE,
55f08c3bdfSopenharmony_ci		.sched_param = &param[0]
56f08c3bdfSopenharmony_ci	}
57f08c3bdfSopenharmony_ci#endif
58f08c3bdfSopenharmony_ci};
59f08c3bdfSopenharmony_ci
60f08c3bdfSopenharmony_cistatic void l_rlimit_show(const int type, struct rlimit *limit)
61f08c3bdfSopenharmony_ci{
62f08c3bdfSopenharmony_ci	SAFE_GETRLIMIT(type, limit);
63f08c3bdfSopenharmony_ci	tst_res(TINFO,
64f08c3bdfSopenharmony_ci		"rlimit rlim_cur=%lu", (unsigned long)(limit->rlim_cur));
65f08c3bdfSopenharmony_ci	tst_res(TINFO,
66f08c3bdfSopenharmony_ci		"rlimit rlim_max=%lu", (unsigned long)(limit->rlim_max));
67f08c3bdfSopenharmony_ci}
68f08c3bdfSopenharmony_ci
69f08c3bdfSopenharmony_cistatic void l_rlimit_setup(const int type, struct rlimit *limit)
70f08c3bdfSopenharmony_ci{
71f08c3bdfSopenharmony_ci	struct rlimit tmp_rlimit;
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	tst_res(TINFO,
74f08c3bdfSopenharmony_ci		"Setting rlim_cur to %lu", (unsigned long)(limit->rlim_cur));
75f08c3bdfSopenharmony_ci	tst_res(TINFO,
76f08c3bdfSopenharmony_ci		"Setting rlim_max to %lu", (unsigned long)(limit->rlim_max));
77f08c3bdfSopenharmony_ci
78f08c3bdfSopenharmony_ci	SAFE_SETRLIMIT(type, limit);
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	l_rlimit_show(RLIMIT_NICE, &tmp_rlimit);
81f08c3bdfSopenharmony_ci
82f08c3bdfSopenharmony_ci	if (tmp_rlimit.rlim_cur != limit->rlim_cur)
83f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO, "Expect rlim_cur = %lu, get %lu",
84f08c3bdfSopenharmony_ci				(unsigned long)(limit->rlim_cur),
85f08c3bdfSopenharmony_ci				(unsigned long)tmp_rlimit.rlim_cur);
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci	if (tmp_rlimit.rlim_max != limit->rlim_max)
88f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO, "Expect rlim_max = %lu, get %lu",
89f08c3bdfSopenharmony_ci				(unsigned long)(limit->rlim_max),
90f08c3bdfSopenharmony_ci				(unsigned long)(tmp_rlimit.rlim_max));
91f08c3bdfSopenharmony_ci}
92f08c3bdfSopenharmony_ci
93f08c3bdfSopenharmony_cistatic void verify_fn(unsigned int i)
94f08c3bdfSopenharmony_ci{
95f08c3bdfSopenharmony_ci	struct sched_variant *tv = &sched_variants[tst_variant];
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	tst_res(TINFO, "Verifying case[%d]: policy = %d, priority = %d",
98f08c3bdfSopenharmony_ci		i + 1, cases[i].policy, cases[i].sched_param->sched_priority);
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_ci	TST_EXP_PASS(tv->sched_setscheduler(*cases[i].pid, cases[i].policy,
101f08c3bdfSopenharmony_ci		     cases[i].sched_param));
102f08c3bdfSopenharmony_ci}
103f08c3bdfSopenharmony_ci
104f08c3bdfSopenharmony_cistatic void setup(void)
105f08c3bdfSopenharmony_ci{
106f08c3bdfSopenharmony_ci	struct sched_variant *tv = &sched_variants[tst_variant];
107f08c3bdfSopenharmony_ci	uid_t ruid, euid, suid;
108f08c3bdfSopenharmony_ci	struct rlimit limit;
109f08c3bdfSopenharmony_ci	struct passwd *pw;
110f08c3bdfSopenharmony_ci	uid_t nobody_uid;
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ci	tst_res(TINFO, "Testing %s variant", tv->desc);
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	pw = SAFE_GETPWNAM("nobody");
115f08c3bdfSopenharmony_ci	nobody_uid = pw->pw_uid;
116f08c3bdfSopenharmony_ci	l_rlimit_show(RLIMIT_NICE, &limit);
117f08c3bdfSopenharmony_ci
118f08c3bdfSopenharmony_ci	/*
119f08c3bdfSopenharmony_ci	* nice rlimit ranges from 1 to 40, mapping to real nice
120f08c3bdfSopenharmony_ci	* value from 19 to -20. We set it to 19, as the default priority
121f08c3bdfSopenharmony_ci	* of process with fair policy is 120, which will be translated
122f08c3bdfSopenharmony_ci	* into nice 20, we make this RLIMIT_NICE smaller than that, to
123f08c3bdfSopenharmony_ci	* verify the can_nice usage issue.
124f08c3bdfSopenharmony_ci	*/
125f08c3bdfSopenharmony_ci	limit.rlim_cur = (RLIMIT_NICE_NORMAL - 1);
126f08c3bdfSopenharmony_ci	limit.rlim_max = (RLIMIT_NICE_NORMAL - 1);
127f08c3bdfSopenharmony_ci
128f08c3bdfSopenharmony_ci	l_rlimit_setup(RLIMIT_NICE, &limit);
129f08c3bdfSopenharmony_ci
130f08c3bdfSopenharmony_ci	tst_res(TINFO, "Setting init sched policy to SCHED_OTHER");
131f08c3bdfSopenharmony_ci	if (tv->sched_setscheduler(0, SCHED_OTHER, &param[0]))
132f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO, "sched_setscheduler(0, SCHED_OTHER, 0)");
133f08c3bdfSopenharmony_ci	if (tv->sched_getscheduler(0) != SCHED_OTHER)
134f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO, "sched_getscheduler(0) != SCHED_OTHER");
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ci	tst_res(TINFO, "Setting euid to nobody to drop privilege");
137f08c3bdfSopenharmony_ci
138f08c3bdfSopenharmony_ci	SAFE_SETEUID(nobody_uid);
139f08c3bdfSopenharmony_ci	SAFE_GETRESUID(&ruid, &euid, &suid);
140f08c3bdfSopenharmony_ci	if (euid != nobody_uid)
141f08c3bdfSopenharmony_ci		tst_brk(TBROK | TERRNO, "ERROR seteuid(nobody_uid)");
142f08c3bdfSopenharmony_ci}
143f08c3bdfSopenharmony_ci
144f08c3bdfSopenharmony_cistatic void do_test(unsigned int i)
145f08c3bdfSopenharmony_ci{
146f08c3bdfSopenharmony_ci	int status = 0;
147f08c3bdfSopenharmony_ci	pid_t f_pid = SAFE_FORK();
148f08c3bdfSopenharmony_ci
149f08c3bdfSopenharmony_ci	if (f_pid == 0) {
150f08c3bdfSopenharmony_ci		tst_res(TINFO, "forked pid is %d", getpid());
151f08c3bdfSopenharmony_ci		verify_fn(i);
152f08c3bdfSopenharmony_ci		exit(0);
153f08c3bdfSopenharmony_ci	}
154f08c3bdfSopenharmony_ci
155f08c3bdfSopenharmony_ci	SAFE_WAIT(&status);
156f08c3bdfSopenharmony_ci}
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_cistatic struct tst_test test = {
159f08c3bdfSopenharmony_ci	.test_variants = ARRAY_SIZE(sched_variants),
160f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(cases),
161f08c3bdfSopenharmony_ci	.test = do_test,
162f08c3bdfSopenharmony_ci	.setup = setup,
163f08c3bdfSopenharmony_ci	.needs_root = 1,
164f08c3bdfSopenharmony_ci	.forks_child = 1
165f08c3bdfSopenharmony_ci};
166f08c3bdfSopenharmony_ci
167