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