1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2012 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "journal-def.h"
30 #include "journal-file.h"
31 #include "journal-authenticate.h"
32 #include "journal-verify.h"
37 static int journal_file_object_verify(JournalFile *f, Object *o) {
43 /* This does various superficial tests about the length an
44 * possible field values. It does not follow any references to
47 if ((o->object.flags & OBJECT_COMPRESSED) &&
48 o->object.type != OBJECT_DATA)
51 switch (o->object.type) {
56 if (le64toh(o->data.entry_offset) <= 0 ||
57 le64toh(o->data.n_entries) <= 0)
60 if (le64toh(o->object.size) - offsetof(DataObject, payload) <= 0)
63 h1 = le64toh(o->data.hash);
65 if (o->object.flags & OBJECT_COMPRESSED) {
68 uint64_t alloc = 0, b_size;
70 if (!uncompress_blob(o->data.payload,
71 le64toh(o->object.size) - offsetof(Object, data.payload),
75 h2 = hash64(b, b_size);
78 return -EPROTONOSUPPORT;
81 h2 = hash64(o->data.payload, le64toh(o->object.size) - offsetof(Object, data.payload));
86 if (!VALID64(o->data.next_hash_offset) ||
87 !VALID64(o->data.next_field_offset) ||
88 !VALID64(o->data.entry_offset) ||
89 !VALID64(o->data.entry_array_offset))
96 if (le64toh(o->object.size) - offsetof(FieldObject, payload) <= 0)
99 if (!VALID64(o->field.next_hash_offset) ||
100 !VALID64(o->field.head_data_offset))
105 if ((le64toh(o->object.size) - offsetof(EntryObject, items)) % sizeof(EntryItem) != 0)
108 if ((le64toh(o->object.size) - offsetof(EntryObject, items)) / sizeof(EntryItem) <= 0)
111 if (le64toh(o->entry.seqnum) <= 0 ||
112 !VALID_REALTIME(le64toh(o->entry.realtime)) ||
113 !VALID_MONOTONIC(le64toh(o->entry.monotonic)))
116 for (i = 0; i < journal_file_entry_n_items(o); i++) {
117 if (o->entry.items[i].object_offset == 0 ||
118 !VALID64(o->entry.items[i].object_offset))
124 case OBJECT_DATA_HASH_TABLE:
125 case OBJECT_FIELD_HASH_TABLE:
126 if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) % sizeof(HashItem) != 0)
129 if ((le64toh(o->object.size) - offsetof(HashTableObject, items)) / sizeof(HashItem) <= 0)
132 for (i = 0; i < journal_file_hash_table_n_items(o); i++) {
133 if (o->hash_table.items[i].head_hash_offset != 0 &&
134 !VALID64(le64toh(o->hash_table.items[i].head_hash_offset)))
136 if (o->hash_table.items[i].tail_hash_offset != 0 &&
137 !VALID64(le64toh(o->hash_table.items[i].tail_hash_offset)))
140 if ((o->hash_table.items[i].head_hash_offset != 0) !=
141 (o->hash_table.items[i].tail_hash_offset != 0))
147 case OBJECT_ENTRY_ARRAY:
148 if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) % sizeof(le64_t) != 0)
151 if ((le64toh(o->object.size) - offsetof(EntryArrayObject, items)) / sizeof(le64_t) <= 0)
154 if (!VALID64(o->entry_array.next_entry_array_offset))
157 for (i = 0; i < journal_file_entry_array_n_items(o); i++)
158 if (o->entry_array.items[i] != 0 &&
159 !VALID64(o->entry_array.items[i]))
165 if (le64toh(o->object.size) != sizeof(TagObject))
168 if (!VALID_EPOCH(o->tag.epoch))
177 static void draw_progress(uint64_t p, usec_t *last_usec) {
181 if (!isatty(STDOUT_FILENO))
184 z = now(CLOCK_MONOTONIC);
187 if (x != 0 && x + 40 * USEC_PER_MSEC > z)
192 n = (3 * columns()) / 4;
193 j = (n * (unsigned) p) / 65535ULL;
196 fputs("\r\x1B[?25l" ANSI_HIGHLIGHT_GREEN_ON, stdout);
198 for (i = 0; i < j; i++)
199 fputs("\xe2\x96\x88", stdout);
201 fputs(ANSI_HIGHLIGHT_OFF, stdout);
203 for (i = 0; i < k; i++)
204 fputs("\xe2\x96\x91", stdout);
206 printf(" %3lu%%", 100LU * (unsigned long) p / 65535LU);
208 fputs("\r\x1B[?25h", stdout);
212 static void flush_progress(void) {
215 if (!isatty(STDOUT_FILENO))
218 n = (3 * columns()) / 4;
222 for (i = 0; i < n + 5; i++)
229 static int write_uint64(int fd, uint64_t p) {
232 k = write(fd, &p, sizeof(p));
241 static int contains_uint64(MMapCache *m, int fd, uint64_t n, uint64_t p) {
256 r = mmap_cache_get(m, fd, PROT_READ|PROT_WRITE, 0, false, c * sizeof(uint64_t), sizeof(uint64_t), NULL, (void **) &z);
275 static int entry_points_to_data(
288 assert(entry_fd >= 0);
290 if (!contains_uint64(f->mmap, entry_fd, n_entries, entry_p)) {
291 log_error("Data object references invalid entry at %llu", (unsigned long long) data_p);
295 r = journal_file_move_to_object(f, OBJECT_ENTRY, entry_p, &o);
299 n = journal_file_entry_n_items(o);
300 for (i = 0; i < n; i++)
301 if (le64toh(o->entry.items[i].object_offset) == data_p) {
307 log_error("Data object not referenced by linked entry at %llu", (unsigned long long) data_p);
311 /* Check if this entry is also in main entry array. Since the
312 * main entry array has already been verified we can rely on
316 n = le64toh(f->header->n_entries);
317 a = le64toh(f->header->entry_array_offset);
322 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
326 m = journal_file_entry_array_n_items(o);
329 if (entry_p <= le64toh(o->entry_array.items[u-1])) {
338 if (le64toh(o->entry_array.items[z]) == entry_p)
344 if (entry_p < le64toh(o->entry_array.items[z]))
350 log_error("Entry object doesn't exist in main entry array at %llu", (unsigned long long) entry_p);
355 a = le64toh(o->entry_array.next_entry_array_offset);
361 static int verify_data(
363 Object *o, uint64_t p,
364 int entry_fd, uint64_t n_entries,
365 int entry_array_fd, uint64_t n_entry_arrays) {
367 uint64_t i, n, a, last, q;
372 assert(entry_fd >= 0);
373 assert(entry_array_fd >= 0);
375 n = le64toh(o->data.n_entries);
376 a = le64toh(o->data.entry_array_offset);
378 /* We already checked this earlier */
381 last = q = le64toh(o->data.entry_offset);
382 r = entry_points_to_data(f, entry_fd, n_entries, q, p);
391 log_error("Array chain too short at %llu", (unsigned long long) p);
395 if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
396 log_error("Invalid array at %llu", (unsigned long long) p);
400 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
404 next = le64toh(o->entry_array.next_entry_array_offset);
405 if (next != 0 && next <= a) {
406 log_error("Array chain has cycle at %llu", (unsigned long long) p);
410 m = journal_file_entry_array_n_items(o);
411 for (j = 0; i < n && j < m; i++, j++) {
413 q = le64toh(o->entry_array.items[j]);
415 log_error("Data object's entry array not sorted at %llu", (unsigned long long) p);
420 r = entry_points_to_data(f, entry_fd, n_entries, q, p);
424 /* Pointer might have moved, reposition */
425 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
436 static int verify_hash_table(
438 int data_fd, uint64_t n_data,
439 int entry_fd, uint64_t n_entries,
440 int entry_array_fd, uint64_t n_entry_arrays,
442 bool show_progress) {
448 assert(data_fd >= 0);
449 assert(entry_fd >= 0);
450 assert(entry_array_fd >= 0);
453 n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
454 for (i = 0; i < n; i++) {
455 uint64_t last = 0, p;
458 draw_progress(0xC000 + (0x3FFF * i / n), last_usec);
460 p = le64toh(f->data_hash_table[i].head_hash_offset);
465 if (!contains_uint64(f->mmap, data_fd, n_data, p)) {
466 log_error("Invalid data object at hash entry %llu of %llu",
467 (unsigned long long) i, (unsigned long long) n);
471 r = journal_file_move_to_object(f, OBJECT_DATA, p, &o);
475 next = le64toh(o->data.next_hash_offset);
476 if (next != 0 && next <= p) {
477 log_error("Hash chain has a cycle in hash entry %llu of %llu",
478 (unsigned long long) i, (unsigned long long) n);
482 if (le64toh(o->data.hash) % n != i) {
483 log_error("Hash value mismatch in hash entry %llu of %llu",
484 (unsigned long long) i, (unsigned long long) n);
488 r = verify_data(f, o, p, entry_fd, n_entries, entry_array_fd, n_entry_arrays);
496 if (last != le64toh(f->data_hash_table[i].tail_hash_offset)) {
497 log_error("Tail hash pointer mismatch in hash table");
505 static int data_object_in_hash_table(JournalFile *f, uint64_t hash, uint64_t p) {
510 n = le64toh(f->header->data_hash_table_size) / sizeof(HashItem);
513 q = le64toh(f->data_hash_table[h].head_hash_offset);
520 r = journal_file_move_to_object(f, OBJECT_DATA, q, &o);
524 q = le64toh(o->data.next_hash_offset);
530 static int verify_entry(
532 Object *o, uint64_t p,
533 int data_fd, uint64_t n_data) {
540 assert(data_fd >= 0);
542 n = journal_file_entry_n_items(o);
543 for (i = 0; i < n; i++) {
547 q = le64toh(o->entry.items[i].object_offset);
548 h = le64toh(o->entry.items[i].hash);
550 if (!contains_uint64(f->mmap, data_fd, n_data, q)) {
551 log_error("Invalid data object at entry %llu",
552 (unsigned long long) p);
556 r = journal_file_move_to_object(f, OBJECT_DATA, q, &u);
560 if (le64toh(u->data.hash) != h) {
561 log_error("Hash mismatch for data object at entry %llu",
562 (unsigned long long) p);
566 r = data_object_in_hash_table(f, h, q);
570 log_error("Data object missing from hash at entry %llu",
571 (unsigned long long) p);
579 static int verify_entry_array(
581 int data_fd, uint64_t n_data,
582 int entry_fd, uint64_t n_entries,
583 int entry_array_fd, uint64_t n_entry_arrays,
585 bool show_progress) {
587 uint64_t i = 0, a, n, last = 0;
591 assert(data_fd >= 0);
592 assert(entry_fd >= 0);
593 assert(entry_array_fd >= 0);
596 n = le64toh(f->header->n_entries);
597 a = le64toh(f->header->entry_array_offset);
603 draw_progress(0x8000 + (0x3FFF * i / n), last_usec);
606 log_error("Array chain too short at %llu of %llu",
607 (unsigned long long) i, (unsigned long long) n);
611 if (!contains_uint64(f->mmap, entry_array_fd, n_entry_arrays, a)) {
612 log_error("Invalid array at %llu of %llu",
613 (unsigned long long) i, (unsigned long long) n);
617 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
621 next = le64toh(o->entry_array.next_entry_array_offset);
622 if (next != 0 && next <= a) {
623 log_error("Array chain has cycle at %llu of %llu",
624 (unsigned long long) i, (unsigned long long) n);
628 m = journal_file_entry_array_n_items(o);
629 for (j = 0; i < n && j < m; i++, j++) {
632 p = le64toh(o->entry_array.items[j]);
634 log_error("Entry array not sorted at %llu of %llu",
635 (unsigned long long) i, (unsigned long long) n);
640 if (!contains_uint64(f->mmap, entry_fd, n_entries, p)) {
641 log_error("Invalid array entry at %llu of %llu",
642 (unsigned long long) i, (unsigned long long) n);
646 r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
650 r = verify_entry(f, o, p, data_fd, n_data);
654 /* Pointer might have moved, reposition */
655 r = journal_file_move_to_object(f, OBJECT_ENTRY_ARRAY, a, &o);
666 int journal_file_verify(
669 usec_t *first_validated, usec_t *last_validated, usec_t *last_contained,
670 bool show_progress) {
673 uint64_t p = 0, last_tag = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;
674 uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
675 sd_id128_t entry_boot_id;
676 bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
677 uint64_t n_weird = 0, n_objects = 0, n_entries = 0, n_data = 0, n_fields = 0, n_data_hash_tables = 0, n_field_hash_tables = 0, n_entry_arrays = 0, n_tags = 0;
678 usec_t last_usec = 0;
679 int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
680 char data_path[] = "/var/tmp/journal-data-XXXXXX",
681 entry_path[] = "/var/tmp/journal-entry-XXXXXX",
682 entry_array_path[] = "/var/tmp/journal-entry-array-XXXXXX";
690 r = journal_file_parse_verification_key(f, key);
692 log_error("Failed to parse seed.");
701 data_fd = mkostemp(data_path, O_CLOEXEC);
703 log_error("Failed to create data file: %m");
709 entry_fd = mkostemp(entry_path, O_CLOEXEC);
711 log_error("Failed to create entry file: %m");
717 entry_array_fd = mkostemp(entry_array_path, O_CLOEXEC);
718 if (entry_array_fd < 0) {
719 log_error("Failed to create entry array file: %m");
723 unlink(entry_array_path);
726 if ((le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SEALED) != 0)
728 if (f->header->compatible_flags != 0)
731 log_error("Cannot verify file with unknown extensions.");
736 for (i = 0; i < sizeof(f->header->reserved); i++)
737 if (f->header->reserved[i] != 0) {
738 log_error("Reserved field in non-zero.");
743 /* First iteration: we go through all objects, verify the
744 * superficial structure, headers, hashes. */
746 p = le64toh(f->header->header_size);
749 draw_progress(0x7FFF * p / le64toh(f->header->tail_object_offset), &last_usec);
751 r = journal_file_move_to_object(f, -1, p, &o);
753 log_error("Invalid object at %llu", (unsigned long long) p);
757 if (p > le64toh(f->header->tail_object_offset)) {
758 log_error("Invalid tail object pointer");
763 if (p == le64toh(f->header->tail_object_offset))
768 r = journal_file_object_verify(f, o);
770 log_error("Invalid object contents at %llu", (unsigned long long) p);
774 if ((o->object.flags & OBJECT_COMPRESSED) && !JOURNAL_HEADER_COMPRESSED(f->header)) {
775 log_error("Compressed object in file without compression at %llu", (unsigned long long) p);
780 switch (o->object.type) {
783 r = write_uint64(data_fd, p);
795 if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
796 log_error("First entry before first tag at %llu", (unsigned long long) p);
801 r = write_uint64(entry_fd, p);
805 if (le64toh(o->entry.realtime) < last_tag_realtime) {
806 log_error("Older entry after newer tag at %llu", (unsigned long long) p);
811 if (!entry_seqnum_set &&
812 le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
813 log_error("Head entry sequence number incorrect at %llu", (unsigned long long) p);
818 if (entry_seqnum_set &&
819 entry_seqnum >= le64toh(o->entry.seqnum)) {
820 log_error("Entry sequence number out of synchronization at %llu", (unsigned long long) p);
825 entry_seqnum = le64toh(o->entry.seqnum);
826 entry_seqnum_set = true;
828 if (entry_monotonic_set &&
829 sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
830 entry_monotonic > le64toh(o->entry.monotonic)) {
831 log_error("Entry timestamp out of synchronization at %llu", (unsigned long long) p);
836 entry_monotonic = le64toh(o->entry.monotonic);
837 entry_boot_id = o->entry.boot_id;
838 entry_monotonic_set = true;
840 if (!entry_realtime_set &&
841 le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) {
842 log_error("Head entry realtime timestamp incorrect");
847 entry_realtime = le64toh(o->entry.realtime);
848 entry_realtime_set = true;
853 case OBJECT_DATA_HASH_TABLE:
854 if (n_data_hash_tables > 1) {
855 log_error("More than one data hash table at %llu", (unsigned long long) p);
860 if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) ||
861 le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
862 log_error("Header fields for data hash table invalid");
867 n_data_hash_tables++;
870 case OBJECT_FIELD_HASH_TABLE:
871 if (n_field_hash_tables > 1) {
872 log_error("More than one field hash table at %llu", (unsigned long long) p);
877 if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
878 le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
879 log_error("Header fields for field hash table invalid");
884 n_field_hash_tables++;
887 case OBJECT_ENTRY_ARRAY:
888 r = write_uint64(entry_array_fd, p);
892 if (p == le64toh(f->header->entry_array_offset)) {
893 if (found_main_entry_array) {
894 log_error("More than one main entry array at %llu", (unsigned long long) p);
899 found_main_entry_array = true;
906 if (!JOURNAL_HEADER_SEALED(f->header)) {
907 log_error("Tag object in file without sealing at %llu", (unsigned long long) p);
912 if (le64toh(o->tag.seqnum) != n_tags + 1) {
913 log_error("Tag sequence number out of synchronization at %llu", (unsigned long long) p);
918 if (le64toh(o->tag.epoch) < last_epoch) {
919 log_error("Epoch sequence out of synchronization at %llu", (unsigned long long) p);
928 log_debug("Checking tag %llu..", (unsigned long long) le64toh(o->tag.seqnum));
930 rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
931 if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
932 log_error("Tag/entry realtime timestamp out of synchronization at %llu", (unsigned long long) p);
937 /* OK, now we know the epoch. So let's now set
938 * it, and calculate the HMAC for everything
939 * since the last tag. */
940 r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch));
944 r = journal_file_hmac_start(f);
949 r = journal_file_hmac_put_header(f);
953 q = le64toh(f->header->header_size);
958 r = journal_file_move_to_object(f, -1, q, &o);
962 r = journal_file_hmac_put_object(f, -1, q);
966 q = q + ALIGN64(le64toh(o->object.size));
969 /* Position might have changed, let's reposition things */
970 r = journal_file_move_to_object(f, -1, p, &o);
974 if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
975 log_error("Tag failed verification at %llu", (unsigned long long) p);
980 f->hmac_running = false;
981 last_tag_realtime = rt;
982 last_sealed_realtime = entry_realtime;
986 last_tag = p + ALIGN64(le64toh(o->object.size));
987 last_epoch = le64toh(o->tag.epoch);
996 if (p == le64toh(f->header->tail_object_offset))
999 p = p + ALIGN64(le64toh(o->object.size));
1003 log_error("Tail object pointer dead");
1008 if (n_objects != le64toh(f->header->n_objects)) {
1009 log_error("Object number mismatch");
1014 if (n_entries != le64toh(f->header->n_entries)) {
1015 log_error("Entry number mismatch");
1020 if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
1021 n_data != le64toh(f->header->n_data)) {
1022 log_error("Data number mismatch");
1027 if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
1028 n_fields != le64toh(f->header->n_fields)) {
1029 log_error("Field number mismatch");
1034 if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
1035 n_tags != le64toh(f->header->n_tags)) {
1036 log_error("Tag number mismatch");
1041 if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) &&
1042 n_entry_arrays != le64toh(f->header->n_entry_arrays)) {
1043 log_error("Entry array number mismatch");
1048 if (n_data_hash_tables != 1) {
1049 log_error("Missing data hash table");
1054 if (n_field_hash_tables != 1) {
1055 log_error("Missing field hash table");
1060 if (!found_main_entry_array) {
1061 log_error("Missing entry array");
1066 if (entry_seqnum_set &&
1067 entry_seqnum != le64toh(f->header->tail_entry_seqnum)) {
1068 log_error("Invalid tail seqnum");
1073 if (entry_monotonic_set &&
1074 (!sd_id128_equal(entry_boot_id, f->header->boot_id) ||
1075 entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
1076 log_error("Invalid tail monotonic timestamp");
1081 if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) {
1082 log_error("Invalid tail realtime timestamp");
1087 /* Second iteration: we follow all objects referenced from the
1088 * two entry points: the object hash table and the entry
1089 * array. We also check that everything referenced (directly
1090 * or indirectly) in the data hash table also exists in the
1091 * entry array, and vice versa. Note that we do not care for
1092 * unreferenced objects. We only care that everything that is
1093 * referenced is consistent. */
1095 r = verify_entry_array(f,
1097 entry_fd, n_entries,
1098 entry_array_fd, n_entry_arrays,
1104 r = verify_hash_table(f,
1106 entry_fd, n_entries,
1107 entry_array_fd, n_entry_arrays,
1116 mmap_cache_close_fd(f->mmap, data_fd);
1117 mmap_cache_close_fd(f->mmap, entry_fd);
1118 mmap_cache_close_fd(f->mmap, entry_array_fd);
1120 close_nointr_nofail(data_fd);
1121 close_nointr_nofail(entry_fd);
1122 close_nointr_nofail(entry_array_fd);
1124 if (first_validated)
1125 *first_validated = last_sealed_realtime > 0 ? le64toh(f->header->head_entry_realtime) : 0;
1127 *last_validated = last_sealed_realtime;
1129 *last_contained = le64toh(f->header->tail_entry_realtime);
1137 log_error("File corruption detected at %s:%llu (of %llu, %llu%%).",
1139 (unsigned long long) p,
1140 (unsigned long long) f->last_stat.st_size,
1141 (unsigned long long) (100 * p / f->last_stat.st_size));
1144 mmap_cache_close_fd(f->mmap, data_fd);
1145 close_nointr_nofail(data_fd);
1148 if (entry_fd >= 0) {
1149 mmap_cache_close_fd(f->mmap, entry_fd);
1150 close_nointr_nofail(entry_fd);
1153 if (entry_array_fd >= 0) {
1154 mmap_cache_close_fd(f->mmap, entry_array_fd);
1155 close_nointr_nofail(entry_array_fd);