1 /*
2 * Copyright (c) International Business Machines Corp., 2001
3 * 03/2001 Written by Wayne Boyer
4 * 11/2016 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21 * Verify that setpriority(2) succeeds set the scheduling priority of
22 * the current process, process group or user.
23 */
24
25 #define _GNU_SOURCE
26 #include <errno.h>
27 #include <pwd.h>
28 #include <stdlib.h>
29 #include <sys/resource.h>
30
31 #include "tst_test.h"
32
33 static const char *username = "ltp_setpriority01";
34 static int pid, uid, user_added;
35
36 static struct tcase {
37 int which;
38 int *who;
39 } tcases[] = {
40 {PRIO_PROCESS, &pid},
41 {PRIO_PGRP, &pid},
42 {PRIO_USER, &uid}
43 };
44
str_which(int which)45 static const char *str_which(int which)
46 {
47 switch (which) {
48 case PRIO_PROCESS:
49 return "PRIO_PROCESS";
50 case PRIO_PGRP:
51 return "PRIO_PGRP";
52 case PRIO_USER:
53 return "PRIO_USER";
54 default:
55 return "???";
56 }
57 }
58
setpriority_test(struct tcase * tc)59 static void setpriority_test(struct tcase *tc)
60 {
61 int new_prio, cur_prio;
62 int failflag = 0;
63
64 for (new_prio = -20; new_prio < 20; new_prio++) {
65 TEST(setpriority(tc->which, *tc->who, new_prio));
66
67 if (TEST_RETURN != 0) {
68 tst_res(TFAIL | TTERRNO,
69 "setpriority(%d, %d, %d) failed",
70 tc->which, *tc->who, new_prio);
71 failflag = 1;
72 continue;
73 }
74
75 cur_prio = SAFE_GETPRIORITY(tc->which, *tc->who);
76
77 if (cur_prio != new_prio) {
78 tst_res(TFAIL, "current priority(%d) and "
79 "new priority(%d) do not match",
80 cur_prio, new_prio);
81 failflag = 1;
82 }
83 }
84
85 if (!failflag) {
86 tst_res(TPASS, "setpriority(%s(%d), %d, -20..19) succeeded",
87 str_which(tc->which), tc->which, *tc->who);
88 }
89 }
90
verify_setpriority(unsigned int n)91 static void verify_setpriority(unsigned int n)
92 {
93 struct tcase *tc = &tcases[n];
94
95 pid = SAFE_FORK();
96 if (pid == 0) {
97 SAFE_SETUID(uid);
98 SAFE_SETPGID(0, 0);
99
100 TST_CHECKPOINT_WAKE_AND_WAIT(0);
101
102 exit(0);
103 }
104
105 TST_CHECKPOINT_WAIT(0);
106
107 setpriority_test(tc);
108
109 TST_CHECKPOINT_WAKE(0);
110
111 tst_reap_children();
112 }
113
setup(void)114 static void setup(void)
115 {
116 const char *const cmd_useradd[] = {"useradd", username, NULL};
117 struct passwd *ltpuser;
118
119 if (eaccess("/etc/passwd", W_OK))
120 tst_brk(TCONF, "/etc/passwd is not accessible");
121
122 tst_run_cmd(cmd_useradd, NULL, NULL, 0);
123 user_added = 1;
124
125 ltpuser = SAFE_GETPWNAM(username);
126 uid = ltpuser->pw_uid;
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_run_cmd(cmd_userdel, NULL, NULL, 1))
137 tst_res(TWARN | TERRNO, "'userdel -r %s' failed", username);
138 }
139
140 static struct tst_test test = {
141 .tid = "setpriority01",
142 .tcnt = ARRAY_SIZE(tcases),
143 .needs_root = 1,
144 .forks_child = 1,
145 .needs_checkpoints = 1,
146 .setup = setup,
147 .cleanup = cleanup,
148 .test = verify_setpriority,
149 };
150