Home | History | Annotate | Download | only in os
      1      0      stevel /*
      2      0      stevel  * CDDL HEADER START
      3      0      stevel  *
      4      0      stevel  * The contents of this file are subject to the terms of the
      5   1544    eschrock  * Common Development and Distribution License (the "License").
      6   1544    eschrock  * You may not use this file except in compliance with the License.
      7      0      stevel  *
      8      0      stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9      0      stevel  * or http://www.opensolaris.org/os/licensing.
     10      0      stevel  * See the License for the specific language governing permissions
     11      0      stevel  * and limitations under the License.
     12      0      stevel  *
     13      0      stevel  * When distributing Covered Code, include this CDDL HEADER in each
     14      0      stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15      0      stevel  * If applicable, add the following below this CDDL HEADER, with the
     16      0      stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     17      0      stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     18      0      stevel  *
     19      0      stevel  * CDDL HEADER END
     20      0      stevel  */
     21      0      stevel /*
     22   9751       james  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23      0      stevel  * Use is subject to license terms.
     24      0      stevel  */
     25      0      stevel 
     26      0      stevel #include <sys/types.h>
     27      0      stevel #include <sys/sysmacros.h>
     28      0      stevel #include <sys/param.h>
     29      0      stevel #include <sys/systm.h>
     30      0      stevel #include <sys/cred_impl.h>
     31      0      stevel #include <sys/vnode.h>
     32      0      stevel #include <sys/vfs.h>
     33      0      stevel #include <sys/stat.h>
     34      0      stevel #include <sys/errno.h>
     35      0      stevel #include <sys/kmem.h>
     36      0      stevel #include <sys/user.h>
     37      0      stevel #include <sys/proc.h>
     38      0      stevel #include <sys/acct.h>
     39      0      stevel #include <sys/ipc_impl.h>
     40      0      stevel #include <sys/cmn_err.h>
     41      0      stevel #include <sys/debug.h>
     42      0      stevel #include <sys/policy.h>
     43      0      stevel #include <sys/kobj.h>
     44      0      stevel #include <sys/msg.h>
     45      0      stevel #include <sys/devpolicy.h>
     46      0      stevel #include <c2/audit.h>
     47      0      stevel #include <sys/varargs.h>
     48   6134      casper #include <sys/klpd.h>
     49      0      stevel #include <sys/modctl.h>
     50      0      stevel #include <sys/disp.h>
     51      0      stevel #include <sys/zone.h>
     52      0      stevel #include <inet/optcom.h>
     53      0      stevel #include <sys/sdt.h>
     54      0      stevel #include <sys/vfs.h>
     55      0      stevel #include <sys/mntent.h>
     56      0      stevel #include <sys/contract_impl.h>
     57   8275        Eric #include <sys/dld_ioc.h>
     58      0      stevel 
     59      0      stevel /*
     60      0      stevel  * There are two possible layers of privilege routines and two possible
     61      0      stevel  * levels of secpolicy.  Plus one other we may not be interested in, so
     62      0      stevel  * we may need as many as 6 but no more.
     63      0      stevel  */
     64      0      stevel #define	MAXPRIVSTACK		6
     65      0      stevel 
     66      0      stevel int priv_debug = 0;
     67      0      stevel 
     68      0      stevel /*
     69      0      stevel  * This file contains the majority of the policy routines.
     70      0      stevel  * Since the policy routines are defined by function and not
     71      0      stevel  * by privilege, there is quite a bit of duplication of
     72      0      stevel  * functions.
     73      0      stevel  *
     74   5331         amw  * The secpolicy functions must not make assumptions about
     75      0      stevel  * locks held or not held as any lock can be held while they're
     76      0      stevel  * being called.
     77      0      stevel  *
     78      0      stevel  * Credentials are read-only so no special precautions need to
     79      0      stevel  * be taken while locking them.
     80      0      stevel  *
     81      0      stevel  * When a new policy check needs to be added to the system the
     82      0      stevel  * following procedure should be followed:
     83      0      stevel  *
     84      0      stevel  *		Pick an appropriate secpolicy_*() function
     85      0      stevel  *			-> done if one exists.
     86      0      stevel  *		Create a new secpolicy function, preferably with
     87      0      stevel  *		a descriptive name using the standard template.
     88      0      stevel  *		Pick an appropriate privilege for the policy.
     89      0      stevel  *		If no appropraite privilege exists, define new one
     90      0      stevel  *		(this should be done with extreme care; in most cases
     91      0      stevel  *		little is gained by adding another privilege)
     92      0      stevel  *
     93      0      stevel  * WHY ROOT IS STILL SPECIAL.
     94      0      stevel  *
     95      0      stevel  * In a number of the policy functions, there are still explicit
     96      0      stevel  * checks for uid 0.  The rationale behind these is that many root
     97      0      stevel  * owned files/objects hold configuration information which can give full
     98      0      stevel  * privileges to the user once written to.  To prevent escalation
     99      0      stevel  * of privilege by allowing just a single privilege to modify root owned
    100      0      stevel  * objects, we've added these root specific checks where we considered
    101      0      stevel  * them necessary: modifying root owned files, changing uids to 0, etc.
    102      0      stevel  *
    103      0      stevel  * PRIVILEGE ESCALATION AND ZONES.
    104      0      stevel  *
    105      0      stevel  * A number of operations potentially allow the caller to achieve
    106      0      stevel  * privileges beyond the ones normally required to perform the operation.
    107      0      stevel  * For example, if allowed to create a setuid 0 executable, a process can
    108      0      stevel  * gain privileges beyond PRIV_FILE_SETID.  Zones, however, place
    109      0      stevel  * restrictions on the ability to gain privileges beyond those available
    110      0      stevel  * within the zone through file and process manipulation.  Hence, such
    111      0      stevel  * operations require that the caller have an effective set that includes
    112      0      stevel  * all privileges available within the current zone, or all privileges
    113      0      stevel  * if executing in the global zone.
    114      0      stevel  *
    115      0      stevel  * This is indicated in the priv_policy* policy checking functions
    116      0      stevel  * through a combination of parameters.  The "priv" parameter indicates
    117      0      stevel  * the privilege that is required, and the "allzone" parameter indicates
    118      0      stevel  * whether or not all privileges in the zone are required.  In addition,
    119      0      stevel  * priv can be set to PRIV_ALL to indicate that all privileges are
    120      0      stevel  * required (regardless of zone).  There are three scenarios of interest:
    121      0      stevel  * (1) operation requires a specific privilege
    122      0      stevel  * (2) operation requires a specific privilege, and requires all
    123      0      stevel  *     privileges available within the zone (or all privileges if in
    124      0      stevel  *     the global zone)
    125      0      stevel  * (3) operation requires all privileges, regardless of zone
    126      0      stevel  *
    127      0      stevel  * For (1), priv should be set to the specific privilege, and allzone
    128      0      stevel  * should be set to B_FALSE.
    129      0      stevel  * For (2), priv should be set to the specific privilege, and allzone
    130      0      stevel  * should be set to B_TRUE.
    131      0      stevel  * For (3), priv should be set to PRIV_ALL, and allzone should be set
    132      0      stevel  * to B_FALSE.
    133      0      stevel  *
    134      0      stevel  */
    135      0      stevel 
    136      0      stevel /*
    137      0      stevel  * The privileges are checked against the Effective set for
    138      0      stevel  * ordinary processes and checked against the Limit set
    139      0      stevel  * for euid 0 processes that haven't manipulated their privilege
    140      0      stevel  * sets.
    141      0      stevel  */
    142      0      stevel #define	HAS_ALLPRIVS(cr)	priv_isfullset(&CR_OEPRIV(cr))
    143      0      stevel #define	ZONEPRIVS(cr)		((cr)->cr_zone->zone_privset)
    144      0      stevel #define	HAS_ALLZONEPRIVS(cr)	priv_issubset(ZONEPRIVS(cr), &CR_OEPRIV(cr))
    145      0      stevel #define	HAS_PRIVILEGE(cr, pr)	((pr) == PRIV_ALL ? \
    146      0      stevel 					HAS_ALLPRIVS(cr) : \
    147      0      stevel 					PRIV_ISASSERT(&CR_OEPRIV(cr), pr))
    148      0      stevel 
    149      0      stevel /*
    150   6134      casper  * Policy checking functions.
    151      0      stevel  *
    152   6134      casper  * All of the system's policy should be implemented here.
    153      0      stevel  */
    154   6134      casper 
    155   6134      casper /*
    156   6134      casper  * Private functions which take an additional va_list argument to
    157   6134      casper  * implement an object specific policy override.
    158   6134      casper  */
    159   6134      casper static int priv_policy_ap(const cred_t *, int, boolean_t, int,
    160   6134      casper     const char *, va_list);
    161   6134      casper static int priv_policy_va(const cred_t *, int, boolean_t, int,
    162   6134      casper     const char *, ...);
    163      0      stevel 
    164      0      stevel /*
    165      0      stevel  * Generic policy calls
    166      0      stevel  *
    167      0      stevel  * The "bottom" functions of policy control
    168      0      stevel  */
    169      0      stevel static char *
    170      0      stevel mprintf(const char *fmt, ...)
    171      0      stevel {
    172      0      stevel 	va_list args;
    173      0      stevel 	char *buf;
    174      0      stevel 	size_t len;
    175      0      stevel 
    176      0      stevel 	va_start(args, fmt);
    177      0      stevel 	len = vsnprintf(NULL, 0, fmt, args) + 1;
    178      0      stevel 	va_end(args);
    179      0      stevel 
    180      0      stevel 	buf = kmem_alloc(len, KM_NOSLEEP);
    181      0      stevel 
    182      0      stevel 	if (buf == NULL)
    183      0      stevel 		return (NULL);
    184      0      stevel 
    185      0      stevel 	va_start(args, fmt);
    186      0      stevel 	(void) vsnprintf(buf, len, fmt, args);
    187      0      stevel 	va_end(args);
    188      0      stevel 
    189      0      stevel 	return (buf);
    190      0      stevel }
    191      0      stevel 
    192      0      stevel /*
    193      0      stevel  * priv_policy_errmsg()
    194      0      stevel  *
    195      0      stevel  * Generate an error message if privilege debugging is enabled system wide
    196      0      stevel  * or for this particular process.
    197      0      stevel  */
    198      0      stevel 
    199      0      stevel #define	FMTHDR	"%s[%d]: missing privilege \"%s\" (euid = %d, syscall = %d)"
    200      0      stevel #define	FMTMSG	" for \"%s\""
    201      0      stevel #define	FMTFUN	" needed at %s+0x%lx"
    202      0      stevel 
    203      0      stevel /* The maximum size privilege format: the concatenation of the above */
    204      0      stevel #define	FMTMAX	FMTHDR FMTMSG FMTFUN "\n"
    205      0      stevel 
    206      0      stevel static void
    207      0      stevel priv_policy_errmsg(const cred_t *cr, int priv, const char *msg)
    208      0      stevel {
    209      0      stevel 	struct proc *me;
    210      0      stevel 	pc_t stack[MAXPRIVSTACK];
    211      0      stevel 	int depth;
    212      0      stevel 	int i;
    213      0      stevel 	char *sym;
    214      0      stevel 	ulong_t off;
    215      0      stevel 	const char *pname;
    216      0      stevel 
    217      0      stevel 	char *cmd;
    218      0      stevel 	char fmt[sizeof (FMTMAX)];
    219      0      stevel 
    220      0      stevel 	if ((me = curproc) == &p0)
    221      0      stevel 		return;
    222      0      stevel 
    223      0      stevel 	/* Privileges must be defined  */
    224      0      stevel 	ASSERT(priv == PRIV_ALL || priv == PRIV_MULTIPLE ||
    225      0      stevel 	    priv == PRIV_ALLZONE || priv == PRIV_GLOBAL ||
    226      0      stevel 	    priv_getbynum(priv) != NULL);
    227      0      stevel 
    228      0      stevel 	if (priv == PRIV_ALLZONE && INGLOBALZONE(me))
    229      0      stevel 		priv = PRIV_ALL;
    230      0      stevel 
    231      0      stevel 	if (curthread->t_pre_sys)
    232      0      stevel 		ttolwp(curthread)->lwp_badpriv = (short)priv;
    233      0      stevel 
    234      0      stevel 	if (priv_debug == 0 && (CR_FLAGS(cr) & PRIV_DEBUG) == 0)
    235      0      stevel 		return;
    236      0      stevel 
    237      0      stevel 	(void) strcpy(fmt, FMTHDR);
    238      0      stevel 
    239      0      stevel 	if (me->p_user.u_comm[0])
    240      0      stevel 		cmd = &me->p_user.u_comm[0];
    241      0      stevel 	else
    242      0      stevel 		cmd = "priv_policy";
    243      0      stevel 
    244      0      stevel 	if (msg != NULL && *msg != '\0') {
    245      0      stevel 		(void) strcat(fmt, FMTMSG);
    246      0      stevel 	} else {
    247      0      stevel 		(void) strcat(fmt, "%s");
    248      0      stevel 		msg = "";
    249      0      stevel 	}
    250      0      stevel 
    251      0      stevel 	sym = NULL;
    252      0      stevel 
    253      0      stevel 	depth = getpcstack(stack, MAXPRIVSTACK);
    254      0      stevel 
    255      0      stevel 	/*
    256      0      stevel 	 * Try to find the first interesting function on the stack.
    257      0      stevel 	 * priv_policy* that's us, so completely uninteresting.
    258      0      stevel 	 * suser(), drv_priv(), secpolicy_* are also called from
    259      0      stevel 	 * too many locations to convey useful information.
    260      0      stevel 	 */
    261      0      stevel 	for (i = 0; i < depth; i++) {
    262      0      stevel 		sym = kobj_getsymname((uintptr_t)stack[i], &off);
    263      0      stevel 		if (sym != NULL &&
    264      0      stevel 		    strstr(sym, "hasprocperm") == 0 &&
    265      0      stevel 		    strcmp("suser", sym) != 0 &&
    266      0      stevel 		    strcmp("ipcaccess", sym) != 0 &&
    267      0      stevel 		    strcmp("drv_priv", sym) != 0 &&
    268      0      stevel 		    strncmp("secpolicy_", sym, 10) != 0 &&
    269      0      stevel 		    strncmp("priv_policy", sym, 11) != 0)
    270      0      stevel 			break;
    271      0      stevel 	}
    272      0      stevel 
    273      0      stevel 	if (sym != NULL)
    274      0      stevel 		(void) strcat(fmt, FMTFUN);
    275      0      stevel 
    276      0      stevel 	(void) strcat(fmt, "\n");
    277      0      stevel 
    278      0      stevel 	switch (priv) {
    279      0      stevel 	case PRIV_ALL:
    280      0      stevel 		pname = "ALL";
    281      0      stevel 		break;
    282      0      stevel 	case PRIV_MULTIPLE:
    283      0      stevel 		pname = "MULTIPLE";
    284      0      stevel 		break;
    285      0      stevel 	case PRIV_ALLZONE:
    286      0      stevel 		pname = "ZONE";
    287      0      stevel 		break;
    288      0      stevel 	case PRIV_GLOBAL:
    289      0      stevel 		pname = "GLOBAL";
    290      0      stevel 		break;
    291      0      stevel 	default:
    292      0      stevel 		pname = priv_getbynum(priv);
    293      0      stevel 		break;
    294      0      stevel 	}
    295      0      stevel 
    296      0      stevel 	if (CR_FLAGS(cr) & PRIV_DEBUG) {
    297      0      stevel 		/* Remember last message, just like lwp_badpriv. */
    298      0      stevel 		if (curthread->t_pdmsg != NULL) {
    299      0      stevel 			kmem_free(curthread->t_pdmsg,
    300      0      stevel 			    strlen(curthread->t_pdmsg) + 1);
    301      0      stevel 		}
    302      0      stevel 
    303      0      stevel 		curthread->t_pdmsg = mprintf(fmt, cmd, me->p_pid, pname,
    304   4543       marks 		    cr->cr_uid, curthread->t_sysnum, msg, sym, off);
    305      0      stevel 
    306      0      stevel 		curthread->t_post_sys = 1;
    307   6134      casper 	}
    308   6134      casper 	if (priv_debug) {
    309      0      stevel 		cmn_err(CE_NOTE, fmt, cmd, me->p_pid, pname, cr->cr_uid,
    310      0      stevel 		    curthread->t_sysnum, msg, sym, off);
    311      0      stevel 	}
    312   6134      casper }
    313   6134      casper 
    314   6134      casper /*
    315   6134      casper  * Override the policy, if appropriate.  Return 0 if the external
    316   6134      casper  * policy engine approves.
    317   6134      casper  */
    318   6134      casper static int
    319   6134      casper priv_policy_override(const cred_t *cr, int priv, boolean_t allzone, va_list ap)
    320   6134      casper {
    321   6134      casper 	priv_set_t set;
    322   6134      casper 	int ret;
    323   6134      casper 
    324   6134      casper 	if (!(CR_FLAGS(cr) & PRIV_XPOLICY))
    325   6134      casper 		return (-1);
    326   6134      casper 
    327   6134      casper 	if (priv == PRIV_ALL) {
    328   6134      casper 		priv_fillset(&set);
    329   6134      casper 	} else if (allzone) {
    330   6134      casper 		set = *ZONEPRIVS(cr);
    331   6134      casper 	} else {
    332   6134      casper 		priv_emptyset(&set);
    333   6134      casper 		priv_addset(&set, priv);
    334   6134      casper 	}
    335   6134      casper 	ret = klpd_call(cr, &set, ap);
    336   6134      casper 	return (ret);
    337   6134      casper }
    338   6134      casper 
    339   6134      casper static int
    340   6134      casper priv_policy_override_set(const cred_t *cr, const priv_set_t *req, ...)
    341   6134      casper {
    342   6134      casper 	va_list ap;
    343   6134      casper 
    344   6134      casper 	if (CR_FLAGS(cr) & PRIV_XPOLICY) {
    345   6134      casper 		va_start(ap, req);
    346   6134      casper 		return (klpd_call(cr, req, ap));
    347   6134      casper 	}
    348   6134      casper 	return (-1);
    349      0      stevel }
    350      0      stevel 
    351      0      stevel /*
    352      0      stevel  * Audit failure, log error message.
    353      0      stevel  */
    354      0      stevel static void
    355      0      stevel priv_policy_err(const cred_t *cr, int priv, boolean_t allzone, const char *msg)
    356      0      stevel {
    357      0      stevel 
    358      0      stevel 	if (audit_active)
    359      0      stevel 		audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 0);
    360      0      stevel 	DTRACE_PROBE2(priv__err, int, priv, boolean_t, allzone);
    361      0      stevel 
    362      0      stevel 	if (priv_debug || (CR_FLAGS(cr) & PRIV_DEBUG) ||
    363      0      stevel 	    curthread->t_pre_sys) {
    364      0      stevel 		if (allzone && !HAS_ALLZONEPRIVS(cr)) {
    365      0      stevel 			priv_policy_errmsg(cr, PRIV_ALLZONE, msg);
    366      0      stevel 		} else {
    367      0      stevel 			ASSERT(!HAS_PRIVILEGE(cr, priv));
    368      0      stevel 			priv_policy_errmsg(cr, priv, msg);
    369      0      stevel 		}
    370      0      stevel 	}
    371      0      stevel }
    372      0      stevel 
    373      0      stevel /*
    374   6134      casper  * priv_policy_ap()
    375      0      stevel  * return 0 or error.
    376      0      stevel  * See block comment above for a description of "priv" and "allzone" usage.
    377      0      stevel  */
    378   6134      casper static int
    379   6134      casper priv_policy_ap(const cred_t *cr, int priv, boolean_t allzone, int err,
    380   6134      casper     const char *msg, va_list ap)
    381      0      stevel {
    382   6134      casper 	if ((HAS_PRIVILEGE(cr, priv) && (!allzone || HAS_ALLZONEPRIVS(cr))) ||
    383   6134      casper 	    (!servicing_interrupt() &&
    384   6134      casper 	    priv_policy_override(cr, priv, allzone, ap) == 0)) {
    385      0      stevel 		if ((allzone || priv == PRIV_ALL ||
    386      0      stevel 		    !PRIV_ISASSERT(priv_basic, priv)) &&
    387      0      stevel 		    !servicing_interrupt()) {
    388   3446         mrj 			PTOU(curproc)->u_acflag |= ASU; /* Needed for SVVS */
    389      0      stevel 			if (audit_active)
    390      0      stevel 				audit_priv(priv,
    391      0      stevel 				    allzone ? ZONEPRIVS(cr) : NULL, 1);
    392      0      stevel 		}
    393      0      stevel 		err = 0;
    394      0      stevel 		DTRACE_PROBE2(priv__ok, int, priv, boolean_t, allzone);
    395      0      stevel 	} else if (!servicing_interrupt()) {
    396      0      stevel 		/* Failure audited in this procedure */
    397      0      stevel 		priv_policy_err(cr, priv, allzone, msg);
    398      0      stevel 	}
    399   6134      casper 	return (err);
    400   6134      casper }
    401      0      stevel 
    402   6134      casper int
    403   6134      casper priv_policy_va(const cred_t *cr, int priv, boolean_t allzone, int err,
    404   6134      casper     const char *msg, ...)
    405   6134      casper {
    406   6134      casper 	int ret;
    407   6134      casper 	va_list ap;
    408   6134      casper 
    409   6134      casper 	va_start(ap, msg);
    410   6134      casper 	ret = priv_policy_ap(cr, priv, allzone, err, msg, ap);
    411   6134      casper 	va_end(ap);
    412   6134      casper 
    413   6134      casper 	return (ret);
    414   6134      casper }
    415   6134      casper 
    416   6134      casper int
    417   6134      casper priv_policy(const cred_t *cr, int priv, boolean_t allzone, int err,
    418   6134      casper     const char *msg)
    419   6134      casper {
    420   6134      casper 	return (priv_policy_va(cr, priv, allzone, err, msg, KLPDARG_NOMORE));
    421      0      stevel }
    422      0      stevel 
    423      0      stevel /*
    424      0      stevel  * Return B_TRUE for sufficient privileges, B_FALSE for insufficient privileges.
    425      0      stevel  */
    426      0      stevel boolean_t
    427      0      stevel priv_policy_choice(const cred_t *cr, int priv, boolean_t allzone)
    428      0      stevel {
    429      0      stevel 	boolean_t res = HAS_PRIVILEGE(cr, priv) &&
    430      0      stevel 	    (!allzone || HAS_ALLZONEPRIVS(cr));
    431      0      stevel 
    432      0      stevel 	/* Audit success only */
    433      0      stevel 	if (res && audit_active &&
    434      0      stevel 	    (allzone || priv == PRIV_ALL || !PRIV_ISASSERT(priv_basic, priv)) &&
    435      0      stevel 	    !servicing_interrupt()) {
    436      0      stevel 		audit_priv(priv, allzone ? ZONEPRIVS(cr) : NULL, 1);
    437      0      stevel 	}
    438      0      stevel 	if (res) {
    439      0      stevel 		DTRACE_PROBE2(priv__ok, int, priv, boolean_t, allzone);
    440      0      stevel 	} else {
    441      0      stevel 		DTRACE_PROBE2(priv__err, int, priv, boolean_t, allzone);
    442      0      stevel 	}
    443      0      stevel 	return (res);
    444      0      stevel }
    445      0      stevel 
    446      0      stevel /*
    447      0      stevel  * Non-auditing variant of priv_policy_choice().
    448      0      stevel  */
    449      0      stevel boolean_t
    450      0      stevel priv_policy_only(const cred_t *cr, int priv, boolean_t allzone)
    451      0      stevel {
    452      0      stevel 	boolean_t res = HAS_PRIVILEGE(cr, priv) &&
    453      0      stevel 	    (!allzone || HAS_ALLZONEPRIVS(cr));
    454      0      stevel 
    455      0      stevel 	if (res) {
    456      0      stevel 		DTRACE_PROBE2(priv__ok, int, priv, boolean_t, allzone);
    457      0      stevel 	} else {
    458      0      stevel 		DTRACE_PROBE2(priv__err, int, priv, boolean_t, allzone);
    459      0      stevel 	}
    460      0      stevel 	return (res);
    461      0      stevel }
    462      0      stevel 
    463      0      stevel /*
    464      0      stevel  * Check whether all privileges in the required set are present.
    465      0      stevel  */
    466      0      stevel static int
    467      0      stevel secpolicy_require_set(const cred_t *cr, const priv_set_t *req, const char *msg)
    468      0      stevel {
    469      0      stevel 	int priv;
    470      0      stevel 	int pfound = -1;
    471      0      stevel 	priv_set_t pset;
    472      0      stevel 
    473      0      stevel 	if (req == PRIV_FULLSET ? HAS_ALLPRIVS(cr) : priv_issubset(req,
    474   4543       marks 	    &CR_OEPRIV(cr))) {
    475      0      stevel 		return (0);
    476      0      stevel 	}
    477   6134      casper 
    478   6134      casper 	if (priv_policy_override_set(cr, req, KLPDARG_NOMORE) == 0)
    479   6134      casper 		return (0);
    480      0      stevel 
    481      0      stevel 	if (req == PRIV_FULLSET || priv_isfullset(req)) {
    482      0      stevel 		priv_policy_err(cr, PRIV_ALL, B_FALSE, msg);
    483      0      stevel 		return (EACCES);
    484      0      stevel 	}
    485      0      stevel 
    486      0      stevel 	pset = CR_OEPRIV(cr);		/* present privileges */
    487      0      stevel 	priv_inverse(&pset);		/* all non present privileges */
    488      0      stevel 	priv_intersect(req, &pset);	/* the actual missing privs */
    489      0      stevel 
    490      0      stevel 	if (audit_active)
    491      0      stevel 		audit_priv(PRIV_NONE, &pset, 0);
    492      0      stevel 	/*
    493      0      stevel 	 * Privilege debugging; special case "one privilege in set".
    494      0      stevel 	 */
    495      0      stevel 	if (priv_debug || (CR_FLAGS(cr) & PRIV_DEBUG) || curthread->t_pre_sys) {
    496      0      stevel 		for (priv = 0; priv < nprivs; priv++) {
    497      0      stevel 			if (priv_ismember(&pset, priv)) {
    498      0      stevel 				if (pfound != -1) {
    499      0      stevel 					/* Multiple missing privs */
    500      0      stevel 					priv_policy_errmsg(cr, PRIV_MULTIPLE,
    501   4543       marks 					    msg);
    502      0      stevel 					return (EACCES);
    503      0      stevel 				}
    504      0      stevel 				pfound = priv;
    505      0      stevel 			}
    506      0      stevel 		}
    507      0      stevel 		ASSERT(pfound != -1);
    508      0      stevel 		/* Just the one missing privilege */
    509      0      stevel 		priv_policy_errmsg(cr, pfound, msg);
    510      0      stevel 	}
    511      0      stevel 
    512      0      stevel 	return (EACCES);
    513      0      stevel }
    514      0      stevel 
    515      0      stevel /*
    516      0      stevel  * Called when an operation requires that the caller be in the
    517      0      stevel  * global zone, regardless of privilege.
    518      0      stevel  */
    519      0      stevel static int
    520      0      stevel priv_policy_global(const cred_t *cr)
    521      0      stevel {
    522      0      stevel 	if (crgetzoneid(cr) == GLOBAL_ZONEID)
    523      0      stevel 		return (0);	/* success */
    524      0      stevel 
    525      0      stevel 	if (priv_debug || (CR_FLAGS(cr) & PRIV_DEBUG) ||
    526      0      stevel 	    curthread->t_pre_sys) {
    527      0      stevel 		priv_policy_errmsg(cr, PRIV_GLOBAL, NULL);
    528      0      stevel 	}
    529      0      stevel 	return (EPERM);
    530      0      stevel }
    531      0      stevel 
    532      0      stevel /*
    533      0      stevel  * Changing process priority
    534      0      stevel  */
    535      0      stevel int
    536      0      stevel secpolicy_setpriority(const cred_t *cr)
    537      0      stevel {
    538      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_PRIOCNTL, B_FALSE, EPERM, NULL));
    539      0      stevel }
    540      0      stevel 
    541      0      stevel /*
    542      0      stevel  * Binding to a privileged port, port must be specified in host byte
    543      0      stevel  * order.
    544      0      stevel  */
    545      0      stevel int
    546   6134      casper secpolicy_net_privaddr(const cred_t *cr, in_port_t port, int proto)
    547      0      stevel {
    548   5331         amw 	char *reason;
    549   5331         amw 	int priv;
    550   5331         amw 
    551   5331         amw 	switch (port) {
    552   5331         amw 	case 137:
    553   5331         amw 	case 138:
    554   5331         amw 	case 139:
    555   5331         amw 	case 445:
    556   5331         amw 		/*
    557   5331         amw 		 * NBT and SMB ports, these are extra privileged ports,
    558   5331         amw 		 * allow bind only if the SYS_SMB privilege is present.
    559   5331         amw 		 */
    560   5331         amw 		priv = PRIV_SYS_SMB;
    561   5331         amw 		reason = "NBT or SMB port";
    562   5331         amw 		break;
    563   5331         amw 
    564   5331         amw 	case 2049:
    565   5331         amw 	case 4045:
    566   5331         amw 		/*
    567   5331         amw 		 * NFS ports, these are extra privileged ports, allow bind
    568   5331         amw 		 * only if the SYS_NFS privilege is present.
    569   5331         amw 		 */
    570   5331         amw 		priv = PRIV_SYS_NFS;
    571   5331         amw 		reason = "NFS port";
    572   5331         amw 		break;
    573   5331         amw 
    574   5331         amw 	default:
    575   5331         amw 		priv = PRIV_NET_PRIVADDR;
    576   5331         amw 		reason = NULL;
    577   5331         amw 		break;
    578   5331         amw 
    579   5331         amw 	}
    580   5331         amw 
    581   6134      casper 	return (priv_policy_va(cr, priv, B_FALSE, EACCES, reason,
    582   6134      casper 	    KLPDARG_PORT, (int)proto, (int)port, KLPDARG_NOMORE));
    583      0      stevel }
    584      0      stevel 
    585      0      stevel /*
    586   1676         jpk  * Binding to a multilevel port on a trusted (labeled) system.
    587   1676         jpk  */
    588   1676         jpk int
    589   1676         jpk secpolicy_net_bindmlp(const cred_t *cr)
    590   1676         jpk {
    591   6134      casper 	return (PRIV_POLICY(cr, PRIV_NET_BINDMLP, B_FALSE, EACCES, NULL));
    592   1676         jpk }
    593   1676         jpk 
    594   1676         jpk /*
    595   1676         jpk  * Allow a communication between a zone and an unlabeled host when their
    596   1676         jpk  * labels don't match.
    597   1676         jpk  */
    598   1676         jpk int
    599   1676         jpk secpolicy_net_mac_aware(const cred_t *cr)
    600   1676         jpk {
    601   6134      casper 	return (PRIV_POLICY(cr, PRIV_NET_MAC_AWARE, B_FALSE, EACCES, NULL));
    602   1676         jpk }
    603   1676         jpk 
    604   1676         jpk /*
    605  10934  sommerfeld  * Allow a privileged process to transmit traffic without explicit labels
    606  10934  sommerfeld  */
    607  10934  sommerfeld int
    608  10934  sommerfeld secpolicy_net_mac_implicit(const cred_t *cr)
    609  10934  sommerfeld {
    610  10934  sommerfeld 	return (PRIV_POLICY(cr, PRIV_NET_MAC_IMPLICIT, B_FALSE, EACCES, NULL));
    611  10934  sommerfeld }
    612  10934  sommerfeld 
    613  10934  sommerfeld /*
    614      0      stevel  * Common routine which determines whether a given credential can
    615      0      stevel  * act on a given mount.
    616      0      stevel  * When called through mount, the parameter needoptcheck is a pointer
    617      0      stevel  * to a boolean variable which will be set to either true or false,
    618      0      stevel  * depending on whether the mount policy should change the mount options.
    619      0      stevel  * In all other cases, needoptcheck should be a NULL pointer.
    620      0      stevel  */
    621      0      stevel static int
    622      0      stevel secpolicy_fs_common(cred_t *cr, vnode_t *mvp, const vfs_t *vfsp,
    623      0      stevel     boolean_t *needoptcheck)
    624      0      stevel {
    625      0      stevel 	boolean_t allzone = B_FALSE;
    626      0      stevel 	boolean_t mounting = needoptcheck != NULL;
    627      0      stevel 
    628      0      stevel 	/*
    629      0      stevel 	 * Short circuit the following cases:
    630      0      stevel 	 *	vfsp == NULL or mvp == NULL (pure privilege check)
    631      0      stevel 	 *	have all privileges - no further checks required
    632      0      stevel 	 *	and no mount options need to be set.
    633      0      stevel 	 */
    634      0      stevel 	if (vfsp == NULL || mvp == NULL || HAS_ALLPRIVS(cr)) {
    635      0      stevel 		if (mounting)
    636      0      stevel 			*needoptcheck = B_FALSE;
    637      0      stevel 
    638   6134      casper 		return (priv_policy_va(cr, PRIV_SYS_MOUNT, allzone, EPERM,
    639   6134      casper 		    NULL, KLPDARG_VNODE, mvp, (char *)NULL, KLPDARG_NOMORE));
    640      0      stevel 	}
    641      0      stevel 
    642      0      stevel 	/*
    643      0      stevel 	 * When operating on an existing mount (either we're not mounting
    644      0      stevel 	 * or we're doing a remount and VFS_REMOUNT will be set), zones
    645      0      stevel 	 * can operate only on mounts established by the zone itself.
    646      0      stevel 	 */
    647      0      stevel 	if (!mounting || (vfsp->vfs_flag & VFS_REMOUNT) != 0) {
    648      0      stevel 		zoneid_t zoneid = crgetzoneid(cr);
    649      0      stevel 
    650      0      stevel 		if (zoneid != GLOBAL_ZONEID &&
    651      0      stevel 		    vfsp->vfs_zone->zone_id != zoneid) {
    652      0      stevel 			return (EPERM);
    653      0      stevel 		}
    654      0      stevel 	}
    655      0      stevel 
    656      0      stevel 	if (mounting)
    657      0      stevel 		*needoptcheck = B_TRUE;
    658      0      stevel 
    659      0      stevel 	/*
    660      0      stevel 	 * Overlay mounts may hide important stuff; if you can't write to a
    661      0      stevel 	 * mount point but would be able to mount on top of it, you can
    662      0      stevel 	 * escalate your privileges.
    663      0      stevel 	 * So we go about asking the same questions namefs does when it
    664      0      stevel 	 * decides whether you can mount over a file or not but with the
    665      0      stevel 	 * added restriction that you can only mount on top of a regular
    666      0      stevel 	 * file or directory.
    667      0      stevel 	 * If we have all the zone's privileges, we skip all other checks,
    668      0      stevel 	 * or else we may actually get in trouble inside the automounter.
    669      0      stevel 	 */
    670      0      stevel 	if ((mvp->v_flag & VROOT) != 0 ||
    671      0      stevel 	    (mvp->v_type != VDIR && mvp->v_type != VREG) ||
    672      0      stevel 	    HAS_ALLZONEPRIVS(cr)) {
    673      0      stevel 		allzone = B_TRUE;
    674      0      stevel 	} else {
    675      0      stevel 		vattr_t va;
    676      0      stevel 		int err;
    677      0      stevel 
    678      0      stevel 		va.va_mask = AT_UID|AT_MODE;
    679   5331         amw 		err = VOP_GETATTR(mvp, &va, 0, cr, NULL);
    680      0      stevel 		if (err != 0)
    681      0      stevel 			return (err);
    682      0      stevel 
    683      0      stevel 		if ((err = secpolicy_vnode_owner(cr, va.va_uid)) != 0)
    684      0      stevel 			return (err);
    685      0      stevel 
    686      0      stevel 		if ((va.va_mode & VWRITE) == 0 &&
    687      0      stevel 		    secpolicy_vnode_access(cr, mvp, va.va_uid, VWRITE) != 0) {
    688      0      stevel 			return (EACCES);
    689      0      stevel 		}
    690      0      stevel 	}
    691   6134      casper 	return (priv_policy_va(cr, PRIV_SYS_MOUNT, allzone, EPERM,
    692   6134      casper 	    NULL, KLPDARG_VNODE, mvp, (char *)NULL, KLPDARG_NOMORE));
    693      0      stevel }
    694      0      stevel 
    695   4543       marks void
    696   4543       marks secpolicy_fs_mount_clearopts(cred_t *cr, struct vfs *vfsp)
    697   4543       marks {
    698   4543       marks 	boolean_t amsuper = HAS_ALLZONEPRIVS(cr);
    699   4543       marks 
    700   4543       marks 	/*
    701   4543       marks 	 * check; if we don't have either "nosuid" or
    702   4543       marks 	 * both "nosetuid" and "nodevices", then we add
    703   4543       marks 	 * "nosuid"; this depends on how the current
    704   4543       marks 	 * implementation works (it first checks nosuid).  In a
    705   4543       marks 	 * zone, a user with all zone privileges can mount with
    706   4543       marks 	 * "setuid" but never with "devices".
    707   4543       marks 	 */
    708   4543       marks 	if (!vfs_optionisset(vfsp, MNTOPT_NOSUID, NULL) &&
    709   4543       marks 	    (!vfs_optionisset(vfsp, MNTOPT_NODEVICES, NULL) ||
    710   4543       marks 	    !vfs_optionisset(vfsp, MNTOPT_NOSETUID, NULL))) {
    711   4543       marks 		if (crgetzoneid(cr) == GLOBAL_ZONEID || !amsuper)
    712   4543       marks 			vfs_setmntopt(vfsp, MNTOPT_NOSUID, NULL, 0);
    713   4543       marks 		else
    714   4543       marks 			vfs_setmntopt(vfsp, MNTOPT_NODEVICES, NULL, 0);
    715   4543       marks 	}
    716   4543       marks 	/*
    717   4543       marks 	 * If we're not the local super user, we set the "restrict"
    718   4543       marks 	 * option to indicate to automountd that this mount should
    719   4543       marks 	 * be handled with care.
    720   4543       marks 	 */
    721   4543       marks 	if (!amsuper)
    722   4543       marks 		vfs_setmntopt(vfsp, MNTOPT_RESTRICT, NULL, 0);
    723   4543       marks 
    724   4543       marks }
    725   4543       marks 
    726    148      casper extern vnode_t *rootvp;
    727    148      casper extern vfs_t *rootvfs;
    728    148      casper 
    729      0      stevel int
    730      0      stevel secpolicy_fs_mount(cred_t *cr, vnode_t *mvp, struct vfs *vfsp)
    731      0      stevel {
    732      0      stevel 	boolean_t needoptchk;
    733      0      stevel 	int error;
    734    148      casper 
    735    148      casper 	/*
    736    148      casper 	 * If it's a remount, get the underlying mount point,
    737    148      casper 	 * except for the root where we use the rootvp.
    738    148      casper 	 */
    739    148      casper 	if ((vfsp->vfs_flag & VFS_REMOUNT) != 0) {
    740    148      casper 		if (vfsp == rootvfs)
    741    148      casper 			mvp = rootvp;
    742    148      casper 		else
    743    148      casper 			mvp = vfsp->vfs_vnodecovered;
    744    148      casper 	}
    745      0      stevel 
    746      0      stevel 	error = secpolicy_fs_common(cr, mvp, vfsp, &needoptchk);
    747      0      stevel 
    748      0      stevel 	if (error == 0 && needoptchk) {
    749   4543       marks 		secpolicy_fs_mount_clearopts(cr, vfsp);
    750   4543       marks 	}
    751      0      stevel 
    752      0      stevel 	return (error);
    753      0      stevel }
    754      0      stevel 
    755      0      stevel /*
    756      0      stevel  * Does the policy computations for "ownership" of a mount;
    757      0      stevel  * here ownership is defined as the ability to "mount"
    758      0      stevel  * the filesystem originally.  The rootvfs doesn't cover any
    759      0      stevel  * vnodes; we attribute its ownership to the rootvp.
    760      0      stevel  */
    761      0      stevel static int
    762      0      stevel secpolicy_fs_owner(cred_t *cr, const struct vfs *vfsp)
    763      0      stevel {
    764      0      stevel 	vnode_t *mvp;
    765      0      stevel 
    766      0      stevel 	if (vfsp == NULL)
    767      0      stevel 		mvp = NULL;
    768      0      stevel 	else if (vfsp == rootvfs)
    769      0      stevel 		mvp = rootvp;
    770      0      stevel 	else
    771      0      stevel 		mvp = vfsp->vfs_vnodecovered;
    772      0      stevel 
    773      0      stevel 	return (secpolicy_fs_common(cr, mvp, vfsp, NULL));
    774      0      stevel }
    775      0      stevel 
    776      0      stevel int
    777      0      stevel secpolicy_fs_unmount(cred_t *cr, struct vfs *vfsp)
    778      0      stevel {
    779      0      stevel 	return (secpolicy_fs_owner(cr, vfsp));
    780      0      stevel }
    781      0      stevel 
    782      0      stevel /*
    783      0      stevel  * Quotas are a resource, but if one has the ability to mount a filesystem, he
    784      0      stevel  * should be able to modify quotas on it.
    785      0      stevel  */
    786      0      stevel int
    787      0      stevel secpolicy_fs_quota(const cred_t *cr, const vfs_t *vfsp)
    788      0      stevel {
    789      0      stevel 	return (secpolicy_fs_owner((cred_t *)cr, vfsp));
    790      0      stevel }
    791      0      stevel 
    792      0      stevel /*
    793      0      stevel  * Exceeding minfree: also a per-mount resource constraint.
    794      0      stevel  */
    795      0      stevel int
    796      0      stevel secpolicy_fs_minfree(const cred_t *cr, const vfs_t *vfsp)
    797      0      stevel {
    798      0      stevel 	return (secpolicy_fs_owner((cred_t *)cr, vfsp));
    799      0      stevel }
    800      0      stevel 
    801      0      stevel int
    802      0      stevel secpolicy_fs_config(const cred_t *cr, const vfs_t *vfsp)
    803      0      stevel {
    804      0      stevel 	return (secpolicy_fs_owner((cred_t *)cr, vfsp));
    805      0      stevel }
    806      0      stevel 
    807      0      stevel /* ARGSUSED */
    808      0      stevel int
    809      0      stevel secpolicy_fs_linkdir(const cred_t *cr, const vfs_t *vfsp)
    810      0      stevel {
    811      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_LINKDIR, B_FALSE, EPERM, NULL));
    812      0      stevel }
    813      0      stevel 
    814      0      stevel /*
    815      0      stevel  * Name:        secpolicy_vnode_access()
    816      0      stevel  *
    817      0      stevel  * Parameters:  Process credential
    818      0      stevel  *		vnode
    819      0      stevel  *		uid of owner of vnode
    820      0      stevel  *		permission bits not granted to the caller when examining
    821      0      stevel  *		file mode bits (i.e., when a process wants to open a
    822      0      stevel  *		mode 444 file for VREAD|VWRITE, this function should be
    823      0      stevel  *		called only with a VWRITE argument).
    824      0      stevel  *
    825      0      stevel  * Normal:      Verifies that cred has the appropriate privileges to
    826      0      stevel  *              override the mode bits that were denied.
    827      0      stevel  *
    828      0      stevel  * Override:    file_dac_execute - if VEXEC bit was denied and vnode is
    829      0      stevel  *                      not a directory.
    830      0      stevel  *              file_dac_read - if VREAD bit was denied.
    831      0      stevel  *              file_dac_search - if VEXEC bit was denied and vnode is
    832      0      stevel  *                      a directory.
    833      0      stevel  *              file_dac_write - if VWRITE bit was denied.
    834      0      stevel  *
    835      0      stevel  *		Root owned files are special cased to protect system
    836      0      stevel  *		configuration files and such.
    837      0      stevel  *
    838      0      stevel  * Output:      EACCES - if privilege check fails.
    839      0      stevel  */
    840      0      stevel 
    841      0      stevel /* ARGSUSED */
    842      0      stevel int
    843      0      stevel secpolicy_vnode_access(const cred_t *cr, vnode_t *vp, uid_t owner, mode_t mode)
    844      0      stevel {
    845   6134      casper 	if ((mode & VREAD) && priv_policy_va(cr, PRIV_FILE_DAC_READ, B_FALSE,
    846   6134      casper 	    EACCES, NULL, KLPDARG_VNODE, vp, (char *)NULL,
    847   6134      casper 	    KLPDARG_NOMORE) != 0) {
    848      0      stevel 		return (EACCES);
    849   6134      casper 	}
    850      0      stevel 
    851      0      stevel 	if (mode & VWRITE) {
    852      0      stevel 		boolean_t allzone;
    853      0      stevel 
    854      0      stevel 		if (owner == 0 && cr->cr_uid != 0)
    855      0      stevel 			allzone = B_TRUE;
    856      0      stevel 		else
    857      0      stevel 			allzone = B_FALSE;
    858   6134      casper 		if (priv_policy_va(cr, PRIV_FILE_DAC_WRITE, allzone, EACCES,
    859   6134      casper 		    NULL, KLPDARG_VNODE, vp, (char *)NULL,
    860   6134      casper 		    KLPDARG_NOMORE) != 0) {
    861      0      stevel 			return (EACCES);
    862   6134      casper 		}
    863      0      stevel 	}
    864      0      stevel 
    865      0      stevel 	if (mode & VEXEC) {
    866      0      stevel 		/*
    867      0      stevel 		 * Directories use file_dac_search to override the execute bit.
    868      0      stevel 		 */
    869   6134      casper 		int p = vp->v_type == VDIR ? PRIV_FILE_DAC_SEARCH :
    870   6134      casper 		    PRIV_FILE_DAC_EXECUTE;
    871      0      stevel 
    872   6134      casper 		return (priv_policy_va(cr, p, B_FALSE, EACCES, NULL,
    873   6134      casper 		    KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE));
    874      0      stevel 	}
    875      0      stevel 	return (0);
    876      0      stevel }
    877      0      stevel 
    878      0      stevel /*
    879      0      stevel  * Name:	secpolicy_vnode_setid_modify()
    880      0      stevel  *
    881      0      stevel  * Normal:	verify that subject can set the file setid flags.
    882      0      stevel  *
    883      0      stevel  * Output:	EPERM - if not privileged.
    884      0      stevel  */
    885      0      stevel 
    886      0      stevel static int
    887      0      stevel secpolicy_vnode_setid_modify(const cred_t *cr, uid_t owner)
    888      0      stevel {
    889      0      stevel 	/* If changing to suid root, must have all zone privs */
    890      0      stevel 	boolean_t allzone = B_TRUE;
    891      0      stevel 
    892      0      stevel 	if (owner != 0) {
    893      0      stevel 		if (owner == cr->cr_uid)
    894      0      stevel 			return (0);
    895      0      stevel 		allzone = B_FALSE;
    896      0      stevel 	}
    897      0      stevel 	return (PRIV_POLICY(cr, PRIV_FILE_SETID, allzone, EPERM, NULL));
    898      0      stevel }
    899      0      stevel 
    900      0      stevel /*
    901      0      stevel  * Are we allowed to retain the set-uid/set-gid bits when
    902      0      stevel  * changing ownership or when writing to a file?
    903      0      stevel  * "issuid" should be true when set-uid; only in that case
    904      0      stevel  * root ownership is checked (setgid is assumed).
    905      0      stevel  */
    906      0      stevel int
    907      0      stevel secpolicy_vnode_setid_retain(const cred_t *cred, boolean_t issuidroot)
    908      0      stevel {
    909      0      stevel 	if (issuidroot && !HAS_ALLZONEPRIVS(cred))
    910      0      stevel 		return (EPERM);
    911      0      stevel 
    912      0      stevel 	return (!PRIV_POLICY_CHOICE(cred, PRIV_FILE_SETID, B_FALSE));
    913      0      stevel }
    914      0      stevel 
    915      0      stevel /*
    916      0      stevel  * Name:	secpolicy_vnode_setids_setgids()
    917      0      stevel  *
    918      0      stevel  * Normal:	verify that subject can set the file setgid flag.
    919      0      stevel  *
    920      0      stevel  * Output:	EPERM - if not privileged
    921      0      stevel  */
    922      0      stevel 
    923      0      stevel int
    924      0      stevel secpolicy_vnode_setids_setgids(const cred_t *cred, gid_t gid)
    925      0      stevel {
    926      0      stevel 	if (!groupmember(gid, cred))
    927      0      stevel 		return (PRIV_POLICY(cred, PRIV_FILE_SETID, B_FALSE, EPERM,
    928      0      stevel 		    NULL));
    929      0      stevel 	return (0);
    930      0      stevel }
    931      0      stevel 
    932      0      stevel /*
    933   7624        Mark  * Name:	secpolicy_vnode_chown
    934   7624        Mark  *
    935   7624        Mark  * Normal:	Determine if subject can chown owner of a file.
    936   7624        Mark  *
    937   7624        Mark  * Output:	EPERM - if access denied
    938   7624        Mark  */
    939   7624        Mark 
    940   7624        Mark int
    941   9866        Mark secpolicy_vnode_chown(const cred_t *cred, uid_t owner)
    942   7624        Mark {
    943   9866        Mark 	boolean_t is_owner = (owner == crgetuid(cred));
    944   9866        Mark 	boolean_t allzone = B_FALSE;
    945   9866        Mark 	int priv;
    946   9866        Mark 
    947   9866        Mark 	if (!is_owner) {
    948   9866        Mark 		allzone = (owner == 0);
    949   9866        Mark 		priv = PRIV_FILE_CHOWN;
    950   9866        Mark 	} else {
    951   9866        Mark 		priv = HAS_PRIVILEGE(cred, PRIV_FILE_CHOWN) ?
    952   9866        Mark 		    PRIV_FILE_CHOWN : PRIV_FILE_CHOWN_SELF;
    953   9866        Mark 	}
    954   9866        Mark 
    955   9866        Mark 	return (PRIV_POLICY(cred, priv, allzone, EPERM, NULL));
    956   7624        Mark }
    957   7624        Mark 
    958   7624        Mark /*
    959   7624        Mark  * Name:	secpolicy_vnode_create_gid
    960   7624        Mark  *
    961   7624        Mark  * Normal:	Determine if subject can change group ownership of a file.
    962   7624        Mark  *
    963   7624        Mark  * Output:	EPERM - if access denied
    964      0      stevel  */
    965      0      stevel int
    966      0      stevel secpolicy_vnode_create_gid(const cred_t *cred)
    967      0      stevel {
    968   9866        Mark 	if (HAS_PRIVILEGE(cred, PRIV_FILE_CHOWN))
    969   9866        Mark 		return (PRIV_POLICY(cred, PRIV_FILE_CHOWN, B_FALSE, EPERM,
    970   9866        Mark 		    NULL));
    971   9866        Mark 	else
    972   9866        Mark 		return (PRIV_POLICY(cred, PRIV_FILE_CHOWN_SELF, B_FALSE, EPERM,
    973   9866        Mark 		    NULL));
    974      0      stevel }
    975      0      stevel 
    976      0      stevel /*
    977      0      stevel  * Name:	secpolicy_vnode_utime_modify()
    978      0      stevel  *
    979      0      stevel  * Normal:	verify that subject can modify the utime on a file.
    980      0      stevel  *
    981      0      stevel  * Output:	EPERM - if access denied.
    982      0      stevel  */
    983      0      stevel 
    984      0      stevel static int
    985      0      stevel secpolicy_vnode_utime_modify(const cred_t *cred)
    986      0      stevel {
    987      0      stevel 	return (PRIV_POLICY(cred, PRIV_FILE_OWNER, B_FALSE, EPERM,
    988      0      stevel 	    "modify file times"));
    989      0      stevel }
    990      0      stevel 
    991      0      stevel 
    992      0      stevel /*
    993      0      stevel  * Name:	secpolicy_vnode_setdac()
    994      0      stevel  *
    995      0      stevel  * Normal:	verify that subject can modify the mode of a file.
    996      0      stevel  *		allzone privilege needed when modifying root owned object.
    997      0      stevel  *
    998      0      stevel  * Output:	EPERM - if access denied.
    999      0      stevel  */
   1000      0      stevel 
   1001      0      stevel int
   1002      0      stevel secpolicy_vnode_setdac(const cred_t *cred, uid_t owner)
   1003      0      stevel {
   1004      0      stevel 	if (owner == cred->cr_uid)
   1005      0      stevel 		return (0);
   1006      0      stevel 
   1007      0      stevel 	return (PRIV_POLICY(cred, PRIV_FILE_OWNER, owner == 0, EPERM, NULL));
   1008      0      stevel }
   1009      0      stevel /*
   1010      0      stevel  * Name:	secpolicy_vnode_stky_modify()
   1011      0      stevel  *
   1012      0      stevel  * Normal:	verify that subject can make a file a "sticky".
   1013      0      stevel  *
   1014      0      stevel  * Output:	EPERM - if access denied.
   1015      0      stevel  */
   1016      0      stevel 
   1017      0      stevel int
   1018      0      stevel secpolicy_vnode_stky_modify(const cred_t *cred)
   1019      0      stevel {
   1020      0      stevel 	return (PRIV_POLICY(cred, PRIV_SYS_CONFIG, B_FALSE, EPERM,
   1021      0      stevel 	    "set file sticky"));
   1022      0      stevel }
   1023      0      stevel 
   1024      0      stevel /*
   1025      0      stevel  * Policy determines whether we can remove an entry from a directory,
   1026      0      stevel  * regardless of permission bits.
   1027      0      stevel  */
   1028      0      stevel int
   1029      0      stevel secpolicy_vnode_remove(const cred_t *cr)
   1030      0      stevel {
   1031      0      stevel 	return (PRIV_POLICY(cr, PRIV_FILE_OWNER, B_FALSE, EACCES,
   1032      0      stevel 	    "sticky directory"));
   1033      0      stevel }
   1034      0      stevel 
   1035      0      stevel int
   1036      0      stevel secpolicy_vnode_owner(const cred_t *cr, uid_t owner)
   1037      0      stevel {
   1038      0      stevel 	boolean_t allzone = (owner == 0);
   1039      0      stevel 
   1040      0      stevel 	if (owner == cr->cr_uid)
   1041      0      stevel 		return (0);
   1042      0      stevel 
   1043      0      stevel 	return (PRIV_POLICY(cr, PRIV_FILE_OWNER, allzone, EPERM, NULL));
   1044      0      stevel }
   1045      0      stevel 
   1046   1115       marks void
   1047   1115       marks secpolicy_setid_clear(vattr_t *vap, cred_t *cr)
   1048   1115       marks {
   1049   1115       marks 	if ((vap->va_mode & (S_ISUID | S_ISGID)) != 0 &&
   1050   1115       marks 	    secpolicy_vnode_setid_retain(cr,
   1051   1115       marks 	    (vap->va_mode & S_ISUID) != 0 &&
   1052   1115       marks 	    (vap->va_mask & AT_UID) != 0 && vap->va_uid == 0) != 0) {
   1053   1115       marks 		vap->va_mask |= AT_MODE;
   1054   1115       marks 		vap->va_mode &= ~(S_ISUID|S_ISGID);
   1055   1115       marks 	}
   1056   1115       marks }
   1057   1115       marks 
   1058   2796       marks int
   1059   2796       marks secpolicy_setid_setsticky_clear(vnode_t *vp, vattr_t *vap, const vattr_t *ovap,
   1060   2796       marks     cred_t *cr)
   1061   2796       marks {
   1062   2796       marks 	int error;
   1063   2796       marks 
   1064   2796       marks 	if ((vap->va_mode & S_ISUID) != 0 &&
   1065   2796       marks 	    (error = secpolicy_vnode_setid_modify(cr,
   1066   2796       marks 	    ovap->va_uid)) != 0) {
   1067   2796       marks 		return (error);
   1068   2796       marks 	}
   1069   2796       marks 
   1070   2796       marks 	/*
   1071   2796       marks 	 * Check privilege if attempting to set the
   1072   2796       marks 	 * sticky bit on a non-directory.
   1073   2796       marks 	 */
   1074   2796       marks 	if (vp->v_type != VDIR && (vap->va_mode & S_ISVTX) != 0 &&
   1075   2796       marks 	    secpolicy_vnode_stky_modify(cr) != 0) {
   1076   4543       marks 		vap->va_mode &= ~S_ISVTX;
   1077   2796       marks 	}
   1078   2796       marks 
   1079   2796       marks 	/*
   1080   2796       marks 	 * Check for privilege if attempting to set the
   1081   2796       marks 	 * group-id bit.
   1082   2796       marks 	 */
   1083   2796       marks 	if ((vap->va_mode & S_ISGID) != 0 &&
   1084   2796       marks 	    secpolicy_vnode_setids_setgids(cr, ovap->va_gid) != 0) {
   1085   4543       marks 		vap->va_mode &= ~S_ISGID;
   1086   2796       marks 	}
   1087   2796       marks 
   1088   2796       marks 	return (0);
   1089   2796       marks }
   1090   2796       marks 
   1091   5331         amw #define	ATTR_FLAG_PRIV(attr, value, cr)	\
   1092   5331         amw 	PRIV_POLICY(cr, value ? PRIV_FILE_FLAG_SET : PRIV_ALL, \
   1093   5331         amw 	B_FALSE, EPERM, NULL)
   1094   5331         amw 
   1095   5331         amw /*
   1096   5331         amw  * Check privileges for setting xvattr attributes
   1097   5331         amw  */
   1098   5331         amw int
   1099   5331         amw secpolicy_xvattr(xvattr_t *xvap, uid_t owner, cred_t *cr, vtype_t vtype)
   1100   5331         amw {
   1101   5331         amw 	xoptattr_t *xoap;
   1102   5331         amw 	int error = 0;
   1103   5331         amw 
   1104   5331         amw 	if ((xoap = xva_getxoptattr(xvap)) == NULL)
   1105   5331         amw 		return (EINVAL);
   1106   5331         amw 
   1107   5331         amw 	/*
   1108   5331         amw 	 * First process the DOS bits
   1109   5331         amw 	 */
   1110   5331         amw 	if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE) ||
   1111   5331         amw 	    XVA_ISSET_REQ(xvap, XAT_HIDDEN) ||
   1112   5331         amw 	    XVA_ISSET_REQ(xvap, XAT_READONLY) ||
   1113   5331         amw 	    XVA_ISSET_REQ(xvap, XAT_SYSTEM) ||
   1114   5331         amw 	    XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
   1115   5331         amw 		if ((error = secpolicy_vnode_owner(cr, owner)) != 0)
   1116   5331         amw 			return (error);
   1117   5331         amw 	}
   1118   5331         amw 
   1119   5331         amw 	/*
   1120   5331         amw 	 * Now handle special attributes
   1121   5331         amw 	 */
   1122   5331         amw 
   1123   5331         amw 	if (XVA_ISSET_REQ(xvap, XAT_IMMUTABLE))
   1124   5331         amw 		error = ATTR_FLAG_PRIV(XAT_IMMUTABLE,
   1125   5331         amw 		    xoap->xoa_immutable, cr);
   1126   5331         amw 	if (error == 0 && XVA_ISSET_REQ(xvap, XAT_NOUNLINK))
   1127   5331         amw 		error = ATTR_FLAG_PRIV(XAT_NOUNLINK,
   1128   5331         amw 		    xoap->xoa_nounlink, cr);
   1129   5331         amw 	if (error == 0 && XVA_ISSET_REQ(xvap, XAT_APPENDONLY))
   1130   5331         amw 		error = ATTR_FLAG_PRIV(XAT_APPENDONLY,
   1131   5331         amw 		    xoap->xoa_appendonly, cr);
   1132   5331         amw 	if (error == 0 && XVA_ISSET_REQ(xvap, XAT_NODUMP))
   1133   5331         amw 		error = ATTR_FLAG_PRIV(XAT_NODUMP,
   1134   5331         amw 		    xoap->xoa_nodump, cr);
   1135   5331         amw 	if (error == 0 && XVA_ISSET_REQ(xvap, XAT_OPAQUE))
   1136   5331         amw 		error = EPERM;
   1137   5331         amw 	if (error == 0 && XVA_ISSET_REQ(xvap, XAT_AV_QUARANTINED)) {
   1138   5331         amw 		error = ATTR_FLAG_PRIV(XAT_AV_QUARANTINED,
   1139   5331         amw 		    xoap->xoa_av_quarantined, cr);
   1140   5545       marks 		if (error == 0 && vtype != VREG && xoap->xoa_av_quarantined)
   1141   5331         amw 			error = EINVAL;
   1142   5331         amw 	}
   1143   5331         amw 	if (error == 0 && XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED))
   1144   5331         amw 		error = ATTR_FLAG_PRIV(XAT_AV_MODIFIED,
   1145   5331         amw 		    xoap->xoa_av_modified, cr);
   1146   5331         amw 	if (error == 0 && XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) {
   1147   5331         amw 		error = ATTR_FLAG_PRIV(XAT_AV_SCANSTAMP,
   1148   5331         amw 		    xoap->xoa_av_scanstamp, cr);
   1149   5331         amw 		if (error == 0 && vtype != VREG)
   1150   5331         amw 			error = EINVAL;
   1151   5331         amw 	}
   1152   5331         amw 	return (error);
   1153   5331         amw }
   1154   5331         amw 
   1155      0      stevel /*
   1156      0      stevel  * This function checks the policy decisions surrounding the
   1157      0      stevel  * vop setattr call.
   1158      0      stevel  *
   1159      0      stevel  * It should be called after sufficient locks have been established
   1160      0      stevel  * on the underlying data structures.  No concurrent modifications
   1161      0      stevel  * should be allowed.
   1162      0      stevel  *
   1163      0      stevel  * The caller must pass in unlocked version of its vaccess function
   1164      0      stevel  * this is required because vop_access function should lock the
   1165      0      stevel  * node for reading.  A three argument function should be defined
   1166      0      stevel  * which accepts the following argument:
   1167      0      stevel  * 	A pointer to the internal "node" type (inode *)
   1168      0      stevel  *	vnode access bits (VREAD|VWRITE|VEXEC)
   1169      0      stevel  *	a pointer to the credential
   1170      0      stevel  *
   1171      0      stevel  * This function makes the following policy decisions:
   1172      0      stevel  *
   1173      0      stevel  *		- change permissions
   1174      0      stevel  *			- permission to change file mode if not owner
   1175      0      stevel  *			- permission to add sticky bit to non-directory
   1176      0      stevel  *			- permission to add set-gid bit
   1177      0      stevel  *
   1178      0      stevel  * The ovap argument should include AT_MODE|AT_UID|AT_GID.
   1179      0      stevel  *
   1180      0      stevel  * If the vap argument does not include AT_MODE, the mode will be copied from
   1181      0      stevel  * ovap.  In certain situations set-uid/set-gid bits need to be removed;
   1182      0      stevel  * this is done by marking vap->va_mask to include AT_MODE and va_mode
   1183      0      stevel  * is updated to the newly computed mode.
   1184      0      stevel  */
   1185      0      stevel 
   1186      0      stevel int
   1187      0      stevel secpolicy_vnode_setattr(cred_t *cr, struct vnode *vp, struct vattr *vap,
   1188      0      stevel 	const struct vattr *ovap, int flags,
   1189      0      stevel 	int unlocked_access(void *, int, cred_t *),
   1190      0      stevel 	void *node)
   1191      0      stevel {
   1192      0      stevel 	int mask = vap->va_mask;
   1193      0      stevel 	int error = 0;
   1194   5331         amw 	boolean_t skipaclchk = (flags & ATTR_NOACLCHECK) ? B_TRUE : B_FALSE;
   1195      0      stevel 
   1196      0      stevel 	if (mask & AT_SIZE) {
   1197      0      stevel 		if (vp->v_type == VDIR) {
   1198      0      stevel 			error = EISDIR;
   1199      0      stevel 			goto out;
   1200      0      stevel 		}
   1201   5331         amw 
   1202   5331         amw 		/*
   1203   5331         amw 		 * If ATTR_NOACLCHECK is set in the flags, then we don't
   1204   5331         amw 		 * perform the secondary unlocked_access() call since the
   1205   5331         amw 		 * ACL (if any) is being checked there.
   1206   5331         amw 		 */
   1207   5331         amw 		if (skipaclchk == B_FALSE) {
   1208   5331         amw 			error = unlocked_access(node, VWRITE, cr);
   1209   5331         amw 			if (error)
   1210   5331         amw 				goto out;
   1211   5331         amw 		}
   1212      0      stevel 	}
   1213      0      stevel 	if (mask & AT_MODE) {
   1214      0      stevel 		/*
   1215      0      stevel 		 * If not the owner of the file then check privilege
   1216      0      stevel 		 * for two things: the privilege to set the mode at all
   1217      0      stevel 		 * and, if we're setting setuid, we also need permissions
   1218      0      stevel 		 * to add the set-uid bit, if we're not the owner.
   1219      0      stevel 		 * In the specific case of creating a set-uid root
   1220      0      stevel 		 * file, we need even more permissions.
   1221      0      stevel 		 */
   1222      0      stevel 		if ((error = secpolicy_vnode_setdac(cr, ovap->va_uid)) != 0)
   1223      0      stevel 			goto out;
   1224      0      stevel 
   1225   2796       marks 		if ((error = secpolicy_setid_setsticky_clear(vp, vap,
   1226   2796       marks 		    ovap, cr)) != 0)
   1227      0      stevel 			goto out;
   1228      0      stevel 	} else
   1229      0      stevel 		vap->va_mode = ovap->va_mode;
   1230      0      stevel 
   1231      0      stevel 	if (mask & (AT_UID|AT_GID)) {
   1232      0      stevel 		boolean_t checkpriv = B_FALSE;
   1233      0      stevel 
   1234      0      stevel 		/*
   1235      0      stevel 		 * Chowning files.
   1236      0      stevel 		 *
   1237      0      stevel 		 * If you are the file owner:
   1238      0      stevel 		 *	chown to other uid		FILE_CHOWN_SELF
   1239      0      stevel 		 *	chown to gid (non-member) 	FILE_CHOWN_SELF
   1240      0      stevel 		 *	chown to gid (member) 		<none>
   1241      0      stevel 		 *
   1242      0      stevel 		 * Instead of PRIV_FILE_CHOWN_SELF, FILE_CHOWN is also
   1243      0      stevel 		 * acceptable but the first one is reported when debugging.
   1244      0      stevel 		 *
   1245      0      stevel 		 * If you are not the file owner:
   1246      0      stevel 		 *	chown from root			PRIV_FILE_CHOWN + zone
   1247      0      stevel 		 *	chown from other to any		PRIV_FILE_CHOWN
   1248      0      stevel 		 *
   1249      0      stevel 		 */
   1250      0      stevel 		if (cr->cr_uid != ovap->va_uid) {
   1251      0      stevel 			checkpriv = B_TRUE;
   1252      0      stevel 		} else {
   1253      0      stevel 			if (((mask & AT_UID) && vap->va_uid != ovap->va_uid) ||
   1254      0      stevel 			    ((mask & AT_GID) && vap->va_gid != ovap->va_gid &&
   1255      0      stevel 			    !groupmember(vap->va_gid, cr))) {
   1256      0      stevel 				checkpriv = B_TRUE;
   1257      0      stevel 			}
   1258      0      stevel 		}
   1259      0      stevel 		/*
   1260      0      stevel 		 * If necessary, check privilege to see if update can be done.
   1261      0      stevel 		 */
   1262      0      stevel 		if (checkpriv &&
   1263   9866        Mark 		    (error = secpolicy_vnode_chown(cr, ovap->va_uid)) != 0) {
   1264      0      stevel 			goto out;
   1265      0      stevel 		}
   1266      0      stevel 
   1267      0      stevel 		/*
   1268      0      stevel 		 * If the file has either the set UID or set GID bits
   1269      0      stevel 		 * set and the caller can set the bits, then leave them.
   1270      0      stevel 		 */
   1271   1115       marks 		secpolicy_setid_clear(vap, cr);
   1272      0      stevel 	}
   1273      0      stevel 	if (mask & (AT_ATIME|AT_MTIME)) {
   1274      0      stevel 		/*
   1275      0      stevel 		 * If not the file owner and not otherwise privileged,
   1276      0      stevel 		 * always return an error when setting the
   1277      0      stevel 		 * time other than the current (ATTR_UTIME flag set).
   1278      0      stevel 		 * If setting the current time (ATTR_UTIME not set) then
   1279      0      stevel 		 * unlocked_access will check permissions according to policy.
   1280      0      stevel 		 */
   1281      0      stevel 		if (cr->cr_uid != ovap->va_uid) {
   1282      0      stevel 			if (flags & ATTR_UTIME)
   1283      0      stevel 				error = secpolicy_vnode_utime_modify(cr);
   1284   5331         amw 			else if (skipaclchk == B_FALSE) {
   1285      0      stevel 				error = unlocked_access(node, VWRITE, cr);
   1286      0      stevel 				if (error == EACCES &&
   1287      0      stevel 				    secpolicy_vnode_utime_modify(cr) == 0)
   1288      0      stevel 					error = 0;
   1289      0      stevel 			}
   1290      0      stevel 			if (error)
   1291      0      stevel 				goto out;
   1292      0      stevel 		}
   1293      0      stevel 	}
   1294   5331         amw 
   1295   5331         amw 	/*
   1296   5331         amw 	 * Check for optional attributes here by checking the following:
   1297   5331         amw 	 */
   1298   5331         amw 	if (mask & AT_XVATTR)
   1299   5331         amw 		error = secpolicy_xvattr((xvattr_t *)vap, ovap->va_uid, cr,
   1300   5331         amw 		    vp->v_type);
   1301      0      stevel out:
   1302      0      stevel 	return (error);
   1303      0      stevel }
   1304      0      stevel 
   1305      0      stevel /*
   1306      0      stevel  * Name:	secpolicy_pcfs_modify_bootpartition()
   1307      0      stevel  *
   1308      0      stevel  * Normal:	verify that subject can modify a pcfs boot partition.
   1309      0      stevel  *
   1310      0      stevel  * Output:	EACCES - if privilege check failed.
   1311      0      stevel  */
   1312      0      stevel /*ARGSUSED*/
   1313      0      stevel int
   1314      0      stevel secpolicy_pcfs_modify_bootpartition(const cred_t *cred)
   1315      0      stevel {
   1316      0      stevel 	return (PRIV_POLICY(cred, PRIV_ALL, B_FALSE, EACCES,
   1317      0      stevel 	    "modify pcfs boot partition"));
   1318      0      stevel }
   1319      0      stevel 
   1320      0      stevel /*
   1321      0      stevel  * System V IPC routines
   1322      0      stevel  */
   1323      0      stevel int
   1324      0      stevel secpolicy_ipc_owner(const cred_t *cr, const struct kipc_perm *ip)
   1325      0      stevel {
   1326      0      stevel 	if (crgetzoneid(cr) != ip->ipc_zoneid ||
   1327      0      stevel 	    (cr->cr_uid != ip->ipc_uid && cr->cr_uid != ip->ipc_cuid)) {
   1328      0      stevel 		boolean_t allzone = B_FALSE;
   1329      0      stevel 		if (ip->ipc_uid == 0 || ip->ipc_cuid == 0)
   1330      0      stevel 			allzone = B_TRUE;
   1331      0      stevel 		return (PRIV_POLICY(cr, PRIV_IPC_OWNER, allzone, EPERM, NULL));
   1332      0      stevel 	}
   1333      0      stevel 	return (0);
   1334      0      stevel }
   1335      0      stevel 
   1336      0      stevel int
   1337      0      stevel secpolicy_ipc_config(const cred_t *cr)
   1338      0      stevel {
   1339      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_IPC_CONFIG, B_FALSE, EPERM, NULL));
   1340      0      stevel }
   1341      0      stevel 
   1342      0      stevel int
   1343      0      stevel secpolicy_ipc_access(const cred_t *cr, const struct kipc_perm *ip, mode_t mode)
   1344      0      stevel {
   1345      0      stevel 
   1346      0      stevel 	boolean_t allzone = B_FALSE;
   1347      0      stevel 
   1348      0      stevel 	ASSERT((mode & (MSG_R|MSG_W)) != 0);
   1349      0      stevel 
   1350      0      stevel 	if ((mode & MSG_R) &&
   1351      0      stevel 	    PRIV_POLICY(cr, PRIV_IPC_DAC_READ, allzone, EACCES, NULL) != 0)
   1352      0      stevel 		return (EACCES);
   1353      0      stevel 
   1354      0      stevel 	if (mode & MSG_W) {
   1355      0      stevel 		if (cr->cr_uid != 0 && (ip->ipc_uid == 0 || ip->ipc_cuid == 0))
   1356      0      stevel 			allzone = B_TRUE;
   1357      0      stevel 
   1358      0      stevel 		return (PRIV_POLICY(cr, PRIV_IPC_DAC_WRITE, allzone, EACCES,
   1359      0      stevel 		    NULL));
   1360      0      stevel 	}
   1361      0      stevel 	return (0);
   1362      0      stevel }
   1363      0      stevel 
   1364      0      stevel int
   1365      0      stevel secpolicy_rsm_access(const cred_t *cr, uid_t owner, mode_t mode)
   1366      0      stevel {
   1367      0      stevel 	boolean_t allzone = B_FALSE;
   1368      0      stevel 
   1369      0      stevel 	ASSERT((mode & (MSG_R|MSG_W)) != 0);
   1370      0      stevel 
   1371      0      stevel 	if ((mode & MSG_R) &&
   1372      0      stevel 	    PRIV_POLICY(cr, PRIV_IPC_DAC_READ, allzone, EACCES, NULL) != 0)
   1373      0      stevel 		return (EACCES);
   1374      0      stevel 
   1375      0      stevel 	if (mode & MSG_W) {
   1376      0      stevel 		if (cr->cr_uid != 0 && owner == 0)
   1377      0      stevel 			allzone = B_TRUE;
   1378      0      stevel 
   1379      0      stevel 		return (PRIV_POLICY(cr, PRIV_IPC_DAC_WRITE, allzone, EACCES,
   1380      0      stevel 		    NULL));
   1381      0      stevel 	}
   1382      0      stevel 	return (0);
   1383      0      stevel }
   1384      0      stevel 
   1385      0      stevel /*
   1386      0      stevel  * Audit configuration.
   1387      0      stevel  */
   1388      0      stevel int
   1389      0      stevel secpolicy_audit_config(const cred_t *cr)
   1390      0      stevel {
   1391      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_AUDIT, B_FALSE, EPERM, NULL));
   1392      0      stevel }
   1393      0      stevel 
   1394      0      stevel /*
   1395      0      stevel  * Audit record generation.
   1396      0      stevel  */
   1397      0      stevel int
   1398      0      stevel secpolicy_audit_modify(const cred_t *cr)
   1399      0      stevel {
   1400      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_AUDIT, B_FALSE, EPERM, NULL));
   1401      0      stevel }
   1402      0      stevel 
   1403      0      stevel /*
   1404      0      stevel  * Get audit attributes.
   1405      0      stevel  * Either PRIV_SYS_AUDIT or PRIV_PROC_AUDIT required; report the
   1406      0      stevel  * "Least" of the two privileges on error.
   1407      0      stevel  */
   1408      0      stevel int
   1409      0      stevel secpolicy_audit_getattr(const cred_t *cr)
   1410      0      stevel {
   1411      0      stevel 	if (!PRIV_POLICY_ONLY(cr, PRIV_SYS_AUDIT, B_FALSE)) {
   1412      0      stevel 		return (PRIV_POLICY(cr, PRIV_PROC_AUDIT, B_FALSE, EPERM,
   1413      0      stevel 		    NULL));
   1414      0      stevel 	} else {
   1415      0      stevel 		return (PRIV_POLICY(cr, PRIV_SYS_AUDIT, B_FALSE, EPERM, NULL));
   1416      0      stevel 	}
   1417      0      stevel }
   1418      0      stevel 
   1419      0      stevel 
   1420      0      stevel /*
   1421      0      stevel  * Locking physical memory
   1422      0      stevel  */
   1423      0      stevel int
   1424      0      stevel secpolicy_lock_memory(const cred_t *cr)
   1425      0      stevel {
   1426      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_LOCK_MEMORY, B_FALSE, EPERM, NULL));
   1427      0      stevel }
   1428      0      stevel 
   1429      0      stevel /*
   1430      0      stevel  * Accounting (both acct(2) and exacct).
   1431      0      stevel  */
   1432      0      stevel int
   1433      0      stevel secpolicy_acct(const cred_t *cr)
   1434      0      stevel {
   1435      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_ACCT, B_FALSE, EPERM, NULL));
   1436      0      stevel }
   1437      0      stevel 
   1438      0      stevel /*
   1439      0      stevel  * Is this process privileged to change its uids at will?
   1440      0      stevel  * Uid 0 is still considered "special" and having the SETID
   1441      0      stevel  * privilege is not sufficient to get uid 0.
   1442      0      stevel  * Files are owned by root, so the privilege would give
   1443      0      stevel  * full access and euid 0 is still effective.
   1444      0      stevel  *
   1445      0      stevel  * If you have the privilege and euid 0 only then do you
   1446      0      stevel  * get the powers of root wrt uid 0.
   1447      0      stevel  *
   1448      0      stevel  * For gid manipulations, this is should be called with an
   1449      0      stevel  * uid of -1.
   1450      0      stevel  *
   1451      0      stevel  */
   1452      0      stevel int
   1453      0      stevel secpolicy_allow_setid(const cred_t *cr, uid_t newuid, boolean_t checkonly)
   1454      0      stevel {
   1455      0      stevel 	boolean_t allzone = B_FALSE;
   1456      0      stevel 
   1457      0      stevel 	if (newuid == 0 && cr->cr_uid != 0 && cr->cr_suid != 0 &&
   1458      0      stevel 	    cr->cr_ruid != 0) {
   1459      0      stevel 		allzone = B_TRUE;
   1460      0      stevel 	}
   1461      0      stevel 
   1462      0      stevel 	return (checkonly ? !PRIV_POLICY_ONLY(cr, PRIV_PROC_SETID, allzone) :
   1463      0      stevel 	    PRIV_POLICY(cr, PRIV_PROC_SETID, allzone, EPERM, NULL));
   1464      0      stevel }
   1465      0      stevel 
   1466      0      stevel 
   1467      0      stevel /*
   1468      0      stevel  * Acting on a different process: if the mode is for writing,
   1469      0      stevel  * the restrictions are more severe.  This is called after
   1470      0      stevel  * we've verified that the uids do not match.
   1471      0      stevel  */
   1472      0      stevel int
   1473      0      stevel secpolicy_proc_owner(const cred_t *scr, const cred_t *tcr, int mode)
   1474      0      stevel {
   1475      0      stevel 	boolean_t allzone = B_FALSE;
   1476      0      stevel 
   1477      0      stevel 	if ((mode & VWRITE) && scr->cr_uid != 0 &&
   1478      0      stevel 	    (tcr->cr_uid == 0 || tcr->cr_ruid == 0 || tcr->cr_suid == 0))
   1479      0      stevel 		allzone = B_TRUE;
   1480      0      stevel 
   1481      0      stevel 	return (PRIV_POLICY(scr, PRIV_PROC_OWNER, allzone, EPERM, NULL));
   1482      0      stevel }
   1483      0      stevel 
   1484      0      stevel int
   1485      0      stevel secpolicy_proc_access(const cred_t *scr)
   1486      0      stevel {
   1487      0      stevel 	return (PRIV_POLICY(scr, PRIV_PROC_OWNER, B_FALSE, EACCES, NULL));
   1488      0      stevel }
   1489      0      stevel 
   1490      0      stevel int
   1491      0      stevel secpolicy_proc_excl_open(const cred_t *scr)
   1492      0      stevel {
   1493      0      stevel 	return (PRIV_POLICY(scr, PRIV_PROC_OWNER, B_FALSE, EBUSY, NULL));
   1494      0      stevel }
   1495      0      stevel 
   1496      0      stevel int
   1497      0      stevel secpolicy_proc_zone(const cred_t *scr)
   1498      0      stevel {
   1499      0      stevel 	return (PRIV_POLICY(scr, PRIV_PROC_ZONE, B_FALSE, EPERM, NULL));
   1500      0      stevel }
   1501      0      stevel 
   1502      0      stevel /*
   1503      0      stevel  * Destroying the system
   1504      0      stevel  */
   1505      0      stevel 
   1506      0      stevel int
   1507      0      stevel secpolicy_kmdb(const cred_t *scr)
   1508      0      stevel {
   1509      0      stevel 	return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
   1510      0      stevel }
   1511      0      stevel 
   1512   1414       cindi int
   1513   1414       cindi secpolicy_error_inject(const cred_t *scr)
   1514   1414       cindi {
   1515   1414       cindi 	return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
   1516   1414       cindi }
   1517   1414       cindi 
   1518      0      stevel /*
   1519      0      stevel  * Processor sets, cpu configuration, resource pools.
   1520      0      stevel  */
   1521      0      stevel int
   1522      0      stevel secpolicy_pset(const cred_t *cr)
   1523      0      stevel {
   1524      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
   1525      0      stevel }
   1526      0      stevel 
   1527      0      stevel int
   1528      0      stevel secpolicy_ponline(const cred_t *cr)
   1529      0      stevel {
   1530      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
   1531      0      stevel }
   1532      0      stevel 
   1533      0      stevel int
   1534      0      stevel secpolicy_pool(const cred_t *cr)
   1535      0      stevel {
   1536      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
   1537      0      stevel }
   1538      0      stevel 
   1539      0      stevel int
   1540      0      stevel secpolicy_blacklist(const cred_t *cr)
   1541      0      stevel {
   1542      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_RES_CONFIG, B_FALSE, EPERM, NULL));
   1543      0      stevel }
   1544      0      stevel 
   1545      0      stevel /*
   1546      0      stevel  * Catch all system configuration.
   1547      0      stevel  */
   1548      0      stevel int
   1549      0      stevel secpolicy_sys_config(const cred_t *cr, boolean_t checkonly)
   1550      0      stevel {
   1551      0      stevel 	if (checkonly) {
   1552      0      stevel 		return (PRIV_POLICY_ONLY(cr, PRIV_SYS_CONFIG, B_FALSE) ? 0 :
   1553      0      stevel 		    EPERM);
   1554      0      stevel 	} else {
   1555      0      stevel 		return (PRIV_POLICY(cr, PRIV_SYS_CONFIG, B_FALSE, EPERM, NULL));
   1556      0      stevel 	}
   1557      0      stevel }
   1558      0      stevel 
   1559      0      stevel /*
   1560      0      stevel  * Zone administration (halt, reboot, etc.) from within zone.
   1561      0      stevel  */
   1562      0      stevel int
   1563      0      stevel secpolicy_zone_admin(const cred_t *cr, boolean_t checkonly)
   1564      0      stevel {
   1565      0      stevel 	if (checkonly) {
   1566      0      stevel 		return (PRIV_POLICY_ONLY(cr, PRIV_SYS_ADMIN, B_FALSE) ? 0 :
   1567      0      stevel 		    EPERM);
   1568      0      stevel 	} else {
   1569      0      stevel 		return (PRIV_POLICY(cr, PRIV_SYS_ADMIN, B_FALSE, EPERM,
   1570      0      stevel 		    NULL));
   1571      0      stevel 	}
   1572      0      stevel }
   1573      0      stevel 
   1574      0      stevel /*
   1575      0      stevel  * Zone configuration (create, halt, enter).
   1576      0      stevel  */
   1577      0      stevel int
   1578      0      stevel secpolicy_zone_config(const cred_t *cr)
   1579      0      stevel {
   1580      0      stevel 	/*
   1581      0      stevel 	 * Require all privileges to avoid possibility of privilege
   1582      0      stevel 	 * escalation.
   1583      0      stevel 	 */
   1584      0      stevel 	return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
   1585      0      stevel }
   1586      0      stevel 
   1587      0      stevel /*
   1588      0      stevel  * Various other system configuration calls
   1589      0      stevel  */
   1590      0      stevel int
   1591      0      stevel secpolicy_coreadm(const cred_t *cr)
   1592      0      stevel {
   1593      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_ADMIN, B_FALSE, EPERM, NULL));
   1594      0      stevel }
   1595      0      stevel 
   1596      0      stevel int
   1597      0      stevel secpolicy_systeminfo(const cred_t *cr)
   1598      0      stevel {
   1599      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_ADMIN, B_FALSE, EPERM, NULL));
   1600      0      stevel }
   1601      0      stevel 
   1602      0      stevel int
   1603      0      stevel secpolicy_dispadm(const cred_t *cr)
   1604      0      stevel {
   1605      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_CONFIG, B_FALSE, EPERM, NULL));
   1606      0      stevel }
   1607      0      stevel 
   1608      0      stevel int
   1609      0      stevel secpolicy_settime(const cred_t *cr)
   1610      0      stevel {
   1611      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_TIME, B_FALSE, EPERM, NULL));
   1612      0      stevel }
   1613      0      stevel 
   1614      0      stevel /*
   1615      0      stevel  * For realtime users: high resolution clock.
   1616      0      stevel  */
   1617      0      stevel int
   1618      0      stevel secpolicy_clock_highres(const cred_t *cr)
   1619      0      stevel {
   1620      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_CLOCK_HIGHRES, B_FALSE, EPERM,
   1621      0      stevel 	    NULL));
   1622      0      stevel }
   1623      0      stevel 
   1624      0      stevel /*
   1625      0      stevel  * drv_priv() is documented as callable from interrupt context, not that
   1626      0      stevel  * anyone ever does, but still.  No debugging or auditing can be done when
   1627      0      stevel  * it is called from interrupt context.
   1628      0      stevel  * returns 0 on succes, EPERM on failure.
   1629      0      stevel  */
   1630      0      stevel int
   1631      0      stevel drv_priv(cred_t *cr)
   1632      0      stevel {
   1633      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_DEVICES, B_FALSE, EPERM, NULL));
   1634      0      stevel }
   1635      0      stevel 
   1636      0      stevel int
   1637      0      stevel secpolicy_sys_devices(const cred_t *cr)
   1638      0      stevel {
   1639      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_DEVICES, B_FALSE, EPERM, NULL));
   1640      0      stevel }
   1641      0      stevel 
   1642      0      stevel int
   1643      0      stevel secpolicy_excl_open(const cred_t *cr)
   1644      0      stevel {
   1645      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_DEVICES, B_FALSE, EBUSY, NULL));
   1646      0      stevel }
   1647      0      stevel 
   1648      0      stevel int
   1649      0      stevel secpolicy_rctlsys(const cred_t *cr, boolean_t is_zone_rctl)
   1650      0      stevel {
   1651      0      stevel 	/* zone.* rctls can only be set from the global zone */
   1652      0      stevel 	if (is_zone_rctl && priv_policy_global(cr) != 0)
   1653      0      stevel 		return (EPERM);
   1654      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_RESOURCE, B_FALSE, EPERM, NULL));
   1655      0      stevel }
   1656      0      stevel 
   1657      0      stevel int
   1658      0      stevel secpolicy_resource(const cred_t *cr)
   1659      0      stevel {
   1660      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_RESOURCE, B_FALSE, EPERM, NULL));
   1661      0      stevel }
   1662      0      stevel 
   1663  10154        Stan int
   1664  10154        Stan secpolicy_resource_anon_mem(const cred_t *cr)
   1665  10154        Stan {
   1666  10154        Stan 	return (PRIV_POLICY_ONLY(cr, PRIV_SYS_RESOURCE, B_FALSE));
   1667  10154        Stan }
   1668  10154        Stan 
   1669      0      stevel /*
   1670      0      stevel  * Processes with a real uid of 0 escape any form of accounting, much
   1671      0      stevel  * like before.
   1672      0      stevel  */
   1673      0      stevel int
   1674      0      stevel secpolicy_newproc(const cred_t *cr)
   1675      0      stevel {
   1676      0      stevel 	if (cr->cr_ruid == 0)
   1677      0      stevel 		return (0);
   1678      0      stevel 
   1679      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_RESOURCE, B_FALSE, EPERM, NULL));
   1680      0      stevel }
   1681      0      stevel 
   1682      0      stevel /*
   1683      0      stevel  * Networking
   1684      0      stevel  */
   1685      0      stevel int
   1686      0      stevel secpolicy_net_rawaccess(const cred_t *cr)
   1687      0      stevel {
   1688      0      stevel 	return (PRIV_POLICY(cr, PRIV_NET_RAWACCESS, B_FALSE, EACCES, NULL));
   1689      0      stevel }
   1690      0      stevel 
   1691  10639      Darren int
   1692  10639      Darren secpolicy_net_observability(const cred_t *cr)
   1693  10639      Darren {
   1694  10639      Darren 	return (PRIV_POLICY(cr, PRIV_NET_OBSERVABILITY, B_FALSE, EACCES, NULL));
   1695  10639      Darren }
   1696  10639      Darren 
   1697      0      stevel /*
   1698      0      stevel  * Need this privilege for accessing the ICMP device
   1699      0      stevel  */
   1700      0      stevel int
   1701      0      stevel secpolicy_net_icmpaccess(const cred_t *cr)
   1702      0      stevel {
   1703      0      stevel 	return (PRIV_POLICY(cr, PRIV_NET_ICMPACCESS, B_FALSE, EACCES, NULL));
   1704      0      stevel }
   1705      0      stevel 
   1706      0      stevel /*
   1707      0      stevel  * There are a few rare cases where the kernel generates ioctls() from
   1708      0      stevel  * interrupt context with a credential of kcred rather than NULL.
   1709      0      stevel  * In those cases, we take the safe and cheap test.
   1710      0      stevel  */
   1711      0      stevel int
   1712      0      stevel secpolicy_net_config(const cred_t *cr, boolean_t checkonly)
   1713      0      stevel {
   1714      0      stevel 	if (checkonly) {
   1715      0      stevel 		return (PRIV_POLICY_ONLY(cr, PRIV_SYS_NET_CONFIG, B_FALSE) ?
   1716      0      stevel 		    0 : EPERM);
   1717      0      stevel 	} else {
   1718      0      stevel 		return (PRIV_POLICY(cr, PRIV_SYS_NET_CONFIG, B_FALSE, EPERM,
   1719      0      stevel 		    NULL));
   1720      0      stevel 	}
   1721      0      stevel }
   1722      0      stevel 
   1723      0      stevel 
   1724      0      stevel /*
   1725   4962    dh155122  * PRIV_SYS_NET_CONFIG is a superset of PRIV_SYS_IP_CONFIG.
   1726   3448    dh155122  *
   1727   3448    dh155122  * There are a few rare cases where the kernel generates ioctls() from
   1728   3448    dh155122  * interrupt context with a credential of kcred rather than NULL.
   1729   3448    dh155122  * In those cases, we take the safe and cheap test.
   1730   3448    dh155122  */
   1731   3448    dh155122 int
   1732   3448    dh155122 secpolicy_ip_config(const cred_t *cr, boolean_t checkonly)
   1733   3448    dh155122 {
   1734   3448    dh155122 	if (PRIV_POLICY_ONLY(cr, PRIV_SYS_NET_CONFIG, B_FALSE))
   1735   3448    dh155122 		return (secpolicy_net_config(cr, checkonly));
   1736   3448    dh155122 
   1737   3448    dh155122 	if (checkonly) {
   1738   3448    dh155122 		return (PRIV_POLICY_ONLY(cr, PRIV_SYS_IP_CONFIG, B_FALSE) ?
   1739   3448    dh155122 		    0 : EPERM);
   1740   3448    dh155122 	} else {
   1741   3448    dh155122 		return (PRIV_POLICY(cr, PRIV_SYS_IP_CONFIG, B_FALSE, EPERM,
   1742   3448    dh155122 		    NULL));
   1743   3448    dh155122 	}
   1744   3448    dh155122 }
   1745   3448    dh155122 
   1746   7408   Sebastien /*
   1747   7408   Sebastien  * PRIV_SYS_NET_CONFIG is a superset of PRIV_SYS_DL_CONFIG.
   1748   7408   Sebastien  */
   1749   7408   Sebastien int
   1750   7408   Sebastien secpolicy_dl_config(const cred_t *cr)
   1751   7408   Sebastien {
   1752   7408   Sebastien 	if (PRIV_POLICY_ONLY(cr, PRIV_SYS_NET_CONFIG, B_FALSE))
   1753   7408   Sebastien 		return (secpolicy_net_config(cr, B_FALSE));
   1754  10616   Sebastien 	return (PRIV_POLICY(cr, PRIV_SYS_DL_CONFIG, B_FALSE, EPERM, NULL));
   1755   7408   Sebastien }
   1756   7408   Sebastien 
   1757  10616   Sebastien /*
   1758  10616   Sebastien  * PRIV_SYS_DL_CONFIG is a superset of PRIV_SYS_IPTUN_CONFIG.
   1759  10616   Sebastien  */
   1760  10616   Sebastien int
   1761  10616   Sebastien secpolicy_iptun_config(const cred_t *cr)
   1762  10616   Sebastien {
   1763  10616   Sebastien 	if (PRIV_POLICY_ONLY(cr, PRIV_SYS_NET_CONFIG, B_FALSE))
   1764  10616   Sebastien 		return (secpolicy_net_config(cr, B_FALSE));
   1765  10616   Sebastien 	if (PRIV_POLICY_ONLY(cr, PRIV_SYS_DL_CONFIG, B_FALSE))
   1766  10616   Sebastien 		return (secpolicy_dl_config(cr));
   1767  10616   Sebastien 	return (PRIV_POLICY(cr, PRIV_SYS_IPTUN_CONFIG, B_FALSE, EPERM, NULL));
   1768  10616   Sebastien }
   1769   3448    dh155122 
   1770   3448    dh155122 /*
   1771   3448    dh155122  * Map IP pseudo privileges to actual privileges.
   1772   3448    dh155122  * So we don't need to recompile IP when we change the privileges.
   1773   3448    dh155122  */
   1774   3448    dh155122 int
   1775   3448    dh155122 secpolicy_ip(const cred_t *cr, int netpriv, boolean_t checkonly)
   1776   3448    dh155122 {
   1777   3448    dh155122 	int priv = PRIV_ALL;
   1778   3448    dh155122 
   1779   3448    dh155122 	switch (netpriv) {
   1780   3448    dh155122 	case OP_CONFIG:
   1781   3448    dh155122 		priv = PRIV_SYS_IP_CONFIG;
   1782   3448    dh155122 		break;
   1783   3448    dh155122 	case OP_RAW:
   1784   3448    dh155122 		priv = PRIV_NET_RAWACCESS;
   1785   3448    dh155122 		break;
   1786   3448    dh155122 	case OP_PRIVPORT:
   1787   3448    dh155122 		priv = PRIV_NET_PRIVADDR;
   1788   3448    dh155122 		break;
   1789   3448    dh155122 	}
   1790   3448    dh155122 	ASSERT(priv != PRIV_ALL);
   1791   3448    dh155122 	if (checkonly)
   1792   3448    dh155122 		return (PRIV_POLICY_ONLY(cr, priv, B_FALSE) ? 0 : EPERM);
   1793   3448    dh155122 	else
   1794   3448    dh155122 		return (PRIV_POLICY(cr, priv, B_FALSE, EPERM, NULL));
   1795   3448    dh155122 }
   1796   3448    dh155122 
   1797   3448    dh155122 /*
   1798      0      stevel  * Map network pseudo privileges to actual privileges.
   1799      0      stevel  * So we don't need to recompile IP when we change the privileges.
   1800      0      stevel  */
   1801      0      stevel int
   1802      0      stevel secpolicy_net(const cred_t *cr, int netpriv, boolean_t checkonly)
   1803      0      stevel {
   1804      0      stevel 	int priv = PRIV_ALL;
   1805      0      stevel 
   1806      0      stevel 	switch (netpriv) {
   1807      0      stevel 	case OP_CONFIG:
   1808      0      stevel 		priv = PRIV_SYS_NET_CONFIG;
   1809      0      stevel 		break;
   1810      0      stevel 	case OP_RAW:
   1811      0      stevel 		priv = PRIV_NET_RAWACCESS;
   1812      0      stevel 		break;
   1813      0      stevel 	case OP_PRIVPORT:
   1814      0      stevel 		priv = PRIV_NET_PRIVADDR;
   1815      0      stevel 		break;
   1816      0      stevel 	}
   1817      0      stevel 	ASSERT(priv != PRIV_ALL);
   1818      0      stevel 	if (checkonly)
   1819      0      stevel 		return (PRIV_POLICY_ONLY(cr, priv, B_FALSE) ? 0 : EPERM);
   1820      0      stevel 	else
   1821      0      stevel 		return (PRIV_POLICY(cr, priv, B_FALSE, EPERM, NULL));
   1822      0      stevel }
   1823      0      stevel 
   1824      0      stevel /*
   1825      0      stevel  * Checks for operations that are either client-only or are used by
   1826      0      stevel  * both clients and servers.
   1827      0      stevel  */
   1828      0      stevel int
   1829      0      stevel secpolicy_nfs(const cred_t *cr)
   1830      0      stevel {
   1831      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_NFS, B_FALSE, EPERM, NULL));
   1832      0      stevel }
   1833      0      stevel 
   1834      0      stevel /*
   1835      0      stevel  * Special case for opening rpcmod: have NFS privileges or network
   1836      0      stevel  * config privileges.
   1837      0      stevel  */
   1838      0      stevel int
   1839      0      stevel secpolicy_rpcmod_open(const cred_t *cr)
   1840      0      stevel {
   1841      0      stevel 	if (PRIV_POLICY_ONLY(cr, PRIV_SYS_NFS, B_FALSE))
   1842      0      stevel 		return (secpolicy_nfs(cr));
   1843      0      stevel 	else
   1844      0      stevel 		return (secpolicy_net_config(cr, NULL));
   1845      0      stevel }
   1846      0      stevel 
   1847      0      stevel int
   1848      0      stevel secpolicy_chroot(const cred_t *cr)
   1849      0      stevel {
   1850      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_CHROOT, B_FALSE, EPERM, NULL));
   1851      0      stevel }
   1852      0      stevel 
   1853      0      stevel int
   1854      0      stevel secpolicy_tasksys(const cred_t *cr)
   1855      0      stevel {
   1856      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_TASKID, B_FALSE, EPERM, NULL));
   1857      0      stevel }
   1858      0      stevel 
   1859      0      stevel /*
   1860      0      stevel  * Basic privilege checks.
   1861      0      stevel  */
   1862      0      stevel int
   1863   6134      casper secpolicy_basic_exec(const cred_t *cr, vnode_t *vp)
   1864      0      stevel {
   1865   6134      casper 	return (priv_policy_va(cr, PRIV_PROC_EXEC, B_FALSE, EPERM, NULL,
   1866   6134      casper 	    KLPDARG_VNODE, vp, (char *)NULL, KLPDARG_NOMORE));
   1867      0      stevel }
   1868      0      stevel 
   1869      0      stevel int
   1870      0      stevel secpolicy_basic_fork(const cred_t *cr)
   1871      0      stevel {
   1872      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_FORK, B_FALSE, EPERM, NULL));
   1873      0      stevel }
   1874      0      stevel 
   1875      0      stevel int
   1876      0      stevel secpolicy_basic_proc(const cred_t *cr)
   1877      0      stevel {
   1878      0      stevel 	return (PRIV_POLICY(cr, PRIV_PROC_SESSION, B_FALSE, EPERM, NULL));
   1879      0      stevel }
   1880      0      stevel 
   1881      0      stevel /*
   1882      0      stevel  * Slightly complicated because we don't want to trigger the policy too
   1883      0      stevel  * often.  First we shortcircuit access to "self" (tp == sp) or if
   1884      0      stevel  * we don't have the privilege but if we have permission
   1885      0      stevel  * just return (0) and we don't flag the privilege as needed.
   1886      0      stevel  * Else, we test for the privilege because we either have it or need it.
   1887      0      stevel  */
   1888      0      stevel int
   1889      0      stevel secpolicy_basic_procinfo(const cred_t *cr, proc_t *tp, proc_t *sp)
   1890      0      stevel {
   1891      0      stevel 	if (tp == sp ||
   1892      0      stevel 	    !HAS_PRIVILEGE(cr, PRIV_PROC_INFO) && prochasprocperm(tp, sp, cr)) {
   1893      0      stevel 		return (0);
   1894      0      stevel 	} else {
   1895      0      stevel 		return (PRIV_POLICY(cr, PRIV_PROC_INFO, B_FALSE, EPERM, NULL));
   1896      0      stevel 	}
   1897      0      stevel }
   1898      0      stevel 
   1899      0      stevel int
   1900      0      stevel secpolicy_basic_link(const cred_t *cr)
   1901      0      stevel {
   1902      0      stevel 	return (PRIV_POLICY(cr, PRIV_FILE_LINK_ANY, B_FALSE, EPERM, NULL));
   1903      0      stevel }
   1904      0      stevel 
   1905      0      stevel /*
   1906      0      stevel  * Additional device protection.
   1907      0      stevel  *
   1908      0      stevel  * Traditionally, a device has specific permissions on the node in
   1909      0      stevel  * the filesystem which govern which devices can be opened by what
   1910      0      stevel  * processes.  In certain cases, it is desirable to add extra
   1911      0      stevel  * restrictions, as writing to certain devices is identical to
   1912      0      stevel  * having a complete run of the system.
   1913      0      stevel  *
   1914      0      stevel  * This mechanism is called the device policy.
   1915      0      stevel  *
   1916      0      stevel  * When a device is opened, its policy entry is looked up in the
   1917      0      stevel  * policy cache and checked.
   1918      0      stevel  */
   1919      0      stevel int
   1920      0      stevel secpolicy_spec_open(const cred_t *cr, struct vnode *vp, int oflag)
   1921      0      stevel {
   1922      0      stevel 	devplcy_t *plcy;
   1923      0      stevel 	int err;
   1924      0      stevel 	struct snode *csp = VTOS(common_specvp(vp));
   1925   4962    dh155122 	priv_set_t pset;
   1926      0      stevel 
   1927      0      stevel 	mutex_enter(&csp->s_lock);
   1928      0      stevel 
   1929      0      stevel 	if (csp->s_plcy == NULL || csp->s_plcy->dp_gen != devplcy_gen) {
   1930      0      stevel 		plcy = devpolicy_find(vp);
   1931      0      stevel 		if (csp->s_plcy)
   1932      0      stevel 			dpfree(csp->s_plcy);
   1933      0      stevel 		csp->s_plcy = plcy;
   1934      0      stevel 		ASSERT(plcy != NULL);
   1935      0      stevel 	} else
   1936      0      stevel 		plcy = csp->s_plcy;
   1937      0      stevel 
   1938      0      stevel 	if (plcy == nullpolicy) {
   1939      0      stevel 		mutex_exit(&csp->s_lock);
   1940      0      stevel 		return (0);
   1941      0      stevel 	}
   1942      0      stevel 
   1943      0      stevel 	dphold(plcy);
   1944      0      stevel 
   1945      0      stevel 	mutex_exit(&csp->s_lock);
   1946      0      stevel 
   1947   4962    dh155122 	if (oflag & FWRITE)
   1948   4962    dh155122 		pset = plcy->dp_wrp;
   1949   4962    dh155122 	else
   1950   4962    dh155122 		pset = plcy->dp_rdp;
   1951   4962    dh155122 	/*
   1952   4962    dh155122 	 * Special case:
   1953   4962    dh155122 	 * PRIV_SYS_NET_CONFIG is a superset of PRIV_SYS_IP_CONFIG.
   1954   4962    dh155122 	 * If PRIV_SYS_NET_CONFIG is present and PRIV_SYS_IP_CONFIG is
   1955   4962    dh155122 	 * required, replace PRIV_SYS_IP_CONFIG with PRIV_SYS_NET_CONFIG
   1956   4962    dh155122 	 * in the required privilege set before doing the check.
   1957   4962    dh155122 	 */
   1958   4962    dh155122 	if (priv_ismember(&pset, PRIV_SYS_IP_CONFIG) &&
   1959   4962    dh155122 	    priv_ismember(&CR_OEPRIV(cr), PRIV_SYS_NET_CONFIG) &&
   1960   4962    dh155122 	    !priv_ismember(&CR_OEPRIV(cr), PRIV_SYS_IP_CONFIG)) {
   1961   4962    dh155122 		priv_delset(&pset, PRIV_SYS_IP_CONFIG);
   1962   4962    dh155122 		priv_addset(&pset, PRIV_SYS_NET_CONFIG);
   1963   4962    dh155122 	}
   1964   4962    dh155122 
   1965   4962    dh155122 	err = secpolicy_require_set(cr, &pset, "devpolicy");
   1966      0      stevel 	dpfree(plcy);
   1967      0      stevel 
   1968      0      stevel 	return (err);
   1969      0      stevel }
   1970      0      stevel 
   1971      0      stevel int
   1972      0      stevel secpolicy_modctl(const cred_t *cr, int cmd)
   1973      0      stevel {
   1974      0      stevel 	switch (cmd) {
   1975      0      stevel 	case MODINFO:
   1976   2723         cth 	case MODGETMAJBIND:
   1977      0      stevel 	case MODGETPATH:
   1978      0      stevel 	case MODGETPATHLEN:
   1979   2723         cth 	case MODGETNAME:
   1980      0      stevel 	case MODGETFBNAME:
   1981      0      stevel 	case MODGETDEVPOLICY:
   1982      0      stevel 	case MODGETDEVPOLICYBYNAME:
   1983   2723         cth 	case MODDEVT2INSTANCE:
   1984   2723         cth 	case MODSIZEOF_DEVID:
   1985   2723         cth 	case MODGETDEVID:
   1986   2723         cth 	case MODSIZEOF_MINORNAME:
   1987   2723         cth 	case MODGETMINORNAME:
   1988   2723         cth 	case MODGETDEVFSPATH_LEN:
   1989   2723         cth 	case MODGETDEVFSPATH:
   1990   2723         cth 	case MODGETDEVFSPATH_MI_LEN:
   1991   2723         cth 	case MODGETDEVFSPATH_MI:
   1992      0      stevel 		/* Unprivileged */
   1993      0      stevel 		return (0);
   1994      0      stevel 	case MODLOAD:
   1995      0      stevel 	case MODSETDEVPOLICY:
   1996      0      stevel 		return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
   1997      0      stevel 	default:
   1998      0      stevel 		return (secpolicy_sys_config(cr, B_FALSE));
   1999      0      stevel 	}
   2000      0      stevel }
   2001      0      stevel 
   2002      0      stevel int
   2003      0      stevel secpolicy_console(const cred_t *cr)
   2004      0      stevel {
   2005      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_DEVICES, B_FALSE, EPERM, NULL));
   2006      0      stevel }
   2007      0      stevel 
   2008      0      stevel int
   2009      0      stevel secpolicy_power_mgmt(const cred_t *cr)
   2010      0      stevel {
   2011      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_DEVICES, B_FALSE, EPERM, NULL));
   2012      0      stevel }
   2013      0      stevel 
   2014      0      stevel /*
   2015      0      stevel  * Simulate terminal input; another escalation of privileges avenue.
   2016      0      stevel  */
   2017      0      stevel 
   2018      0      stevel int
   2019      0      stevel secpolicy_sti(const cred_t *cr)
   2020      0      stevel {
   2021      0      stevel 	return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
   2022      0      stevel }
   2023      0      stevel 
   2024   1676         jpk boolean_t
   2025   1676         jpk secpolicy_net_reply_equal(const cred_t *cr)
   2026   1676         jpk {
   2027   1676         jpk 	return (PRIV_POLICY(cr, PRIV_SYS_CONFIG, B_FALSE, EPERM, NULL));
   2028   1676         jpk }
   2029   1676         jpk 
   2030      0      stevel int
   2031      0      stevel secpolicy_swapctl(const cred_t *cr)
   2032      0      stevel {
   2033      0      stevel 	return (PRIV_POLICY(cr, PRIV_SYS_CONFIG, B_FALSE, EPERM, NULL));
   2034      0      stevel }
   2035      0      stevel 
   2036      0      stevel int
   2037      0      stevel secpolicy_cpc_cpu(const cred_t *cr)
   2038      0      stevel {
   2039      0      stevel 	return (PRIV_POLICY(cr, PRIV_CPC_CPU, B_FALSE, EACCES, NULL));
   2040      0      stevel }
   2041      0      stevel 
   2042      0      stevel /*
   2043   6073       acruz  * secpolicy_contract_identity
   2044   6073       acruz  *
   2045   6073       acruz  * Determine if the subject may set the process contract FMRI value
   2046   6073       acruz  */
   2047   6073       acruz int
   2048   6073       acruz secpolicy_contract_identity(const cred_t *cr)
   2049   6073       acruz {
   2050   6073       acruz 	return (PRIV_POLICY(cr, PRIV_CONTRACT_IDENTITY, B_FALSE, EPERM, NULL));
   2051   6073       acruz }
   2052   6073       acruz 
   2053   6073       acruz /*
   2054      0      stevel  * secpolicy_contract_observer
   2055      0      stevel  *
   2056      0      stevel  * Determine if the subject may observe a specific contract's events.
   2057      0      stevel  */
   2058      0      stevel int
   2059      0      stevel secpolicy_contract_observer(const cred_t *cr, struct contract *ct)
   2060      0      stevel {
   2061      0      stevel 	if (contract_owned(ct, cr, B_FALSE))
   2062      0      stevel 		return (0);
   2063      0      stevel 	return (PRIV_POLICY(cr, PRIV_CONTRACT_OBSERVER, B_FALSE, EPERM, NULL));
   2064      0      stevel }
   2065      0      stevel 
   2066      0      stevel /*
   2067      0      stevel  * secpolicy_contract_observer_choice
   2068      0      stevel  *
   2069      0      stevel  * Determine if the subject may observe any contract's events.  Just
   2070      0      stevel  * tests privilege and audits on success.
   2071      0      stevel  */
   2072      0      stevel boolean_t
   2073      0      stevel secpolicy_contract_observer_choice(const cred_t *cr)
   2074      0      stevel {
   2075      0      stevel 	return (PRIV_POLICY_CHOICE(cr, PRIV_CONTRACT_OBSERVER, B_FALSE));
   2076      0      stevel }
   2077      0      stevel 
   2078      0      stevel /*
   2079      0      stevel  * secpolicy_contract_event
   2080      0      stevel  *
   2081      0      stevel  * Determine if the subject may request critical contract events or
   2082      0      stevel  * reliable contract event delivery.
   2083      0      stevel  */
   2084      0      stevel int
   2085      0      stevel secpolicy_contract_event(const cred_t *cr)
   2086      0      stevel {
   2087      0      stevel 	return (PRIV_POLICY(cr, PRIV_CONTRACT_EVENT, B_FALSE, EPERM, NULL));
   2088      0      stevel }
   2089      0      stevel 
   2090      0      stevel /*
   2091      0      stevel  * secpolicy_contract_event_choice
   2092      0      stevel  *
   2093      0      stevel  * Determine if the subject may retain contract events in its critical
   2094      0      stevel  * set when a change in other terms would normally require a change in
   2095      0      stevel  * the critical set.  Just tests privilege and audits on success.
   2096      0      stevel  */
   2097      0      stevel boolean_t
   2098      0      stevel secpolicy_contract_event_choice(const cred_t *cr)
   2099      0      stevel {
   2100      0      stevel 	return (PRIV_POLICY_CHOICE(cr, PRIV_CONTRACT_EVENT, B_FALSE));
   2101      0      stevel }
   2102      0      stevel 
   2103      0      stevel /*
   2104   1544    eschrock  * secpolicy_gart_access
   2105      0      stevel  *
   2106   1544    eschrock  * Determine if the subject has sufficient priveleges to make ioctls to agpgart
   2107   1544    eschrock  * device.
   2108      0      stevel  */
   2109      0      stevel int
   2110      0      stevel secpolicy_gart_access(const cred_t *cr)
   2111      0      stevel {
   2112   1862      casper 	return (PRIV_POLICY(cr, PRIV_GRAPHICS_ACCESS, B_FALSE, EPERM, NULL));
   2113      0      stevel }
   2114      0      stevel 
   2115      0      stevel /*
   2116   1544    eschrock  * secpolicy_gart_map
   2117      0      stevel  *
   2118   1544    eschrock  * Determine if the subject has sufficient priveleges to map aperture range
   2119   1544    eschrock  * through agpgart driver.
   2120      0      stevel  */
   2121      0      stevel int
   2122      0      stevel secpolicy_gart_map(const cred_t *cr)
   2123      0      stevel {
   2124   1862      casper 	if (PRIV_POLICY_ONLY(cr, PRIV_GRAPHICS_ACCESS, B_FALSE)) {
   2125   1862      casper 		return (PRIV_POLICY(cr, PRIV_GRAPHICS_ACCESS, B_FALSE, EPERM,
   2126   1862      casper 		    NULL));
   2127   1862      casper 	} else {
   2128   1862      casper 		return (PRIV_POLICY(cr, PRIV_GRAPHICS_MAP, B_FALSE, EPERM,
   2129   1862      casper 		    NULL));
   2130      0      stevel 	}
   2131      0      stevel }
   2132    789      ahrens 
   2133    789      ahrens /*
   2134   1544    eschrock  * secpolicy_zinject
   2135   1544    eschrock  *
   2136   1544    eschrock  * Determine if the subject can inject faults in the ZFS fault injection
   2137   1544    eschrock  * framework.  Requires all privileges.
   2138   1544    eschrock  */
   2139   1544    eschrock int
   2140   1544    eschrock secpolicy_zinject(const cred_t *cr)
   2141   1544    eschrock {
   2142   1544    eschrock 	return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
   2143   1544    eschrock }
   2144   1544    eschrock 
   2145   1544    eschrock /*
   2146    789      ahrens  * secpolicy_zfs
   2147    789      ahrens  *
   2148   1544    eschrock  * Determine if the subject has permission to manipulate ZFS datasets
   2149   1544    eschrock  * (not pools).  Equivalent to the SYS_MOUNT privilege.
   2150    789      ahrens  */
   2151    789      ahrens int
   2152    789      ahrens secpolicy_zfs(const cred_t *cr)
   2153    789      ahrens {
   2154    789      ahrens 	return (PRIV_POLICY(cr, PRIV_SYS_MOUNT, B_FALSE, EPERM, NULL));
   2155    789      ahrens }
   2156   4321      casper 
   2157   4321      casper /*
   2158   4321      casper  * secpolicy_idmap
   2159   4321      casper  *
   2160   4321      casper  * Determine if the calling process has permissions to register an SID
   2161   4321      casper  * mapping daemon and allocate ephemeral IDs.
   2162   4321      casper  */
   2163   4321      casper int
   2164   4321      casper secpolicy_idmap(const cred_t *cr)
   2165   4321      casper {
   2166   5771    jp151216 	return (PRIV_POLICY(cr, PRIV_FILE_SETID, B_TRUE, EPERM, NULL));
   2167   4321      casper }
   2168   4581     sherrym 
   2169   4581     sherrym /*
   2170   4581     sherrym  * secpolicy_ucode_update
   2171   4581     sherrym  *
   2172   4581     sherrym  * Determine if the subject has sufficient privilege to update microcode.
   2173   4581     sherrym  */
   2174   4581     sherrym int
   2175   4581     sherrym secpolicy_ucode_update(const cred_t *scr)
   2176   4581     sherrym {
   2177   4581     sherrym 	return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
   2178   4581     sherrym }
   2179   4962    dh155122 
   2180   4962    dh155122 /*
   2181   4962    dh155122  * secpolicy_sadopen
   2182   4962    dh155122  *
   2183   4962    dh155122  * Determine if the subject has sufficient privilege to access /dev/sad/admin.
   2184   4962    dh155122  * /dev/sad/admin appear in global zone and exclusive-IP zones only.
   2185   4962    dh155122  * In global zone, sys_config is required.
   2186   4962    dh155122  * In exclusive-IP zones, sys_ip_config is required.
   2187   4962    dh155122  * Note that sys_config is prohibited in non-global zones.
   2188   4962    dh155122  */
   2189   4962    dh155122 int
   2190   4962    dh155122 secpolicy_sadopen(const cred_t *credp)
   2191   4962    dh155122 {
   2192   4962    dh155122 	priv_set_t pset;
   2193   4962    dh155122 
   2194   4962    dh155122 	priv_emptyset(&pset);
   2195   4962    dh155122 
   2196   4962    dh155122 	if (crgetzoneid(credp) == GLOBAL_ZONEID)
   2197   4962    dh155122 		priv_addset(&pset, PRIV_SYS_CONFIG);
   2198   4962    dh155122 	else
   2199   4962    dh155122 		priv_addset(&pset, PRIV_SYS_IP_CONFIG);
   2200   4962    dh155122 
   2201   4962    dh155122 	return (secpolicy_require_set(credp, &pset, "devpolicy"));
   2202   4962    dh155122 }
   2203   5331         amw 
   2204   6134      casper 
   2205   6134      casper /*
   2206   6134      casper  * Add privileges to a particular privilege set; this is called when the
   2207   6134      casper  * current sets of privileges are not sufficient.  I.e., we should always
   2208   6134      casper  * call the policy override functions from here.
   2209   6134      casper  * What we are allowed to have is in the Observed Permitted set; so
   2210   6134      casper  * we compute the difference between that and the newset.
   2211   6134      casper  */
   2212   6134      casper int
   2213   6134      casper secpolicy_require_privs(const cred_t *cr, const priv_set_t *nset)
   2214   6134      casper {
   2215   6134      casper 	priv_set_t rqd;
   2216   6134      casper 
   2217   6134      casper 	rqd = CR_OPPRIV(cr);
   2218   6134      casper 
   2219   6134      casper 	priv_inverse(&rqd);
   2220   6134      casper 	priv_intersect(nset, &rqd);
   2221   6134      casper 
   2222   6134      casper 	return (secpolicy_require_set(cr, &rqd, NULL));
   2223   6134      casper }
   2224   6134      casper 
   2225   5331         amw /*
   2226   5331         amw  * secpolicy_smb
   2227   5331         amw  *
   2228   5331         amw  * Determine if the cred_t has PRIV_SYS_SMB privilege, indicating
   2229   5331         amw  * that it has permission to access the smbsrv kernel driver.
   2230   5331         amw  * PRIV_POLICY checks the privilege and audits the check.
   2231   5331         amw  *
   2232   5331         amw  * Returns:
   2233   5331         amw  * 0       Driver access is allowed.
   2234   5331         amw  * EPERM   Driver access is NOT permitted.
   2235   5331         amw  */
   2236   5331         amw int
   2237   5331         amw secpolicy_smb(const cred_t *cr)
   2238   5331         amw {
   2239   5331         amw 	return (PRIV_POLICY(cr, PRIV_SYS_SMB, B_FALSE, EPERM, NULL));
   2240   5331         amw }
   2241   5440    jm199354 
   2242   5440    jm199354 /*
   2243   5440    jm199354  * secpolicy_vscan
   2244   5440    jm199354  *
   2245   5440    jm199354  * Determine if cred_t has the necessary privileges to access a file
   2246   5440    jm199354  * for virus scanning and update its extended system attributes.
   2247   5440    jm199354  * PRIV_FILE_DAC_SEARCH, PRIV_FILE_DAC_READ - file access
   2248   5440    jm199354  * PRIV_FILE_FLAG_SET - set extended system attributes
   2249   5440    jm199354  *
   2250   5440    jm199354  * PRIV_POLICY checks the privilege and audits the check.
   2251   5440    jm199354  *
   2252   5440    jm199354  * Returns:
   2253   5440    jm199354  * 0      file access for virus scanning allowed.
   2254   5440    jm199354  * EPERM  file access for virus scanning is NOT permitted.
   2255   5440    jm199354  */
   2256   5440    jm199354 int
   2257   5440    jm199354 secpolicy_vscan(const cred_t *cr)
   2258   5440    jm199354 {
   2259   5440    jm199354 	if ((PRIV_POLICY(cr, PRIV_FILE_DAC_SEARCH, B_FALSE, EPERM, NULL)) ||
   2260   5440    jm199354 	    (PRIV_POLICY(cr, PRIV_FILE_DAC_READ, B_FALSE, EPERM, NULL)) ||
   2261   5440    jm199354 	    (PRIV_POLICY(cr, PRIV_FILE_FLAG_SET, B_FALSE, EPERM, NULL))) {
   2262   5440    jm199354 		return (EPERM);
   2263   5440    jm199354 	}
   2264   5440    jm199354 
   2265   5440    jm199354 	return (0);
   2266   5440    jm199354 }
   2267   6007     thurlow 
   2268   6007     thurlow /*
   2269   6007     thurlow  * secpolicy_smbfs_login
   2270   6007     thurlow  *
   2271   6007     thurlow  * Determines if the caller can add and delete the smbfs login
   2272   6007     thurlow  * password in the the nsmb kernel module for the CIFS client.
   2273   6007     thurlow  *
   2274   6007     thurlow  * Returns:
   2275   6007     thurlow  * 0       access is allowed.
   2276   6007     thurlow  * EPERM   access is NOT allowed.
   2277   6007     thurlow  */
   2278   6007     thurlow int
   2279   6007     thurlow secpolicy_smbfs_login(const cred_t *cr, uid_t uid)
   2280   6007     thurlow {
   2281   6007     thurlow 	uid_t cruid = crgetruid(cr);
   2282   6007     thurlow 
   2283   6007     thurlow 	if (cruid == uid)
   2284   6007     thurlow 		return (0);
   2285   6007     thurlow 	return (PRIV_POLICY(cr, PRIV_PROC_OWNER, B_FALSE,
   2286   6007     thurlow 	    EPERM, NULL));
   2287   6007     thurlow }
   2288   6784     johnlev 
   2289   6784     johnlev /*
   2290   6784     johnlev  * secpolicy_xvm_control
   2291   6784     johnlev  *
   2292   6784     johnlev  * Determines if a caller can control the xVM hypervisor and/or running
   2293   6784     johnlev  * domains (x86 specific).
   2294   6784     johnlev  *
   2295   6784     johnlev  * Returns:
   2296   6784     johnlev  * 0       access is allowed.
   2297   6784     johnlev  * EPERM   access is NOT allowed.
   2298   6784     johnlev  */
   2299   6784     johnlev int
   2300   6784     johnlev secpolicy_xvm_control(const cred_t *cr)
   2301   6784     johnlev {
   2302   6784     johnlev 	if (PRIV_POLICY(cr, PRIV_XVM_CONTROL, B_FALSE, EPERM, NULL))
   2303   6784     johnlev 		return (EPERM);
   2304   6784     johnlev 	return (0);
   2305   6784     johnlev }
   2306   8275        Eric 
   2307   8275        Eric /*
   2308   9751       james  * secpolicy_ppp_config
   2309   9751       james  *
   2310   9751       james  * Determine if the subject has sufficient privileges to configure PPP and
   2311   9751       james  * PPP-related devices.
   2312   9751       james  */
   2313   9751       james int
   2314   9751       james secpolicy_ppp_config(const cred_t *cr)
   2315   9751       james {
   2316   9751       james 	if (PRIV_POLICY_ONLY(cr, PRIV_SYS_NET_CONFIG, B_FALSE))
   2317   9751       james 		return (secpolicy_net_config(cr, B_FALSE));
   2318   9751       james 	return (PRIV_POLICY(cr, PRIV_SYS_PPP_CONFIG, B_FALSE, EPERM, NULL));
   2319   9751       james }
   2320