summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/syscall/psecflags.c
diff options
context:
space:
mode:
authorRichard Lowe <richlowe@richlowe.net>2014-04-16 02:39:14 +0100
committerRichard Lowe <richlowe@richlowe.net>2016-10-15 12:02:16 -0400
commitd2a70789f056fc6c9ce3ab047b52126d80b0e3da (patch)
treebcf5eedbc5aeec80cac59ea37052e3b87108c253 /usr/src/uts/common/syscall/psecflags.c
parent8ab1c3f559468e655c4eb8acce993320403dd72b (diff)
downloadillumos-joyent-d2a70789f056fc6c9ce3ab047b52126d80b0e3da.tar.gz
7029 want per-process exploit mitigation features (secflags)
7030 want basic address space layout randomization (ASLR) 7031 noexec_user_stack should be a security-flag 7032 want a means to forbid mappings around NULL Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net> Reviewed by: Patrick Mooney <pmooney@joyent.com> Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src/uts/common/syscall/psecflags.c')
-rw-r--r--usr/src/uts/common/syscall/psecflags.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/usr/src/uts/common/syscall/psecflags.c b/usr/src/uts/common/syscall/psecflags.c
new file mode 100644
index 0000000000..08d923e76b
--- /dev/null
+++ b/usr/src/uts/common/syscall/psecflags.c
@@ -0,0 +1,121 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/* Copyright 2015, Richard Lowe. */
+
+#include <sys/ddi.h>
+#include <sys/errno.h>
+#include <sys/policy.h>
+#include <sys/proc.h>
+#include <sys/procset.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <c2/audit.h>
+
+struct psdargs {
+ psecflagwhich_t which;
+ const secflagdelta_t *delta;
+};
+
+void
+secflags_apply_delta(secflagset_t *set, const secflagdelta_t *delta)
+{
+ if (delta->psd_ass_active) {
+ secflags_copy(set, &delta->psd_assign);
+ } else {
+ if (!secflags_isempty(delta->psd_add)) {
+ secflags_union(set, &delta->psd_add);
+ }
+ if (!secflags_isempty(delta->psd_rem)) {
+ secflags_difference(set, &delta->psd_rem);
+ }
+ }
+}
+
+
+static int
+psecdo(proc_t *p, struct psdargs *args)
+{
+ secflagset_t *set;
+ int ret = 0;
+
+ mutex_enter(&p->p_lock);
+
+ if (secpolicy_psecflags(CRED(), p, curproc) != 0) {
+ ret = EPERM;
+ goto out;
+ }
+
+ ASSERT(args->which != PSF_EFFECTIVE);
+
+ if (!psecflags_validate_delta(&p->p_secflags, args->delta)) {
+ ret = EINVAL;
+ goto out;
+ }
+
+ if (AU_AUDITING())
+ audit_psecflags(p, args->which, args->delta);
+
+ switch (args->which) {
+ case PSF_INHERIT:
+ set = &p->p_secflags.psf_inherit;
+ break;
+ case PSF_LOWER:
+ set = &p->p_secflags.psf_lower;
+ break;
+ case PSF_UPPER:
+ set = &p->p_secflags.psf_upper;
+ break;
+ }
+
+ secflags_apply_delta(set, args->delta);
+
+ /*
+ * Add any flag now in the lower that is not in the inheritable.
+ */
+ secflags_union(&p->p_secflags.psf_inherit, &p->p_secflags.psf_lower);
+
+out:
+ mutex_exit(&p->p_lock);
+ return (ret);
+}
+
+int
+psecflags(procset_t *psp, psecflagwhich_t which, secflagdelta_t *ap)
+{
+ procset_t procset;
+ secflagdelta_t args;
+ int rv = 0;
+ struct psdargs psd = {
+ .which = which,
+ };
+
+ /* Can never change the effective flags */
+ if (psd.which == PSF_EFFECTIVE)
+ return (EINVAL);
+
+ if (copyin(psp, &procset, sizeof (procset)) != 0)
+ return (set_errno(EFAULT));
+
+ if (copyin(ap, &args, sizeof (secflagdelta_t)) != 0)
+ return (set_errno(EFAULT));
+
+ psd.delta = &args;
+
+ /* secflags are per-process, procset must be in terms of processes */
+ if ((procset.p_lidtype == P_LWPID) ||
+ (procset.p_ridtype == P_LWPID))
+ return (set_errno(EINVAL));
+
+ rv = dotoprocs(&procset, psecdo, (caddr_t)&psd);
+
+ return (rv ? set_errno(rv) : 0);
+}