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