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