Skip to content
Closed
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
77 changes: 68 additions & 9 deletions plugins/in_kubernetes_events/kubernetes_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>

#include <fluent-bit/flb_input_plugin.h>
#include <fluent-bit/flb_network.h>
Expand Down Expand Up @@ -179,20 +181,31 @@ static int refresh_token_if_needed(struct k8s_events *ctx)
static msgpack_object *record_get_field_ptr(msgpack_object *obj, const char *fieldname)
{
int i;
size_t fieldname_len;
msgpack_object *k;
msgpack_object *v;

if (obj->type != MSGPACK_OBJECT_MAP) {
return NULL;
}

fieldname_len = strlen(fieldname);

for (i = 0; i < obj->via.map.size; i++) {
k = &obj->via.map.ptr[i].key;
if (k->type != MSGPACK_OBJECT_STR) {
continue;
}

if (strncmp(k->via.str.ptr, fieldname, strlen(fieldname)) == 0) {
/*
* msgpack strings are not NUL terminated: k->via.str.ptr points
* directly into the decode buffer for exactly k->via.str.size
* bytes. Require an exact length match before comparing so we
* never read past that boundary, and so a key that merely shares
* a prefix with fieldname cannot match.
*/
if ((size_t) k->via.str.size == fieldname_len &&
strncmp(k->via.str.ptr, fieldname, fieldname_len) == 0) {
Comment on lines +207 to +208

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve SQL metadata lookup after exact matching

When FLB_HAVE_SQLDB is enabled and the db option is configured, this exact-length lookup makes k8s_events_sql_insert_event() stop finding the event metadata map: that function still calls record_get_field_ptr(item, "meta"), which previously matched the Kubernetes "metadata" key only because the old code accepted prefixes. With this change the insert path always logs unable to find metadata to save event, so the database never records processed UIDs and DB-backed duplicate filtering no longer works; update that caller to request "metadata" before relying on exact key matching.

Useful? React with 👍 / 👎.

v = &obj->via.map.ptr[i].val;
return v;
}
Expand Down Expand Up @@ -220,6 +233,7 @@ static int record_get_field_time(msgpack_object *obj, const char *fieldname, str
{
msgpack_object *v;
struct flb_tm tm = { 0 };
char buf[64];

v = record_get_field_ptr(obj, fieldname);
if (v == NULL) {
Expand All @@ -229,9 +243,26 @@ static int record_get_field_time(msgpack_object *obj, const char *fieldname, str
return -1;
}

if (flb_strptime(v->via.str.ptr, "%Y-%m-%dT%H:%M:%SZ", &tm) == NULL) {
/*
* msgpack strings are not NUL terminated: v->via.str.ptr points
* directly into the decode buffer for exactly v->via.str.size bytes.
* Copy it into a bounded, NUL-terminated stack buffer before handing
* it to flb_strptime(), instead of scanning the raw buffer directly.
*/
if (v->via.str.size == 0 || v->via.str.size >= sizeof(buf)) {
return -2;
}
memcpy(buf, v->via.str.ptr, v->via.str.size);
buf[v->via.str.size] = '\0';

{
char *end;

end = flb_strptime(buf, "%Y-%m-%dT%H:%M:%SZ", &tm);
if (end == NULL || *end != '\0') {
return -2;
}
}

val->tm.tv_sec = flb_parser_tm2time(&tm, FLB_FALSE);
val->tm.tv_nsec = 0;
Expand All @@ -242,7 +273,9 @@ static int record_get_field_time(msgpack_object *obj, const char *fieldname, str
static int record_get_field_uint64(msgpack_object *obj, const char *fieldname, uint64_t *val)
{
msgpack_object *v;
char buf[32];
char *end;
size_t len;

v = record_get_field_ptr(obj, fieldname);
if (v == NULL) {
Expand All @@ -251,8 +284,35 @@ static int record_get_field_uint64(msgpack_object *obj, const char *fieldname, u

/* attempt to parse string as number... */
if (v->type == MSGPACK_OBJECT_STR) {
*val = strtoul(v->via.str.ptr, &end, 10);
if (end == NULL || (end < v->via.str.ptr + v->via.str.size)) {
/*
* msgpack strings are not NUL terminated: v->via.str.ptr points
* directly into the decode buffer for exactly v->via.str.size
* bytes. Copy it into a bounded, NUL-terminated stack buffer
* before calling strtoul() on it, instead of scanning the raw
* buffer directly (no valid uint64 needs more than 20 digits).
*/
len = v->via.str.size;
if (len == 0 || len > sizeof(buf) - 1) {
return -1;
}
memcpy(buf, v->via.str.ptr, len);
buf[len] = '\0';

/*
* strtoull() itself accepts a leading '+'/'-' and skips leading
* whitespace, which would let a value like "-5" silently wrap
* around into a huge positive number instead of being rejected.
* Kubernetes resourceVersion (the only caller) is always a plain,
* unsigned, digits-only decimal string, so require that directly
* before parsing.
*/
if (!isdigit((unsigned char) buf[0])) {
return -1;
}

errno = 0;
*val = strtoull(buf, &end, 10);
if (errno == ERANGE || end == buf || *end != '\0') {
return -1;
}
return 0;
Expand All @@ -262,8 +322,7 @@ static int record_get_field_uint64(msgpack_object *obj, const char *fieldname, u
return 0;
}
if (v->type == MSGPACK_OBJECT_NEGATIVE_INTEGER) {
*val = (uint64_t)v->via.i64;
return 0;
return -1;
}
return -1;
}
Expand All @@ -277,12 +336,12 @@ static int item_get_timestamp(msgpack_object *obj, struct flb_time *event_time)
* NULL while having metadata.creationTimestamp set.
*/
ret = record_get_field_time(obj, "lastTimestamp", event_time);
if (ret != -1) {
if (ret == 0) {
return FLB_TRUE;
}

ret = record_get_field_time(obj, "firstTimestamp", event_time);
if (ret != -1) {
if (ret == 0) {
return FLB_TRUE;
}

Expand All @@ -292,7 +351,7 @@ static int item_get_timestamp(msgpack_object *obj, struct flb_time *event_time)
}

ret = record_get_field_time(metadata, "creationTimestamp", event_time);
if (ret != -1) {
if (ret == 0) {
return FLB_TRUE;
}

Expand Down
Loading