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