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,
10f08c3bdfSopenharmony_ci *  1) setpriority(2) fails with -1 and sets errno to EINVAL if 'which'
11f08c3bdfSopenharmony_ci *     argument was not one of PRIO_PROCESS, PRIO_PGRP, or PRIO_USER.
12f08c3bdfSopenharmony_ci *  2) setpriority(2) fails with -1 and sets errno to ESRCH if no
13f08c3bdfSopenharmony_ci *     process was located for 'which' and 'who' arguments.
14f08c3bdfSopenharmony_ci *  3) setpriority(2) fails with -1 and sets errno to EACCES if an
15f08c3bdfSopenharmony_ci *     unprivileged user attempted to lower a process priority.
16f08c3bdfSopenharmony_ci *  4) setpriority(2) fails with -1 and sets errno to EPERM if an
17f08c3bdfSopenharmony_ci *     unprivileged user attempted to change a process which ID is
18f08c3bdfSopenharmony_ci *     different from the test process.
19f08c3bdfSopenharmony_ci */
20f08c3bdfSopenharmony_ci
21f08c3bdfSopenharmony_ci#include <errno.h>
22f08c3bdfSopenharmony_ci#include <pwd.h>
23f08c3bdfSopenharmony_ci#include <stdlib.h>
24f08c3bdfSopenharmony_ci#include <sys/resource.h>
25f08c3bdfSopenharmony_ci#include <sys/time.h>
26f08c3bdfSopenharmony_ci#include <sys/types.h>
27f08c3bdfSopenharmony_ci#include "tst_test.h"
28f08c3bdfSopenharmony_ci
29f08c3bdfSopenharmony_ci#define NEW_PRIO	-2
30f08c3bdfSopenharmony_ci#define INVAL_FLAG	-1
31f08c3bdfSopenharmony_ci#define INVAL_ID	-1
32f08c3bdfSopenharmony_ci#define INIT_PID	1
33f08c3bdfSopenharmony_ci
34f08c3bdfSopenharmony_cistatic uid_t uid;
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_cistatic struct tcase {
37f08c3bdfSopenharmony_ci	int which;
38f08c3bdfSopenharmony_ci	int who;
39f08c3bdfSopenharmony_ci	int prio;
40f08c3bdfSopenharmony_ci	int exp_errno;
41f08c3bdfSopenharmony_ci	int unprivil;
42f08c3bdfSopenharmony_ci} tcases[] = {
43f08c3bdfSopenharmony_ci	{INVAL_FLAG, 0, NEW_PRIO, EINVAL, 0},
44f08c3bdfSopenharmony_ci
45f08c3bdfSopenharmony_ci	{PRIO_PROCESS, INVAL_ID, NEW_PRIO, ESRCH, 0},
46f08c3bdfSopenharmony_ci	{PRIO_PGRP, INVAL_ID, NEW_PRIO, ESRCH, 0},
47f08c3bdfSopenharmony_ci	{PRIO_USER, INVAL_ID, NEW_PRIO, ESRCH, 0},
48f08c3bdfSopenharmony_ci
49f08c3bdfSopenharmony_ci	{PRIO_PROCESS, 0, NEW_PRIO, EACCES, 1},
50f08c3bdfSopenharmony_ci	{PRIO_PGRP, 0, NEW_PRIO, EACCES, 1},
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_ci	{PRIO_PROCESS, INIT_PID, NEW_PRIO, EPERM, 1}
53f08c3bdfSopenharmony_ci};
54f08c3bdfSopenharmony_ci
55f08c3bdfSopenharmony_cistatic void setpriority_test(struct tcase *tc)
56f08c3bdfSopenharmony_ci{
57f08c3bdfSopenharmony_ci	char *desc = "";
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_ci	if (tc->unprivil)
60f08c3bdfSopenharmony_ci		desc = "as unprivileged user ";
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	TEST(setpriority(tc->which, tc->who, tc->prio));
63f08c3bdfSopenharmony_ci
64f08c3bdfSopenharmony_ci	if (TST_RET != -1) {
65f08c3bdfSopenharmony_ci		tst_res(TFAIL,
66f08c3bdfSopenharmony_ci			"setpriority(%d, %d, %d) %ssucceeds unexpectedly "
67f08c3bdfSopenharmony_ci			"returned %ld", tc->which, tc->who, tc->prio, desc,
68f08c3bdfSopenharmony_ci			TST_RET);
69f08c3bdfSopenharmony_ci		return;
70f08c3bdfSopenharmony_ci	}
71f08c3bdfSopenharmony_ci
72f08c3bdfSopenharmony_ci	if (TST_ERR != tc->exp_errno) {
73f08c3bdfSopenharmony_ci		tst_res(TFAIL | TTERRNO,
74f08c3bdfSopenharmony_ci			"setpriority(%d, %d, %d) %sshould fail with %s",
75f08c3bdfSopenharmony_ci			tc->which, tc->who, tc->prio, desc,
76f08c3bdfSopenharmony_ci			tst_strerrno(tc->exp_errno));
77f08c3bdfSopenharmony_ci		return;
78f08c3bdfSopenharmony_ci	}
79f08c3bdfSopenharmony_ci
80f08c3bdfSopenharmony_ci	tst_res(TPASS | TTERRNO,
81f08c3bdfSopenharmony_ci		"setpriority(%d, %d, %d) %sfails as expected",
82f08c3bdfSopenharmony_ci		tc->which, tc->who, tc->prio, desc);
83f08c3bdfSopenharmony_ci}
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_cistatic void verify_setpriority(unsigned int n)
86f08c3bdfSopenharmony_ci{
87f08c3bdfSopenharmony_ci	struct tcase *tc = &tcases[n];
88f08c3bdfSopenharmony_ci
89f08c3bdfSopenharmony_ci	if (tc->unprivil) {
90f08c3bdfSopenharmony_ci		if (!SAFE_FORK()) {
91f08c3bdfSopenharmony_ci			SAFE_SETUID(uid);
92f08c3bdfSopenharmony_ci			SAFE_SETPGID(0, 0);
93f08c3bdfSopenharmony_ci			setpriority_test(tc);
94f08c3bdfSopenharmony_ci			exit(0);
95f08c3bdfSopenharmony_ci		}
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci		tst_reap_children();
98f08c3bdfSopenharmony_ci	} else {
99f08c3bdfSopenharmony_ci		setpriority_test(tc);
100f08c3bdfSopenharmony_ci	}
101f08c3bdfSopenharmony_ci}
102f08c3bdfSopenharmony_ci
103f08c3bdfSopenharmony_cistatic void setup(void)
104f08c3bdfSopenharmony_ci{
105f08c3bdfSopenharmony_ci	struct passwd *ltpuser;
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci	ltpuser = SAFE_GETPWNAM("nobody");
108f08c3bdfSopenharmony_ci	uid = ltpuser->pw_uid;
109f08c3bdfSopenharmony_ci}
110f08c3bdfSopenharmony_ci
111f08c3bdfSopenharmony_cistatic struct tst_test test = {
112f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcases),
113f08c3bdfSopenharmony_ci	.needs_root = 1,
114f08c3bdfSopenharmony_ci	.forks_child = 1,
115f08c3bdfSopenharmony_ci	.setup = setup,
116f08c3bdfSopenharmony_ci	.test = verify_setpriority,
117f08c3bdfSopenharmony_ci};
118