Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Feb 2019 06:17:24 +0000 (UTC)
From:      "Simon J. Gerraty" <sjg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r344567 - in head: etc/mtree include sbin sbin/veriexec
Message-ID:  <201902260617.x1Q6HOra098699@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: sjg
Date: Tue Feb 26 06:17:23 2019
New Revision: 344567
URL: https://svnweb.freebsd.org/changeset/base/344567

Log:
  Add verifying manifest loader for mac_veriexec
  
  This tool will verify a signed manifest and load contents into
  mac_veriexec for storage
  
  Sponsored by:	Juniper Networks
  Differential Revision:	D16575

Added:
  head/sbin/veriexec/
  head/sbin/veriexec/Makefile   (contents, props changed)
  head/sbin/veriexec/Makefile.depend   (contents, props changed)
  head/sbin/veriexec/manifest_lexer.l   (contents, props changed)
  head/sbin/veriexec/manifest_parser.y   (contents, props changed)
  head/sbin/veriexec/veriexec.8   (contents, props changed)
  head/sbin/veriexec/veriexec.c   (contents, props changed)
  head/sbin/veriexec/veriexec.h   (contents, props changed)
Modified:
  head/etc/mtree/BSD.include.dist
  head/include/Makefile
  head/sbin/Makefile

Modified: head/etc/mtree/BSD.include.dist
==============================================================================
--- head/etc/mtree/BSD.include.dist	Tue Feb 26 06:11:01 2019	(r344566)
+++ head/etc/mtree/BSD.include.dist	Tue Feb 26 06:17:23 2019	(r344567)
@@ -160,6 +160,8 @@
         ..
         usb
         ..
+        veriexec
+        ..
         vkbd
         ..
         wi
@@ -353,6 +355,8 @@
         mac_mls
         ..
         mac_partition
+        ..
+        mac_veriexec
         ..
     ..
     ssp

Modified: head/include/Makefile
==============================================================================
--- head/include/Makefile	Tue Feb 26 06:11:01 2019	(r344566)
+++ head/include/Makefile	Tue Feb 26 06:17:23 2019	(r344567)
@@ -47,7 +47,7 @@ LSUBDIRS=	cam/ata cam/mmc cam/nvme cam/scsi \
 	dev/hwpmc dev/hyperv \
 	dev/ic dev/iicbus dev/io dev/mfi dev/mmc dev/nvme \
 	dev/ofw dev/pbio dev/pci ${_dev_powermac_nvram} dev/ppbus dev/smbus \
-	dev/speaker dev/tcp_log dev/vkbd dev/wi \
+	dev/speaker dev/tcp_log dev/veriexec dev/vkbd dev/wi \
 	fs/devfs fs/fdescfs fs/msdosfs fs/nandfs fs/nfs fs/nullfs \
 	fs/procfs fs/smbfs fs/udf fs/unionfs \
 	geom/cache geom/concat geom/eli geom/gate geom/journal geom/label \
@@ -60,6 +60,7 @@ LSUBDIRS=	cam/ata cam/mmc cam/nvme cam/scsi \
 	security/audit \
 	security/mac_biba security/mac_bsdextended security/mac_lomac \
 	security/mac_mls security/mac_partition \
+	security/mac_veriexec \
 	sys/disk \
 	ufs/ffs ufs/ufs
 
@@ -157,7 +158,7 @@ copies: .PHONY .META
 		done; \
 	fi
 .endfor
-.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci} ${LSUBSUBDIRS}
+.for i in ${LDIRS} ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec} ${LSUBSUBDIRS}
 	cd ${SRCTOP}/sys; \
 	${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 $i/*.h \
 	    ${SDESTDIR}${INCLUDEDIR}/$i
@@ -196,6 +197,9 @@ copies: .PHONY .META
 	cd ${SRCTOP}/sys/dev/pci; \
 	${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 pcireg.h \
 	    ${SDESTDIR}${INCLUDEDIR}/dev/pci
+	cd ${SRCTOP}/sys/dev/veriexec; \
+	${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 veriexec_ioctl.h \
+	    ${SDESTDIR}${INCLUDEDIR}/dev/veriexec
 	cd ${SRCTOP}/sys/fs/cd9660/; \
 	${INSTALL} -C ${TAG_ARGS} -o ${BINOWN} -g ${BINGRP} -m 444 *.h \
 	    ${SDESTDIR}${INCLUDEDIR}/isofs/cd9660
@@ -264,7 +268,7 @@ symlinks: .PHONY .META
 		${INSTALL_SYMLINK} ${TAG_ARGS} ../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \
 	done
 .endfor
-.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci}
+.for i in ${LSUBDIRS:Ndev/agp:Ndev/acpica:Ndev/bktr:Ndev/evdev:Ndev/hyperv:Ndev/nand:Ndev/pci:Ndev/veriexec}
 	cd ${SRCTOP}/sys/$i; \
 	for h in *.h; do \
 		${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/$i/$$h ${SDESTDIR}${INCLUDEDIR}/$i; \
@@ -311,6 +315,11 @@ symlinks: .PHONY .META
 	for h in pcireg.h; do \
 		${INSTALL_SYMLINK} ${TAG_ARGS} ../../../../sys/dev/pci/$$h \
 		    ${SDESTDIR}${INCLUDEDIR}/dev/pci; \
+	done
+	cd ${SRCTOP}/sys/dev/veriexec; \
+	for h in veriexec_ioctl.h; do \
+		ln -fs ../../../../sys/dev/veriexec/$$h \
+		    ${SDESTDIR}${INCLUDEDIR}/dev/veriexec; \
 	done
 .for i in ${LSUBSUBDIRS}
 	cd ${SRCTOP}/sys/$i; \

Modified: head/sbin/Makefile
==============================================================================
--- head/sbin/Makefile	Tue Feb 26 06:11:01 2019	(r344566)
+++ head/sbin/Makefile	Tue Feb 26 06:17:23 2019	(r344567)
@@ -87,6 +87,7 @@ SUBDIR.${MK_PF}+=	pfctl
 SUBDIR.${MK_PF}+=	pflogd
 SUBDIR.${MK_QUOTAS}+=	quotacheck
 SUBDIR.${MK_ROUTED}+=	routed
+SUBDIR.${MK_VERIEXEC}+=	veriexec
 SUBDIR.${MK_ZFS}+=	bectl
 SUBDIR.${MK_ZFS}+=	zfsbootcfg
 

Added: head/sbin/veriexec/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexec/Makefile	Tue Feb 26 06:17:23 2019	(r344567)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+PROG=	veriexec
+MAN=	veriexec.8
+SRCS= \
+	veriexec.c \
+	manifest_parser.y \
+	manifest_lexer.l
+
+LIBADD+= veriexec secureboot bearssl
+
+NO_SHARED=
+
+.include <bsd.prog.mk>
+
+CFLAGS+= -I${.CURDIR} ${XCFLAGS.${.TARGET:T:R}:U}
+
+XCFLAGS.manifest_lexer+= -Wno-missing-variable-declarations \
+	-Wno-unneeded-internal-declaration
+XCFLAGS.manifest_parser+= -Wno-missing-variable-declarations

Added: head/sbin/veriexec/Makefile.depend
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexec/Makefile.depend	Tue Feb 26 06:17:23 2019	(r344567)
@@ -0,0 +1,20 @@
+# $FreeBSD$
+# Autogenerated - do NOT edit!
+
+DIRDEPS = \
+	gnu/lib/csu \
+	include \
+	include/xlocale \
+	lib/${CSU_DIR} \
+	lib/libbearssl \
+	lib/libc \
+	lib/libcompiler_rt \
+	lib/libsecureboot \
+	lib/libveriexec \
+
+
+.include <dirdeps.mk>
+
+.if ${DEP_RELDIR} == ${_DEP_RELDIR}
+# local dependencies - needed for -jN in clean tree
+.endif

Added: head/sbin/veriexec/manifest_lexer.l
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexec/manifest_lexer.l	Tue Feb 26 06:17:23 2019	(r344567)
@@ -0,0 +1,151 @@
+%{
+/*-
+ * Copyright (c) 2004-2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "veriexec.h"
+#include "manifest_parser.h"
+
+#define YY_NO_UNPUT
+
+int lineno = 1;
+int bol = 1;
+extern int parser_version;
+ 
+void yyerror(const char *message);
+void warning(const char *message);
+int yylex(void);
+
+%}
+
+%%
+
+\n {
+	lineno++;
+	bol=1;
+	return EOL;
+}
+
+[/a-zA-Z0-9\.][^ \t\n=]*  {
+	yylval.string = strdup(yytext);
+	if (bol) {
+		bol=0;
+		return PATH;
+	} else
+		return STRING;
+}
+
+= {
+	return EQ;
+}
+
+
+[ \t\r] ;  /* eat white ones */
+
+#>[0-9]+ {
+        /*
+         * If we are older than the specified version
+         * ignore rest of line, otherwise just discard this token.
+         */
+        int skip = atoi(&yytext[2]);
+
+        VERBOSE(3, ("%s: skip if %d <= %d\n", yytext, parser_version, skip));
+        if (parser_version <= skip) {
+		/* treat as a comment, yyless() is cheaper than yyunput() */
+		yytext[yyleng - 1] = '#';
+		yyless(2);
+        }
+}
+
+#[^>\n].* ;      /* comment */
+
+.    yyerror("invalid character");
+
+%%
+
+static char *manifest_file = NULL;
+
+struct string_buf {
+	const char *buf;
+	size_t pos, size;
+};
+
+static int
+read_string_buf (void *token, char *dest, int count)
+{
+	struct string_buf *str_buf_p = (struct string_buf *)token;
+	ssize_t n;
+
+	if (count < 0)
+		return 0;
+
+	n = str_buf_p->size - str_buf_p->pos;
+	if (count < n)
+		n = count;
+
+	memcpy(dest, str_buf_p->buf + str_buf_p->pos, n);
+	str_buf_p->pos += n;
+
+	return n;
+}
+
+FILE *
+manifest_open (const char *file, const char *file_content)
+{
+	static struct string_buf str_buf;
+    
+	if (manifest_file) {
+		free(manifest_file);
+		fclose(yyin);
+	}
+
+	str_buf.buf  = file_content;
+	str_buf.pos  = 0;
+	str_buf.size = strlen(file_content);
+	yyin = fropen(&str_buf, read_string_buf);
+	if (yyin) {
+		manifest_file = strdup(file);
+		lineno = 1;
+		manifest_parser_init();
+	} else
+		manifest_file = NULL;
+	return yyin;
+}
+
+void
+yyerror(const char *string)
+{
+	fprintf(stderr, "%s: %d: %s at %s\n",
+	    manifest_file, lineno, string, yytext);
+}
+
+int
+yywrap(void)
+{
+	return (1);
+}

Added: head/sbin/veriexec/manifest_parser.y
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexec/manifest_parser.y	Tue Feb 26 06:17:23 2019	(r344567)
@@ -0,0 +1,301 @@
+%{
+/*-
+ * Copyright (c) 2004-2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <err.h>
+#include <sysexits.h>
+#include <libsecureboot.h>
+
+#include "veriexec.h"
+
+int yylex(void);
+void yyerror(const char *);
+
+/* function prototypes */
+static int convert(char *fp, unsigned int count, unsigned char *out);
+static void do_ioctl(void);
+static int get_fingerprint_type(const char *fp_type);
+
+/* ioctl parameter struct */
+#ifdef MAXLABELLEN
+static struct verified_exec_label_params lparams;
+static struct verified_exec_params *params = &lparams.params;
+#else
+static struct verified_exec_params oparams;
+static struct verified_exec_params *params = &oparams;
+#endif
+
+#ifndef SHA256_DIGEST_LENGTH
+# define SHA_DIGEST_LENGTH br_sha1_SIZE
+# define SHA256_DIGEST_LENGTH br_sha256_SIZE
+# define SHA384_DIGEST_LENGTH br_sha384_SIZE
+#endif
+
+static int fmode;
+ 
+extern int lineno;
+extern int dev_fd;
+
+struct fingerprint_type {
+	const char *fp_type;
+	int fp_size;
+};
+
+/* static globals */
+static const struct fingerprint_type fingerprint_table[] = {
+	{ "sha1", SHA_DIGEST_LENGTH },
+	{ "sha256", SHA256_DIGEST_LENGTH },
+#if MAXFINGERPRINTLEN > 32
+	{ "sha384", SHA384_DIGEST_LENGTH },
+#endif
+	{ NULL, 0 }
+};
+
+/*
+ * Indicate to lexer our version.
+ * A token #>NUMBER will be consumed (and discared)
+ * by lexer if parser_version > NUMBER
+ * Otherwise the rest of the line will be discared
+ * as for a comment.
+ */
+int parser_version = 1;
+ 
+%}
+
+%union {
+	char *string;
+	int  intval;
+}
+
+%token EOL
+%token <string> EQ
+%token <string> PATH
+%token <string> STRING
+
+%%
+
+statement: /* empty */
+	| statement path attributes eol
+	| statement error eol {
+		yyclearin; /* discard lookahead */
+		yyerrok;   /* no more error */
+		fprintf(stderr,
+		    "skipping to next fingerprint\n");
+	}
+	;
+
+attributes: /* empty */
+	| attributes flag
+	| attributes attr
+	;
+
+attr: STRING EQ STRING
+{
+	int fptype;
+
+	fptype = get_fingerprint_type($1);
+
+	/*
+	 * There's only one attribute we care about
+	 */
+	if (fingerprint_table[fptype].fp_size) {
+		strlcpy(params->fp_type, $1, sizeof(params->fp_type));
+		if (convert($3, fingerprint_table[fptype].fp_size,
+			params->fingerprint) < 0) {
+			yyerror("bad fingerprint");
+			YYERROR;
+		}
+	} else if (strcmp($1, "label") == 0) {
+		static int warned_labels = 0;
+
+#ifdef VERIEXEC_LABEL
+		strlcpy(lparams.label, $3, sizeof(lparams.label));
+		VERBOSE(3, ("version=%d label=%s\n", VeriexecVersion,
+			lparams.label));
+		if (VeriexecVersion > 1) {
+			params->flags |= VERIEXEC_LABEL;
+		} else
+#endif
+		if (!warned_labels) {
+			warnx("ignoring labels");
+			warned_labels = 1;
+		}
+	} else if (strcmp($1, "mode") == 0) {
+		fmode = (int)strtol($3, NULL, 8);
+	}
+};
+
+flag: STRING
+{
+	/*
+	 * indirect only matters if the interpreter itself is not
+	 * executable.
+	 */
+	if (!strcmp($1, "indirect")) {
+		params->flags |= VERIEXEC_INDIRECT;
+	} else if (!strcmp($1, "no_ptrace")) {
+		params->flags |= VERIEXEC_NOTRACE;
+	} else if (!strcmp($1, "trusted")) {
+		params->flags |= VERIEXEC_TRUSTED;
+	} else if (!strcmp($1, "no_fips")) {
+#ifdef VERIEXEC_NOFIPS
+		params->flags |= VERIEXEC_NOFIPS;
+#endif
+	}
+}
+;
+
+path: PATH 
+{
+	if (strlen($1) >= MAXPATHLEN) {
+		yyerror("Path >= MAXPATHLEN");
+		YYERROR;
+	}
+	/*
+	 * The majority of files in the manifest are relative
+	 * to the package mount point, but we want absolute paths.
+	 * Prepending '/' is actually all we need.
+	 */
+	if (snprintf(params->file, sizeof(params->file), "%s%s%s",
+		Cdir ? Cdir : "",
+		($1[0] == '/') ? "" : "/",
+		$1) >= (int)sizeof(params->file)) {
+		errx(EX_DATAERR, "cannot form pathname");
+	}
+	params->flags = 0;
+	fmode = -1;			/* unknown */
+};
+
+eol: EOL
+{
+	if (!YYRECOVERING()) { /* Don't do the ioctl if we saw an error */
+		do_ioctl();
+	}
+	params->fp_type[0] = '\0';	/* invalidate it */
+};
+
+%%
+
+void
+manifest_parser_init(void)
+{
+	params->fp_type[0] = '\0';      /* invalidate it */
+}
+
+int
+get_fingerprint_type(const char *fp_type)
+{
+	int i;
+
+	for (i = 0; fingerprint_table[i].fp_type; i++)
+		if (!strcmp(fp_type, fingerprint_table[i].fp_type))
+			break;
+
+	return (i);
+}
+
+/*
+ * Convert: takes the hexadecimal string pointed to by fp and converts
+ * it to a "count" byte binary number which is stored in the array pointed to
+ * by out.  Returns -1 if the conversion fails.
+ */
+static int
+convert(char *fp, unsigned int count, unsigned char *out)
+{
+        unsigned int i;
+        int value;
+        
+        for (i = 0; i < count; i++) {
+		value = 0;
+		if (isdigit(fp[i * 2]))
+			value += fp[i * 2] - '0';
+		else if (isxdigit(fp[i * 2]))
+			value += 10 + tolower(fp[i * 2]) - 'a';
+		else
+			return (-1);
+		value <<= 4;
+		if (isdigit(fp[i * 2 + 1]))
+			value += fp[i * 2 + 1] - '0';
+		else if (isxdigit(fp[i * 2 + 1]))
+			value += 10 + tolower(fp[i * 2 + 1]) - 'a';
+		else
+			return (-1);
+		out[i] = value;
+	}
+
+	return (i);
+}
+
+/*
+ * Perform the load of the fingerprint.  Assumes that the fingerprint
+ * pseudo-device is opened and the file handle is in fd.
+ */
+static void
+do_ioctl(void)
+{
+	struct stat st;
+
+	if (params->fp_type[0] == '\0') {
+		VERBOSE(1,("skipping %s\n", params->file));
+		return;
+	}
+
+	/*
+	 * See if the path is executable, if not put it on the FILE list.
+	 */
+	if (fmode > 0) {
+		if (!(fmode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+			params->flags |= VERIEXEC_FILE;
+		}
+	} else if (stat(params->file, &st) == 0) {
+		if (!(st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))) {
+			params->flags |= VERIEXEC_FILE;
+		}
+	}
+	/*
+	 * We may be forcing some flags...
+	 */
+	params->flags |= ForceFlags;
+	VERBOSE(1, ("loading %s for %s %s flags=%#x\n",
+		params->fp_type,
+		(params->flags == VERIEXEC_FILE) ? "file" : "executable",
+		params->file, params->flags));
+
+#ifdef VERIEXEC_LABEL
+	if (params->flags & VERIEXEC_LABEL) {
+		if (ioctl(dev_fd, VERIEXEC_LABEL_LOAD, &lparams) < 0)
+			warn("cannot update veriexec label for %s",
+			    params->file);
+	} else
+#endif
+	if (ioctl(dev_fd, VERIEXEC_SIGNED_LOAD, params) < 0)
+		warn("cannot update veriexec for %s", params->file);
+	params->fp_type[0] = '\0';
+}

Added: head/sbin/veriexec/veriexec.8
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexec/veriexec.8	Tue Feb 26 06:17:23 2019	(r344567)
@@ -0,0 +1,146 @@
+.\"-
+.\" Copyright (c) 2018, Juniper Networks, Inc.
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+.\" "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 COPYRIGHT
+.\" OWNER OR CONTRIBUTORS 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 4, 2018
+.Dt VERIEXEC 8
+.Os
+.Sh NAME
+.Nm veriexec
+.Nd manipulate state of mac_veriexec
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Op Fl C Ar directory
+.Pa manifest
+.Nm
+.Fl z Ar state
+.Nm
+.Fl i Ar state
+.Nm
+.Fl x
+.Ar file ...
+.Sh DESCRIPTION
+.Nm
+is a utility to query or manipulate the state of
+.Xr mac_veriexec 4 .
+.Pp
+The first form is for loading a
+.Pa manifest .
+.Nm
+first verifies a digital signature of the
+.Ar manifest
+and if successful, parses it and feeds its content to kernel.
+.Pp
+The second form with
+.Fl z
+is used to modify the
+.Ar state ,
+and with
+.Fl i
+to query the current
+.Ar state .
+.Pp
+The final form with
+.Fl x
+is used to test whether
+.Ar file
+is verified or not.
+This requires
+.Xr mac_veriexec 4
+to be in the
+.Ql active
+or
+.Ql enforce
+state.
+.Pp
+The possible states
+are:
+.Bl -tag -width enforce
+.It Ar loaded
+set automatically when first
+.Pa manifest
+has been loaded.
+.It Ar active
+.Xr mac_veriexec 4
+will begin checking files.
+This state can only be entered from the
+.Ar loaded
+state.
+.It Ar enforce
+.Xr mac_veriexec 4
+will fail attempts to
+.Xr exec 2
+or
+.Xr open 2
+files with
+.Dv O_VERIFY
+unless verified.
+.It Ar locked
+prevent loading of any more manifests.
+.El
+.Sh MANIFESTS
+The manifest contains a mapping of relative pathnames to fingerprints
+with optional flags.
+For example:
+.Bd -literal -offset indent
+sbin/veriexec sha256=f22136...c0ff71 no_ptrace
+usr/bin/python sha256=5944d9...876525 indirect
+sbin/somedaemon sha256=77fc2f...63f5687 label=mod1/val1,mod2/val2
+.Ed
+The supported flags are:
+.Bl -tag -width indirect
+.It Ql indirect
+the executable cannot be run directly,
+but can be used as an interpreter for example via:
+.Bd -literal -offset indent
+#!/usr/bin/python
+.Ed
+.It Ql no_ptrace
+do not allow running executable under a debugger.
+Useful for any application critical to the security state of system.
+.El
+.Pp
+The
+.Ql label
+argument allows associating a
+.Xr maclabel 7
+with the executable.
+Neither
+.Nm
+nor
+.Xr mac_veriexec 4
+(if it supports labels)
+pay any attention to the content of the label
+they are provided for the use of other
+.Xr mac 4
+modules.
+.Sh HISTORY
+The Verified Exec system first appeared in NetBSD.
+This utility derrives from the one found in Junos.
+The key difference is the requirement that manifest files
+be digitally signed.
+
+

Added: head/sbin/veriexec/veriexec.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexec/veriexec.c	Tue Feb 26 06:17:23 2019	(r344567)
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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 <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <paths.h>
+#include <err.h>
+#include <syslog.h>
+#include <libsecureboot.h>
+#include <libveriexec.h>
+
+#include "veriexec.h"
+
+int dev_fd = -1;
+int ForceFlags = 0;
+int Verbose = 0;
+int VeriexecVersion = 0;
+
+const char *Cdir = NULL;
+
+static int
+veriexec_load(const char *manifest)
+{
+	unsigned char *content;
+	int rc;
+
+	content = verify_signed(manifest, VEF_VERBOSE);
+	if (!content)
+		errx(EX_USAGE, "cannot verify %s", manifest);
+	if (manifest_open(manifest, content)) {
+		rc = yyparse();
+	} else {
+		err(EX_NOINPUT, "cannot load %s", manifest);
+	}
+	free(content);
+	return (rc);
+}
+
+int
+main(int argc, char *argv[])
+{
+	unsigned long ctl;
+	int c;
+	int x;
+
+	dev_fd = open(_PATH_DEV_VERIEXEC, O_WRONLY, 0);
+
+	while ((c = getopt(argc, argv, "C:i:x:vz:")) != -1) {
+		switch (c) {
+		case 'C':
+			Cdir = optarg;
+			break;
+		case 'i':
+			if (dev_fd < 0) {
+				err(EX_UNAVAILABLE, "cannot open veriexec");
+			}
+			if (ioctl(dev_fd, VERIEXEC_GETSTATE, &x)) {
+				err(EX_UNAVAILABLE,
+				    "Cannot get veriexec state");
+			}
+			switch (optarg[0]) {
+			case 'a':	/* active */
+				ctl = VERIEXEC_STATE_ACTIVE;
+				break;
+			case 'e':	/* enforce */
+				ctl = VERIEXEC_STATE_ENFORCE;
+				break;
+			case 'l':	/* loaded/locked */
+				ctl = (strncmp(optarg, "lock", 4)) ?
+				    VERIEXEC_STATE_LOCKED :
+				    VERIEXEC_STATE_LOADED;
+				break;
+			default:
+				errx(EX_USAGE, "unknown state %s", optarg);
+				break;
+			}
+			exit((x & ctl) == 0);
+			break;
+		case 'v':
+			Verbose++;
+			break;
+		case 'x':
+			/*
+			 * -x says all other args are paths to check.
+			 */
+			for (x = 0; optind < argc; optind++) {
+				if (veriexec_check_path(argv[optind])) {
+					warn("%s", argv[optind]);
+					x = 2;
+				}
+			}
+			exit(x);
+			break;
+		case 'z':
+			switch (optarg[0]) {
+			case 'a':	/* active */
+				ctl = VERIEXEC_ACTIVE;
+				break;
+			case 'd':	/* debug* */
+				ctl = (strstr(optarg, "off")) ?
+				    VERIEXEC_DEBUG_OFF : VERIEXEC_DEBUG_ON;
+				if (optind < argc && ctl == VERIEXEC_DEBUG_ON) {
+					x = atoi(argv[optind]);
+					if (x == 0)
+						ctl = VERIEXEC_DEBUG_OFF;
+				}
+				break;
+			case 'e':	/* enforce */
+				ctl = VERIEXEC_ENFORCE;
+				break;
+			case 'g':
+				ctl = VERIEXEC_GETSTATE; /* get state */
+				break;
+			case 'l':	/* lock */
+				ctl = VERIEXEC_LOCK;
+				break;
+			default:
+				errx(EX_USAGE, "unknown command %s", optarg);
+				break;
+			}
+			if (dev_fd < 0) {
+				err(EX_UNAVAILABLE, "cannot open veriexec");
+			}
+			if (ioctl(dev_fd, ctl, &x)) {
+				err(EX_UNAVAILABLE, "cannot %s veriexec", optarg);
+			}
+			if (ctl == VERIEXEC_DEBUG_ON ||
+			    ctl == VERIEXEC_DEBUG_OFF) {
+				printf("debug is: %d\n", x);
+			} else if (ctl == VERIEXEC_GETSTATE) {
+				printf("%#o\n", x);
+			}
+			exit(EX_OK);
+			break;
+		}
+	}
+	openlog(getprogname(), LOG_PID, LOG_AUTH);
+	if (ve_trust_init() < 1)
+		errx(EX_OSFILE, "cannot initialize trust store");
+#ifdef VERIEXEC_GETVERSION
+	if (ioctl(dev_fd, VERIEXEC_GETVERSION, &VeriexecVersion)) {
+		VeriexecVersion = 0;	/* unknown */
+	}
+#endif
+
+	for (; optind < argc; optind++) {
+		if (veriexec_load(argv[optind])) {
+			err(EX_DATAERR, "cannot load %s", argv[optind]);
+		}
+	}
+	exit(EX_OK);
+}

Added: head/sbin/veriexec/veriexec.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sbin/veriexec/veriexec.h	Tue Feb 26 06:17:23 2019	(r344567)
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2018, Juniper Networks, Inc.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 COPYRIGHT
+ * OWNER OR CONTRIBUTORS 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __VERIEXEC_H__
+#define __VERIEXEC_H__
+
+#include <sys/ioctl.h>
+#include <dev/veriexec/veriexec_ioctl.h>
+
+extern int dev_fd;
+extern int parser_version;
+extern int ForceFlags;
+extern int Verbose;
+extern int VeriexecVersion;
+extern const char *Cdir;
+
+#define VERBOSE(n, x) if (Verbose > n) printf x
+
+FILE * manifest_open (const char *file, const char *file_content);
+void manifest_parser_init(void);
+int yyparse(void);
+extern FILE *yyin;
+
+#endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201902260617.x1Q6HOra098699>