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 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 	.tid = "setpriority01",
    142 	.tcnt = ARRAY_SIZE(tcases),
    143 	.needs_root = 1,
    144 	.forks_child = 1,
    145 	.needs_checkpoints = 1,
    146 	.setup = setup,
    147 	.cleanup = cleanup,
    148 	.test = verify_setpriority,
    149 };
    150