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 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 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 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 .tcnt = ARRAY_SIZE(tcases), 125 .needs_root = 1, 126 .forks_child = 1, 127 .setup = setup, 128 .test = verify_setpriority, 129 }; 130