1 /*
2 * $FreeBSD$
3 *
4 * Copyright (c) 2011, 2012, 2013, 2015, 2016, 2019, Juniper Networks, Inc.
5 * All rights reserved.
6 *
7 * Originally derived from:
8 * $NetBSD: kern_verifiedexec.c,v 1.7 2003/11/18 13:13:03 martin Exp $
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h>
33
34 #include "opt_mac.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/exec.h>
39 #include <sys/lock.h>
40 #include <sys/malloc.h>
41 #include <sys/mutex.h>
42 #include <sys/proc.h>
43 #include <sys/sbuf.h>
44 #include <sys/vnode.h>
45
46 #include "mac_veriexec.h"
47 #include "mac_veriexec_internal.h"
48
49 /**
50 * @brief per-device meta-data storage
51 */
52 struct veriexec_dev_list {
53 dev_t fsid; /**< file system identifier of the mount point */
54 LIST_HEAD(filehead, mac_veriexec_file_info) file_head;
55 /**< list of per-file meta-data information */
56 LIST_ENTRY(veriexec_dev_list) entries;
57 /**< next entries in the device list */
58 };
59
60 typedef LIST_HEAD(veriexec_devhead, veriexec_dev_list) veriexec_devhead_t;
61
62 /**
63 * @brief Mutex to protect the meta-data store lists
64 */
65 struct mtx ve_mutex;
66
67 /**
68 * @brief Executables meta-data storage
69 *
70 * This is used to store the fingerprints for potentially-executable files.
71 */
72 veriexec_devhead_t veriexec_dev_head;
73
74 /**
75 * @brief Plain file meta-data storage
76 *
77 * This is used for files that are not allowed to be executed, but should
78 * have fingerprint validation available.
79 */
80 veriexec_devhead_t veriexec_file_dev_head;
81
82 /**
83 * @internal
84 * @brief Search the @p head meta-data list for the specified file identifier
85 * @p fileid in the file system identified by @p fsid
86 *
87 * If meta-data exists for file system identified by @p fsid, it has a
88 * fingerprint list, and @p found_dev is not @c NULL then store true in the
89 * location pointed to by @p found_dev
90 *
91 * @param head meta-data list to search
92 * @param fsid file system identifier to look for
93 * @param fileid file to look for
94 * @param gen generation of file
95 * @param found_dev indicator that an entry for the file system was found
96 *
97 * @return A pointer to the meta-data inforation if meta-data exists for
98 * the specified file identifier, otherwise @c NULL
99 */
100 static struct mac_veriexec_file_info *
101 get_veriexec_file(struct veriexec_devhead *head, dev_t fsid, long fileid,
102 unsigned long gen, int *found_dev)
103 {
104 struct veriexec_dev_list *lp;
105 struct mac_veriexec_file_info *ip, *tip;
106
107 ip = NULL;
108
109 /* Initialize the value found_dev, if non-NULL */
110 if (found_dev != NULL)
111 *found_dev = 0;
112
113 VERIEXEC_DEBUG(3, ("searching for file %ju.%lu on device %ju,"
114 " files=%d\n", (uintmax_t)fileid, gen, (uintmax_t)fsid,
115 (head == &veriexec_file_dev_head)));
116
117 /* Get a lock to access the list */
118 mtx_lock(&ve_mutex);
119
120 /* First, look for the file system */
121 for (lp = LIST_FIRST(head); lp != NULL; lp = LIST_NEXT(lp, entries))
122 if (lp->fsid == fsid)
123 break;
124
125 /* We found the file system in the list */
126 if (lp != NULL) {
127 VERIEXEC_DEBUG(3, ("found matching dev number %ju\n",
128 (uintmax_t)lp->fsid));
129
130 /* If found_dev is non-NULL, store true there */
131 if (found_dev != NULL)
132 *found_dev = 1;
133
134 /* Next, look for the meta-data information for the file */
135 LIST_FOREACH_SAFE(ip, &(lp->file_head), entries, tip) {
136 if (ip->fileid == fileid) {
137 if (ip->gen == gen)
138 break;
139 /* we need to garbage collect */
140 LIST_REMOVE(ip, entries);
141 if (ip->label)
142 free(ip->label, M_VERIEXEC);
143 free(ip, M_VERIEXEC);
144 }
145 }
146 }
147
148 /* Release the lock we obtained earlier */
149 mtx_unlock(&ve_mutex);
150
151 /* Return the meta-data information we found, if anything */
152 return (ip);
153 }
154
155 /**
156 * @internal
157 * @brief Display the fingerprint for each entry in the device list
158 *
159 * @param sbp sbuf to write output to
160 * @param lp pointer to device list
161 */
162 static void
163 mac_veriexec_print_db_dev_list(struct sbuf *sbp, struct veriexec_dev_list *lp)
164 {
165 struct mac_veriexec_file_info *ip;
166
167 #define FPB(i) (ip->fingerprint[i])
168 for (ip = LIST_FIRST(&(lp->file_head)); ip != NULL;
169 ip = LIST_NEXT(ip, entries))
170 sbuf_printf(sbp, " %ld: %u %ld [%02x %02x %02x %02x %02x "
171 "%02x %02x %02x...]\n", ip->fileid, ip->flags, ip->gen,
172 FPB(0), FPB(1), FPB(2), FPB(3), FPB(4), FPB(5), FPB(6),
173 FPB(7));
174 }
175
176 /**
177 * @internal
178 * @brief Display the device list
179 *
180 * @param sbp sbuf to write output to
181 * @param head pointer to head of the device list
182 */
183 static void
184 mac_veriexec_print_db_head(struct sbuf *sbp, struct veriexec_devhead *head)
185 {
186 struct veriexec_dev_list *lp;
187
188 for (lp = LIST_FIRST(head); lp != NULL; lp = LIST_NEXT(lp, entries)) {
189 sbuf_printf(sbp, " FS id: %ju\n", (uintmax_t)lp->fsid);
190 mac_veriexec_print_db_dev_list(sbp, lp);
191 }
192
193 }
194
195 /**
196 * @internal
197 * @brief Generate human-readable output for the current fingerprint database
198 *
199 * @param sbp sbuf to write output to
200 */
201 void
202 mac_veriexec_metadata_print_db(struct sbuf *sbp)
203 {
204 struct {
205 struct veriexec_devhead *h;
206 const char *name;
207 } fpdbs[] = {
208 { &veriexec_file_dev_head, "regular files" },
209 { &veriexec_dev_head, "executable files" },
210 };
211 int i;
212
213 mtx_lock(&ve_mutex);
214 for (i = 0; i < sizeof(fpdbs)/sizeof(fpdbs[0]); i++) {
215 sbuf_printf(sbp, "%s fingerprint db:\n", fpdbs[i].name);
216 mac_veriexec_print_db_head(sbp, fpdbs[i].h);
217 }
218 mtx_unlock(&ve_mutex);
219 }
220 /**
221 * @brief Determine if the meta-data store has an entry for the specified file.
222 *
223 * @param fsid file system identifier to look for
224 * @param fileid file to look for
225 * @param gen generation of file
226 *
227 * @return 1 if there is an entry in the meta-data store, 0 otherwise.
228 */
229 int
230 mac_veriexec_metadata_has_file(dev_t fsid, long fileid, unsigned long gen)
231 {
232
233 return (mac_veriexec_metadata_get_file_info(fsid, fileid, gen, NULL,
234 VERIEXEC_FILES_FIRST) != NULL);
235 }
236
237 /**
238 * @brief Search the list of devices looking for the one given, in order to
239 * release the resources used by it.
240 *
241 * If found, free all file entries for it, and remove it from the list.
242 *
243 * @note Called with @a ve_mutex held
244 *
245 * @param fsid file system identifier to look for
246 * @param head meta-data list to search
247 *
248 * @return 0 if the device entry was freed, otherwise an error code
249 */
250 static int
251 free_veriexec_dev(dev_t fsid, struct veriexec_devhead *head)
252 {
253 struct veriexec_dev_list *lp;
254 struct mac_veriexec_file_info *ip, *nip;
255
256 /* Look for the file system */
257 for (lp = LIST_FIRST(head); lp != NULL;
258 lp = LIST_NEXT(lp, entries))
259 if (lp->fsid == fsid) break;
260
261 /* If lp is NULL, we did not find it */
262 if (lp == NULL)
263 return ENOENT;
264
265 /* Unhook lp, before we free it and its content */
266 LIST_REMOVE(lp, entries);
267
268 /* Release the lock */
269 mtx_unlock(&ve_mutex);
270
271 /* Free the file entries in the list */
272 for (ip = LIST_FIRST(&(lp->file_head)); ip != NULL; ip = nip) {
273 nip = LIST_NEXT(ip, entries);
274 LIST_REMOVE(ip, entries);
275 if (ip->label)
276 free(ip->label, M_VERIEXEC);
277 free(ip, M_VERIEXEC);
278 }
279
280 /* Free the meta-data entry for the device */
281 free(lp, M_VERIEXEC);
282
283 /* Re-acquire the lock */
284 mtx_lock(&ve_mutex);
285 return 0;
286 }
287
288 /**
289 * @brief Search the list of devices looking for the one given.
290 *
291 * If it is not in the list then add it.
292 *
293 * @note Called with @a ve_mutex held
294 *
295 * @param fsid file system identifier to look for
296 * @param head meta-data list to search
297 *
298 * @return A pointer to the meta-data entry for the device, if found or added,
299 * otherwise @c NULL
300 */
301 static struct veriexec_dev_list *
302 find_veriexec_dev(dev_t fsid, struct veriexec_devhead *head)
303 {
304 struct veriexec_dev_list *lp;
305 struct veriexec_dev_list *np = NULL;
306
307 search:
308 /* Look for the file system */
309 for (lp = LIST_FIRST(head); lp != NULL;
310 lp = LIST_NEXT(lp, entries))
311 if (lp->fsid == fsid) break;
312
313 if (lp == NULL) {
314 if (np == NULL) {
315 /*
316 * If pointer is null then entry not there,
317 * add a new one, first try to malloc while
318 * we hold mutex - should work most of the time.
319 */
320 np = malloc(sizeof(struct veriexec_dev_list),
321 M_VERIEXEC, M_NOWAIT);
322 if (np == NULL) {
323 /*
324 * So much for that plan, dop the mutex
325 * and repeat...
326 */
327 mtx_unlock(&ve_mutex);
328 np = malloc(sizeof(struct veriexec_dev_list),
329 M_VERIEXEC, M_WAITOK);
330 mtx_lock(&ve_mutex);
331 /*
332 * Repeat the search, in case someone
333 * added this while we slept.
334 */
335 goto search;
336 }
337 }
338 if (np) {
339 /* Add the entry to the list */
340 lp = np;
341 LIST_INIT(&(lp->file_head));
342 lp->fsid = fsid;
343 LIST_INSERT_HEAD(head, lp, entries);
344 }
345 } else if (np) {
346 /*
347 * Someone else did it while we slept.
348 */
349 mtx_unlock(&ve_mutex);
350 free(np, M_VERIEXEC);
351 mtx_lock(&ve_mutex);
352 }
353
354 return (lp);
355 }
356
357 /**
358 * @internal
359 * @brief Allocate and initialize label record with the provided data.
360 *
361 * @param labelp Location to store the initialized label
362 * @param src Pointer to label string to copy
363 * @param srclen Length of label string to copy
364 *
365 * @return Length of resulting label
366 *
367 * @note Called with ve_mutex locked.
368 */
369 static size_t
370 mac_veriexec_init_label(char **labelp, size_t labellen, char *src,
371 size_t srclen)
372 {
373 char *label;
374
375 label = *labelp;
376 if (labellen < srclen) {
377 mtx_unlock(&ve_mutex);
378 if (label != NULL)
379 free(label, M_VERIEXEC);
380 label = malloc(srclen, M_VERIEXEC, M_WAITOK);
381 mtx_lock(&ve_mutex);
382 labellen = srclen;
383 *labelp = label;
384 }
385 memcpy(label, src, srclen);
386 return labellen;
387 }
388
389 /**
390 * @brief When a device is unmounted, we want to toss the signatures recorded
391 * against it.
392 *
393 * We are being called from unmount() with the root vnode just before it is
394 * freed.
395 *
396 * @param fsid file system identifier to look for
397 * @param td calling thread
398 *
399 * @return 0 on success, otherwise an error code.
400 */
401 int
402 mac_veriexec_metadata_unmounted(dev_t fsid, struct thread *td)
403 {
404 int error;
405
406 /*
407 * The device can have entries on both lists.
408 */
409 mtx_lock(&ve_mutex);
410 error = free_veriexec_dev(fsid, &veriexec_dev_head);
411 if (error && error != ENOENT) {
412 mtx_unlock(&ve_mutex);
413 return error;
414 }
415 error = free_veriexec_dev(fsid, &veriexec_file_dev_head);
416 mtx_unlock(&ve_mutex);
417 if (error && error != ENOENT) {
418 return error;
419 }
420 return 0;
421 }
422
423 /**
424 * @brief Return the flags assigned to the file identified by file system
425 * identifier @p fsid and file identifier @p fileid.
426 *
427 * @param fsid file system identifier
428 * @param fileid file identifier within the file system
429 * @param gen generation of file
430 * @param flags pointer to location to store the flags
431 * @param check_files if 1, check the files list first, otherwise check the
432 * exectuables list first
433 *
434 * @return 0 on success, otherwise an error code.
435 */
436 int
437 mac_veriexec_metadata_get_file_flags(dev_t fsid, long fileid, unsigned long gen,
438 int *flags, int check_files)
439 {
440 struct mac_veriexec_file_info *ip;
441 int found_dev;
442
443 ip = mac_veriexec_metadata_get_file_info(fsid, fileid, gen, &found_dev,
444 check_files);
445 if (ip == NULL)
446 return (ENOENT);
447
448 *flags = ip->flags;
449 return (0);
450 }
451
452 /**
453 * @brief get the files for the specified process
454 *
455 * @param cred credentials to use
456 * @param p process to get the flags for
457 * @param flags where to store the flags
458 * @param check_files if 1, check the files list first, otherwise check the
459 * exectuables list first
460 *
461 * @return 0 if the process has an entry in the meta-data store, otherwise an
462 * error code
463 */
464 int
465 mac_veriexec_metadata_get_executable_flags(struct ucred *cred, struct proc *p,
466 int *flags, int check_files)
467 {
468 struct vnode *proc_vn;
469 struct vattr vap;
470 int error;
471
472 /* Get the text vnode for the process */
473 proc_vn = p->p_textvp;
474 if (proc_vn == NULL)
475 return EINVAL;
476
477 /* Get vnode attributes */
478 error = VOP_GETATTR(proc_vn, &vap, cred);
479 if (error)
480 return error;
481
482 error = mac_veriexec_metadata_get_file_flags(vap.va_fsid,
483 vap.va_fileid, vap.va_gen, flags,
484 (check_files == VERIEXEC_FILES_FIRST));
485
486 return (error);
487 }
488
489 /**
490 * @brief Ensure the fingerprint status for the vnode @p vp is assigned to its
491 * MAC label.
492 *
493 * @param vp vnode to check
494 * @param vap vnode attributes to use
495 * @param td calling thread
496 * @param check_files if 1, check the files list first, otherwise check the
497 * exectuables list first
498 *
499 * @return 0 on success, otherwise an error code.
500 */
501 int
502 mac_veriexec_metadata_fetch_fingerprint_status(struct vnode *vp,
503 struct vattr *vap, struct thread *td, int check_files)
504 {
505 unsigned char digest[MAXFINGERPRINTLEN];
506 struct mac_veriexec_file_info *ip;
507 int error, found_dev;
508 fingerprint_status_t status;
509
510 error = 0;
511 ip = NULL;
512
513 status = mac_veriexec_get_fingerprint_status(vp);
514 if (status == FINGERPRINT_INVALID || status == FINGERPRINT_NODEV) {
515 found_dev = 0;
516 ip = mac_veriexec_metadata_get_file_info(vap->va_fsid,
517 vap->va_fileid, vap->va_gen, &found_dev, check_files);
518 if (ip == NULL) {
519 status = (found_dev) ? FINGERPRINT_NOENTRY :
520 FINGERPRINT_NODEV;
521 VERIEXEC_DEBUG(3,
522 ("fingerprint status is %d for dev %ju, file "
523 "%ju.%lu\n", status, (uintmax_t)vap->va_fsid,
524 (uintmax_t)vap->va_fileid, vap->va_gen));
525 } else {
526 /*
527 * evaluate and compare fingerprint
528 */
529 error = mac_veriexec_fingerprint_check_vnode(vp, ip,
530 td, vap->va_size, digest);
531 switch (error) {
532 case 0:
533 /* Process flags */
534 if ((ip->flags & VERIEXEC_INDIRECT))
535 status = FINGERPRINT_INDIRECT;
536 else if ((ip->flags & VERIEXEC_FILE))
537 status = FINGERPRINT_FILE;
538 else
539 status = FINGERPRINT_VALID;
540 VERIEXEC_DEBUG(2,
541 ("%sfingerprint matches for dev %ju, file "
542 "%ju.%lu\n",
543 (status == FINGERPRINT_INDIRECT) ?
544 "indirect " :
545 (status == FINGERPRINT_FILE) ?
546 "file " : "", (uintmax_t)vap->va_fsid,
547 (uintmax_t)vap->va_fileid, vap->va_gen));
548 break;
549
550 case EAUTH:
551 #ifdef VERIFIED_EXEC_DEBUG_VERBOSE
552 {
553 char have[MAXFINGERPRINTLEN * 2 + 1];
554 char want[MAXFINGERPRINTLEN * 2 + 1];
555 int i, len;
556
557 len = ip->ops->digest_len;
558 for (i = 0; i < len; i++) {
559 sprintf(&want[i * 2], "%02x",
560 ip->fingerprint[i]);
561 sprintf(&have[i * 2], "%02x",
562 digest[i]);
563 }
564 log(LOG_ERR, MAC_VERIEXEC_FULLNAME
565 ": fingerprint for dev %ju, file "
566 "%ju.%lu %s != %s\n",
567 (uintmax_t)vap->va_fsid,
568 (uintmax_t)vap->va_fileid,
569 vap->va_gen,
570 have, want);
571 }
572 #endif
573 status = FINGERPRINT_NOMATCH;
574 break;
575 default:
576 VERIEXEC_DEBUG(2,
577 ("fingerprint status error %d\n", error));
578 break;
579 }
580 }
581 mac_veriexec_set_fingerprint_status(vp, status);
582 }
583 return (error);
584 }
585
586 /**
587 * Add a file and its fingerprint to the list of files attached
588 * to the device @p fsid.
589 *
590 * Only add the entry if it is not already on the list.
591 *
592 * @note Called with @a ve_mutex held
593 *
594 * @param file_dev if 1, the entry should be added on the file list,
595 * otherwise it should be added on the executable list
596 * @param fsid file system identifier of device
597 * @param fileid file to add
598 * @param gen generation of file
599 * @param fingerprint fingerprint to add to the store
600 * @param flags flags to set in the store
601 * @param fp_type digest type
602 * @param override if 1, override any values already stored
603 *
604 * @return 0 on success, otherwise an error code.
605 */
606 int
607 mac_veriexec_metadata_add_file(int file_dev, dev_t fsid, long fileid,
608 unsigned long gen, unsigned char fingerprint[MAXFINGERPRINTLEN],
609 char *label, size_t labellen, int flags, const char *fp_type, int override)
610 {
611 struct mac_veriexec_fpops *fpops;
612 struct veriexec_dev_list *lp;
613 struct veriexec_devhead *head;
614 struct mac_veriexec_file_info *ip;
615 struct mac_veriexec_file_info *np = NULL;
616
617 /* Label and labellen must be set if VERIEXEC_LABEL is set */
618 if ((flags & VERIEXEC_LABEL) != 0 && (label == NULL || labellen == 0))
619 return (EINVAL);
620
621 /* Look up the device entry */
622 if (file_dev)
623 head = &veriexec_file_dev_head;
624 else
625 head = &veriexec_dev_head;
626 lp = find_veriexec_dev(fsid, head);
627
628 /* Look up the fingerprint operations for the digest type */
629 fpops = mac_veriexec_fingerprint_lookup_ops(fp_type);
630 if (fpops == NULL)
631 return (EOPNOTSUPP);
632
633 search:
634 for (ip = LIST_FIRST(&(lp->file_head)); ip != NULL;
635 ip = LIST_NEXT(ip, entries)) {
636 /* check for a dupe file in the list, skip if an entry
637 * exists for this file except for when the flags contains
638 * VERIEXEC_INDIRECT, always set the flags when it is so
639 * we don't get a hole caused by conflicting flags on
640 * hardlinked files. XXX maybe we should validate
641 * fingerprint is same and complain if it is not...
642 */
643 if (ip->fileid == fileid && ip->gen == gen) {
644 if (override) {
645 /*
646 * for a signed load we allow overrides,
647 * otherwise fingerpints needed for pkg loads
648 * can fail (the files are on temp device).
649 */
650 ip->flags = flags;
651 ip->ops = fpops;
652 memcpy(ip->fingerprint, fingerprint,
653 fpops->digest_len);
654 if (flags & VERIEXEC_LABEL) {
655 ip->labellen = mac_veriexec_init_label(
656 &ip->label, ip->labellen, label,
657 labellen);
658 } else if (ip->labellen > 0) {
659 free(ip->label, M_VERIEXEC);
660 ip->labellen = 0;
661 ip->label = NULL;
662 }
663 } else if ((flags & (VERIEXEC_INDIRECT|VERIEXEC_FILE)))
664 ip->flags |= flags;
665
666 if (np) {
667 /* unlikely but... we don't need it now. */
668 mtx_unlock(&ve_mutex);
669 free(np, M_VERIEXEC);
670 mtx_lock(&ve_mutex);
671 }
672 return (0);
673 }
674 }
675
676 /*
677 * We may have been past here before...
678 */
679 if (np == NULL) {
680 /*
681 * We first try with mutex held and nowait.
682 */
683 np = malloc(sizeof(struct mac_veriexec_file_info), M_VERIEXEC,
684 M_NOWAIT);
685 if (np == NULL) {
686 /*
687 * It was worth a try, now
688 * drop mutex while we malloc.
689 */
690 mtx_unlock(&ve_mutex);
691 np = malloc(sizeof(struct mac_veriexec_file_info),
692 M_VERIEXEC, M_WAITOK);
693 mtx_lock(&ve_mutex);
694 /*
695 * We now have to repeat our search!
696 */
697 goto search;
698 }
699 }
700
701 /* Set up the meta-data entry */
702 ip = np;
703 ip->flags = flags;
704 ip->ops = fpops;
705 ip->fileid = fileid;
706 ip->gen = gen;
707 memcpy(ip->fingerprint, fingerprint, fpops->digest_len);
708 if (flags & VERIEXEC_LABEL)
709 ip->labellen = mac_veriexec_init_label(&ip->label,
710 ip->labellen, label, labellen);
711 else {
712 ip->label = NULL;
713 ip->labellen = 0;
714 }
715
716 VERIEXEC_DEBUG(3, ("add file %ju.%lu (files=%d)\n",
717 (uintmax_t)ip->fileid,
718 ip->gen, file_dev));
719
720 /* Add the entry to the list */
721 LIST_INSERT_HEAD(&(lp->file_head), ip, entries);
722 #ifdef DEBUG_VERIEXEC_FINGERPRINT
723 {
724 off_t offset;
725
726 printf("Stored %s fingerprint:\n", fp_type);
727 for (offset = 0; offset < fpops->digest_len; offset++)
728 printf("%02x", fingerprint[offset]);
729 printf("\n");
730 }
731 #endif
732 return (0);
733 }
734
735 /**
736 * @brief Search the meta-data store for information on the specified file.
737 *
738 * @param fsid file system identifier to look for
739 * @param fileid file to look for
740 * @param gen generation of file
741 * @param found_dev indicator that an entry for the file system was found
742 * @param check_files if 1, check the files list first, otherwise check the
743 * exectuables list first
744 *
745 * @return A pointer to the meta-data inforation if meta-data exists for
746 * the specified file identifier, otherwise @c NULL
747 */
748 struct mac_veriexec_file_info *
749 mac_veriexec_metadata_get_file_info(dev_t fsid, long fileid, unsigned long gen,
750 int *found_dev, int check_files)
751 {
752 struct veriexec_devhead *search[3];
753 struct mac_veriexec_file_info *ip;
754 int x;
755
756 /* Determine the order of the lists to search */
757 if (check_files) {
758 search[0] = &veriexec_file_dev_head;
759 search[1] = &veriexec_dev_head;
760 } else {
761 search[0] = &veriexec_dev_head;
762 search[1] = &veriexec_file_dev_head;
763 }
764 search[2] = NULL;
765
766 VERIEXEC_DEBUG(3, ("%s: searching for dev %ju, file %lu\n",
767 __func__, (uintmax_t)fsid, fileid));
768
769 /* Search for the specified file */
770 for (ip = NULL, x = 0; ip == NULL && search[x]; x++)
771 ip = get_veriexec_file(search[x], fsid, fileid, gen, found_dev);
772
773 return (ip);
774 }
775
776 /**
777 * @brief Intialize the meta-data store
778 */
779 void
780 mac_veriexec_metadata_init(void)
781 {
782
783 mtx_init(&ve_mutex, "veriexec lock", NULL, MTX_DEF);
784 LIST_INIT(&veriexec_dev_head);
785 LIST_INIT(&veriexec_file_dev_head);
786 }
Cache object: cf9beaf2fb3d352f81a436d5cee1efea
|