Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions src/database.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
#include "hs_db_hmac_key.h"
#include "nfa/nfa_internal.h"
#include "nfa/limex_internal.h"
#include "fdr/fdr.h"
#include "fdr/fdr_internal.h"
#include "hwlm/hwlm_internal.h"
#include "rose/rose_internal.h"
#include "util/compile_error.h"
#include "util/unaligned.h"
Expand Down Expand Up @@ -270,6 +273,69 @@ hs_error_t db_check_integrity(const hs_database_t *db) {
return HS_SUCCESS;
}

/**
* \brief Validate FDR engineID fields in HWLM matchers (CWE-125).
*
* fdrExec() uses fdr->engineID as an index into a static funcs[] dispatch
* table of FDR_ENGINE_COUNT entries. A forged value >= FDR_ENGINE_COUNT
* causes a global-buffer-overflow. Reject any database containing such a
* value before hs_scan() can reach fdrExec().
*
* We check every HWLM matcher reachable from the RoseEngine (fmatcherOffset,
* ematcherOffset, amatcherOffset, sbmatcherOffset, drmatcherOffset).
*/
static
hs_error_t db_validate_fdr_engine_id(const struct RoseEngine *rose,
u32 rose_size) {
const char *base = (const char *)rose;

/* All matcher offset fields we need to check */
const u32 offsets[] = {
rose->fmatcherOffset,
rose->ematcherOffset,
rose->amatcherOffset,
rose->sbmatcherOffset,
rose->drmatcherOffset,
};

for (u32 k = 0; k < ARRAY_LENGTH(offsets); k++) {
u32 off = offsets[k];
if (!off) {
continue;
}

if (unlikely(off >= rose_size ||
off + sizeof(struct HWLM) > rose_size)) {
DEBUG_PRINTF("HWLM matcher offset %u out of bounds\n", off);
return HS_INVALID;
}
Comment on lines +307 to +311

const struct HWLM *hwlm = (const struct HWLM *)(base + off);

if (hwlm->type != HWLM_ENGINE_FDR) {
continue; /* only FDR engines have an engineID */
}

/* FDR struct immediately follows the HWLM header (cache-line aligned).
* Use the same layout formula as HWLM_C_DATA(). */
u32 fdr_rel = (u32)ROUNDUP_CL(sizeof(struct HWLM));
if (unlikely((u64a)off + fdr_rel + sizeof(struct FDR) > rose_size)) {
DEBUG_PRINTF("FDR struct out of bounds at offset %u\n", off);
return HS_INVALID;
}

const struct FDR *fdr = (const struct FDR *)HWLM_C_DATA(hwlm);

if (unlikely(fdr->engineID >= FDR_ENGINE_COUNT)) {
DEBUG_PRINTF("FDR engineID %u >= FDR_ENGINE_COUNT %u\n",
fdr->engineID, FDR_ENGINE_COUNT);
return HS_INVALID;
}
}

return HS_SUCCESS;
}

/**
* \brief Validate critical RoseEngine offsets to prevent out-of-bounds
* access (CWE-125) when scanning a deserialized database.
Expand Down Expand Up @@ -497,6 +563,12 @@ hs_error_t db_validate_rose_offsets(const hs_database_t *db) {
return HS_INVALID;
}

/* Validate FDR engineID (CWE-125). */
if (unlikely(db_validate_fdr_engine_id(rose, rose_size) != HS_SUCCESS)) {
DEBUG_PRINTF("FDR engineID validation failed\n");
return HS_INVALID;
}

DEBUG_PRINTF("rose offset validation passed\n");
return HS_SUCCESS;
}
Expand Down
8 changes: 8 additions & 0 deletions src/fdr/fdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,10 @@ hwlm_error_t fdrExec(const struct FDR *fdr, const u8 *buf, size_t len,
if (unlikely(a.start_offset >= a.len)) {
return HWLM_SUCCESS;
} else {
assert(fdr->engineID < ARRAY_LENGTH(funcs));
if (unlikely(fdr->engineID >= ARRAY_LENGTH(funcs))) {
return HWLM_SUCCESS; /* reject: forged engineID */
}
Comment on lines +848 to +851
assert(funcs[fdr->engineID]);
return funcs[fdr->engineID](fdr, &a, groups);
}
Expand Down Expand Up @@ -873,6 +877,10 @@ hwlm_error_t fdrExecStreaming(const struct FDR *fdr, const u8 *hbuf,
if (unlikely(a.start_offset >= a.len)) {
ret = HWLM_SUCCESS;
} else {
assert(fdr->engineID < ARRAY_LENGTH(funcs));
if (unlikely(fdr->engineID >= ARRAY_LENGTH(funcs))) {
return HWLM_SUCCESS; /* reject: forged engineID */
}
assert(funcs[fdr->engineID]);
ret = funcs[fdr->engineID](fdr, &a, groups);
}
Expand Down
4 changes: 4 additions & 0 deletions src/fdr/fdr.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
#include "ue2common.h"
#include "hwlm/hwlm.h"

/** Number of entries in the fdrExec dispatch table (funcs[]). Any serialized
* FDR engineID must be strictly less than this value. */
#define FDR_ENGINE_COUNT 19
Comment on lines +39 to +41

// C linkage in the API
#ifdef __cplusplus
extern "C" {
Expand Down