• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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