mirror of
https://salsa.debian.org/ha-team/libqb
synced 2026-01-03 06:57:38 +00:00
Fix: ringbuffer: Add file header version field and detect reading corrupted blackbox files using hash value
In the future, if something changes in the file header we can increment the version and split up the parsing into separate functions for backwards compatibility.
This commit is contained in:
parent
11b18cced4
commit
a2bdeed3cc
@ -22,6 +22,8 @@
|
||||
#include <qb/qbdefs.h>
|
||||
#include "atomic_int.h"
|
||||
|
||||
#define QB_RB_FILE_HEADER_VERSION 1
|
||||
|
||||
/*
|
||||
* #define CRAZY_DEBUG_PRINTFS 1
|
||||
*/
|
||||
@ -717,17 +719,33 @@ print_header(struct qb_ringbuffer_s * rb)
|
||||
#endif /* S_SPLINT_S */
|
||||
}
|
||||
|
||||
/*
|
||||
* FILE HEADER ORDER
|
||||
* 1. word_size
|
||||
* 2. write_pt
|
||||
* 3. read_pt
|
||||
* 4. version
|
||||
* 5. header_hash
|
||||
*
|
||||
* 6. data
|
||||
*/
|
||||
|
||||
ssize_t
|
||||
qb_rb_write_to_file(struct qb_ringbuffer_s * rb, int32_t fd)
|
||||
{
|
||||
ssize_t result;
|
||||
ssize_t written_size = 0;
|
||||
uint32_t hash = 0;
|
||||
uint32_t version = QB_RB_FILE_HEADER_VERSION;
|
||||
|
||||
if (rb == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
print_header(rb);
|
||||
|
||||
/*
|
||||
* 1. word_size
|
||||
*/
|
||||
result = write(fd, &rb->shared_hdr->word_size, sizeof(uint32_t));
|
||||
if (result != sizeof(uint32_t)) {
|
||||
return -errno;
|
||||
@ -735,7 +753,7 @@ qb_rb_write_to_file(struct qb_ringbuffer_s * rb, int32_t fd)
|
||||
written_size += result;
|
||||
|
||||
/*
|
||||
* store the read & write pointers
|
||||
* 2. 3. store the read & write pointers
|
||||
*/
|
||||
result = write(fd, (void *)&rb->shared_hdr->write_pt, sizeof(uint32_t));
|
||||
if (result != sizeof(uint32_t)) {
|
||||
@ -748,6 +766,25 @@ qb_rb_write_to_file(struct qb_ringbuffer_s * rb, int32_t fd)
|
||||
}
|
||||
written_size += result;
|
||||
|
||||
/*
|
||||
* 4. version used
|
||||
*/
|
||||
result = write(fd, &version, sizeof(uint32_t));
|
||||
if (result != sizeof(uint32_t)) {
|
||||
return -errno;
|
||||
}
|
||||
written_size += result;
|
||||
|
||||
/*
|
||||
* 5. hash helps us verify header is not corrupted on file read
|
||||
*/
|
||||
hash = rb->shared_hdr->word_size + rb->shared_hdr->write_pt + rb->shared_hdr->read_pt + QB_RB_FILE_HEADER_VERSION;
|
||||
result = write(fd, &hash, sizeof(uint32_t));
|
||||
if (result != sizeof(uint32_t)) {
|
||||
return -errno;
|
||||
}
|
||||
written_size += result;
|
||||
|
||||
result = write(fd, rb->shared_data,
|
||||
rb->shared_hdr->word_size * sizeof(uint32_t));
|
||||
if (result != rb->shared_hdr->word_size * sizeof(uint32_t)) {
|
||||
@ -770,11 +807,17 @@ qb_rb_create_from_file(int32_t fd, uint32_t flags)
|
||||
uint32_t write_pt;
|
||||
struct qb_ringbuffer_s *rb;
|
||||
uint32_t word_size = 0;
|
||||
uint32_t version = 0;
|
||||
uint32_t hash = 0;
|
||||
uint32_t calculated_hash = 0;
|
||||
|
||||
if (fd < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. word size
|
||||
*/
|
||||
n_required = sizeof(uint32_t);
|
||||
n_read = read(fd, &word_size, n_required);
|
||||
if (n_read != n_required) {
|
||||
@ -783,6 +826,9 @@ qb_rb_create_from_file(int32_t fd, uint32_t flags)
|
||||
}
|
||||
total_read += n_read;
|
||||
|
||||
/*
|
||||
* 2. 3. read & write pointers
|
||||
*/
|
||||
n_read = read(fd, &write_pt, sizeof(uint32_t));
|
||||
assert(n_read == sizeof(uint32_t));
|
||||
total_read += n_read;
|
||||
@ -791,12 +837,41 @@ qb_rb_create_from_file(int32_t fd, uint32_t flags)
|
||||
assert(n_read == sizeof(uint32_t));
|
||||
total_read += n_read;
|
||||
|
||||
if (write_pt > word_size || read_pt > word_size) {
|
||||
qb_util_log(LOG_ERR, "Corrupt blackbox: read_pt:%d, write_pt:%d, word_size:%d",
|
||||
read_pt, write_pt, word_size);
|
||||
/*
|
||||
* 4. version
|
||||
*/
|
||||
n_required = sizeof(uint32_t);
|
||||
n_read = read(fd, &version, n_required);
|
||||
if (n_read != n_required) {
|
||||
qb_util_perror(LOG_ERR, "Unable to read blackbox file header");
|
||||
return NULL;
|
||||
}
|
||||
total_read += n_read;
|
||||
|
||||
/*
|
||||
* 5. Hash
|
||||
*/
|
||||
n_required = sizeof(uint32_t);
|
||||
n_read = read(fd, &hash, n_required);
|
||||
if (n_read != n_required) {
|
||||
qb_util_perror(LOG_ERR, "Unable to read blackbox file header");
|
||||
return NULL;
|
||||
}
|
||||
total_read += n_read;
|
||||
|
||||
calculated_hash = word_size + write_pt + read_pt + version;
|
||||
if (hash != calculated_hash) {
|
||||
qb_util_log(LOG_ERR, "Corrupt blackbox: File header hash (%d) does not match calculated hash (%d)", hash, calculated_hash);
|
||||
return NULL;
|
||||
} else if (version != QB_RB_FILE_HEADER_VERSION) {
|
||||
qb_util_log(LOG_ERR, "Wrong file header version. Expected %d got %d",
|
||||
QB_RB_FILE_HEADER_VERSION, version);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* 6. data
|
||||
*/
|
||||
n_required = (word_size * sizeof(uint32_t));
|
||||
rb = qb_rb_open("create_from_file", n_required,
|
||||
QB_RB_FLAG_CREATE | QB_RB_FLAG_NO_SEMAPHORE, 0);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user