changeset 7904:db26d3243ce7

[fmac-discuss] [PATCH v2] Replace PRIV_ALL/PRIV_FULLSET tests with specific privileges, mediate secpolicy_require_set Second version of a patch that replaces PRIV_ALL and PRIV_FULLSET checks with specific privilege checks and introduces FMAC mediation of secpolicy_require_set(). These changes complete the support for further restricting the use of privileges via FMAC. Changes since the prior version: - Fixed firmware update comment. - Introduce separate privileges for kmdb vs error_inject (I don't see any callers of the latter, btw). - Rename a couple of the new privileges for clarity. In running the resulting system, I noticed that the initial ifconfig invocation triggers a require_set check on all privileges when opening the udp pseudo device. If I understand correctly, this is because it accesses the device before device policy has been loaded and the initial default policy requires all privs for any device access. Hopefully we can alleviate that problem in some manner so that we don't have to allow the ifconfig_t domain all privileges in policy, possibly by moving up the loading of device policy. (updated) Webrev available at: http://cr.opensolaris.org/~sds/privall/
author Stephen Smalley <sds@tycho.nsa.gov>
date Thu, 18 Dec 2008 12:32:30 -0500
parents cb99113a9ac7
children cc909c8184bb
files usr/src/uts/common/dtrace/dtrace.c usr/src/uts/common/dtrace/fasttrap.c usr/src/uts/common/fmac/fmac.c usr/src/uts/common/os/policy.c usr/src/uts/common/os/priv_defs usr/src/uts/common/sys/fmac/fmac.h usr/src/uts/intel/io/dktp/dcdev/dadk.c
diffstat 7 files changed, 76 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/dtrace/dtrace.c	Wed Nov 26 11:02:24 2008 -0500
+++ b/usr/src/uts/common/dtrace/dtrace.c	Thu Dec 18 12:32:30 2008 -0500
@@ -6370,7 +6370,7 @@
 {
 	uint32_t priv;
 
-	if (cr == NULL || PRIV_POLICY_ONLY(cr, PRIV_ALL, B_FALSE)) {
+	if (cr == NULL || PRIV_POLICY_ONLY(cr, PRIV_DTRACE_ALL, B_FALSE)) {
 		/*
 		 * For DTRACE_PRIV_ALL, the uid and zoneid don't matter.
 		 */
@@ -10033,7 +10033,7 @@
 	ASSERT(MUTEX_HELD(&dtrace_lock));
 
 	if (size > dtrace_nonroot_maxsize &&
-	    !PRIV_POLICY_CHOICE(CRED(), PRIV_ALL, B_FALSE))
+	    !PRIV_POLICY_CHOICE(CRED(), PRIV_DTRACE_ALL, B_FALSE))
 		return (EFBIG);
 
 	cp = cpu_list;
@@ -12104,7 +12104,7 @@
 	 * actual anonymous tracing, or the possession of all privileges, all of
 	 * the normal checks are bypassed.
 	 */
-	if (cr == NULL || PRIV_POLICY_ONLY(cr, PRIV_ALL, B_FALSE)) {
+	if (cr == NULL || PRIV_POLICY_ONLY(cr, PRIV_DTRACE_ALL, B_FALSE)) {
 		state->dts_cred.dcr_visible = DTRACE_CRV_ALL;
 		state->dts_cred.dcr_action = DTRACE_CRA_ALL;
 	} else {
--- a/usr/src/uts/common/dtrace/fasttrap.c	Wed Nov 26 11:02:24 2008 -0500
+++ b/usr/src/uts/common/dtrace/fasttrap.c	Thu Dec 18 12:32:30 2008 -0500
@@ -43,6 +43,7 @@
 #include <sys/dtrace_impl.h>
 #include <sys/sysmacros.h>
 #include <sys/proc.h>
+#include <sys/priv_const.h>
 #include <sys/priv.h>
 #include <sys/policy.h>
 #include <util/qsort.h>
@@ -1968,7 +1969,7 @@
 			}
 		}
 
-		if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) {
+		if (!PRIV_POLICY_CHOICE(cr, PRIV_DTRACE_ALL, B_FALSE)) {
 			proc_t *p;
 			pid_t pid = probe->ftps_pid;
 
@@ -2008,7 +2009,7 @@
 		if (copyin((void *)arg, &instr, sizeof (instr)) != 0)
 			return (EFAULT);
 
-		if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) {
+		if (!PRIV_POLICY_CHOICE(cr, PRIV_DTRACE_ALL, B_FALSE)) {
 			proc_t *p;
 			pid_t pid = instr.ftiq_pid;
 
--- a/usr/src/uts/common/fmac/fmac.c	Wed Nov 26 11:02:24 2008 -0500
+++ b/usr/src/uts/common/fmac/fmac.c	Thu Dec 18 12:32:30 2008 -0500
@@ -36,6 +36,7 @@
 #include <sys/kobj.h>
 #include <sys/vfs.h>
 #include <sys/acl.h>
+#include <sys/priv_impl.h>
 #include <sys/fmac/security.h>
 #include <sys/fmac/fmac.h>
 #include <sys/fmac/avc.h>
@@ -883,3 +884,15 @@
 	ad.u.priv.priv = priv;
 	return (avc_has_perm(cr_secid, cr_secid, sclass, av, &ad));
 }
+
+int
+fmac_priv_require_set(const cred_t *cr, const priv_set_t *req)
+{
+	int priv;
+
+	for (priv = 0; priv < nprivs; priv++)
+		if (priv_ismember(req, priv))
+			if (fmac_priv_restrict(cr, priv))
+				return (EACCES);
+	return (0);
+}
--- a/usr/src/uts/common/os/policy.c	Wed Nov 26 11:02:24 2008 -0500
+++ b/usr/src/uts/common/os/policy.c	Thu Dec 18 12:32:30 2008 -0500
@@ -475,11 +475,11 @@
 
 	if (req == PRIV_FULLSET ? HAS_ALLPRIVS(cr) : priv_issubset(req,
 	    &CR_OEPRIV(cr))) {
-		return (0);
+		return (fmac_priv_require_set(cr, req));
 	}
 
 	if (priv_policy_override_set(cr, req, KLPDARG_NOMORE) == 0)
-		return (0);
+		return (fmac_priv_require_set(cr, req));
 
 	if (req == PRIV_FULLSET || priv_isfullset(req)) {
 		priv_policy_err(cr, PRIV_ALL, B_FALSE, msg);
@@ -1321,7 +1321,7 @@
 int
 secpolicy_pcfs_modify_bootpartition(const cred_t *cred)
 {
-	return (PRIV_POLICY(cred, PRIV_ALL, B_FALSE, EACCES,
+	return (PRIV_POLICY(cred, PRIV_BOOTPART_MODIFY, B_FALSE, EACCES,
 	    "modify pcfs boot partition"));
 }
 
@@ -1514,13 +1514,13 @@
 int
 secpolicy_kmdb(const cred_t *scr)
 {
-	return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
+	return (PRIV_POLICY(scr, PRIV_KMDB, B_FALSE, EPERM, NULL));
 }
 
 int
 secpolicy_error_inject(const cred_t *scr)
 {
-	return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
+	return (PRIV_POLICY(scr, PRIV_ERROR_INJECT, B_FALSE, EPERM, NULL));
 }
 
 /*
@@ -1585,11 +1585,7 @@
 int
 secpolicy_zone_config(const cred_t *cr)
 {
-	/*
-	 * Require all privileges to avoid possibility of privilege
-	 * escalation.
-	 */
-	return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+	return (PRIV_POLICY(cr, PRIV_ZONE_CONFIG, B_FALSE, EPERM, NULL));
 }
 
 /*
@@ -1979,7 +1975,8 @@
 		return (0);
 	case MODLOAD:
 	case MODSETDEVPOLICY:
-		return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+		return (PRIV_POLICY(cr, PRIV_MODULE_LOAD, B_FALSE, EPERM,
+		    NULL));
 	default:
 		return (secpolicy_sys_config(cr, B_FALSE));
 	}
@@ -2004,7 +2001,7 @@
 int
 secpolicy_sti(const cred_t *cr)
 {
-	return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+	return (PRIV_POLICY(cr, PRIV_TTY_INPUT, B_FALSE, EPERM, NULL));
 }
 
 boolean_t
@@ -2125,7 +2122,7 @@
 int
 secpolicy_zinject(const cred_t *cr)
 {
-	return (secpolicy_require_set(cr, PRIV_FULLSET, NULL));
+	return (PRIV_POLICY(cr, PRIV_ZFS_INJECT, B_FALSE, EPERM, NULL));
 }
 
 /*
@@ -2160,7 +2157,7 @@
 int
 secpolicy_ucode_update(const cred_t *scr)
 {
-	return (PRIV_POLICY(scr, PRIV_ALL, B_FALSE, EPERM, NULL));
+	return (PRIV_POLICY(scr, PRIV_UCODE_UPDATE, B_FALSE, EPERM, NULL));
 }
 
 /*
--- a/usr/src/uts/common/os/priv_defs	Wed Nov 26 11:02:24 2008 -0500
+++ b/usr/src/uts/common/os/priv_defs	Thu Dec 18 12:32:30 2008 -0500
@@ -32,6 +32,10 @@
 # should be ordered alphabetically.
 #
 
+privilege PRIV_BOOTPART_MODIFY
+
+	Allows a process to modify a pcfs boot partition.
+
 privilege PRIV_CONTRACT_EVENT
 
 	Allows a process to request critical events without limitation.
@@ -72,6 +76,14 @@
 	Allows use of the syscall and profile DTrace providers to
 	examine processes to which the user has permissions.
 
+privilege PRIV_DTRACE_ALL
+
+	Allows DTrace tracing of all credentials.
+
+privilege PRIV_ERROR_INJECT
+
+	Allows error injection.
+
 privilege PRIV_FILE_CHOWN
 
 	Allows a process to change a file's owner user ID.
@@ -162,6 +174,10 @@
 	Allows a process to set immutable, nounlink or appendonly
 	file attributes.
 
+privilege PRIV_FIRMWARE_UPDATE
+
+	Allows a process to update firmware.
+
 privilege PRIV_GRAPHICS_ACCESS
 
 	Allows a process to make privileged ioctls to graphics devices.
@@ -201,6 +217,14 @@
 	Additional restrictions apply if the owner of the object has uid 0
 	and the effective uid of the current process is not 0.
 
+privilege PRIV_KMDB
+
+	Allows access to /dev/kmdb.
+
+privilege PRIV_MODULE_LOAD
+
+	Allows a process to load a module or set device policy.
+
 privilege PRIV_NET_BINDMLP
 
 	Allow a process to bind to a port that is configured as a
@@ -447,6 +471,14 @@
 	This privilege is interpreted only if the system is configured
 	with Trusted Extensions.
 
+privilege PRIV_TTY_INPUT
+
+	Allows a process to simulate terminal input.
+
+privilege PRIV_UCODE_UPDATE
+
+	Allows a process to update the microcode of the platform.
+
 privilege PRIV_VIRT_MANAGE
 
 	Allows a process to manage virtualized environments such as
@@ -560,6 +592,14 @@
 	managing guest domains and the hypervisor. This privilege is
 	used only if booted into xVM on x86 platforms.
 
+privilege PRIV_ZFS_INJECT
+
+	Allows a process to inject faults in the ZFS fault injection framework.
+
+privilege PRIV_ZONE_CONFIG
+	
+	Allows a process to configure zones (create, halt, enter).
+
 set PRIV_EFFECTIVE
 
 	Set of privileges currently in effect.
--- a/usr/src/uts/common/sys/fmac/fmac.h	Wed Nov 26 11:02:24 2008 -0500
+++ b/usr/src/uts/common/sys/fmac/fmac.h	Thu Dec 18 12:32:30 2008 -0500
@@ -35,6 +35,7 @@
 #include <sys/inttypes.h>
 #include <sys/vfs.h>
 #include <sys/vnode.h>
+#include <sys/priv.h>
 #else
 #include <inttypes.h>
 #endif /* _KERNEL */
@@ -107,6 +108,7 @@
     access_vector_t perms);
 int fmac_vnode_priv_access(const cred_t *, vnode_t *, int, int);
 int fmac_priv_restrict(const cred_t *cr, int priv);
+int fmac_priv_require_set(const cred_t *cr, const priv_set_t *req);
 int fmac_xvattr(cred_t *cr, vnode_t *vp, int priv, int err);
 #endif /* _KERNEL */
 
--- a/usr/src/uts/intel/io/dktp/dcdev/dadk.c	Wed Nov 26 11:02:24 2008 -0500
+++ b/usr/src/uts/intel/io/dktp/dcdev/dadk.c	Thu Dec 18 12:32:30 2008 -0500
@@ -36,6 +36,7 @@
 #include <sys/vtoc.h>
 #include <sys/dkio.h>
 #include <sys/policy.h>
+#include <sys/priv_const.h>
 #include <sys/priv.h>
 
 #include <sys/dktp/dadev.h>
@@ -810,10 +811,10 @@
 	case DKIOC_UPDATEFW:
 
 		/*
-		 * Require PRIV_ALL privilege to invoke DKIOC_UPDATEFW
-		 * to protect the firmware update from malicious use
+		 * Protect the firmware update from malicious use
 		 */
-		if (PRIV_POLICY(cred_p, PRIV_ALL, B_FALSE, EPERM, NULL) != 0)
+		if (PRIV_POLICY(cred_p, PRIV_FIRMWARE_UPDATE, B_FALSE,
+		    EPERM, NULL) != 0)
 			return (EPERM);
 		else
 			return (dadk_ctl_ioctl(dadkp, cmd, arg, flag));