Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F171641947
D27364.id79963.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
28 KB
Referenced Files
None
Subscribers
None
D27364.id79963.diff
View Options
Index: etc/mtree/BSD.include.dist
===================================================================
--- etc/mtree/BSD.include.dist
+++ etc/mtree/BSD.include.dist
@@ -290,6 +290,8 @@
..
mac_bsdextended
..
+ mac_grantbylabel
+ ..
mac_lomac
..
mac_mls
Index: include/Makefile
===================================================================
--- include/Makefile
+++ include/Makefile
@@ -59,7 +59,9 @@
netinet/netdump \
netinet/tcp_stacks \
security/audit \
- security/mac_biba security/mac_bsdextended security/mac_lomac \
+ security/mac_biba security/mac_bsdextended \
+ security/mac_grantbylabel \
+ security/mac_lomac \
security/mac_mls security/mac_partition \
security/mac_veriexec \
sys/disk \
Index: lib/libveriexec/Makefile
===================================================================
--- lib/libveriexec/Makefile
+++ lib/libveriexec/Makefile
@@ -1,6 +1,6 @@
# $FreeBSD$
-.include <src.opts.mk>
+.include <bsd.own.mk>
LIB= veriexec
MAN= veriexec.3
@@ -8,7 +8,10 @@
WARNS?= 2
-SRCS= veriexec_check.c
+SRCS= \
+ exec_script.c \
+ gbl_check.c \
+ veriexec_check.c
.include <bsd.lib.mk>
Index: lib/libveriexec/exec_script.c
===================================================================
--- /dev/null
+++ lib/libveriexec/exec_script.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2019, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/mac.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <security/mac_grantbylabel/mac_grantbylabel.h>
+
+#include "libveriexec.h"
+
+static char *
+find_interpreter(const char *script)
+{
+ static const char ws[] = " \t\n\r";
+ static char buf[MAXPATHLEN+4]; /* allow space for #! etc */
+ char *cp;
+ int fd;
+ int n;
+
+ cp = NULL;
+ if ((fd = open(script, O_RDONLY)) >= 0) {
+ if ((n = read(fd, buf, sizeof(buf))) > 0) {
+ if (strncmp(buf, "#!", 2) == 0) {
+ buf[sizeof(buf) - 1] = '\0';
+ cp = &buf[2];
+ if ((n = strspn(cp, ws)) > 0)
+ cp += n;
+ if ((n = strcspn(cp, ws)) > 0) {
+ cp[n] = '\0';
+ } else {
+ cp = NULL;
+ }
+ }
+ }
+ close(fd);
+ }
+ return (cp);
+}
+
+/**
+ * @brief exec a python or similar script
+ *
+ * Python and similar scripts must normally be signed and
+ * run directly rather than fed to the interpreter which
+ * is not normally allowed to be run directly.
+ *
+ * If direct execv of script fails due to EAUTH
+ * and process has GBL_VERIEXEC syslog event and run via
+ * interpreter.
+ *
+ * If interpreter is NULL look at first block of script
+ * to find ``#!`` magic.
+ *
+ * @prarm[in] interpreter
+ * if NULL, extract from script if necessary
+ *
+ * @prarm[in] argv
+ * argv for execv(2)
+ * argv[0] must be full path.
+ * Python at least requires argv[1] to also be the script path.
+ *
+ * @return
+ * error on failure usually EPERM or EAUTH
+ */
+int
+execv_script(const char *interpreter, char * const *argv)
+{
+ const char *script;
+ int rc;
+
+ script = argv[0];
+ if (veriexec_check_path(script) == 0) {
+ rc = execv(script, argv);
+ }
+ /* still here? we might be allowed to run via interpreter */
+ if (gbl_check_pid(0) & GBL_VERIEXEC) {
+ if (!interpreter)
+ interpreter = find_interpreter(script);
+ if (interpreter) {
+ syslog(LOG_NOTICE, "running %s via %s",
+ script, interpreter);
+ rc = execv(interpreter, argv);
+ }
+ }
+ return (rc);
+}
+
+#if defined(MAIN) || defined(UNIT_TEST)
+#include <sys/wait.h>
+#include <err.h>
+
+int
+main(int argc __unused, char *argv[])
+{
+ const char *interp;
+ int c;
+ int s;
+ pid_t child;
+
+ openlog("exec_script", LOG_PID|LOG_PERROR, LOG_DAEMON);
+
+ interp = NULL;
+ while ((c = getopt(argc, argv, "i:")) != -1) {
+ switch (c) {
+ case 'i':
+ interp = optarg;
+ break;
+ default:
+ errx(1, "unknown option: -%c", c);
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+ /* we need a child */
+ child = fork();
+ if (child < 0)
+ err(2, "fork");
+ if (child == 0) {
+ c = execv_script(interp, argv);
+ err(2, "exec_script(%s,%s)", interp, argv[0]);
+ }
+ c = waitpid(child, &s, 0);
+ printf("%s: exit %d\n", argv[0], WEXITSTATUS(s));
+ return (0);
+}
+#endif
Index: lib/libveriexec/gbl_check.c
===================================================================
--- /dev/null
+++ lib/libveriexec/gbl_check.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/mac.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <security/mac_grantbylabel/mac_grantbylabel.h>
+
+/**
+ * @brief does path have a gbl label
+ *
+ * @return
+ * @li 0 if no label or module not loaded
+ * @li value of label
+ */
+unsigned int
+gbl_check_path(const char *path)
+{
+ struct mac_grantbylabel_fetch_gbl_args gbl;
+ int fd;
+ int rc;
+
+ rc = 0;
+ if ((fd = open(path, O_RDONLY|O_VERIFY)) >= 0) {
+ gbl.u.fd = fd;
+ if (mac_syscall(MAC_GRANTBYLABEL_NAME,
+ MAC_GRANTBYLABEL_FETCH_GBL,
+ &gbl) == 0) {
+ rc = gbl.gbl;
+ }
+ close(fd);
+ }
+ return(rc);
+}
+
+/**
+ * @brief does pid have a gbl label
+ *
+ * @return
+ * @li 0 if no label or module not loaded
+ * @li value of label
+ */
+unsigned int
+gbl_check_pid(pid_t pid)
+{
+ struct mac_grantbylabel_fetch_gbl_args gbl;
+ int rc;
+
+ rc = 0;
+ gbl.u.pid = pid;
+ if (mac_syscall(MAC_GRANTBYLABEL_NAME,
+ MAC_GRANTBYLABEL_FETCH_PID_GBL, &gbl) == 0) {
+ rc = gbl.gbl;
+ }
+ return(rc);
+}
Index: lib/libveriexec/libveriexec.h
===================================================================
--- lib/libveriexec/libveriexec.h
+++ lib/libveriexec/libveriexec.h
@@ -29,9 +29,14 @@
#ifndef __LIBVERIEXEC_H__
#define __LIBVERIEXEC_H__
-int veriexec_check_fd_mode(int, unsigned int);
-int veriexec_check_path_mode(const char *, unsigned int);
-int veriexec_check_fd(int);
-int veriexec_check_path(const char *);
+int veriexec_check_fd_mode(int, unsigned int);
+int veriexec_check_path_mode(const char *, unsigned int);
+int veriexec_check_fd(int);
+int veriexec_check_path(const char *);
+unsigned int gbl_check_path(const char *);
+unsigned int gbl_check_pid(pid_t);
+int execv_script(const char *, char * const *);
+
+#define HAVE_GBL_CHECK_PID 1
#endif /* __LIBVERIEXEC_H__ */
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -3435,7 +3435,7 @@
dev/videomode/edid.c optional videomode
dev/videomode/pickmode.c optional videomode
dev/videomode/vesagtf.c optional videomode
-dev/veriexec/verified_exec.c optional veriexec mac_veriexec
+dev/veriexec/verified_exec.c optional mac_veriexec
dev/vge/if_vge.c optional vge
dev/viapm/viapm.c optional viapm pci
dev/virtio/virtio.c optional virtio
Index: sys/kern/kern_exec.c
===================================================================
--- sys/kern/kern_exec.c
+++ sys/kern/kern_exec.c
@@ -826,6 +826,17 @@
oldtextvp = p->p_textvp;
p->p_textvp = newtextvp;
+#ifdef MAC
+ error = mac_proc_check_resource(p->p_ucred, p);
+ if (error) {
+ if (p->p_textvp) {
+ p->p_textvp = oldtextvp;
+ oldtextvp = NULL;
+ }
+ goto exec_fail_dealloc;
+ }
+#endif
+
#ifdef KDTRACE_HOOKS
/*
* Tell the DTrace fasttrap provider about the exec if it
Index: sys/security/mac/mac_framework.h
===================================================================
--- sys/security/mac/mac_framework.h
+++ sys/security/mac/mac_framework.h
@@ -312,6 +312,7 @@
}
int mac_proc_check_debug(struct ucred *cred, struct proc *p);
+int mac_proc_check_resource(struct ucred *cred, struct proc *p);
int mac_proc_check_sched(struct ucred *cred, struct proc *p);
int mac_proc_check_signal(struct ucred *cred, struct proc *p,
int signum);
Index: sys/security/mac/mac_policy.h
===================================================================
--- sys/security/mac/mac_policy.h
+++ sys/security/mac/mac_policy.h
@@ -389,6 +389,8 @@
typedef int (*mpo_proc_check_debug_t)(struct ucred *cred,
struct proc *p);
+typedef int (*mpo_proc_check_resource_t)(struct ucred *cred,
+ struct proc *proc);
typedef int (*mpo_proc_check_sched_t)(struct ucred *cred,
struct proc *p);
typedef int (*mpo_proc_check_signal_t)(struct ucred *cred,
@@ -833,6 +835,7 @@
mpo_priv_grant_t mpo_priv_grant;
mpo_proc_check_debug_t mpo_proc_check_debug;
+ mpo_proc_check_resource_t mpo_proc_check_resource;
mpo_proc_check_sched_t mpo_proc_check_sched;
mpo_proc_check_signal_t mpo_proc_check_signal;
mpo_proc_check_wait_t mpo_proc_check_wait;
Index: sys/security/mac/mac_process.c
===================================================================
--- sys/security/mac/mac_process.c
+++ sys/security/mac/mac_process.c
@@ -431,3 +431,18 @@
return (error);
}
+
+MAC_CHECK_PROBE_DEFINE2(proc_check_resource, "struct ucred *", "struct proc *");
+
+int
+mac_proc_check_resource(struct ucred *cred, struct proc *p)
+{
+ int error;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ MAC_POLICY_CHECK_NOSLEEP(proc_check_resource, cred, p);
+ MAC_CHECK_PROBE2(proc_check_resource, error, cred, p);
+
+ return (error);
+}
Index: sys/security/mac_grantbylabel/mac_grantbylabel.h
===================================================================
--- /dev/null
+++ sys/security/mac_grantbylabel/mac_grantbylabel.h
@@ -0,0 +1,66 @@
+/*
+ * $FreeBSD$
+ *
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _SECURITY_MAC_GRANTBYLABEL_H
+#define _SECURITY_MAC_GRANTBYLABEL_H
+
+#include <security/mac_veriexec/mac_veriexec.h>
+
+#define MAC_GRANTBYLABEL_NAME "mac_grantbylabel"
+
+/* the bits we use to represent tokens */
+#define GBL_EMPTY (1<<0)
+#define GBL_BIND (1<<1)
+#define GBL_IPC (1<<2)
+#define GBL_NET (1<<3)
+#define GBL_PROC (1<<4)
+#define GBL_RTSOCK (1<<5)
+#define GBL_SYSCTL (1<<6)
+#define GBL_VACCESS (1<<7)
+#define GBL_VERIEXEC (1<<8)
+
+#define GBL_MAX 8
+
+/* this should suffice for now */
+typedef uint32_t gbl_label_t;
+
+#define MAC_GRANTBYLABEL_FETCH_GBL 1
+#define MAC_GRANTBYLABEL_FETCH_PID_GBL 2
+
+struct mac_grantbylabel_fetch_gbl_args {
+ union {
+ int fd;
+ pid_t pid;
+ } u;
+ gbl_label_t gbl;
+};
+
+#endif
Index: sys/security/mac_grantbylabel/mac_grantbylabel.c
===================================================================
--- /dev/null
+++ sys/security/mac_grantbylabel/mac_grantbylabel.c
@@ -0,0 +1,404 @@
+/*-
+ * $FreeBSD$
+ *
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include "opt_mac.h"
+
+#include <sys/param.h>
+#include <sys/capsicum.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mac.h>
+#include <sys/namei.h>
+#include <sys/priv.h>
+#include <sys/sysctl.h>
+#include <sys/syslog.h>
+#include <security/mac/mac_policy.h>
+
+#include "mac_grantbylabel.h"
+#include <security/mac_veriexec/mac_veriexec_internal.h>
+
+#define MAC_GRANTBYLABEL_FULLNAME "MAC/grantbylabel"
+
+#ifdef MAC_GRANTBYLABEL_DEBUG
+# ifndef MAC_DEBUG
+# define MAC_DEBUG
+# endif
+# define GRANTBYLABEL_DEBUG(n, x) if (mac_grantbylabel_debug >= (n)) printf x
+
+static int mac_grantbylabel_debug;
+
+SYSCTL_DECL(_security_mac);
+SYSCTL_NODE(_security_mac, OID_AUTO, grantbylabel, CTLFLAG_RW, 0,
+ "MAC/grantbylabel policy controls");
+SYSCTL_INT(_security_mac_grantbylabel, OID_AUTO, debug, CTLFLAG_RW,
+ &mac_grantbylabel_debug, 0, "Debug mac_grantbylabel");
+
+#else
+# define GRANTBYLABEL_DEBUG(n, x)
+#endif
+
+#ifdef MAC_DEBUG
+#define MAC_GRANTBYLABEL_DBG(_lvl, _fmt, ...) \
+ do { \
+ GRANTBYLABEL_DEBUG((_lvl), (MAC_GRANTBYLABEL_FULLNAME ": " _fmt \
+ "\n", ##__VA_ARGS__)); \
+ } while(0)
+#else
+#define MAC_GRANTBYLABEL_DBG(_lvl, _fmt, ...)
+#endif
+
+
+/* label token prefix */
+#define GBL_PREFIX "gbl/"
+
+static int mac_grantbylabel_slot;
+
+#define SLOT(l) \
+ mac_label_get((l), mac_grantbylabel_slot)
+#define SLOT_SET(l, v) \
+ mac_label_set((l), mac_grantbylabel_slot, (v))
+
+
+/**
+ * @brief parse label into bitmask
+ *
+ * We are only interested in tokens prefixed by GBL_PREFIX ("gbl/").
+ *
+ * @return 32bit mask
+ */
+static gbl_label_t
+gbl_parse_label(const char *label)
+{
+ gbl_label_t gbl;
+ char *cp;
+
+ if (!(label && *label))
+ return GBL_EMPTY;
+ gbl = 0;
+ for (cp = strstr(label, GBL_PREFIX); cp; cp = strstr(cp, GBL_PREFIX)) {
+ /* check we didn't find "fugbl/" */
+ if (cp > label && cp[-1] != ',') {
+ cp += sizeof(GBL_PREFIX);
+ continue;
+ }
+ cp += sizeof(GBL_PREFIX) - 1;
+ switch (*cp) {
+ case 'b':
+ if (strncmp(cp, "bind", 4) == 0)
+ gbl |= GBL_BIND;
+ break;
+ case 'd':
+ if (strncmp(cp, "daemon", 6) == 0)
+ gbl |= (GBL_BIND|GBL_IPC|GBL_NET|GBL_PROC|
+ GBL_SYSCTL|GBL_VACCESS);
+ break;
+ case 'i':
+ if (strncmp(cp, "ipc", 3) == 0)
+ gbl |= GBL_IPC;
+ break;
+ case 'n':
+ if (strncmp(cp, "net", 3) == 0)
+ gbl |= GBL_NET;
+ break;
+ case 'p':
+ if (strncmp(cp, "proc", 4) == 0)
+ gbl |= GBL_PROC;
+ break;
+ case 'r':
+ if (strncmp(cp, "rtsock", 6) == 0)
+ gbl |= GBL_RTSOCK;
+ break;
+ case 's':
+ if (strncmp(cp, "sysctl", 6) == 0)
+ gbl |= GBL_SYSCTL;
+ break;
+ case 'v':
+ if (strncmp(cp, "vaccess", 7) == 0)
+ gbl |= GBL_VACCESS;
+ else if (strncmp(cp, "veriexec", 8) == 0)
+ gbl |= GBL_VERIEXEC;
+ break;
+ default: /* ignore unknown? */
+ MAC_GRANTBYLABEL_DBG(1,
+ "ignoring unknown token at %s/%s",
+ GBL_PREFIX, cp);
+ break;
+ }
+ }
+
+ return gbl;
+}
+
+
+/**
+ * @brief grant priv if warranted
+ *
+ * If the cred is root, we have nothing to do.
+ * Otherwise see if the current process has a label
+ * that grants it the requested priv.
+ */
+static int
+mac_grantbylabel_priv_grant(struct ucred *cred, int priv)
+{
+ gbl_label_t label;
+ int rc;
+
+ rc = EPERM; /* default response */
+
+ if ((curproc->p_flag & (P_KPROC|P_SYSTEM)))
+ return rc; /* not interested */
+
+ switch (priv) {
+ case PRIV_VERIEXEC_DIRECT:
+ case PRIV_VERIEXEC_NOVERIFY:
+ /* XXX might want to skip in FIPS mode */
+ break;
+ default:
+ if (cred->cr_uid == 0)
+ return rc; /* not interested */
+ break;
+ }
+
+ label = (gbl_label_t)SLOT(curproc->p_textvp->v_label);
+
+ /*
+ * We look at the extra privs granted
+ * via process label.
+ */
+ switch (priv) {
+ case PRIV_IPC_READ:
+ case PRIV_IPC_WRITE:
+ if (label & GBL_IPC)
+ rc = 0;
+ break;
+ case PRIV_NETINET_BINDANY:
+ case PRIV_NETINET_RESERVEDPORT: /* socket bind low port */
+ case PRIV_NETINET_REUSEPORT:
+ if (label & GBL_BIND)
+ rc = 0;
+ break;
+ case PRIV_NETINET_ADDRCTRL6:
+ case PRIV_NET_LAGG:
+ case PRIV_NET_SETIFFIB:
+ case PRIV_NET_SETIFVNET:
+ case PRIV_NETINET_SETHDROPTS:
+ case PRIV_NET_VXLAN:
+ case PRIV_NETINET_GETCRED:
+ case PRIV_NETINET_IPSEC:
+ case PRIV_NETINET_RAW:
+ if (label & GBL_NET)
+ rc = 0;
+ break;
+ case PRIV_NETINET_MROUTE:
+ case PRIV_NET_ROUTE:
+ if (label & GBL_RTSOCK)
+ rc = 0;
+ break;
+ case PRIV_PROC_LIMIT:
+ case PRIV_PROC_SETRLIMIT:
+ if (label & GBL_PROC)
+ rc = 0;
+ break;
+ case PRIV_SYSCTL_WRITE:
+ if (label & GBL_SYSCTL)
+ rc = 0;
+ break;
+ case PRIV_VFS_ADMIN:
+ case PRIV_VFS_BLOCKRESERVE:
+ case PRIV_VFS_CHOWN:
+ case PRIV_VFS_EXEC: /* vaccess file and accmode & VEXEC */
+ case PRIV_VFS_GENERATION:
+ case PRIV_VFS_LOOKUP: /* vaccess DIR */
+ case PRIV_VFS_READ:
+ case PRIV_VFS_WRITE:
+ if (label & GBL_VACCESS)
+ rc = 0;
+ break;
+ case PRIV_VERIEXEC_DIRECT:
+ /*
+ * We are here because we are attempting to direct exec
+ * something with the 'indirect' flag set.
+ * We need to check parent label for this one.
+ */
+ PROC_LOCK(curproc);
+ label = (gbl_label_t)SLOT(curproc->p_pptr->p_textvp->v_label);
+ if (label & GBL_VERIEXEC) {
+ rc = 0;
+ /*
+ * Of course the only reason to be running an
+ * interpreter this way is to bypass O_VERIFY
+ * so we can run unsigned script.
+ * We set GBL_VERIEXEC on p_label for
+ * PRIV_VERIEXEC_NOVERIFY below
+ */
+ SLOT_SET(curproc->p_label, GBL_VERIEXEC);
+ }
+ PROC_UNLOCK(curproc);
+ break;
+ case PRIV_VERIEXEC_NOVERIFY:
+ /* we look at p_label! see above */
+ label = (gbl_label_t)SLOT(curproc->p_label);
+ if (label & GBL_VERIEXEC)
+ rc = 0;
+ break;
+ default:
+ break;
+ }
+ MAC_GRANTBYLABEL_DBG(rc ? 1 : 2,
+ "pid=%d priv=%d, label=%#o rc=%d",
+ curproc->p_pid, priv, label, rc);
+
+ return rc;
+}
+
+
+/*
+ * If proc->p_textvp does not yet have a label,
+ * fetch file info from mac_veriexec
+ * and set label (if any) else set.
+ * If there is no label set it to GBL_EMPTY.
+ */
+static int
+mac_grantbylabel_proc_check_resource(struct ucred *cred,
+ struct proc *proc)
+{
+ struct vattr va;
+ const char *label;
+ int error;
+
+ if (!SLOT(proc->p_textvp->v_label)) {
+ error = VOP_GETATTR(proc->p_textvp, &va, cred);
+ if (!error) {
+ label = mac_veriexec_metadata_get_file_label(va.va_fsid,
+ va.va_fileid, va.va_gen, FALSE);
+ if (label) {
+ MAC_GRANTBYLABEL_DBG(1,
+ "label=%s dev=%ju, file %ju.%lu",
+ label,
+ (uintmax_t)va.va_fsid,
+ (uintmax_t)va.va_fileid,
+ va.va_gen);
+ SLOT_SET(proc->p_textvp->v_label,
+ (intptr_t)gbl_parse_label(label));
+ return 0;
+ }
+ }
+ SLOT_SET(proc->p_textvp->v_label,
+ (intptr_t)GBL_EMPTY);
+ }
+ return 0;
+}
+
+static int
+mac_grantbylabel_syscall(struct thread *td, int call, void *arg)
+{
+ cap_rights_t rights;
+ struct mac_grantbylabel_fetch_gbl_args *gbl_args;
+ gbl_label_t gbl;
+ struct vattr va;
+ struct file *fp;
+ struct proc *proc;
+ const char *label;
+ int error;
+
+ error = EOPNOTSUPP;
+ switch (call) {
+ case MAC_GRANTBYLABEL_FETCH_GBL:
+ gbl_args = arg;
+ gbl = 0;
+ error = getvnode(td, (uintptr_t) gbl_args->u.fd,
+ cap_rights_init(&rights), &fp);
+ if (error)
+ return (error);
+
+ if (fp->f_type != DTYPE_VNODE) {
+ error = EINVAL;
+ goto cleanup_file;
+ }
+
+ vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
+ error = VOP_GETATTR(fp->f_vnode, &va, td->td_ucred);
+ if (!error) {
+ label = mac_veriexec_metadata_get_file_label(va.va_fsid,
+ va.va_fileid, va.va_gen, FALSE);
+ if (label) {
+ gbl = gbl_parse_label(label);
+ } else {
+ error = EOPNOTSUPP;
+ }
+ }
+ VOP_UNLOCK(fp->f_vnode);
+cleanup_file:
+ fdrop(fp, td);
+ break;
+ case MAC_GRANTBYLABEL_FETCH_PID_GBL:
+ gbl_args = arg;
+ gbl = 0;
+
+ /* right now we only support curproc */
+ if (gbl_args->u.pid == 0
+ || gbl_args->u.pid == curproc->p_pid) {
+ proc = curproc;
+ error = 0;
+ } else {
+ return (EINVAL);
+ }
+ gbl = SLOT(proc->p_textvp->v_label);
+ break;
+ }
+ if (error == 0) {
+ error = copyout(&gbl, &gbl_args->gbl,
+ sizeof(gbl_label_t));
+ }
+ return error;
+}
+
+static struct mac_policy_ops mac_grantbylabel_ops =
+{
+ .mpo_proc_check_resource = mac_grantbylabel_proc_check_resource,
+ .mpo_priv_grant = mac_grantbylabel_priv_grant,
+ .mpo_syscall = mac_grantbylabel_syscall,
+};
+
+#ifdef MAC_GRANTBYLABEL_DEBUG
+# define MAC_GRANTBYLABEL_MPC_FLAGS MPC_LOADTIME_FLAG_UNLOADOK
+#else
+# define MAC_GRANTBYLABEL_MPC_FLAGS MPC_LOADTIME_FLAG_NOTLATE
+#endif
+
+MAC_POLICY_SET(&mac_grantbylabel_ops, mac_grantbylabel, MAC_GRANTBYLABEL_FULLNAME,
+ MAC_GRANTBYLABEL_MPC_FLAGS, &mac_grantbylabel_slot);
+MODULE_VERSION(mac_grantbylabel, 1);
+MODULE_DEPEND(mac_grantbylabel, mac_veriexec, 1, 1, 1);
Index: sys/security/mac_veriexec/mac_veriexec.h
===================================================================
--- sys/security/mac_veriexec/mac_veriexec.h
+++ sys/security/mac_veriexec/mac_veriexec.h
@@ -157,6 +157,8 @@
int override);
int mac_veriexec_metadata_has_file(dev_t fsid, long fileid,
unsigned long gen);
+const char * mac_veriexec_metadata_get_file_label(dev_t fsid, long fileid,
+ unsigned long gen, int check_files);
int mac_veriexec_proc_is_trusted(struct ucred *cred, struct proc *p);
#endif
Index: sys/security/mac_veriexec/mac_veriexec.c
===================================================================
--- sys/security/mac_veriexec/mac_veriexec.c
+++ sys/security/mac_veriexec/mac_veriexec.c
@@ -52,6 +52,7 @@
#include <sys/vnode.h>
#include <fs/nullfs/null.h>
#include <security/mac/mac_policy.h>
+#include <security/mac/mac_framework.h>
#include "mac_veriexec.h"
#include "mac_veriexec_internal.h"
@@ -529,6 +530,10 @@
return (error);
break;
default:
+ if (mac_priv_grant(cred, PRIV_VERIEXEC_NOVERIFY) == 0) {
+
+ return (0);
+ }
/*
* Caller wants open to fail unless there is a valid
* fingerprint registered.
Index: sys/security/mac_veriexec/veriexec_fingerprint.c
===================================================================
--- sys/security/mac_veriexec/veriexec_fingerprint.c
+++ sys/security/mac_veriexec/veriexec_fingerprint.c
@@ -46,6 +46,7 @@
#include <sys/sbuf.h>
#include <sys/syslog.h>
#include <sys/vnode.h>
+#include <sys/priv.h>
#include "mac_veriexec.h"
#include "mac_veriexec_internal.h"
@@ -215,7 +216,7 @@
int error;
/* reject fingerprint if writers are active */
- if (vp->v_writecount > 0)
+ if (vp->v_writecount)
return (ETXTBSY);
if ((vp->v_mount->mnt_flag & MNT_VERIFIED) != 0) {
Index: sys/security/mac_veriexec/veriexec_metadata.c
===================================================================
--- sys/security/mac_veriexec/veriexec_metadata.c
+++ sys/security/mac_veriexec/veriexec_metadata.c
@@ -138,8 +138,6 @@
break;
/* we need to garbage collect */
LIST_REMOVE(ip, entries);
- if (ip->label)
- free(ip->label, M_VERIEXEC);
free(ip, M_VERIEXEC);
}
}
@@ -584,6 +582,30 @@
}
/**
+ * Return label if we have one
+ *
+ * @param fsid file system identifier to look for
+ * @param fileid file to look for
+ * @param gen generation of file
+ * @param check_files look at non-executable files?
+ *
+ * @return A pointer to the label or @c NULL
+ */
+const char *
+mac_veriexec_metadata_get_file_label(dev_t fsid, long fileid,
+ unsigned long gen, int check_files)
+{
+ struct mac_veriexec_file_info *ip;
+
+ ip = mac_veriexec_metadata_get_file_info(fsid, fileid, gen,
+ NULL, check_files);
+ if (ip && (ip->flags & VERIEXEC_LABEL)) {
+ return ip->label;
+ }
+ return NULL;
+}
+
+/**
* Add a file and its fingerprint to the list of files attached
* to the device @p fsid.
*
Index: sys/sys/priv.h
===================================================================
--- sys/sys/priv.h
+++ sys/sys/priv.h
@@ -512,9 +512,16 @@
#define PRIV_KMEM_WRITE 681 /* Open mem/kmem for writing. */
/*
+ * veriexec override privileges - very rare!
+ */
+#define PRIV_VERIEXEC_DIRECT 700 /* Can override 'indirect' */
+#define PRIV_VERIEXEC_NOVERIFY 701 /* Can override O_VERIFY */
+
+
+/*
* Track end of privilege list.
*/
-#define _PRIV_HIGHEST 682
+#define _PRIV_HIGHEST 702
/*
* Validate that a named privilege is known by the privilege system. Invalid
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Sep 13, 9:24 AM (4 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38846357
Default Alt Text
D27364.id79963.diff (28 KB)
Attached To
Mode
D27364: mac_grantbylabel focused priv escallation via maclabel
Attached
Detach File
Event Timeline
Log In to Comment