policy.c revision 37294019745c29c42448424cc3bce79eb1c6a785
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2013, Joyent, Inc. All rights reserved.
*/
#include <sys/sysmacros.h>
#include <sys/cred_impl.h>
#include <sys/ipc_impl.h>
#include <sys/devpolicy.h>
#include <sys/contract_impl.h>
/*
* There are two possible layers of privilege routines and two possible
* levels of secpolicy. Plus one other we may not be interested in, so
* we may need as many as 6 but no more.
*/
#define MAXPRIVSTACK 6
int priv_debug = 0;
int priv_basic_test = -1;
/*
* This file contains the majority of the policy routines.
* Since the policy routines are defined by function and not
* by privilege, there is quite a bit of duplication of
* functions.
*
* The secpolicy functions must not make assumptions about
* locks held or not held as any lock can be held while they're
* being called.
*
* Credentials are read-only so no special precautions need to
* be taken while locking them.
*
* When a new policy check needs to be added to the system the
* following procedure should be followed:
*
* Pick an appropriate secpolicy_*() function
* -> done if one exists.
* Create a new secpolicy function, preferably with
* a descriptive name using the standard template.
* Pick an appropriate privilege for the policy.
* If no appropraite privilege exists, define new one
* (this should be done with extreme care; in most cases
* little is gained by adding another privilege)
*
* WHY ROOT IS STILL SPECIAL.
*
* In a number of the policy functions, there are still explicit
* checks for uid 0. The rationale behind these is that many root
* privileges to the user once written to. To prevent escalation
* of privilege by allowing just a single privilege to modify root owned
* objects, we've added these root specific checks where we considered
* them necessary: modifying root owned files, changing uids to 0, etc.
*
* PRIVILEGE ESCALATION AND ZONES.
*
* A number of operations potentially allow the caller to achieve
* privileges beyond the ones normally required to perform the operation.
* For example, if allowed to create a setuid 0 executable, a process can
* gain privileges beyond PRIV_FILE_SETID. Zones, however, place
* restrictions on the ability to gain privileges beyond those available
* within the zone through file and process manipulation. Hence, such
* operations require that the caller have an effective set that includes
* all privileges available within the current zone, or all privileges
* if executing in the global zone.
*
* This is indicated in the priv_policy* policy checking functions
* through a combination of parameters. The "priv" parameter indicates
* the privilege that is required, and the "allzone" parameter indicates
* whether or not all privileges in the zone are required. In addition,
* priv can be set to PRIV_ALL to indicate that all privileges are
* required (regardless of zone). There are three scenarios of interest:
* (1) operation requires a specific privilege
* (2) operation requires a specific privilege, and requires all
* privileges available within the zone (or all privileges if in
* the global zone)
* (3) operation requires all privileges, regardless of zone
*
* For (1), priv should be set to the specific privilege, and allzone
* should be set to B_FALSE.
* For (2), priv should be set to the specific privilege, and allzone
* should be set to B_TRUE.
* For (3), priv should be set to PRIV_ALL, and allzone should be set
* to B_FALSE.
*
*/
/*
* The privileges are checked against the Effective set for
* ordinary processes and checked against the Limit set
* for euid 0 processes that haven't manipulated their privilege
* sets.
*/
HAS_ALLPRIVS(cr) : \
return (0); \
}
/*
* Policy checking functions.
*
* All of the system's policy should be implemented here.
*/
/*
* Private functions which take an additional va_list argument to
* implement an object specific policy override.
*/
const char *, va_list);
const char *, ...);
/*
* Generic policy calls
*
* The "bottom" functions of policy control
*/
static char *
{
char *buf;
return (NULL);
return (buf);
}
/*
* priv_policy_errmsg()
*
* Generate an error message if privilege debugging is enabled system wide
* or for this particular process.
*/
#define FMTHDR "%s[%d]: missing privilege \"%s\" (euid = %d, syscall = %d)"
#define FMTMSG " for \"%s\""
#define FMTFUN " needed at %s+0x%lx"
/* The maximum size privilege format: the concatenation of the above */
static void
{
int depth;
int i;
char *sym;
const char *pname;
char *cmd;
return;
/* Privileges must be defined */
return;
else
cmd = "priv_policy";
} else {
msg = "";
}
/*
* Try to find the first interesting function on the stack.
* priv_policy* that's us, so completely uninteresting.
* suser(), drv_priv(), secpolicy_* are also called from
* too many locations to convey useful information.
*/
for (i = 0; i < depth; i++) {
break;
}
switch (priv) {
case PRIV_ALL:
pname = "ALL";
break;
case PRIV_MULTIPLE:
pname = "MULTIPLE";
break;
case PRIV_ALLZONE:
pname = "ZONE";
break;
case PRIV_GLOBAL:
pname = "GLOBAL";
break;
default:
break;
}
/* Remember last message, just like lwp_badpriv. */
}
}
if (priv_debug) {
}
}
/*
* Override the policy, if appropriate. Return 0 if the external
* policy engine approves.
*/
static int
{
int ret;
return (-1);
priv_fillset(&set);
} else if (allzone) {
} else {
priv_emptyset(&set);
}
return (ret);
}
static int
{
}
return (-1);
}
static int
{
int ret;
return (ret);
}
/*
* Audit failure, log error message.
*/
static void
{
if (AU_AUDITING())
} else {
}
}
}
/*
* priv_policy_ap()
* return 0 or error.
* See block comment above for a description of "priv" and "allzone" usage.
*/
static int
{
(!servicing_interrupt() &&
!servicing_interrupt()) {
if (AU_AUDITING())
}
err = 0;
} else if (!servicing_interrupt()) {
/* Failure audited in this procedure */
}
return (err);
}
int
const char *msg, ...)
{
int ret;
return (ret);
}
int
const char *msg)
{
}
/*
* Return B_TRUE for sufficient privileges, B_FALSE for insufficient privileges.
*/
{
/* Audit success only */
if (res && AU_AUDITING() &&
!servicing_interrupt()) {
}
if (res) {
} else {
}
return (res);
}
/*
* Non-auditing variant of priv_policy_choice().
*/
{
if (res) {
} else {
}
return (res);
}
/*
* Check whether all privileges in the required set are present.
*/
static int
const char *msg, ...)
{
int priv;
int pfound = -1;
int ret;
return (0);
}
if (ret == 0)
return (0);
return (EACCES);
}
if (AU_AUDITING())
/*
* Privilege debugging; special case "one privilege in set".
*/
if (pfound != -1) {
/* Multiple missing privs */
msg);
return (EACCES);
}
}
}
/* Just the one missing privilege */
}
return (EACCES);
}
/*
* Called when an operation requires that the caller be in the
* global zone, regardless of privilege.
*/
static int
{
return (0); /* success */
}
return (EPERM);
}
/*
* Raising process priority
*/
int
{
return (0);
return (secpolicy_setpriority(cr));
}
/*
* Changing process priority or scheduling class
*/
int
{
}
/*
* Binding to a privileged port, port must be specified in host byte
* order.
* When adding a new privilege which allows binding to currently privileged
* ports, then you MUST also allow processes with PRIV_NET_PRIVADDR bind
* to these ports because of backward compatibility.
*/
int
{
char *reason;
int priv;
switch (port) {
case 137:
case 138:
case 139:
case 445:
/*
* NBT and SMB ports, these are normal privileged ports,
* allow bind only if the SYS_SMB or NET_PRIVADDR privilege
* is present.
* Try both, if neither is present return an error for
* priv SYS_SMB.
*/
else
priv = PRIV_SYS_SMB;
reason = "NBT or SMB port";
break;
case 2049:
case 4045:
/*
* NFS ports, these are extra privileged ports, allow bind
* only if the SYS_NFS privilege is present.
*/
priv = PRIV_SYS_NFS;
reason = "NFS port";
break;
default:
break;
}
}
/*
* Binding to a multilevel port on a trusted (labeled) system.
*/
int
{
}
/*
* Allow a communication between a zone and an unlabeled host when their
* labels don't match.
*/
int
{
}
/*
* Allow a privileged process to transmit traffic without explicit labels
*/
int
{
}
/*
* Common routine which determines whether a given credential can
* act on a given mount.
* When called through mount, the parameter needoptcheck is a pointer
* to a boolean variable which will be set to either true or false,
* depending on whether the mount policy should change the mount options.
* In all other cases, needoptcheck should be a NULL pointer.
*/
static int
{
/*
* Short circuit the following cases:
* vfsp == NULL or mvp == NULL (pure privilege check)
* have all privileges - no further checks required
* and no mount options need to be set.
*/
if (mounting)
*needoptcheck = B_FALSE;
}
/*
* When operating on an existing mount (either we're not mounting
* or we're doing a remount and VFS_REMOUNT will be set), zones
* can operate only on mounts established by the zone itself.
*/
if (zoneid != GLOBAL_ZONEID &&
return (EPERM);
}
}
if (mounting)
*needoptcheck = B_TRUE;
/*
* Overlay mounts may hide important stuff; if you can't write to a
* mount point but would be able to mount on top of it, you can
* escalate your privileges.
* So we go about asking the same questions namefs does when it
* decides whether you can mount over a file or not but with the
* added restriction that you can only mount on top of a regular
* file or directory.
* If we have all the zone's privileges, we skip all other checks,
* or else we may actually get in trouble inside the automounter.
*/
HAS_ALLZONEPRIVS(cr)) {
} else {
int err;
if (err != 0)
return (err);
return (err);
VWRITE) != 0) {
return (EACCES);
}
}
}
void
{
/*
* check; if we don't have either "nosuid" or
* both "nosetuid" and "nodevices", then we add
* "nosuid"; this depends on how the current
* implementation works (it first checks nosuid). In a
* zone, a user with all zone privileges can mount with
* "setuid" but never with "devices".
*/
else
}
/*
* If we're not the local super user, we set the "restrict"
* option to indicate to automountd that this mount should
* be handled with care.
*/
if (!amsuper)
}
int
secpolicy_fs_allowed_mount(const char *fsname)
{
const char *p;
if (INGLOBALZONE(curproc))
return (0);
return (ENOENT);
return (0);
}
p = curzone->zone_fs_allowed;
while (p != NULL && *p != '\0') {
char c = *(p + len);
if (c == '\0' || c == ',')
return (0);
}
/* skip to beyond the next comma */
p++;
}
return (EPERM);
}
int
{
int error;
/*
* If it's a remount, get the underlying mount point,
* except for the root where we use the rootvp.
*/
else
}
if (error == 0 && needoptchk) {
}
return (error);
}
/*
* Does the policy computations for "ownership" of a mount;
* here ownership is defined as the ability to "mount"
* the filesystem originally. The rootvfs doesn't cover any
* vnodes; we attribute its ownership to the rootvp.
*/
static int
{
else
}
int
{
}
/*
* Quotas are a resource, but if one has the ability to mount a filesystem, he
* should be able to modify quotas on it.
*/
int
{
}
/*
* Exceeding minfree: also a per-mount resource constraint.
*/
int
{
}
int
{
}
/* ARGSUSED */
int
{
}
/*
* Name: secpolicy_vnode_access()
*
* Parameters: Process credential
* vnode
* uid of owner of vnode
* permission bits not granted to the caller when examining
* file mode bits (i.e., when a process wants to open a
* mode 444 file for VREAD|VWRITE, this function should be
* called only with a VWRITE argument).
*
* Normal: Verifies that cred has the appropriate privileges to
* override the mode bits that were denied.
*
* Override: file_dac_execute - if VEXEC bit was denied and vnode is
* not a directory.
* file_dac_read - if VREAD bit was denied.
* file_dac_search - if VEXEC bit was denied and vnode is
* a directory.
* file_dac_write - if VWRITE bit was denied.
*
* Root owned files are special cased to protect system
* configuration files and such.
*
* Output: EACCES - if privilege check fails.
*/
int
{
KLPDARG_NOMORE) != 0) {
return (EACCES);
}
else
KLPDARG_NOMORE) != 0) {
return (EACCES);
}
}
/*
* Directories use file_dac_search to override the execute bit.
*/
}
return (0);
}
/*
* Like secpolicy_vnode_access() but we get the actual wanted mode and the
* current mode of the file, not the missing bits.
*/
int
{
/* Inline the basic privileges tests. */
return (EACCES);
}
return (EACCES);
}
if (mode == 0)
return (0);
KLPDARG_NOMORE) != 0) {
return (EACCES);
}
else
KLPDARG_NOMORE) != 0) {
return (EACCES);
}
}
/*
* Directories use file_dac_search to override the execute bit.
*/
}
return (0);
}
/*
* This is a special routine for ZFS; it is used to determine whether
* any of the privileges in effect allow any form of access to the
* file. There's no reason to audit this or any reason to record
* this. More work is needed to do the "KPLD" stuff.
*/
int
{
static int privs[] = {
};
int i;
/* Same as secpolicy_vnode_setdac */
return (0);
for (i = 0; i < sizeof (privs)/sizeof (int); i++) {
int priv;
case PRIV_FILE_DAC_EXECUTE:
continue;
break;
case PRIV_FILE_DAC_SEARCH:
continue;
break;
case PRIV_FILE_DAC_WRITE:
case PRIV_FILE_OWNER:
case PRIV_FILE_CHOWN:
/* We know here that if owner == 0, that cr_uid != 0 */
break;
}
return (0);
}
return (EPERM);
}
/*
* Name: secpolicy_vnode_setid_modify()
*
* Normal: verify that subject can set the file setid flags.
*
* Output: EPERM - if not privileged.
*/
static int
{
/* If changing to suid root, must have all zone privs */
if (owner != 0) {
return (0);
}
}
/*
* changing ownership or when writing to a file?
* "issuid" should be true when set-uid; only in that case
* root ownership is checked (setgid is assumed).
*/
int
{
return (EPERM);
}
/*
* Name: secpolicy_vnode_setids_setgids()
*
* Normal: verify that subject can set the file setgid flag.
*
* Output: EPERM - if not privileged
*/
int
{
NULL));
return (0);
}
/*
* Name: secpolicy_vnode_chown
*
* Normal: Determine if subject can chown owner of a file.
*
* Output: EPERM - if access denied
*/
int
{
int priv;
if (!is_owner) {
} else {
}
}
/*
* Name: secpolicy_vnode_create_gid
*
* Normal: Determine if subject can change group ownership of a file.
*
* Output: EPERM - if access denied
*/
int
{
NULL));
else
NULL));
}
/*
* Name: secpolicy_vnode_utime_modify()
*
* Normal: verify that subject can modify the utime on a file.
*
* Output: EPERM - if access denied.
*/
static int
{
"modify file times"));
}
/*
* Name: secpolicy_vnode_setdac()
*
* Normal: verify that subject can modify the mode of a file.
* allzone privilege needed when modifying root owned object.
*
* Output: EPERM - if access denied.
*/
int
{
return (0);
}
/*
* Name: secpolicy_vnode_stky_modify()
*
* Normal: verify that subject can make a file a "sticky".
*
* Output: EPERM - if access denied.
*/
int
{
"set file sticky"));
}
/*
* Policy determines whether we can remove an entry from a directory,
* regardless of permission bits.
*/
int
{
"sticky directory"));
}
int
{
return (0);
}
void
{
}
}
int
{
int error;
return (error);
}
/*
* Check privilege if attempting to set the
* sticky bit on a non-directory.
*/
secpolicy_vnode_stky_modify(cr) != 0) {
}
/*
* Check for privilege if attempting to set the
* group-id bit.
*/
}
return (0);
}
/*
* Check privileges for setting xvattr attributes
*/
int
{
int error = 0;
return (EINVAL);
/*
* First process the DOS bits
*/
return (error);
}
/*
* Now handle special attributes
*/
}
}
return (error);
}
/*
* This function checks the policy decisions surrounding the
* vop setattr call.
*
* It should be called after sufficient locks have been established
* on the underlying data structures. No concurrent modifications
* should be allowed.
*
* The caller must pass in unlocked version of its vaccess function
* this is required because vop_access function should lock the
* node for reading. A three argument function should be defined
* which accepts the following argument:
* A pointer to the internal "node" type (inode *)
* vnode access bits (VREAD|VWRITE|VEXEC)
* a pointer to the credential
*
* This function makes the following policy decisions:
*
* - change permissions
* - permission to change file mode if not owner
* - permission to add sticky bit to non-directory
* - permission to add set-gid bit
*
* The ovap argument should include AT_MODE|AT_UID|AT_GID.
*
* If the vap argument does not include AT_MODE, the mode will be copied from
* this is done by marking vap->va_mask to include AT_MODE and va_mode
* is updated to the newly computed mode.
*/
int
int unlocked_access(void *, int, cred_t *),
void *node)
{
int error = 0;
goto out;
}
/*
* If ATTR_NOACLCHECK is set in the flags, then we don't
* perform the secondary unlocked_access() call since the
* ACL (if any) is being checked there.
*/
if (skipaclchk == B_FALSE) {
if (error)
goto out;
}
}
/*
* If not the owner of the file then check privilege
* for two things: the privilege to set the mode at all
* and, if we're setting setuid, we also need permissions
* to add the set-uid bit, if we're not the owner.
* In the specific case of creating a set-uid root
* file, we need even more permissions.
*/
goto out;
goto out;
} else
/*
* Chowning files.
*
* If you are the file owner:
* chown to other uid FILE_CHOWN_SELF
* chown to gid (non-member) FILE_CHOWN_SELF
* chown to gid (member) <none>
*
* Instead of PRIV_FILE_CHOWN_SELF, FILE_CHOWN is also
* acceptable but the first one is reported when debugging.
*
* If you are not the file owner:
* chown from root PRIV_FILE_CHOWN + zone
* chown from other to any PRIV_FILE_CHOWN
*
*/
} else {
}
}
/*
* If necessary, check privilege to see if update can be done.
*/
if (checkpriv &&
goto out;
}
/*
* If the file has either the set UID or set GID bits
* set and the caller can set the bits, then leave them.
*/
}
/*
* If not the file owner and not otherwise privileged,
* always return an error when setting the
* time other than the current (ATTR_UTIME flag set).
* If setting the current time (ATTR_UTIME not set) then
* unlocked_access will check permissions according to policy.
*/
if (flags & ATTR_UTIME)
else if (skipaclchk == B_FALSE) {
secpolicy_vnode_utime_modify(cr) == 0)
error = 0;
}
if (error)
goto out;
}
}
/*
* Check for optional attributes here by checking the following:
*/
out:
return (error);
}
/*
* Name: secpolicy_pcfs_modify_bootpartition()
*
* Normal: verify that subject can modify a pcfs boot partition.
*
* Output: EACCES - if privilege check failed.
*/
/*ARGSUSED*/
int
{
"modify pcfs boot partition"));
}
/*
* System V IPC routines
*/
int
{
}
return (0);
}
int
{
}
int
{
return (EACCES);
NULL));
}
return (0);
}
int
{
return (EACCES);
NULL));
}
return (0);
}
/*
* Audit configuration.
*/
int
{
}
/*
* Audit record generation.
*/
int
{
}
/*
* Get audit attributes.
* Either PRIV_SYS_AUDIT or PRIV_PROC_AUDIT required; report the
* "Least" of the two privileges on error.
*/
int
{
int priv;
else
if (checkonly)
else
}
/*
* Locking physical memory
*/
int
{
}
/*
* Accounting (both acct(2) and exacct).
*/
int
{
}
/*
* Is this process privileged to change its uids at will?
* Uid 0 is still considered "special" and having the SETID
* privilege is not sufficient to get uid 0.
* Files are owned by root, so the privilege would give
* full access and euid 0 is still effective.
*
* If you have the privilege and euid 0 only then do you
* get the powers of root wrt uid 0.
*
* For gid manipulations, this is should be called with an
* uid of -1.
*
*/
int
{
}
}
/*
* Acting on a different process: if the mode is for writing,
* the restrictions are more severe. This is called after
* we've verified that the uids do not match.
*/
int
{
}
int
{
}
int
{
}
int
{
}
/*
* Destroying the system
*/
int
{
}
int
{
}
/*
* Processor sets, cpu configuration, resource pools.
*/
int
{
}
/*
* Processor set binding.
*/
int
{
return (secpolicy_pset(cr));
}
int
{
}
int
{
}
int
{
}
/*
* Catch all system configuration.
*/
int
{
if (checkonly) {
EPERM);
} else {
}
}
/*
* Zone administration (halt, reboot, etc.) from within zone.
*/
int
{
if (checkonly) {
EPERM);
} else {
NULL));
}
}
/*
* Zone configuration (create, halt, enter).
*/
int
{
/*
* Require all privileges to avoid possibility of privilege
* escalation.
*/
}
/*
* Various other system configuration calls
*/
int
{
}
int
{
}
int
{
}
int
{
}
/*
* For realtime users: high resolution clock.
*/
int
{
NULL));
}
/*
* drv_priv() is documented as callable from interrupt context, not that
* anyone ever does, but still. No debugging or auditing can be done when
* it is called from interrupt context.
* returns 0 on succes, EPERM on failure.
*/
int
{
}
int
{
}
int
{
}
int
{
/* zone.* rctls can only be set from the global zone */
return (EPERM);
}
int
{
}
int
{
}
/*
* Processes with a real uid of 0 escape any form of accounting, much
* like before.
*/
int
{
return (0);
}
/*
* Networking
*/
int
{
}
int
{
}
/*
* Need this privilege for accessing the ICMP device
*/
int
{
}
/*
* There are a few rare cases where the kernel generates ioctls() from
* interrupt context with a credential of kcred rather than NULL.
* In those cases, we take the safe and cheap test.
*/
int
{
if (checkonly) {
0 : EPERM);
} else {
NULL));
}
}
/*
* PRIV_SYS_NET_CONFIG is a superset of PRIV_SYS_IP_CONFIG.
*
* There are a few rare cases where the kernel generates ioctls() from
* interrupt context with a credential of kcred rather than NULL.
* In those cases, we take the safe and cheap test.
*/
int
{
if (checkonly) {
0 : EPERM);
} else {
NULL));
}
}
/*
* PRIV_SYS_NET_CONFIG is a superset of PRIV_SYS_DL_CONFIG.
*/
int
{
}
/*
* PRIV_SYS_DL_CONFIG is a superset of PRIV_SYS_IPTUN_CONFIG.
*/
int
{
return (secpolicy_dl_config(cr));
}
/*
* Map IP pseudo privileges to actual privileges.
* So we don't need to recompile IP when we change the privileges.
*/
int
{
switch (netpriv) {
case OP_CONFIG:
break;
case OP_RAW:
break;
case OP_PRIVPORT:
break;
}
if (checkonly)
else
}
/*
* Map network pseudo privileges to actual privileges.
* So we don't need to recompile IP when we change the privileges.
*/
int
{
switch (netpriv) {
case OP_CONFIG:
break;
case OP_RAW:
break;
case OP_PRIVPORT:
break;
}
if (checkonly)
else
}
/*
* Checks for operations that are either client-only or are used by
* both clients and servers.
*/
int
{
}
/*
* Special case for opening rpcmod: have NFS privileges or network
* config privileges.
*/
int
{
return (secpolicy_nfs(cr));
else
}
int
{
}
int
{
}
int
{
}
int
{
}
/*
* Basic privilege checks.
*/
int
{
}
int
{
}
int
{
}
/*
* Slightly complicated because we don't want to trigger the policy too
* often. First we shortcircuit access to "self" (tp == sp) or if
* we don't have the privilege but if we have permission
* just return (0) and we don't flag the privilege as needed.
* Else, we test for the privilege because we either have it or need it.
*/
int
{
return (0);
} else {
}
}
int
{
}
int
{
}
/* ARGSUSED */
int
{
}
/* ARGSUSED */
int
{
}
/*
* Additional device protection.
*
* Traditionally, a device has specific permissions on the node in
* the filesystem which govern which devices can be opened by what
* processes. In certain cases, it is desirable to add extra
* restrictions, as writing to certain devices is identical to
* having a complete run of the system.
*
* This mechanism is called the device policy.
*
* When a device is opened, its policy entry is looked up in the
* policy cache and checked.
*/
int
{
int err;
} else
if (plcy == nullpolicy) {
return (0);
}
else
/*
* Special case:
* PRIV_SYS_NET_CONFIG is a superset of PRIV_SYS_IP_CONFIG.
* If PRIV_SYS_NET_CONFIG is present and PRIV_SYS_IP_CONFIG is
* required, replace PRIV_SYS_IP_CONFIG with PRIV_SYS_NET_CONFIG
* in the required privilege set before doing the check.
*/
}
return (err);
}
int
{
switch (cmd) {
case MODINFO:
case MODGETMAJBIND:
case MODGETPATH:
case MODGETPATHLEN:
case MODGETNAME:
case MODGETFBNAME:
case MODGETDEVPOLICY:
case MODGETDEVPOLICYBYNAME:
case MODDEVT2INSTANCE:
case MODSIZEOF_DEVID:
case MODGETDEVID:
case MODSIZEOF_MINORNAME:
case MODGETMINORNAME:
case MODGETDEVFSPATH_LEN:
case MODGETDEVFSPATH:
case MODGETDEVFSPATH_MI_LEN:
case MODGETDEVFSPATH_MI:
/* Unprivileged */
return (0);
case MODLOAD:
case MODSETDEVPOLICY:
KLPDARG_NONE));
default:
}
}
int
{
}
int
{
}
/*
* Simulate terminal input; another escalation of privileges avenue.
*/
int
{
}
{
}
int
{
}
int
{
}
/*
* secpolicy_contract_identity
*
* Determine if the subject may set the process contract FMRI value
*/
int
{
}
/*
* secpolicy_contract_observer
*
* Determine if the subject may observe a specific contract's events.
*/
int
{
return (0);
}
/*
* secpolicy_contract_observer_choice
*
* Determine if the subject may observe any contract's events. Just
* tests privilege and audits on success.
*/
{
}
/*
* secpolicy_contract_event
*
* Determine if the subject may request critical contract events or
* reliable contract event delivery.
*/
int
{
}
/*
* secpolicy_contract_event_choice
*
* Determine if the subject may retain contract events in its critical
* set when a change in other terms would normally require a change in
* the critical set. Just tests privilege and audits on success.
*/
{
}
/*
* secpolicy_gart_access
*
* Determine if the subject has sufficient priveleges to make ioctls to agpgart
* device.
*/
int
{
}
/*
* secpolicy_gart_map
*
* Determine if the subject has sufficient priveleges to map aperture range
* through agpgart driver.
*/
int
{
NULL));
} else {
NULL));
}
}
/*
* secpolicy_zinject
*
* Determine if the subject can inject faults in the ZFS fault injection
* framework. Requires all privileges.
*/
int
{
}
/*
* secpolicy_zfs
*
* Determine if the subject has permission to manipulate ZFS datasets
* (not pools). Equivalent to the SYS_MOUNT privilege.
*/
int
{
}
/*
* secpolicy_idmap
*
* Determine if the calling process has permissions to register an SID
* mapping daemon and allocate ephemeral IDs.
*/
int
{
}
/*
* secpolicy_ucode_update
*
* Determine if the subject has sufficient privilege to update microcode.
*/
int
{
}
/*
* secpolicy_sadopen
*
* In global zone, sys_config is required.
* In exclusive-IP zones, sys_ip_config is required.
* Note that sys_config is prohibited in non-global zones.
*/
int
{
else
}
/*
* Add privileges to a particular privilege set; this is called when the
* current sets of privileges are not sufficient. I.e., we should always
* call the policy override functions from here.
* What we are allowed to have is in the Observed Permitted set; so
* we compute the difference between that and the newset.
*/
int
{
priv_inverse(&rqd);
}
/*
* secpolicy_smb
*
* Determine if the cred_t has PRIV_SYS_SMB privilege, indicating
* that it has permission to access the smbsrv kernel driver.
* PRIV_POLICY checks the privilege and audits the check.
*
* Returns:
* 0 Driver access is allowed.
* EPERM Driver access is NOT permitted.
*/
int
{
}
/*
* secpolicy_vscan
*
* Determine if cred_t has the necessary privileges to access a file
* for virus scanning and update its extended system attributes.
* PRIV_FILE_DAC_SEARCH, PRIV_FILE_DAC_READ - file access
* PRIV_FILE_FLAG_SET - set extended system attributes
*
* PRIV_POLICY checks the privilege and audits the check.
*
* Returns:
* 0 file access for virus scanning allowed.
* EPERM file access for virus scanning is NOT permitted.
*/
int
{
return (EPERM);
}
return (0);
}
/*
* secpolicy_smbfs_login
*
* Determines if the caller can add and delete the smbfs login
* password in the the nsmb kernel module for the CIFS client.
*
* Returns:
* 0 access is allowed.
* EPERM access is NOT allowed.
*/
int
{
return (0);
}
/*
* secpolicy_xvm_control
*
* domains (x86 specific).
*
* Returns:
* 0 access is allowed.
* EPERM access is NOT allowed.
*/
int
{
return (EPERM);
return (0);
}
/*
* secpolicy_ppp_config
*
* Determine if the subject has sufficient privileges to configure PPP and
* PPP-related devices.
*/
int
{
}