1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001
4f08c3bdfSopenharmony_ci *  03/2001 Written by Wayne Boyer
5f08c3bdfSopenharmony_ci *  11/2016 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
6f08c3bdfSopenharmony_ci */
7f08c3bdfSopenharmony_ci
8f08c3bdfSopenharmony_ci/*
9f08c3bdfSopenharmony_ci * Verify that setpriority(2) succeeds set the scheduling priority of
10f08c3bdfSopenharmony_ci * the current process, process group or user.
11f08c3bdfSopenharmony_ci */
12f08c3bdfSopenharmony_ci
13f08c3bdfSopenharmony_ci#define _GNU_SOURCE
14f08c3bdfSopenharmony_ci#include <errno.h>
15f08c3bdfSopenharmony_ci#include <pwd.h>
16f08c3bdfSopenharmony_ci#include <stdlib.h>
17f08c3bdfSopenharmony_ci#include <sys/resource.h>
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_ci#include "tst_test.h"
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_cistatic const char *username = "ltp_setpriority01";
22f08c3bdfSopenharmony_cistatic int pid, uid, user_added;
23f08c3bdfSopenharmony_ci
24f08c3bdfSopenharmony_cistatic struct tcase {
25f08c3bdfSopenharmony_ci	int which;
26f08c3bdfSopenharmony_ci	int *who;
27f08c3bdfSopenharmony_ci} tcases[] = {
28f08c3bdfSopenharmony_ci	{PRIO_PROCESS, &pid},
29f08c3bdfSopenharmony_ci	{PRIO_PGRP, &pid},
30f08c3bdfSopenharmony_ci	{PRIO_USER, &uid}
31f08c3bdfSopenharmony_ci};
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_cistatic const char *str_which(int which)
34f08c3bdfSopenharmony_ci{
35f08c3bdfSopenharmony_ci	switch (which) {
36f08c3bdfSopenharmony_ci	case PRIO_PROCESS:
37f08c3bdfSopenharmony_ci		return "PRIO_PROCESS";
38f08c3bdfSopenharmony_ci	case PRIO_PGRP:
39f08c3bdfSopenharmony_ci		return "PRIO_PGRP";
40f08c3bdfSopenharmony_ci	case PRIO_USER:
41f08c3bdfSopenharmony_ci		return "PRIO_USER";
42f08c3bdfSopenharmony_ci	default:
43f08c3bdfSopenharmony_ci		return "???";
44f08c3bdfSopenharmony_ci	}
45f08c3bdfSopenharmony_ci}
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_cistatic void setpriority_test(struct tcase *tc)
48f08c3bdfSopenharmony_ci{
49f08c3bdfSopenharmony_ci	int new_prio, cur_prio;
50f08c3bdfSopenharmony_ci	int failflag = 0;
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci	for (new_prio = -20; new_prio < 20; new_prio++) {
53f08c3bdfSopenharmony_ci		TEST(setpriority(tc->which, *tc->who, new_prio));
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_ci		if (TST_RET != 0) {
56f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO,
57f08c3bdfSopenharmony_ci				"setpriority(%d, %d, %d) failed",
58f08c3bdfSopenharmony_ci				tc->which, *tc->who, new_prio);
59f08c3bdfSopenharmony_ci			failflag = 1;
60f08c3bdfSopenharmony_ci			continue;
61f08c3bdfSopenharmony_ci		}
62f08c3bdfSopenharmony_ci
63f08c3bdfSopenharmony_ci		cur_prio = SAFE_GETPRIORITY(tc->which, *tc->who);
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ci		if (cur_prio != new_prio) {
66f08c3bdfSopenharmony_ci			tst_res(TFAIL, "current priority(%d) and "
67f08c3bdfSopenharmony_ci				"new priority(%d) do not match",
68f08c3bdfSopenharmony_ci				cur_prio, new_prio);
69f08c3bdfSopenharmony_ci			failflag = 1;
70f08c3bdfSopenharmony_ci		}
71f08c3bdfSopenharmony_ci	}
72f08c3bdfSopenharmony_ci
73f08c3bdfSopenharmony_ci	if (!failflag) {
74f08c3bdfSopenharmony_ci		tst_res(TPASS, "setpriority(%s(%d), %d, -20..19) succeeded",
75f08c3bdfSopenharmony_ci			str_which(tc->which), tc->which, *tc->who);
76f08c3bdfSopenharmony_ci	}
77f08c3bdfSopenharmony_ci}
78f08c3bdfSopenharmony_ci
79f08c3bdfSopenharmony_cistatic void verify_setpriority(unsigned int n)
80f08c3bdfSopenharmony_ci{
81f08c3bdfSopenharmony_ci	struct tcase *tc = &tcases[n];
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci	if (tc->which == PRIO_USER && !user_added) {
84f08c3bdfSopenharmony_ci		tst_res(TCONF, "setpriority(%s(%d), %d, -20..19) skipped - Can't add user",
85f08c3bdfSopenharmony_ci			str_which(tc->which), tc->which, *tc->who);
86f08c3bdfSopenharmony_ci		return;
87f08c3bdfSopenharmony_ci	}
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	pid = SAFE_FORK();
90f08c3bdfSopenharmony_ci	if (pid == 0) {
91f08c3bdfSopenharmony_ci		if (user_added)
92f08c3bdfSopenharmony_ci			SAFE_SETUID(uid);
93f08c3bdfSopenharmony_ci		SAFE_SETPGID(0, 0);
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_ci		TST_CHECKPOINT_WAKE_AND_WAIT(0);
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci		exit(0);
98f08c3bdfSopenharmony_ci	}
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAIT(0);
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_ci	setpriority_test(tc);
103f08c3bdfSopenharmony_ci
104f08c3bdfSopenharmony_ci	TST_CHECKPOINT_WAKE(0);
105f08c3bdfSopenharmony_ci
106f08c3bdfSopenharmony_ci	tst_reap_children();
107f08c3bdfSopenharmony_ci}
108f08c3bdfSopenharmony_ci
109f08c3bdfSopenharmony_cistatic void setup(void)
110f08c3bdfSopenharmony_ci{
111f08c3bdfSopenharmony_ci	const char *const cmd_useradd[] = {"useradd", username, NULL};
112f08c3bdfSopenharmony_ci	struct passwd *ltpuser;
113f08c3bdfSopenharmony_ci	int rc;
114f08c3bdfSopenharmony_ci
115f08c3bdfSopenharmony_ci	switch ((rc = tst_cmd(cmd_useradd, NULL, NULL, TST_CMD_PASS_RETVAL))) {
116f08c3bdfSopenharmony_ci	case 0:
117f08c3bdfSopenharmony_ci		user_added = 1;
118f08c3bdfSopenharmony_ci		ltpuser = SAFE_GETPWNAM(username);
119f08c3bdfSopenharmony_ci		uid = ltpuser->pw_uid;
120f08c3bdfSopenharmony_ci		return;
121f08c3bdfSopenharmony_ci	case 1:
122f08c3bdfSopenharmony_ci	case 255:
123f08c3bdfSopenharmony_ci		return;
124f08c3bdfSopenharmony_ci	default:
125f08c3bdfSopenharmony_ci		tst_brk(TBROK, "Useradd failed (%d)", rc);
126f08c3bdfSopenharmony_ci	}
127f08c3bdfSopenharmony_ci}
128f08c3bdfSopenharmony_ci
129f08c3bdfSopenharmony_cistatic void cleanup(void)
130f08c3bdfSopenharmony_ci{
131f08c3bdfSopenharmony_ci	if (!user_added)
132f08c3bdfSopenharmony_ci		return;
133f08c3bdfSopenharmony_ci
134f08c3bdfSopenharmony_ci	const char *const cmd_userdel[] = {"userdel", "-r", username, NULL};
135f08c3bdfSopenharmony_ci
136f08c3bdfSopenharmony_ci	if (tst_cmd(cmd_userdel, NULL, NULL, TST_CMD_PASS_RETVAL))
137f08c3bdfSopenharmony_ci		tst_res(TWARN | TERRNO, "'userdel -r %s' failed", username);
138f08c3bdfSopenharmony_ci}
139f08c3bdfSopenharmony_ci
140f08c3bdfSopenharmony_cistatic struct tst_test test = {
141f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
142f08c3bdfSopenharmony_ci	.needs_root = 1,
143f08c3bdfSopenharmony_ci	.forks_child = 1,
144f08c3bdfSopenharmony_ci	.needs_checkpoints = 1,
145f08c3bdfSopenharmony_ci	.setup = setup,
146f08c3bdfSopenharmony_ci	.cleanup = cleanup,
147f08c3bdfSopenharmony_ci	.test = verify_setpriority,
148f08c3bdfSopenharmony_ci};
149