Home | History | Annotate | Download | only in setpriority
      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,
     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