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 (at) 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 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 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 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 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 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 .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