It is unclear whether we should modify veriexecctl to not set the error for EEXIST, or if we should modify veriexecgen to not generate multiple entries (with different names) for the same file. (It seems to me unreasonable to expect the user to remove the duplicates.)

A third option would be to modify the kernel code to not complain when attempting to add a new entry, as long as the new fingerprint type and value match the existing values.

The attached patch implements this option.

Comments/suggestions welcomed.
Index: kern_veriexec.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_veriexec.c,v
retrieving revision 1.14
diff -u -p -r1.14 kern_veriexec.c
--- kern_veriexec.c     29 Aug 2017 10:23:12 -0000      1.14
+++ kern_veriexec.c     29 Aug 2017 10:37:17 -0000
@@ -1050,9 +1050,11 @@ veriexec_file_add(struct lwp *l, prop_di
 {
        struct veriexec_table_entry *vte;
        struct veriexec_file_entry *vfe = NULL;
+       struct veriexec_file_entry *ovfe;
        struct vnode *vp;
        const char *file, *fp_type;
        int error;
+       bool ignore_dup = false;
 
        if (!prop_dictionary_get_cstring_nocopy(dict, "file", &file))
                return (EINVAL);
@@ -1096,12 +1098,6 @@ veriexec_file_add(struct lwp *l, prop_di
 
        rw_enter(&veriexec_op_lock, RW_WRITER);
 
-       if (veriexec_get(vp)) {
-               /* We already have an entry for this file. */
-               error = EEXIST;
-               goto unlock_out;
-       }
-
        /* Continue entry initialization. */
        if (prop_dictionary_get_uint8(dict, "entry-type", &vfe->type) == FALSE)
                vfe->type = 0;
@@ -1140,6 +1136,22 @@ veriexec_file_add(struct lwp *l, prop_di
                vfe->status = status;
        }
 
+       /*
+        * If we already have an entry for this file, and it matches
+        * the new entry exactly (except for the filename, since it
+        * might be hard-linked!), we just ignore the new entry.  If
+        * the new entry differs, report the error.
+        */
+       if ((ovfe = veriexec_get(vp)) != NULL) {
+               error = EEXIST;
+               if (vfe->type == ovfe->type &&
+                   vfe->status == ovfe->status &&
+                   vfe->ops == ovfe->ops &&
+                   memcmp(vfe->fp, ovfe->fp, vfs->ops->hash_len) == 0)
+                       ignore_dup = true;
+               goto unlock_out;
+       }
+
        vte = veriexec_table_lookup(vp->v_mount);
        if (vte == NULL)
                vte = veriexec_table_add(l, vp->v_mount);
@@ -1174,6 +1186,9 @@ veriexec_file_add(struct lwp *l, prop_di
        if (error)
                veriexec_file_free(vfe);
 
+       if (ignore_dup && error == EEXIST)
+               error = 0;
+
        return (error);
 }
 

Reply via email to