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
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to