[fmac-discuss] [PATCH v2] Replace PRIV_ALL/PRIV_FULLSET tests with specific privileges, mediate secpolicy_require_set
Stephen Smalley
sds at tycho.nsa.gov
Wed Dec 17 10:10:26 PST 2008
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/
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c
--- a/usr/src/uts/common/dtrace/dtrace.c
+++ b/usr/src/uts/common/dtrace/dtrace.c
@@ -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 {
diff --git a/usr/src/uts/common/dtrace/fasttrap.c b/usr/src/uts/common/dtrace/fasttrap.c
--- a/usr/src/uts/common/dtrace/fasttrap.c
+++ b/usr/src/uts/common/dtrace/fasttrap.c
@@ -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;
diff --git a/usr/src/uts/common/fmac/fmac.c b/usr/src/uts/common/fmac/fmac.c
--- a/usr/src/uts/common/fmac/fmac.c
+++ b/usr/src/uts/common/fmac/fmac.c
@@ -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);
+}
diff --git a/usr/src/uts/common/os/policy.c b/usr/src/uts/common/os/policy.c
--- a/usr/src/uts/common/os/policy.c
+++ b/usr/src/uts/common/os/policy.c
@@ -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));
}
/*
diff --git a/usr/src/uts/common/os/priv_defs b/usr/src/uts/common/os/priv_defs
--- a/usr/src/uts/common/os/priv_defs
+++ b/usr/src/uts/common/os/priv_defs
@@ -31,6 +31,10 @@
# add the new privilege at the end; for ordinary releases privileges
# should be ordered alphabetically.
#
+
+privilege PRIV_BOOTPART_MODIFY
+
+ Allows a process to modify a pcfs boot partition.
privilege PRIV_CONTRACT_EVENT
@@ -71,6 +75,14 @@
Allows DTrace user-level tracing.
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
@@ -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.
@@ -200,6 +216,14 @@
Message Queue, Semaphore Set, or Shared Memory Segment.
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
@@ -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.
diff --git a/usr/src/uts/common/sys/fmac/fmac.h b/usr/src/uts/common/sys/fmac/fmac.h
--- a/usr/src/uts/common/sys/fmac/fmac.h
+++ b/usr/src/uts/common/sys/fmac/fmac.h
@@ -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 */
diff --git a/usr/src/uts/intel/io/dktp/dcdev/dadk.c b/usr/src/uts/intel/io/dktp/dcdev/dadk.c
--- a/usr/src/uts/intel/io/dktp/dcdev/dadk.c
+++ b/usr/src/uts/intel/io/dktp/dcdev/dadk.c
@@ -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));
--
Stephen Smalley
National Security Agency
More information about the fmac-discuss
mailing list