Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 May 2019 19:27:07 +0000 (UTC)
From:      "Stephen J. Kiernan" <stevek@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r347942 - in head/sys: dev/veriexec security/mac_veriexec
Message-ID:  <201905171927.x4HJR76V033628@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: stevek
Date: Fri May 17 19:27:07 2019
New Revision: 347942
URL: https://svnweb.freebsd.org/changeset/base/347942

Log:
  Add a new ioctl for the larger params struct that includes the label.
  
  We need to make the find_veriexec_file() function available publicly, so
  rename it to mac_veriexec_metadata_find_file_info() and make it non-static.
  
  Bump the version of the veriexec device interface so user space will know
  the labelized version of fingerprint loading is available.
  
  Approved by:	sjg
  Obtained from:	Juniper Networks, Inc.
  Differential Revision:	https://reviews.freebsd.org/D20295

Modified:
  head/sys/dev/veriexec/veriexec_ioctl.h
  head/sys/dev/veriexec/verified_exec.c
  head/sys/security/mac_veriexec/mac_veriexec.h
  head/sys/security/mac_veriexec/mac_veriexec_internal.h
  head/sys/security/mac_veriexec/veriexec_metadata.c

Modified: head/sys/dev/veriexec/veriexec_ioctl.h
==============================================================================
--- head/sys/dev/veriexec/veriexec_ioctl.h	Fri May 17 18:25:53 2019	(r347941)
+++ head/sys/dev/veriexec/veriexec_ioctl.h	Fri May 17 19:27:07 2019	(r347942)
@@ -46,6 +46,11 @@ struct verified_exec_params  {
 	unsigned char fingerprint[MAXFINGERPRINTLEN];
 };
 
+struct verified_exec_label_params  {
+	struct verified_exec_params params;
+	char label[MAXLABELLEN];
+};
+
 #define VERIEXEC_LOAD		_IOW('S', 0x1, struct verified_exec_params)
 #define VERIEXEC_ACTIVE		_IO('S', 0x2)	/* start checking */
 #define VERIEXEC_ENFORCE 	_IO('S', 0x3)	/* fail exec */
@@ -55,6 +60,7 @@ struct verified_exec_params  {
 #define VERIEXEC_GETSTATE 	_IOR('S', 0x7, int) /* get state */
 #define VERIEXEC_SIGNED_LOAD	_IOW('S', 0x8, struct verified_exec_params)
 #define VERIEXEC_GETVERSION	_IOR('S', 0x9, int) /* get version */
+#define VERIEXEC_LABEL_LOAD	_IOW('S', 0xa, struct verified_exec_label_params)
 
 #define	_PATH_DEV_VERIEXEC	_PATH_DEV "veriexec"
 

Modified: head/sys/dev/veriexec/verified_exec.c
==============================================================================
--- head/sys/dev/veriexec/verified_exec.c	Fri May 17 18:25:53 2019	(r347941)
+++ head/sys/dev/veriexec/verified_exec.c	Fri May 17 19:27:07 2019	(r347942)
@@ -68,6 +68,7 @@ verifiedexecioctl(struct cdev *dev __unused, u_long cm
 {
 	struct nameidata nid;
 	struct vattr vattr;
+	struct verified_exec_label_params *lparams;
 	struct verified_exec_params *params;
 	int error = 0;
 
@@ -102,7 +103,12 @@ verifiedexecioctl(struct cdev *dev __unused, u_long cm
 	if (error)
 		return (error);
 
-	params = (struct verified_exec_params *)data;
+	lparams = (struct verified_exec_label_params *)data;
+	if (cmd == VERIEXEC_LABEL_LOAD)
+		params = &lparams->params;
+	else
+		params = (struct verified_exec_params *)data;
+
 	switch (cmd) {
 	case VERIEXEC_ACTIVE:
 		mtx_lock(&ve_mutex);
@@ -158,6 +164,7 @@ verifiedexecioctl(struct cdev *dev __unused, u_long cm
 			return (EPERM);	/* no updates when secure */
 
 		/* FALLTHROUGH */
+	case VERIEXEC_LABEL_LOAD:
 	case VERIEXEC_SIGNED_LOAD:
 		/*
 		 * If we use a loader that will only use a
@@ -176,8 +183,9 @@ verifiedexecioctl(struct cdev *dev __unused, u_long cm
 		if (mac_veriexec_in_state(VERIEXEC_STATE_LOCKED))
 			error = EPERM;
 		else {
+			size_t labellen = 0;
 			int flags = FREAD;
-			int override = (cmd == VERIEXEC_SIGNED_LOAD);
+			int override = (cmd != VERIEXEC_LOAD);
 
 			/*
 			 * Get the attributes for the file name passed
@@ -221,13 +229,18 @@ verifiedexecioctl(struct cdev *dev __unused, u_long cm
 			    FINGERPRINT_INVALID);
 			VOP_UNLOCK(nid.ni_vp, 0);
 			(void) vn_close(nid.ni_vp, FREAD, td->td_ucred, td);
+			if (params->flags & VERIEXEC_LABEL)
+				labellen = strnlen(lparams->label,
+				    sizeof(lparams->label) - 1) + 1;
 
 			mtx_lock(&ve_mutex);
 			error = mac_veriexec_metadata_add_file(
 			    ((params->flags & VERIEXEC_FILE) != 0),
 			    vattr.va_fsid, vattr.va_fileid, vattr.va_gen,
-			    params->fingerprint, params->flags,
-			    params->fp_type, override);
+			    params->fingerprint,
+			    (params->flags & VERIEXEC_LABEL) ?
+			    lparams->label : NULL, labellen,
+			    params->flags, params->fp_type, override);
 
 			mac_veriexec_set_state(VERIEXEC_STATE_LOADED);
 			mtx_unlock(&ve_mutex);

Modified: head/sys/security/mac_veriexec/mac_veriexec.h
==============================================================================
--- head/sys/security/mac_veriexec/mac_veriexec.h	Fri May 17 18:25:53 2019	(r347941)
+++ head/sys/security/mac_veriexec/mac_veriexec.h	Fri May 17 19:27:07 2019	(r347942)
@@ -1,7 +1,7 @@
 /*
  * $FreeBSD$
  *
- * Copyright (c) 2011, 2012, 2013, 2015, 2016, Juniper Networks, Inc.
+ * Copyright (c) 2011, 2012, 2013, 2015, 2016, 2019, Juniper Networks, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -49,6 +49,7 @@
  * Enough room for the largest signature...
  */
 #define MAXFINGERPRINTLEN	64	/* enough room for largest signature */
+#define MAXLABELLEN		128
 
 /*
  * Types of veriexec inodes we can have
@@ -57,8 +58,8 @@
 #define VERIEXEC_FILE		(1<<1)  /* Fingerprint of a plain file */
 #define VERIEXEC_NOTRACE	(1<<2)	/**< PTRACE not allowed */
 #define VERIEXEC_TRUSTED	(1<<3)	/**< Safe to write /dev/mem */
-/* XXX these are currently unimplemented */
 #define VERIEXEC_NOFIPS		(1<<4)	/**< Not allowed in FIPS mode */
+#define VERIEXEC_LABEL		(1<<5)	/**< We have a label */
 
 #define VERIEXEC_STATE_INACTIVE	0	/**< Ignore */
 #define VERIEXEC_STATE_LOADED	(1<<0)	/**< Sigs have been loaded */
@@ -71,7 +72,7 @@
 /**
  * Version of the MAC/veriexec module
  */
-#define	MAC_VERIEXEC_VERSION	1
+#define	MAC_VERIEXEC_VERSION	2
 
 /* Valid states for the fingerprint flag - if signed exec is being used */
 typedef enum fingerprint_status {
@@ -152,7 +153,8 @@ int	mac_veriexec_fingerprint_modevent(module_t mod, in
  */
 int	mac_veriexec_metadata_add_file(int file_dev, dev_t fsid, long fileid, 
 	    unsigned long gen, unsigned char fingerprint[MAXFINGERPRINTLEN], 
-	    int flags, const char *fp_type, int override);
+	    char *label, size_t labellen, int flags, const char *fp_type,
+	    int override);
 int	mac_veriexec_metadata_has_file(dev_t fsid, long fileid, 
 	    unsigned long gen);
 int	mac_veriexec_proc_is_trusted(struct ucred *cred, struct proc *p);

Modified: head/sys/security/mac_veriexec/mac_veriexec_internal.h
==============================================================================
--- head/sys/security/mac_veriexec/mac_veriexec_internal.h	Fri May 17 18:25:53 2019	(r347941)
+++ head/sys/security/mac_veriexec/mac_veriexec_internal.h	Fri May 17 19:27:07 2019	(r347942)
@@ -1,7 +1,7 @@
 /*
  * $FreeBSD$
  *
- * Copyright (c) 2011, 2012, 2013, 2015, 2016, Juniper Networks, Inc.
+ * Copyright (c) 2011, 2012, 2013, 2015, 2016, 2019, Juniper Networks, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -54,6 +54,8 @@ struct mac_veriexec_file_info
 	unsigned long gen;
 	struct mac_veriexec_fpops *ops;
 	unsigned char fingerprint[MAXFINGERPRINTLEN];
+	char *label;
+	size_t labellen;
 	LIST_ENTRY(mac_veriexec_file_info) entries;
 };
 
@@ -76,6 +78,9 @@ int	mac_veriexec_metadata_get_executable_flags(struct 
 	    struct proc *p, int *flags, int check_files);
 int	mac_veriexec_metadata_get_file_flags(dev_t fsid, long fileid,
 	    unsigned long gen, int *flags, int check_files);
+struct mac_veriexec_file_info *
+	mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid,
+	    unsigned long gen, int *found_dev, int check_files);
 void	mac_veriexec_metadata_init(void);
 void	mac_veriexec_metadata_print_db(struct sbuf *sbp);
 int	mac_veriexec_metadata_unmounted(dev_t fsid, struct thread *td);

Modified: head/sys/security/mac_veriexec/veriexec_metadata.c
==============================================================================
--- head/sys/security/mac_veriexec/veriexec_metadata.c	Fri May 17 18:25:53 2019	(r347941)
+++ head/sys/security/mac_veriexec/veriexec_metadata.c	Fri May 17 19:27:07 2019	(r347942)
@@ -1,7 +1,7 @@
 /*
  * $FreeBSD$
  *
- * Copyright (c) 2011, 2012, 2013, 2015, 2016, Juniper Networks, Inc.
+ * Copyright (c) 2011, 2012, 2013, 2015, 2016, 2019, Juniper Networks, Inc.
  * All rights reserved.
  *
  * Originally derived from:
@@ -138,6 +138,8 @@ get_veriexec_file(struct veriexec_devhead *head, dev_t
 					break;
 				/* we need to garbage collect */
 				LIST_REMOVE(ip, entries);
+				if (ip->label)
+					free(ip->label, M_VERIEXEC);
 				free(ip, M_VERIEXEC);
 			}
 		}
@@ -152,48 +154,6 @@ get_veriexec_file(struct veriexec_devhead *head, dev_t
 
 /**
  * @internal
- * @brief Search the meta-data store for information on the specified file.
- *
- * @param fsid		file system identifier to look for
- * @param fileid	file to look for
- * @param gen		generation of file
- * @param found_dev	indicator that an entry for the file system was found
- * @param check_files	if 1, check the files list first, otherwise check the
- * 			exectuables list first
- *
- * @return A pointer to the meta-data inforation if meta-data exists for
- *     the specified file identifier, otherwise @c NULL
- */
-static struct mac_veriexec_file_info *
-find_veriexec_file(dev_t fsid, long fileid, unsigned long gen, int *found_dev,
-    int check_files)
-{
-	struct veriexec_devhead *search[3];
-	struct mac_veriexec_file_info *ip;
-	int x;
-
-	/* Determine the order of the lists to search */
-	if (check_files) {
-		search[0] = &veriexec_file_dev_head;
-		search[1] = &veriexec_dev_head;
-	} else {
-		search[0] = &veriexec_dev_head;
-		search[1] = &veriexec_file_dev_head;
-	}
-	search[2] = NULL;
-
-	VERIEXEC_DEBUG(3, ("%s: searching for dev %ju, file %lu\n",
-	    __func__, (uintmax_t)fsid, fileid));
-
-	/* Search for the specified file */
-	for (ip = NULL, x = 0; ip == NULL && search[x]; x++)
-		ip = get_veriexec_file(search[x], fsid, fileid, gen, found_dev);
-
-	return (ip);
-}
-
-/**
- * @internal
  * @brief Display the fingerprint for each entry in the device list
  *
  * @param sbp		sbuf to write output to
@@ -270,7 +230,7 @@ int
 mac_veriexec_metadata_has_file(dev_t fsid, long fileid, unsigned long gen)
 {
 
-	return (find_veriexec_file(fsid, fileid, gen, NULL,
+	return (mac_veriexec_metadata_get_file_info(fsid, fileid, gen, NULL,
 	    VERIEXEC_FILES_FIRST) != NULL);
 }
 
@@ -312,6 +272,8 @@ free_veriexec_dev(dev_t fsid, struct veriexec_devhead 
 	for (ip = LIST_FIRST(&(lp->file_head)); ip != NULL; ip = nip) {
 		nip = LIST_NEXT(ip, entries);
 		LIST_REMOVE(ip, entries);
+		if (ip->label)
+			free(ip->label, M_VERIEXEC);
 		free(ip, M_VERIEXEC);
 	}
 
@@ -393,6 +355,38 @@ search:
 }
 
 /**
+ * @internal
+ * @brief Allocate and initialize label record with the provided data.
+ *
+ * @param labelp	Location to store the initialized label
+ * @param src		Pointer to label string to copy
+ * @param srclen	Length of label string to copy
+ *
+ * @return Length of resulting label
+ *
+ * @note Called with ve_mutex locked.
+ */
+static size_t
+mac_veriexec_init_label(char **labelp, size_t labellen, char *src,
+    size_t srclen)
+{
+	char *label;
+
+	label = *labelp;
+	if (labellen < srclen) {
+		mtx_unlock(&ve_mutex);
+		if (label != NULL)
+			free(label, M_VERIEXEC);
+		label = malloc(srclen, M_VERIEXEC, M_WAITOK);
+		mtx_lock(&ve_mutex);
+		labellen = srclen;
+		*labelp = label;
+	}
+	memcpy(label, src, srclen);
+	return labellen;
+}
+
+/**
  * @brief When a device is unmounted, we want to toss the signatures recorded
  *     against it.
  *
@@ -446,7 +440,8 @@ mac_veriexec_metadata_get_file_flags(dev_t fsid, long 
 	struct mac_veriexec_file_info *ip;
 	int found_dev;
 
-	ip = find_veriexec_file(fsid, fileid, gen, &found_dev, check_files);
+	ip = mac_veriexec_metadata_get_file_info(fsid, fileid, gen, &found_dev,
+	    check_files);
 	if (ip == NULL)
 		return (ENOENT);
 
@@ -518,8 +513,8 @@ mac_veriexec_metadata_fetch_fingerprint_status(struct 
 	status = mac_veriexec_get_fingerprint_status(vp);
 	if (status == FINGERPRINT_INVALID || status == FINGERPRINT_NODEV) {
 		found_dev = 0;
-		ip = find_veriexec_file(vap->va_fsid, vap->va_fileid,
-		    vap->va_gen, &found_dev, check_files);
+		ip = mac_veriexec_metadata_get_file_info(vap->va_fsid,
+		    vap->va_fileid, vap->va_gen, &found_dev, check_files);
 		if (ip == NULL) {
 			status = (found_dev) ? FINGERPRINT_NOENTRY :
 			    FINGERPRINT_NODEV;
@@ -611,7 +606,7 @@ mac_veriexec_metadata_fetch_fingerprint_status(struct 
 int
 mac_veriexec_metadata_add_file(int file_dev, dev_t fsid, long fileid,
     unsigned long gen, unsigned char fingerprint[MAXFINGERPRINTLEN],
-    int flags, const char *fp_type, int override)
+    char *label, size_t labellen, int flags, const char *fp_type, int override)
 {
 	struct mac_veriexec_fpops *fpops;
 	struct veriexec_dev_list *lp;
@@ -619,6 +614,10 @@ mac_veriexec_metadata_add_file(int file_dev, dev_t fsi
 	struct mac_veriexec_file_info *ip;
 	struct mac_veriexec_file_info *np = NULL;
 
+	/* Label and labellen must be set if VERIEXEC_LABEL is set */
+	if ((flags & VERIEXEC_LABEL) != 0 && (label == NULL || labellen == 0))
+		return (EINVAL);
+
 	/* Look up the device entry */
 	if (file_dev)
 		head = &veriexec_file_dev_head;
@@ -652,6 +651,15 @@ search:
 				ip->ops = fpops;
 				memcpy(ip->fingerprint, fingerprint,
 				    fpops->digest_len);
+				if (flags & VERIEXEC_LABEL) {
+					ip->labellen = mac_veriexec_init_label(
+					    &ip->label, ip->labellen, label,
+					    labellen);
+				} else if (ip->labellen > 0) {
+					free(ip->label, M_VERIEXEC);
+					ip->labellen = 0;
+					ip->label = NULL;
+				}
 			} else if ((flags & (VERIEXEC_INDIRECT|VERIEXEC_FILE)))
 				ip->flags |= flags;
 
@@ -697,6 +705,13 @@ search:
 	ip->fileid = fileid;
 	ip->gen = gen;
 	memcpy(ip->fingerprint, fingerprint, fpops->digest_len);
+	if (flags & VERIEXEC_LABEL)
+		ip->labellen = mac_veriexec_init_label(&ip->label,
+		    ip->labellen, label, labellen);
+	else {
+		ip->label = NULL;
+		ip->labellen = 0;
+	}
 
 	VERIEXEC_DEBUG(3, ("add file %ju.%lu (files=%d)\n",
 	    (uintmax_t)ip->fileid,
@@ -716,6 +731,48 @@ search:
 #endif
 	return (0);
 }
+
+/**
+ * @brief Search the meta-data store for information on the specified file.
+ *
+ * @param fsid		file system identifier to look for
+ * @param fileid	file to look for
+ * @param gen		generation of file
+ * @param found_dev	indicator that an entry for the file system was found
+ * @param check_files	if 1, check the files list first, otherwise check the
+ * 			exectuables list first
+ *
+ * @return A pointer to the meta-data inforation if meta-data exists for
+ *     the specified file identifier, otherwise @c NULL
+ */
+struct mac_veriexec_file_info *
+mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid, unsigned long gen,
+    int *found_dev, int check_files)
+{
+	struct veriexec_devhead *search[3];
+	struct mac_veriexec_file_info *ip;
+	int x;
+
+	/* Determine the order of the lists to search */
+	if (check_files) {
+		search[0] = &veriexec_file_dev_head;
+		search[1] = &veriexec_dev_head;
+	} else {
+		search[0] = &veriexec_dev_head;
+		search[1] = &veriexec_file_dev_head;
+	}
+	search[2] = NULL;
+
+	VERIEXEC_DEBUG(3, ("%s: searching for dev %ju, file %lu\n",
+	    __func__, (uintmax_t)fsid, fileid));
+
+	/* Search for the specified file */
+	for (ip = NULL, x = 0; ip == NULL && search[x]; x++)
+		ip = get_veriexec_file(search[x], fsid, fileid, gen, found_dev);
+
+	return (ip);
+}
+
 
 /**
  * @brief Intialize the meta-data store



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