Esempio n. 1
0
int hash_remove(void *_hash_table, void *e)
{
	struct hash_table *t = _hash_table;
	void *i, *last_i;
	unsigned int hash;

	verify_hash_table(t);

	hash = t->hash_func(e, NULL, t->table_size);
	last_i = NULL;
	for(i = t->table[hash]; i != NULL; last_i = i, i = NEXT(t, i)) {
		if(i == e) {
			if(last_i != NULL)
				PUT_IN_NEXT(t, last_i, NEXT(t, i));
			else
				t->table[hash] = NEXT(t, i);
			t->num_elems--;
			verify_hash_table(t);
			return NO_ERROR;
		}
	}

	verify_hash_table(t);

	return ERR_GENERAL;
}
Esempio n. 2
0
int hash_insert(void *_hash_table, void *e)
{
	struct hash_table *t = _hash_table;
	unsigned int hash;

//	dprintf("hash_insert: table 0x%x, element 0x%x\n", t, e);

	verify_hash_table(t);

	hash = t->hash_func(e, NULL, t->table_size);
	PUT_IN_NEXT(t, e, t->table[hash]);
	t->table[hash] = e;
	t->num_elems++;

	verify_hash_table(t);

	return 0;
}
Esempio n. 3
0
void *hash_find(void *_hash_table, void *e)
{
	struct hash_table *t = _hash_table;
	void *i;
	unsigned int hash;

	verify_hash_table(t);

	hash = t->hash_func(e, NULL, t->table_size);
	for(i = t->table[hash]; i != NULL; i = NEXT(t, i)) {
		if(i == e) {
			return i;
		}
	}

	return NULL;
}
Esempio n. 4
0
void *hash_lookup(void *_hash_table, const void *key)
{
	struct hash_table *t = _hash_table;
	void *i;
	unsigned int hash;

	if(t->compare_func == NULL)
		return NULL;

	verify_hash_table(t);

	hash = t->hash_func(NULL, key, t->table_size);
	for(i = t->table[hash]; i != NULL; i = NEXT(t, i)) {
		if(t->compare_func(i, key) == 0) {
			return i;
		}
	}

	return NULL;
}
Esempio n. 5
0
void *hash_next(void *_hash_table, struct hash_iterator *i)
{
	struct hash_table *t = _hash_table;
	unsigned int index;

	verify_hash_table(t);

restart:
	if(!i->ptr) {
		for(index = (unsigned int)(i->bucket + 1); index < t->table_size; index++) {
			if(t->table[index]) {
				i->bucket = index;
				i->ptr = t->table[index];
				break;
			}
		}
	} else {
		i->ptr = NEXT(t, i->ptr);
		if(!i->ptr)
			goto restart;
	}

	return i->ptr;
}
Esempio n. 6
0
int journal_file_verify(
                JournalFile *f,
                const char *key,
                usec_t *first_contained, usec_t *last_validated, usec_t *last_contained,
                bool show_progress) {
        int r;
        Object *o;
        uint64_t p = 0, last_epoch = 0, last_tag_realtime = 0, last_sealed_realtime = 0;

        uint64_t entry_seqnum = 0, entry_monotonic = 0, entry_realtime = 0;
        sd_id128_t entry_boot_id;
        bool entry_seqnum_set = false, entry_monotonic_set = false, entry_realtime_set = false, found_main_entry_array = false;
        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;
        usec_t last_usec = 0;
        int data_fd = -1, entry_fd = -1, entry_array_fd = -1;
        unsigned i;
        bool found_last = false;
#ifdef HAVE_GCRYPT
        uint64_t last_tag = 0;
#endif
        assert(f);

        if (key) {
#ifdef HAVE_GCRYPT
                r = journal_file_parse_verification_key(f, key);
                if (r < 0) {
                        log_error("Failed to parse seed.");
                        return r;
                }
#else
                return -ENOTSUP;
#endif
        } else if (f->seal)
                return -ENOKEY;

        data_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
        if (data_fd < 0) {
                log_error_errno(errno, "Failed to create data file: %m");
                r = -errno;
                goto fail;
        }

        entry_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
        if (entry_fd < 0) {
                log_error_errno(errno, "Failed to create entry file: %m");
                r = -errno;
                goto fail;
        }

        entry_array_fd = open_tmpfile("/var/tmp", O_RDWR | O_CLOEXEC);
        if (entry_array_fd < 0) {
                log_error_errno(errno, "Failed to create entry array file: %m");
                r = -errno;
                goto fail;
        }

        if (le32toh(f->header->compatible_flags) & ~HEADER_COMPATIBLE_SUPPORTED) {
                log_error("Cannot verify file with unknown extensions.");
                r = -ENOTSUP;
                goto fail;
        }

        for (i = 0; i < sizeof(f->header->reserved); i++)
                if (f->header->reserved[i] != 0) {
                        error(offsetof(Header, reserved[i]), "Reserved field is non-zero");
                        r = -EBADMSG;
                        goto fail;
                }

        /* First iteration: we go through all objects, verify the
         * superficial structure, headers, hashes. */

        p = le64toh(f->header->header_size);
        for (;;) {
                /* Early exit if there are no objects in the file, at all */
                if (le64toh(f->header->tail_object_offset) == 0)
                        break;

                if (show_progress)
                        draw_progress(scale_progress(0x7FFF, p, le64toh(f->header->tail_object_offset)), &last_usec);

                r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
                if (r < 0) {
                        error(p, "Invalid object");
                        goto fail;
                }

                if (p > le64toh(f->header->tail_object_offset)) {
                        error(offsetof(Header, tail_object_offset), "Invalid tail object pointer");
                        r = -EBADMSG;
                        goto fail;
                }

                n_objects ++;

                r = journal_file_object_verify(f, p, o);
                if (r < 0) {
                        error(p, "Invalid object contents: %s", strerror(-r));
                        goto fail;
                }

                if ((o->object.flags & OBJECT_COMPRESSED_XZ) &&
                    (o->object.flags & OBJECT_COMPRESSED_LZ4)) {
                        error(p, "Objected with double compression");
                        r = -EINVAL;
                        goto fail;
                }

                if ((o->object.flags & OBJECT_COMPRESSED_XZ) && !JOURNAL_HEADER_COMPRESSED_XZ(f->header)) {
                        error(p, "XZ compressed object in file without XZ compression");
                        r = -EBADMSG;
                        goto fail;
                }

                if ((o->object.flags & OBJECT_COMPRESSED_LZ4) && !JOURNAL_HEADER_COMPRESSED_LZ4(f->header)) {
                        error(p, "LZ4 compressed object in file without LZ4 compression");
                        r = -EBADMSG;
                        goto fail;
                }

                switch (o->object.type) {

                case OBJECT_DATA:
                        r = write_uint64(data_fd, p);
                        if (r < 0)
                                goto fail;

                        n_data++;
                        break;

                case OBJECT_FIELD:
                        n_fields++;
                        break;

                case OBJECT_ENTRY:
                        if (JOURNAL_HEADER_SEALED(f->header) && n_tags <= 0) {
                                error(p, "First entry before first tag");
                                r = -EBADMSG;
                                goto fail;
                        }

                        r = write_uint64(entry_fd, p);
                        if (r < 0)
                                goto fail;

                        if (le64toh(o->entry.realtime) < last_tag_realtime) {
                                error(p, "Older entry after newer tag");
                                r = -EBADMSG;
                                goto fail;
                        }

                        if (!entry_seqnum_set &&
                            le64toh(o->entry.seqnum) != le64toh(f->header->head_entry_seqnum)) {
                                error(p, "Head entry sequence number incorrect");
                                r = -EBADMSG;
                                goto fail;
                        }

                        if (entry_seqnum_set &&
                            entry_seqnum >= le64toh(o->entry.seqnum)) {
                                error(p, "Entry sequence number out of synchronization");
                                r = -EBADMSG;
                                goto fail;
                        }

                        entry_seqnum = le64toh(o->entry.seqnum);
                        entry_seqnum_set = true;

                        if (entry_monotonic_set &&
                            sd_id128_equal(entry_boot_id, o->entry.boot_id) &&
                            entry_monotonic > le64toh(o->entry.monotonic)) {
                                error(p, "Entry timestamp out of synchronization");
                                r = -EBADMSG;
                                goto fail;
                        }

                        entry_monotonic = le64toh(o->entry.monotonic);
                        entry_boot_id = o->entry.boot_id;
                        entry_monotonic_set = true;

                        if (!entry_realtime_set &&
                            le64toh(o->entry.realtime) != le64toh(f->header->head_entry_realtime)) {
                                error(p, "Head entry realtime timestamp incorrect");
                                r = -EBADMSG;
                                goto fail;
                        }

                        entry_realtime = le64toh(o->entry.realtime);
                        entry_realtime_set = true;

                        n_entries ++;
                        break;

                case OBJECT_DATA_HASH_TABLE:
                        if (n_data_hash_tables > 1) {
                                error(p, "More than one data hash table");
                                r = -EBADMSG;
                                goto fail;
                        }

                        if (le64toh(f->header->data_hash_table_offset) != p + offsetof(HashTableObject, items) ||
                            le64toh(f->header->data_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
                                error(p, "header fields for data hash table invalid");
                                r = -EBADMSG;
                                goto fail;
                        }

                        n_data_hash_tables++;
                        break;

                case OBJECT_FIELD_HASH_TABLE:
                        if (n_field_hash_tables > 1) {
                                error(p, "More than one field hash table");
                                r = -EBADMSG;
                                goto fail;
                        }

                        if (le64toh(f->header->field_hash_table_offset) != p + offsetof(HashTableObject, items) ||
                            le64toh(f->header->field_hash_table_size) != le64toh(o->object.size) - offsetof(HashTableObject, items)) {
                                error(p, "Header fields for field hash table invalid");
                                r = -EBADMSG;
                                goto fail;
                        }

                        n_field_hash_tables++;
                        break;

                case OBJECT_ENTRY_ARRAY:
                        r = write_uint64(entry_array_fd, p);
                        if (r < 0)
                                goto fail;

                        if (p == le64toh(f->header->entry_array_offset)) {
                                if (found_main_entry_array) {
                                        error(p, "More than one main entry array");
                                        r = -EBADMSG;
                                        goto fail;
                                }

                                found_main_entry_array = true;
                        }

                        n_entry_arrays++;
                        break;

                case OBJECT_TAG:
                        if (!JOURNAL_HEADER_SEALED(f->header)) {
                                error(p, "Tag object in file without sealing");
                                r = -EBADMSG;
                                goto fail;
                        }

                        if (le64toh(o->tag.seqnum) != n_tags + 1) {
                                error(p, "Tag sequence number out of synchronization");
                                r = -EBADMSG;
                                goto fail;
                        }

                        if (le64toh(o->tag.epoch) < last_epoch) {
                                error(p, "Epoch sequence out of synchronization");
                                r = -EBADMSG;
                                goto fail;
                        }

#ifdef HAVE_GCRYPT
                        if (f->seal) {
                                uint64_t q, rt;

                                debug(p, "Checking tag %"PRIu64"...", le64toh(o->tag.seqnum));

                                rt = f->fss_start_usec + o->tag.epoch * f->fss_interval_usec;
                                if (entry_realtime_set && entry_realtime >= rt + f->fss_interval_usec) {
                                        error(p, "tag/entry realtime timestamp out of synchronization");
                                        r = -EBADMSG;
                                        goto fail;
                                }

                                /* OK, now we know the epoch. So let's now set
                                 * it, and calculate the HMAC for everything
                                 * since the last tag. */
                                r = journal_file_fsprg_seek(f, le64toh(o->tag.epoch));
                                if (r < 0)
                                        goto fail;

                                r = journal_file_hmac_start(f);
                                if (r < 0)
                                        goto fail;

                                if (last_tag == 0) {
                                        r = journal_file_hmac_put_header(f);
                                        if (r < 0)
                                                goto fail;

                                        q = le64toh(f->header->header_size);
                                } else
                                        q = last_tag;

                                while (q <= p) {
                                        r = journal_file_move_to_object(f, OBJECT_UNUSED, q, &o);
                                        if (r < 0)
                                                goto fail;

                                        r = journal_file_hmac_put_object(f, OBJECT_UNUSED, o, q);
                                        if (r < 0)
                                                goto fail;

                                        q = q + ALIGN64(le64toh(o->object.size));
                                }

                                /* Position might have changed, let's reposition things */
                                r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
                                if (r < 0)
                                        goto fail;

                                if (memcmp(o->tag.tag, gcry_md_read(f->hmac, 0), TAG_LENGTH) != 0) {
                                        error(p, "Tag failed verification");
                                        r = -EBADMSG;
                                        goto fail;
                                }

                                f->hmac_running = false;
                                last_tag_realtime = rt;
                                last_sealed_realtime = entry_realtime;
                        }

                        last_tag = p + ALIGN64(le64toh(o->object.size));
#endif

                        last_epoch = le64toh(o->tag.epoch);

                        n_tags ++;
                        break;

                default:
                        n_weird ++;
                }

                if (p == le64toh(f->header->tail_object_offset)) {
                        found_last = true;
                        break;
                }

                p = p + ALIGN64(le64toh(o->object.size));
        };

        if (!found_last && le64toh(f->header->tail_object_offset) != 0) {
                error(le64toh(f->header->tail_object_offset), "Tail object pointer dead");
                r = -EBADMSG;
                goto fail;
        }

        if (n_objects != le64toh(f->header->n_objects)) {
                error(offsetof(Header, n_objects), "Object number mismatch");
                r = -EBADMSG;
                goto fail;
        }

        if (n_entries != le64toh(f->header->n_entries)) {
                error(offsetof(Header, n_entries), "Entry number mismatch");
                r = -EBADMSG;
                goto fail;
        }

        if (JOURNAL_HEADER_CONTAINS(f->header, n_data) &&
            n_data != le64toh(f->header->n_data)) {
                error(offsetof(Header, n_data), "Data number mismatch");
                r = -EBADMSG;
                goto fail;
        }

        if (JOURNAL_HEADER_CONTAINS(f->header, n_fields) &&
            n_fields != le64toh(f->header->n_fields)) {
                error(offsetof(Header, n_fields), "Field number mismatch");
                r = -EBADMSG;
                goto fail;
        }

        if (JOURNAL_HEADER_CONTAINS(f->header, n_tags) &&
            n_tags != le64toh(f->header->n_tags)) {
                error(offsetof(Header, n_tags), "Tag number mismatch");
                r = -EBADMSG;
                goto fail;
        }

        if (JOURNAL_HEADER_CONTAINS(f->header, n_entry_arrays) &&
            n_entry_arrays != le64toh(f->header->n_entry_arrays)) {
                error(offsetof(Header, n_entry_arrays), "Entry array number mismatch");
                r = -EBADMSG;
                goto fail;
        }

        if (!found_main_entry_array && le64toh(f->header->entry_array_offset) != 0) {
                error(0, "Missing entry array");
                r = -EBADMSG;
                goto fail;
        }

        if (entry_seqnum_set &&
            entry_seqnum != le64toh(f->header->tail_entry_seqnum)) {
                error(offsetof(Header, tail_entry_seqnum), "Invalid tail seqnum");
                r = -EBADMSG;
                goto fail;
        }

        if (entry_monotonic_set &&
            (!sd_id128_equal(entry_boot_id, f->header->boot_id) ||
             entry_monotonic != le64toh(f->header->tail_entry_monotonic))) {
                error(0, "Invalid tail monotonic timestamp");
                r = -EBADMSG;
                goto fail;
        }

        if (entry_realtime_set && entry_realtime != le64toh(f->header->tail_entry_realtime)) {
                error(0, "Invalid tail realtime timestamp");
                r = -EBADMSG;
                goto fail;
        }

        /* Second iteration: we follow all objects referenced from the
         * two entry points: the object hash table and the entry
         * array. We also check that everything referenced (directly
         * or indirectly) in the data hash table also exists in the
         * entry array, and vice versa. Note that we do not care for
         * unreferenced objects. We only care that everything that is
         * referenced is consistent. */

        r = verify_entry_array(f,
                               data_fd, n_data,
                               entry_fd, n_entries,
                               entry_array_fd, n_entry_arrays,
                               &last_usec,
                               show_progress);
        if (r < 0)
                goto fail;

        r = verify_hash_table(f,
                              data_fd, n_data,
                              entry_fd, n_entries,
                              entry_array_fd, n_entry_arrays,
                              &last_usec,
                              show_progress);
        if (r < 0)
                goto fail;

        if (show_progress)
                flush_progress();

        mmap_cache_close_fd(f->mmap, data_fd);
        mmap_cache_close_fd(f->mmap, entry_fd);
        mmap_cache_close_fd(f->mmap, entry_array_fd);

        safe_close(data_fd);
        safe_close(entry_fd);
        safe_close(entry_array_fd);

        if (first_contained)
                *first_contained = le64toh(f->header->head_entry_realtime);
        if (last_validated)
                *last_validated = last_sealed_realtime;
        if (last_contained)
                *last_contained = le64toh(f->header->tail_entry_realtime);

        return 0;

fail:
        if (show_progress)
                flush_progress();

        log_error("File corruption detected at %s:"OFSfmt" (of %llu bytes, %"PRIu64"%%).",
                  f->path,
                  p,
                  (unsigned long long) f->last_stat.st_size,
                  100 * p / f->last_stat.st_size);

        if (data_fd >= 0) {
                mmap_cache_close_fd(f->mmap, data_fd);
                safe_close(data_fd);
        }

        if (entry_fd >= 0) {
                mmap_cache_close_fd(f->mmap, entry_fd);
                safe_close(entry_fd);
        }

        if (entry_array_fd >= 0) {
                mmap_cache_close_fd(f->mmap, entry_array_fd);
                safe_close(entry_array_fd);
        }

        return r;
}
Esempio n. 7
0
int
main()
{
	struct sockaddr_in	from_addr;
	socklen_t		from_addr_len;
	ssize_t			recvbytes;
	int			sockfd;
	char			buf[64*1024];
	char			done;
#ifdef	TIMEIT
#endif
	struct timeval		start_time, end_time;
	unsigned long long	s, e;


	if ((sockfd = init_tracker_comm(TRACKER_PORT)) < 0) {
		fprintf(stderr, "main:init_tracker_comm:failed\n");
		abort();
	}

	if (init_hash_table(HASH_TABLE_ENTRIES) != 0) {
		fprintf(stderr, "main:init_hash_table:failed\n");
		abort();
	}

#ifdef	DEBUG
	fprintf(stderr, "main:starting\n");
#endif

	/*
	 * needed for shuffle()
	 */
	srand(time(NULL));

	done = 0;
	while (!done) {
		from_addr_len = sizeof(from_addr);
		recvbytes = tracker_recv(sockfd, buf, sizeof(buf),
			(struct sockaddr *)&from_addr, &from_addr_len, NULL);

		if (recvbytes > 0) {
			tracker_header_t	*p;

			p = (tracker_header_t *)buf;

			gettimeofday(&start_time, NULL);
#ifdef	TIMEIT
#endif

			fprintf(stderr, "%lld : main:op %d from %s seqno %d\n",
				(long long int)start_time.tv_sec, p->op,
				inet_ntoa(from_addr.sin_addr), p->seqno);
#ifdef	DEBUG
#endif

			switch(p->op) {
			case LOOKUP:
				{
					tracker_lookup_req_t	*req;

					req = (tracker_lookup_req_t *)buf;
					dolookup(sockfd, req->hash, req->header.seqno, &from_addr);
				}
				break;

			case REGISTER:
				register_hash(buf, &from_addr);
				break;

			case UNREGISTER:
				unregister_hash(buf, &from_addr);
				break;

			case PEER_DONE:
				unregister_all(buf, &from_addr);
				break;

			case STOP_SERVER:
				fprintf(stderr,
					"Received 'STOP_SERVER' from (%s)\n",
					inet_ntoa(from_addr.sin_addr));
				exit(0);

			default:
				fprintf(stderr, "Unknown op (%d)\n", p->op);
				abort();
				break;
			}

			gettimeofday(&end_time, NULL);
			s = (start_time.tv_sec * 1000000) + start_time.tv_usec;
			e = (end_time.tv_sec * 1000000) + end_time.tv_usec;
			fprintf(stderr, "main:svc time: %lld\n", (e - s));
#ifdef	TIMEIT
#endif
#ifdef	LATER
			verify_hash_table();
#endif
		}
	}

	return(0);
}