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