xref: /onnv-gate/usr/src/lib/libc/port/gen/setpriority.c (revision 6812:febeba71273d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
52712Snn35248  * Common Development and Distribution License (the "License").
62712Snn35248  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
216247Sraf 
220Sstevel@tonic-gate /*
236247Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
280Sstevel@tonic-gate /*	  All Rights Reserved  	*/
290Sstevel@tonic-gate 
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
320Sstevel@tonic-gate  * The Regents of the University of California
330Sstevel@tonic-gate  * All Rights Reserved
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
360Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
370Sstevel@tonic-gate  * contributors.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
410Sstevel@tonic-gate 
42*6812Sraf #include "lint.h"
430Sstevel@tonic-gate #include <string.h>
446247Sraf #include <limits.h>
450Sstevel@tonic-gate #include <sys/types.h>
460Sstevel@tonic-gate #include <sys/time.h>
470Sstevel@tonic-gate #include <sys/resource.h>
480Sstevel@tonic-gate #include <sys/procset.h>
490Sstevel@tonic-gate #include <sys/priocntl.h>
502712Snn35248 #include <limits.h>
510Sstevel@tonic-gate #include <errno.h>
522712Snn35248 #include <priv.h>
530Sstevel@tonic-gate 
540Sstevel@tonic-gate static idtype_t
prio_to_idtype(int which)550Sstevel@tonic-gate prio_to_idtype(int which)
560Sstevel@tonic-gate {
570Sstevel@tonic-gate 	switch (which) {
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	case PRIO_PROCESS:
600Sstevel@tonic-gate 		return (P_PID);
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	case PRIO_PGRP:
630Sstevel@tonic-gate 		return (P_PGID);
640Sstevel@tonic-gate 
650Sstevel@tonic-gate 	case PRIO_USER:
660Sstevel@tonic-gate 		return (P_UID);
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 	case PRIO_GROUP:
690Sstevel@tonic-gate 		return (P_GID);
700Sstevel@tonic-gate 
710Sstevel@tonic-gate 	case PRIO_SESSION:
720Sstevel@tonic-gate 		return (P_SID);
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	case PRIO_LWP:
750Sstevel@tonic-gate 		return (P_LWPID);
760Sstevel@tonic-gate 
770Sstevel@tonic-gate 	case PRIO_TASK:
780Sstevel@tonic-gate 		return (P_TASKID);
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	case PRIO_PROJECT:
810Sstevel@tonic-gate 		return (P_PROJID);
820Sstevel@tonic-gate 
830Sstevel@tonic-gate 	case PRIO_ZONE:
840Sstevel@tonic-gate 		return (P_ZONEID);
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	case PRIO_CONTRACT:
870Sstevel@tonic-gate 		return (P_CTID);
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 	default:
900Sstevel@tonic-gate 		return (-1);
910Sstevel@tonic-gate 	}
920Sstevel@tonic-gate }
930Sstevel@tonic-gate 
940Sstevel@tonic-gate static int
old_idtype(int which)950Sstevel@tonic-gate old_idtype(int which)
960Sstevel@tonic-gate {
970Sstevel@tonic-gate 	switch (which) {
980Sstevel@tonic-gate 	case PRIO_PROCESS:
990Sstevel@tonic-gate 	case PRIO_PGRP:
1000Sstevel@tonic-gate 	case PRIO_USER:
1010Sstevel@tonic-gate 		return (1);
1020Sstevel@tonic-gate 	default:
1030Sstevel@tonic-gate 		return (0);
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate int
getpriority(int which,id_t who)1080Sstevel@tonic-gate getpriority(int which, id_t who)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	id_t id;
1110Sstevel@tonic-gate 	idtype_t idtype;
1120Sstevel@tonic-gate 	pcnice_t pcnice;
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	if ((idtype = prio_to_idtype(which)) == -1) {
1150Sstevel@tonic-gate 		errno = EINVAL;
1160Sstevel@tonic-gate 		return (-1);
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	if (who < 0) {
1200Sstevel@tonic-gate 		if (old_idtype(which)) {
1210Sstevel@tonic-gate 			errno = EINVAL;
1220Sstevel@tonic-gate 			return (-1);
1230Sstevel@tonic-gate 		} else if (who != P_MYID) {
1240Sstevel@tonic-gate 			errno = EINVAL;
1250Sstevel@tonic-gate 			return (-1);
1260Sstevel@tonic-gate 		}
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 	/*
1300Sstevel@tonic-gate 	 * The POSIX standard requires that a 0 value for the who argument
1310Sstevel@tonic-gate 	 * should specify the current process, process group, or user.
1320Sstevel@tonic-gate 	 * For all other id types we can treat zero as normal id value.
1330Sstevel@tonic-gate 	 */
1340Sstevel@tonic-gate 	if (who == 0 && old_idtype(which))
1350Sstevel@tonic-gate 		id = P_MYID;
1360Sstevel@tonic-gate 	else
1370Sstevel@tonic-gate 		id = who;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	pcnice.pc_val = 0;
1400Sstevel@tonic-gate 	pcnice.pc_op = PC_GETNICE;
1410Sstevel@tonic-gate 
1426247Sraf 	if (priocntl(idtype, id, PC_DONICE, &pcnice) == -1)
1430Sstevel@tonic-gate 		return (-1);
1440Sstevel@tonic-gate 	else
1450Sstevel@tonic-gate 		return (pcnice.pc_val);
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate int
setpriority(int which,id_t who,int prio)1490Sstevel@tonic-gate setpriority(int which, id_t who, int prio)
1500Sstevel@tonic-gate {
1510Sstevel@tonic-gate 	id_t id;
1520Sstevel@tonic-gate 	idtype_t idtype;
1530Sstevel@tonic-gate 	pcnice_t pcnice;
1542712Snn35248 	int ret;
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	if ((idtype = prio_to_idtype(which)) == -1) {
1570Sstevel@tonic-gate 		errno = EINVAL;
1580Sstevel@tonic-gate 		return (-1);
1590Sstevel@tonic-gate 	}
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	if (who < 0) {
1620Sstevel@tonic-gate 		if (old_idtype(which)) {
1630Sstevel@tonic-gate 			errno = EINVAL;
1640Sstevel@tonic-gate 			return (-1);
1650Sstevel@tonic-gate 		} else if (who != P_MYID) {
1660Sstevel@tonic-gate 			errno = EINVAL;
1670Sstevel@tonic-gate 			return (-1);
1680Sstevel@tonic-gate 		}
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	if (who == 0 && old_idtype(which))
1720Sstevel@tonic-gate 		id = P_MYID;
1730Sstevel@tonic-gate 	else
1740Sstevel@tonic-gate 		id = who;
1750Sstevel@tonic-gate 
1766247Sraf 	if (prio > NZERO - 1)
1776247Sraf 		prio = NZERO - 1;
1786247Sraf 	else if (prio < -NZERO)
1796247Sraf 		prio = -NZERO;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	pcnice.pc_val = prio;
1820Sstevel@tonic-gate 	pcnice.pc_op = PC_SETNICE;
1830Sstevel@tonic-gate 
1846247Sraf 	ret = priocntl(idtype, id, PC_DONICE, &pcnice);
1852712Snn35248 
1862712Snn35248 	if (ret != 0 && errno == EPERM) {
1872712Snn35248 		pcnice_t	gpcnice = { 0, PC_GETNICE };
1886247Sraf 		priv_set_t	*pset = NULL;
1892712Snn35248 
1902712Snn35248 		/*
1912712Snn35248 		 * The priocntl PC_DONICE subcommand returns EPERM if we lack
1922712Snn35248 		 * sufficient privileges to carry out the operation, but
1936247Sraf 		 * setpriority(3C) may need to return EACCES.  We can't just
1946247Sraf 		 * change EPERM to EACCES, because there are other conditions
1956247Sraf 		 * which legitimately cause EPERM (such as an euid/ruid mismatch
1962712Snn35248 		 * between the current process and the target.).
1976247Sraf 		 *
1982712Snn35248 		 * setpriority(3C) must return EACCES if we lack the privilege
1992712Snn35248 		 * checked for below and we are trying to increase the process
2002712Snn35248 		 * priority (by lowering the numeric value of its priority).
2012712Snn35248 		 */
2026247Sraf 		if (priocntl(idtype, id, PC_DONICE, &gpcnice) == 0 &&
2036247Sraf 		    prio < gpcnice.pc_val) {
2046247Sraf 			if ((pset = priv_allocset()) != NULL &&
2056247Sraf 			    getppriv(PRIV_EFFECTIVE, pset) == 0 &&
2066247Sraf 			    !priv_ismember(pset, "proc_priocntl"))
2076247Sraf 				errno = EACCES;
2086247Sraf 			if (pset != NULL)
2096247Sraf 				priv_freeset(pset);
2106247Sraf 		}
2112712Snn35248 	}
2122712Snn35248 
2132712Snn35248 	return (ret);
2140Sstevel@tonic-gate }
215