Skip to content
Merged
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
8 changes: 8 additions & 0 deletions src/analysisd/decoders/plugins/ossecalert_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ void *OSSECAlert_Decoder_Exec(Eventinfo *lf)
snprintf(oa_newlocation, 255, "%s|%s", lf->location, oa_location);
free(lf->location);
os_strdup(oa_newlocation, lf->location);
if (lf->flags & EF_FREE_HNAME) {
/* OS_CleanMSG gave us an owned hostname (agent name, #1668):
* release it before aliasing, or Free_Eventinfo frees
* lf->location twice.
*/
free(lf->hostname);
lf->flags &= ~EF_FREE_HNAME;
}
lf->hostname = lf->location;


Expand Down
18 changes: 18 additions & 0 deletions src/tests/regressions/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ REGRESSION_BINS = \
issue_2065_sender_counter \
issue_1611_local_ip_bind \
issue_1668_agent_hostname \
issue_1668_ossecalert_hostname \
unmerge_path_traversal \
jsonout_default \
issue_1814_control_chars \
Expand Down Expand Up @@ -94,6 +95,20 @@ issue_1668_agent_hostname: tests/regressions/issue_1668_agent_hostname.c \
-Wl,--start-group shared.a os_regex.a os_net.a os_xml.a os_zlib.a -Wl,--end-group \
-lpcre2-8 -lm -lpthread -lz

issue_1668_ossecalert_hostname: tests/regressions/issue_1668_ossecalert_hostname.c \
analysisd/cleanevent.c analysisd/eventinfo.c analysisd/eventinfo_list.c \
analysisd/decoders/plugins/ossecalert_decoder.c shared.a
$(CC) $(CFLAGS) -I./analysisd -c analysisd/cleanevent.c -o analysisd/cleanevent-1668oa.o
$(CC) $(CFLAGS) -I./analysisd -c analysisd/eventinfo.c -o analysisd/eventinfo-1668oa.o
$(CC) $(CFLAGS) -I./analysisd -c analysisd/eventinfo_list.c -o analysisd/eventinfo_list-1668oa.o
$(CC) $(CFLAGS) -I./analysisd -c analysisd/decoders/plugins/ossecalert_decoder.c \
-o analysisd/decoders/plugins/ossecalert_decoder-1668oa.o
$(CC) $(CFLAGS) -I./analysisd -o $@ tests/regressions/issue_1668_ossecalert_hostname.c \
analysisd/cleanevent-1668oa.o analysisd/eventinfo-1668oa.o analysisd/eventinfo_list-1668oa.o \
analysisd/decoders/plugins/ossecalert_decoder-1668oa.o \
-Wl,--start-group shared.a os_regex.a os_net.a os_xml.a os_zlib.a -Wl,--end-group \
-lpcre2-8 -lm -lpthread -lz

unmerge_path_traversal: tests/regressions/unmerge_path_traversal.c shared.a
$(CC) $(CFLAGS) -o $@ tests/regressions/unmerge_path_traversal.c \
-Wl,--start-group shared.a os_regex.a -Wl,--end-group \
Expand Down Expand Up @@ -182,6 +197,9 @@ clean:
rm -f $(REGRESSION_BINS) \
analysisd/cleanevent-1668.o analysisd/eventinfo-1668.o \
analysisd/eventinfo_list-1668.o \
analysisd/cleanevent-1668oa.o analysisd/eventinfo-1668oa.o \
analysisd/eventinfo_list-1668oa.o \
analysisd/decoders/plugins/ossecalert_decoder-1668oa.o \
analysisd/cleanevent-1814.o os_auth/ssl-2100.o \
logcollector/read_multiline-underflow.o \
os_crypto/shared/msgs-checksum.o \
Expand Down
2 changes: 2 additions & 0 deletions src/tests/regressions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
# - issue_1274_auth_ipv6_key auth IPv6 key handling
# - issue_2065_sender_counter sender_counter isolated from agent 0 rids
# - issue_1611_local_ip_bind remoted local_ip / ipv6 bind family
# - issue_1668_agent_hostname agent name vs device hostname split
# - issue_1668_ossecalert_hostname OSSECAlert decoder vs owned hostname (double free)
# - jsonout_default jsonout_output on when the XML tag is omitted
# - issue_1814_control_chars strip controls, keep UTF-8
# - issue_1953_xml_recursion OS_ReadXML recursion limit
Expand Down
124 changes: 124 additions & 0 deletions src/tests/regressions/issue_1668_ossecalert_hostname.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Regression for the OSSECAlert decoder after #1668: an agent event with no
* syslog hostname reaches the decoder with an owned lf->hostname
* (EF_FREE_HNAME set). The decoder aliases lf->hostname to lf->location,
* so Free_Eventinfo() used to free the same buffer twice.
*
* ANT-2026-5ZOE8CQ9 / CWE-415
*
* Build (from src/ after make TARGET=server):
* make -f tests/regressions/Makefile issue_1668_ossecalert_hostname
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "shared.h"
#include "analysisd/eventinfo.h"
#include "analysisd/cleanevent.h"
#include "analysisd/config.h"
#include "analysisd/analysisd.h"

_Config Config;
__thread time_t c_time;
__thread int __crt_hour;
__thread int __crt_wday;
char __shost[512];
OSDecoderInfo *NULL_Decoder = NULL;
int alert_only = 1;

void *OSSECAlert_Decoder_Exec(Eventinfo *lf);

static int run_case(const char *name, const char *msg, int want_rule)
{
Eventinfo *lf;
OSDecoderInfo decoder_info;
char *buf;
int rc;
int failed = 0;

printf("--- %s ---\n", name);
os_calloc(1, sizeof(*lf), lf);
Zero_Eventinfo(lf);
memset(&decoder_info, 0, sizeof(decoder_info));
lf->decoder_info = &decoder_info;

os_strdup(msg, buf);
rc = OS_CleanMSG_ex(buf, lf, time(NULL), 0);
free(buf);

if (rc != 0) {
printf("FAIL: OS_CleanMSG_ex returned %d\n", rc);
Free_Eventinfo(lf);
return 1;
}

OSSECAlert_Decoder_Exec(lf);

/* An owned hostname must never share storage with location. */
if ((lf->flags & EF_FREE_HNAME) && lf->hostname == lf->location) {
printf("FAIL: hostname aliases location while EF_FREE_HNAME is set\n");
failed = 1;
}
if (want_rule && !lf->generated_rule) {
printf("FAIL: decoder did not run to completion\n");
failed = 1;
}
if (!failed) {
printf("OK: hostname='%s' location='%s' flags=0x%x\n",
lf->hostname ? lf->hostname : "",
lf->location ? lf->location : "", lf->flags);
}

/* glibc aborts here on the double free. */
Free_Eventinfo(lf);
return failed;
}

int main(void)
{
int failed = 0;
static int rule_1002;

memset(&Config, 0, sizeof(Config));
Config.decoder_order_size = 8;
Config.g_rules_hash = OSHash_Create();
OSHash_Add(Config.g_rules_hash, "1002", &rule_1002);
strncpy(__shost, "managerhost", sizeof(__shost) - 1);
c_time = time(NULL);

printf("=== Issue 1668: OSSECAlert decoder hostname ownership ===\n");

/* No syslog header: hostname is an owned copy of the agent name.
* Trailing field without ';' takes the decoder's early return. */
failed |= run_case(
"agent, no header, early return",
"1:(agent1) any->/var/log/app.log:"
"ossec: Alert Level: 3; Rule: 1002 - x; Location: y; z",
0);

/* Same, but the decoder runs to the end (two spaces after ';'). */
failed |= run_case(
"agent, no header, full decode",
"1:(agent1) any->/var/log/app.log:"
"ossec: Alert Level: 3; Rule: 1002 - x; Location: y; text",
1);

/* Syslog header: hostname points into the log buffer on entry. */
failed |= run_case(
"agent, syslog header",
"1:(agent1) any->/var/log/app.log:"
"Jan 15 12:00:00 web1 ossec: Alert Level: 3; Rule: 1002 - x; "
"Location: y; text",
1);

if (failed) {
printf("\nFAIL: issue_1668_ossecalert_hostname\n");
return 1;
}

printf("\nPASS: issue_1668_ossecalert_hostname\n");
return 0;
}
Loading