From 7780613e65b4c0790a77380dcad669e6078b0473 Mon Sep 17 00:00:00 2001 From: BinduSri-6522866 Date: Thu, 4 Dec 2025 02:33:20 +0530 Subject: [PATCH] Patch fluent-bit for CVE-2025-12977 [High] and CVE-2025-12969 [Medium] (#15199) (cherry picked from commit 22f4c0e9fee7821906d1e8bd121599f9daf2ee70) --- SPECS/fluent-bit/CVE-2025-12969.patch | 321 ++++++++++++++ SPECS/fluent-bit/CVE-2025-12977.patch | 595 ++++++++++++++++++++++++++ SPECS/fluent-bit/fluent-bit.spec | 7 +- 3 files changed, 922 insertions(+), 1 deletion(-) create mode 100644 SPECS/fluent-bit/CVE-2025-12969.patch create mode 100644 SPECS/fluent-bit/CVE-2025-12977.patch diff --git a/SPECS/fluent-bit/CVE-2025-12969.patch b/SPECS/fluent-bit/CVE-2025-12969.patch new file mode 100644 index 00000000000..acc29af07b5 --- /dev/null +++ b/SPECS/fluent-bit/CVE-2025-12969.patch @@ -0,0 +1,321 @@ +From e42b5cebbdd3d9c702babf446a3143abf78e2d87 Mon Sep 17 00:00:00 2001 +From: Hiroshi Hatake +Date: Fri, 3 Oct 2025 16:14:34 +0900 +Subject: [PATCH] in_forward: Handle shared_key lifetime correctly + +Signed-off-by: Hiroshi Hatake + +Upstream Patch reference: https://patch-diff.githubusercontent.com/raw/fluent/fluent-bit/pull/10973.diff +--- + plugins/in_forward/fw.c | 10 +++ + plugins/in_forward/fw.h | 4 +- + plugins/in_forward/fw_config.c | 41 +++++++-- + plugins/in_forward/fw_conn.c | 13 ++- + tests/runtime/in_forward.c | 156 +++++++++++++++++++++++++++++++++ + 5 files changed, 215 insertions(+), 9 deletions(-) + +diff --git a/plugins/in_forward/fw.c b/plugins/in_forward/fw.c +index 7c99d58..2827639 100644 +--- a/plugins/in_forward/fw.c ++++ b/plugins/in_forward/fw.c +@@ -325,6 +325,16 @@ static int in_fw_init(struct flb_input_instance *ins, + return -1; + } + ++ /* Users-only configuration must be rejected unless a (possibly empty) shared key is enabled. */ ++ if (mk_list_size(&ctx->users) > 0 && ++ ctx->shared_key == NULL && ++ ctx->empty_shared_key == FLB_FALSE) { ++ flb_plg_error(ctx->ins, "security.users is set but no shared_key or empty_shared_key"); ++ delete_users(ctx); ++ fw_config_destroy(ctx); ++ return -1; ++ } ++ + flb_input_downstream_set(ctx->downstream, ctx->ins); + + flb_net_socket_nonblocking(ctx->downstream->server_fd); +diff --git a/plugins/in_forward/fw.h b/plugins/in_forward/fw.h +index 70c5de5..282e03d 100644 +--- a/plugins/in_forward/fw.h ++++ b/plugins/in_forward/fw.h +@@ -60,9 +60,11 @@ struct flb_in_fw_config { + flb_sds_t unix_perm_str; /* Permission (config map) */ + + /* secure forward */ +- flb_sds_t shared_key; /* shared key */ ++ flb_sds_t shared_key; /* shared key */ ++ int owns_shared_key; /* own flag of shared key */ + flb_sds_t self_hostname; /* hostname used in certificate */ + struct mk_list users; /* username and password pairs */ ++ int empty_shared_key; /* use an empty string as shared key */ + + int coll_fd; + struct flb_downstream *downstream; /* Client manager */ +diff --git a/plugins/in_forward/fw_config.c b/plugins/in_forward/fw_config.c +index b3a2293..fb1cbc4 100644 +--- a/plugins/in_forward/fw_config.c ++++ b/plugins/in_forward/fw_config.c +@@ -26,6 +26,35 @@ + #include "fw_conn.h" + #include "fw_config.h" + ++static void fw_destroy_shared_key(struct flb_in_fw_config *config) ++{ ++ if (config->owns_shared_key && config->shared_key) { ++ flb_sds_destroy(config->shared_key); ++ } ++ ++ config->shared_key = NULL; ++ config->owns_shared_key = FLB_FALSE; ++} ++ ++static int fw_create_empty_shared_key(struct flb_in_fw_config *config, ++ struct flb_input_instance *i_ins) ++{ ++ flb_sds_t empty_key = flb_sds_create(""); ++ if (!empty_key) { ++ flb_plg_error(i_ins, "empty shared_key alloc failed"); ++ return -1; ++ } ++ else { ++ if (config->owns_shared_key && config->shared_key) { ++ flb_sds_destroy(config->shared_key); ++ } ++ config->shared_key = empty_key; ++ config->owns_shared_key = FLB_TRUE; ++ } ++ ++ return 0; ++} ++ + struct flb_in_fw_config *fw_config_init(struct flb_input_instance *i_ins) + { + char tmp[16]; +@@ -86,12 +115,10 @@ struct flb_in_fw_config *fw_config_init(struct flb_input_instance *i_ins) + } + + /* Shared Key */ +- p = flb_input_get_property("shared_key", i_ins); +- if (p) { +- config->shared_key = flb_sds_create(p); +- } +- else { +- config->shared_key = NULL; ++ if (config->empty_shared_key) { ++ if (fw_create_empty_shared_key(config, i_ins) == -1) { ++ return NULL; ++ } + } + + /* Self Hostname */ +@@ -132,7 +159,7 @@ int fw_config_destroy(struct flb_in_fw_config *config) + flb_free(config->tcp_port); + } + +- flb_sds_destroy(config->shared_key); ++ fw_destroy_shared_key(config); + flb_sds_destroy(config->self_hostname); + + flb_free(config); +diff --git a/plugins/in_forward/fw_conn.c b/plugins/in_forward/fw_conn.c +index 292538d..7d794b6 100644 +--- a/plugins/in_forward/fw_conn.c ++++ b/plugins/in_forward/fw_conn.c +@@ -142,7 +142,18 @@ struct fw_conn *fw_conn_add(struct flb_connection *connection, struct flb_in_fw_ + } + + conn->handshake_status = FW_HANDSHAKE_ESTABLISHED; +- if (ctx->shared_key != NULL) { ++ /* ++ * Always force the secure-forward handshake when: ++ * - a shared key is configured, or ++ * - empty_shared_key is enabled (empty string shared key), or ++ * - user authentication is configured (users > 0). ++ * ++ * This closes the gap where "users-only" previously skipped authentication entirely. ++ */ ++ conn->handshake_status = FW_HANDSHAKE_ESTABLISHED; /* default */ ++ if (ctx->shared_key != NULL || ++ ctx->empty_shared_key == FLB_TRUE || ++ mk_list_size(&ctx->users) > 0) { + conn->handshake_status = FW_HANDSHAKE_HELO; + helo = flb_malloc(sizeof(struct flb_in_fw_helo)); + if (!helo) { +diff --git a/tests/runtime/in_forward.c b/tests/runtime/in_forward.c +index 6cabfa9..fdef739 100644 +--- a/tests/runtime/in_forward.c ++++ b/tests/runtime/in_forward.c +@@ -566,6 +566,158 @@ void flb_test_unix_perm() + #endif /* FLB_HAVE_UNIX_SOCKET */ + + ++static int cb_count_only(void *record, size_t size, void *data) ++{ ++ int n = get_output_num(); ++ set_output_num(n + 1); ++ flb_free(record); ++ return 0; ++} ++ ++ ++static flb_ctx_t *fw_make_ctx_with_forward(int *in_ffd_out, int *out_ffd_out) ++{ ++ struct flb_lib_out_cb cb = {0}; ++ flb_ctx_t *ctx; ++ int in_ffd, out_ffd, ret; ++ ++ ctx = flb_create(); ++ TEST_CHECK(ctx != NULL); ++ if (!ctx) { return NULL; } ++ ++ flb_service_set(ctx, ++ "Flush", "0.200000000", ++ "Grace", "1", ++ "Log_Level", "error", ++ NULL); ++ ++ /* forward input */ ++ in_ffd = flb_input(ctx, (char *) "forward", NULL); ++ TEST_CHECK(in_ffd >= 0); ++ if (in_ffd < 0) { flb_destroy(ctx); return NULL; } ++ ++ /* lib output: count only (no payload check) */ ++ cb.cb = cb_count_only; ++ cb.data = NULL; ++ out_ffd = flb_output(ctx, (char *) "lib", (void *) &cb); ++ TEST_CHECK(out_ffd >= 0); ++ if (out_ffd < 0) { ++ flb_destroy(ctx); ++ return NULL; ++ } ++ ret = flb_output_set(ctx, out_ffd, ++ "match", "*", ++ "format", "json", ++ NULL); ++ TEST_CHECK(ret == 0); ++ ++ if (in_ffd_out) *in_ffd_out = in_ffd; ++ if (out_ffd_out) *out_ffd_out = out_ffd; ++ return ctx; ++} ++ ++/* 1) users-only => must fail to start (fail-close) */ ++void flb_test_fw_auth_users_only_fail_start() ++{ ++ flb_ctx_t *ctx; ++ int in_ffd, out_ffd, ret; ++ ++ ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd); ++ TEST_CHECK(ctx != NULL); ++ if (!ctx) { ++ return; ++ } ++ ++ ret = flb_input_set(ctx, in_ffd, ++ "tag", "test", ++ "security.users", "alice s3cr3t", ++ NULL); ++ TEST_CHECK(ret == 0); ++ ++ ret = flb_start(ctx); ++ TEST_CHECK(ret != 0); ++ if (ret == 0) { ++ TEST_MSG("users-only config unexpectedly started; fail-close not enforced"); ++ flb_stop(ctx); ++ } ++ flb_destroy(ctx); ++} ++ ++/* 2) empty_shared_key + users => start OK */ ++void flb_test_fw_auth_empty_shared_key_plus_users_start_ok() ++{ ++ flb_ctx_t *ctx; ++ int in_ffd, out_ffd, ret; ++ ++ ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd); ++ TEST_CHECK(ctx != NULL); ++ if (!ctx) { return; } ++ ++ ret = flb_input_set(ctx, in_ffd, ++ "tag", "test", ++ "empty_shared_key", "true", ++ "security.users", "alice s3cr3t", ++ NULL); ++ TEST_CHECK(ret == 0); ++ ++ ret = flb_start(ctx); ++ TEST_CHECK(ret == 0); ++ if (ret == 0) { ++ flb_stop(ctx); ++ } ++ flb_destroy(ctx); ++} ++ ++/* 3) shared_key only => start OK (backward compatible) */ ++void flb_test_fw_auth_shared_key_only_start_ok() ++{ ++ flb_ctx_t *ctx; ++ int in_ffd, out_ffd, ret; ++ ++ ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd); ++ TEST_CHECK(ctx != NULL); ++ if (!ctx) { return; } ++ ++ ret = flb_input_set(ctx, in_ffd, ++ "tag", "test", ++ "shared_key", "k", ++ NULL); ++ TEST_CHECK(ret == 0); ++ ++ ret = flb_start(ctx); ++ TEST_CHECK(ret == 0); ++ if (ret == 0) { ++ flb_stop(ctx); ++ } ++ flb_destroy(ctx); ++} ++ ++/* 4) shared_key + users => start OK (both checks) */ ++void flb_test_fw_auth_shared_key_plus_users_start_ok() ++{ ++ flb_ctx_t *ctx; ++ int in_ffd, out_ffd, ret; ++ ++ ctx = fw_make_ctx_with_forward(&in_ffd, &out_ffd); ++ TEST_CHECK(ctx != NULL); ++ if (!ctx) { return; } ++ ++ ret = flb_input_set(ctx, in_ffd, ++ "tag", "test", ++ "shared_key", "k", ++ "security.users", "alice s3cr3t", ++ NULL); ++ TEST_CHECK(ret == 0); ++ ++ ret = flb_start(ctx); ++ TEST_CHECK(ret == 0); ++ if (ret == 0) { ++ flb_stop(ctx); ++ } ++ flb_destroy(ctx); ++} ++ ++ + TEST_LIST = { + {"forward", flb_test_forward}, + {"forward_port", flb_test_forward_port}, +@@ -574,6 +726,10 @@ TEST_LIST = { + {"unix_path", flb_test_unix_path}, + {"unix_perm", flb_test_unix_perm}, + #endif ++ {"fw_auth_users_only_fail_start", flb_test_fw_auth_users_only_fail_start}, ++ {"fw_auth_empty_shared_key_plus_users_start_ok", flb_test_fw_auth_empty_shared_key_plus_users_start_ok}, ++ {"fw_auth_shared_key_only_start_ok", flb_test_fw_auth_shared_key_only_start_ok}, ++ {"fw_auth_shared_key_plus_users_start_ok", flb_test_fw_auth_shared_key_plus_users_start_ok}, + {NULL, NULL} + }; + +-- +2.45.4 + diff --git a/SPECS/fluent-bit/CVE-2025-12977.patch b/SPECS/fluent-bit/CVE-2025-12977.patch new file mode 100644 index 00000000000..6bdfd2a6bde --- /dev/null +++ b/SPECS/fluent-bit/CVE-2025-12977.patch @@ -0,0 +1,595 @@ +From 55f6b8329f40d9920ea2836a027a55a09935cb6b Mon Sep 17 00:00:00 2001 +From: Eduardo Silva +Date: Thu, 2 Oct 2025 12:04:47 -0600 +Subject: [PATCH] in_splunk: use record accessor for tag key extraction and add + listening info + +Replace manual key lookup with record accessor pattern for better +performance and support for nested/complex key patterns. Add log +messages showing listening interface and port for both HTTP versions. + +Signed-off-by: Eduardo Silva + +Upstream Patch reference: https://patch-diff.githubusercontent.com/raw/fluent/fluent-bit/pull/10967.diff +--- + plugins/in_elasticsearch/in_elasticsearch.h | 6 +- + .../in_elasticsearch_bulk_prot.c | 77 ++++--------- + .../in_elasticsearch_config.c | 13 +++ + plugins/in_http/http.h | 4 +- + plugins/in_http/http_config.c | 17 ++- + plugins/in_http/http_prot.c | 103 +++++++----------- + plugins/in_splunk/splunk.c | 6 + + plugins/in_splunk/splunk.h | 4 +- + plugins/in_splunk/splunk_config.c | 14 +++ + plugins/in_splunk/splunk_prot.c | 76 ++++--------- + 10 files changed, 142 insertions(+), 178 deletions(-) + +diff --git a/plugins/in_elasticsearch/in_elasticsearch.h b/plugins/in_elasticsearch/in_elasticsearch.h +index 6af1895..7f532cb 100644 +--- a/plugins/in_elasticsearch/in_elasticsearch.h ++++ b/plugins/in_elasticsearch/in_elasticsearch.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -35,14 +36,15 @@ + struct flb_in_elasticsearch { + flb_sds_t listen; + flb_sds_t tcp_port; +- const char *tag_key; +- const char *meta_key; ++ flb_sds_t tag_key; ++ flb_sds_t meta_key; + flb_sds_t hostname; + flb_sds_t es_version; + char cluster_name[16]; + char node_name[12]; + + struct flb_log_event_encoder log_encoder; ++ struct flb_record_accessor *ra_tag_key; + + struct flb_input_instance *ins; + +diff --git a/plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c b/plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c +index ca9f7ac..552adda 100644 +--- a/plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c ++++ b/plugins/in_elasticsearch/in_elasticsearch_bulk_prot.c +@@ -22,6 +22,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -245,67 +247,32 @@ static int send_response(struct in_elasticsearch_bulk_conn *conn, int http_statu + /* implements functionality to get tag from key in record */ + static flb_sds_t tag_key(struct flb_in_elasticsearch *ctx, msgpack_object *map) + { +- size_t map_size = map->via.map.size; +- msgpack_object_kv *kv; +- msgpack_object key; +- msgpack_object val; +- char *key_str = NULL; +- char *val_str = NULL; +- size_t key_str_size = 0; +- size_t val_str_size = 0; +- int j; +- int check = FLB_FALSE; +- int found = FLB_FALSE; +- flb_sds_t tag; +- +- kv = map->via.map.ptr; ++ flb_sds_t tag = NULL; ++ struct flb_ra_value *ra_val; + +- for(j=0; j < map_size; j++) { +- check = FLB_FALSE; +- found = FLB_FALSE; +- key = (kv+j)->key; +- if (key.type == MSGPACK_OBJECT_BIN) { +- key_str = (char *) key.via.bin.ptr; +- key_str_size = key.via.bin.size; +- check = FLB_TRUE; +- } +- if (key.type == MSGPACK_OBJECT_STR) { +- key_str = (char *) key.via.str.ptr; +- key_str_size = key.via.str.size; +- check = FLB_TRUE; +- } +- +- if (check == FLB_TRUE) { +- if (strncmp(ctx->tag_key, key_str, key_str_size) == 0) { +- val = (kv+j)->val; +- if (val.type == MSGPACK_OBJECT_BIN) { +- val_str = (char *) val.via.bin.ptr; +- val_str_size = val.via.str.size; +- found = FLB_TRUE; +- break; +- } +- if (val.type == MSGPACK_OBJECT_STR) { +- val_str = (char *) val.via.str.ptr; +- val_str_size = val.via.str.size; +- found = FLB_TRUE; +- break; +- } +- } +- } ++ /* If no record accessor is configured, return NULL */ ++ if (!ctx->ra_tag_key) { ++ return NULL; + } + +- if (found == FLB_TRUE) { +- tag = flb_sds_create_len(val_str, val_str_size); +- if (!tag) { +- flb_errno(); +- return NULL; +- } +- return tag; ++ /* Use record accessor to get the value */ ++ ra_val = flb_ra_get_value_object(ctx->ra_tag_key, *map); ++ if (!ra_val) { ++ flb_plg_warn(ctx->ins, "Could not find tag_key %s in record", ctx->tag_key); ++ return NULL; + } + ++ /* Convert the value to string */ ++ if (ra_val->type == FLB_RA_STRING) { ++ tag = flb_sds_create_len(ra_val->o.via.str.ptr, ra_val->o.via.str.size); ++ } ++ else { ++ flb_plg_error(ctx->ins, "tag_key %s value is not a string or binary", ctx->tag_key); ++ } + +- flb_plg_error(ctx->ins, "Could not find tag_key %s in record", ctx->tag_key); +- return NULL; ++ /* Clean up the record accessor value */ ++ flb_ra_key_value_destroy(ra_val); ++ return tag; + } + + static int get_write_op(struct flb_in_elasticsearch *ctx, msgpack_object *map, flb_sds_t *out_write_op, size_t *out_key_size) +diff --git a/plugins/in_elasticsearch/in_elasticsearch_config.c b/plugins/in_elasticsearch/in_elasticsearch_config.c +index e8c53f1..52751fd 100644 +--- a/plugins/in_elasticsearch/in_elasticsearch_config.c ++++ b/plugins/in_elasticsearch/in_elasticsearch_config.c +@@ -70,12 +70,25 @@ struct flb_in_elasticsearch *in_elasticsearch_config_create(struct flb_input_ins + return ctx = NULL; + } + ++ /* Create record accessor for tag_key if specified */ ++ if (ctx->tag_key) { ++ ctx->ra_tag_key = flb_ra_create(ctx->tag_key, FLB_TRUE); ++ if (!ctx->ra_tag_key) { ++ flb_plg_error(ctx->ins, "invalid record accessor pattern for tag_key: %s", ctx->tag_key); ++ in_elasticsearch_config_destroy(ctx); ++ return NULL; ++ } ++ } + + return ctx; + } + + int in_elasticsearch_config_destroy(struct flb_in_elasticsearch *ctx) + { ++ if (ctx->ra_tag_key) { ++ flb_ra_destroy(ctx->ra_tag_key); ++ } ++ + flb_log_event_encoder_destroy(&ctx->log_encoder); + + /* release all connections */ +diff --git a/plugins/in_http/http.h b/plugins/in_http/http.h +index 4298a37..2e37967 100644 +--- a/plugins/in_http/http.h ++++ b/plugins/in_http/http.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -36,7 +37,8 @@ struct flb_http { + int successful_response_code; + flb_sds_t listen; + flb_sds_t tcp_port; +- const char *tag_key; ++ flb_sds_t tag_key; ++ struct flb_record_accessor *ra_tag_key; + + /* Success HTTP headers */ + struct mk_list *success_headers; +diff --git a/plugins/in_http/http_config.c b/plugins/in_http/http_config.c +index 343e699..eb3afc8 100644 +--- a/plugins/in_http/http_config.c ++++ b/plugins/in_http/http_config.c +@@ -69,9 +69,7 @@ struct flb_http *http_config_create(struct flb_input_instance *ins) + + if (ret != FLB_EVENT_ENCODER_SUCCESS) { + flb_plg_error(ctx->ins, "error initializing event encoder : %d", ret); +- + http_config_destroy(ctx); +- + return NULL; + } + +@@ -79,10 +77,19 @@ struct flb_http *http_config_create(struct flb_input_instance *ins) + + if (ctx->success_headers_str == NULL) { + http_config_destroy(ctx); +- + return NULL; + } + ++ /* Create record accessor for tag_key if specified */ ++ if (ctx->tag_key) { ++ ctx->ra_tag_key = flb_ra_create(ctx->tag_key, FLB_TRUE); ++ if (!ctx->ra_tag_key) { ++ flb_plg_error(ctx->ins, "invalid record accessor pattern for tag_key: %s", ctx->tag_key); ++ http_config_destroy(ctx); ++ return NULL; ++ } ++ } ++ + flb_config_map_foreach(header_iterator, header_pair, ctx->success_headers) { + header_name = mk_list_entry_first(header_pair->val.list, + struct flb_slist_entry, +@@ -126,6 +133,10 @@ struct flb_http *http_config_create(struct flb_input_instance *ins) + + int http_config_destroy(struct flb_http *ctx) + { ++ if (ctx->ra_tag_key) { ++ flb_ra_destroy(ctx->ra_tag_key); ++ } ++ + /* release all connections */ + http_conn_release_all(ctx); + +diff --git a/plugins/in_http/http_prot.c b/plugins/in_http/http_prot.c +index be86138..82bb6aa 100644 +--- a/plugins/in_http/http_prot.c ++++ b/plugins/in_http/http_prot.c +@@ -21,6 +21,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -36,8 +38,7 @@ static inline char hex2nibble(char c) + if ((c >= 0x30) && (c <= '9')) { + return c - 0x30; + } +- // 0x30-0x39 are digits, 0x41-0x46 A-F, +- // so there is a gap at 0x40 ++ /* 0x30-0x39 are digits, 0x41-0x46 A-F, so there is a gap at 0x40 */ + if ((c >= 'A') && (c <= 'F')) { + return (c - 'A') + 10; + } +@@ -145,70 +146,54 @@ static int send_response(struct http_conn *conn, int http_status, char *message) + return 0; + } + +-/* implements functionality to get tag from key in record */ +-static flb_sds_t tag_key(struct flb_http *ctx, msgpack_object *map) ++static void sanitize_tag(flb_sds_t tag) + { +- size_t map_size = map->via.map.size; +- msgpack_object_kv *kv; +- msgpack_object key; +- msgpack_object val; +- char *key_str = NULL; +- char *val_str = NULL; +- size_t key_str_size = 0; +- size_t val_str_size = 0; +- int j; +- int check = FLB_FALSE; +- int found = FLB_FALSE; +- flb_sds_t tag; ++ size_t i; + +- kv = map->via.map.ptr; ++ if (!tag) { ++ return; ++ } + +- for(j=0; j < map_size; j++) { +- check = FLB_FALSE; +- found = FLB_FALSE; +- key = (kv+j)->key; +- if (key.type == MSGPACK_OBJECT_BIN) { +- key_str = (char *) key.via.bin.ptr; +- key_str_size = key.via.bin.size; +- check = FLB_TRUE; +- } +- if (key.type == MSGPACK_OBJECT_STR) { +- key_str = (char *) key.via.str.ptr; +- key_str_size = key.via.str.size; +- check = FLB_TRUE; ++ for (i = 0; i < flb_sds_len(tag); i++) { ++ if (!isalnum(tag[i]) && tag[i] != '_' && tag[i] != '.') { ++ tag[i] = '_'; + } ++ } ++} + +- if (check == FLB_TRUE) { +- if (strncmp(ctx->tag_key, key_str, key_str_size) == 0) { +- val = (kv+j)->val; +- if (val.type == MSGPACK_OBJECT_BIN) { +- val_str = (char *) val.via.bin.ptr; +- val_str_size = val.via.str.size; +- found = FLB_TRUE; +- break; +- } +- if (val.type == MSGPACK_OBJECT_STR) { +- val_str = (char *) val.via.str.ptr; +- val_str_size = val.via.str.size; +- found = FLB_TRUE; +- break; +- } +- } +- } ++/* implements functionality to get tag from key in record */ ++static flb_sds_t tag_key(struct flb_http *ctx, msgpack_object *map) ++{ ++ struct flb_ra_value *ra_val; ++ flb_sds_t tag = NULL; ++ ++ /* If no record accessor is configured, return NULL */ ++ if (!ctx->ra_tag_key) { ++ return NULL; + } + +- if (found == FLB_TRUE) { +- tag = flb_sds_create_len(val_str, val_str_size); +- if (!tag) { +- flb_errno(); +- return NULL; ++ /* Use record accessor to get the value */ ++ ra_val = flb_ra_get_value_object(ctx->ra_tag_key, *map); ++ if (!ra_val) { ++ flb_plg_debug(ctx->ins, "Could not find tag_key %s in record", ctx->tag_key); ++ return NULL; ++ } ++ ++ /* Convert the value to string */ ++ if (ra_val->type == FLB_RA_STRING) { ++ tag = flb_sds_create_len(ra_val->o.via.str.ptr, ra_val->o.via.str.size); ++ if (tag) { ++ sanitize_tag(tag); + } +- return tag; ++ } ++ else { ++ flb_plg_debug(ctx->ins, "tag_key %s value is not a string", ctx->tag_key); + } + ++ /* Clean up the record accessor value */ ++ flb_ra_key_value_destroy(ra_val); + +- flb_plg_error(ctx->ins, "Could not find tag_key %s in record", ctx->tag_key); +- return NULL; ++ return tag; + } + + int process_pack(struct flb_http *ctx, flb_sds_t tag, char *buf, size_t size) +@@ -588,7 +573,6 @@ int http_prot_handle(struct flb_http *ctx, struct http_conn *conn, + struct mk_http_session *session, + struct mk_http_request *request) + { +- int i; + int ret; + int len; + char *uri; +@@ -637,12 +621,7 @@ int http_prot_handle(struct flb_http *ctx, struct http_conn *conn, + /* New tag skipping the URI '/' */ + flb_sds_cat(tag, uri + 1, len - 1); + +- /* Sanitize, only allow alphanum chars */ +- for (i = 0; i < flb_sds_len(tag); i++) { +- if (!isalnum(tag[i]) && tag[i] != '_' && tag[i] != '.') { +- tag[i] = '_'; +- } +- } ++ sanitize_tag(tag); + } + + mk_mem_free(uri); +diff --git a/plugins/in_splunk/splunk.c b/plugins/in_splunk/splunk.c +index 1511a8f..c77a841 100644 +--- a/plugins/in_splunk/splunk.c ++++ b/plugins/in_splunk/splunk.c +@@ -133,6 +133,9 @@ static int in_splunk_init(struct flb_input_instance *ins, + ctx->http_server.request_callback = splunk_prot_handle_ng; + + flb_input_downstream_set(ctx->http_server.downstream, ctx->ins); ++ ++ flb_plg_info(ctx->ins, "listening on %s:%u", ++ ins->host.listen, ins->host.port); + } + else { + ctx->downstream = flb_downstream_create(FLB_TRANSPORT_TCP, +@@ -155,6 +158,8 @@ static int in_splunk_init(struct flb_input_instance *ins, + + flb_input_downstream_set(ctx->downstream, ctx->ins); + ++ flb_plg_info(ctx->ins, "listening on %s:%s", ctx->listen, ctx->tcp_port); ++ + /* Collect upon data available on the standard input */ + ret = flb_input_set_collector_socket(ins, + in_splunk_collect, +@@ -170,6 +175,7 @@ static int in_splunk_init(struct flb_input_instance *ins, + ctx->collector_id = ret; + } + ++ + return 0; + } + +diff --git a/plugins/in_splunk/splunk.h b/plugins/in_splunk/splunk.h +index ac811e9..961d365 100644 +--- a/plugins/in_splunk/splunk.h ++++ b/plugins/in_splunk/splunk.h +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -35,7 +36,8 @@ + struct flb_splunk { + flb_sds_t listen; + flb_sds_t tcp_port; +- const char *tag_key; ++ flb_sds_t tag_key; ++ struct flb_record_accessor *ra_tag_key; + + /* Success HTTP headers */ + struct mk_list *success_headers; +diff --git a/plugins/in_splunk/splunk_config.c b/plugins/in_splunk/splunk_config.c +index a6e5562..74a35bd 100644 +--- a/plugins/in_splunk/splunk_config.c ++++ b/plugins/in_splunk/splunk_config.c +@@ -145,11 +145,25 @@ struct flb_splunk *splunk_config_create(struct flb_input_instance *ins) + } + } + ++ /* Create record accessor for tag_key if specified */ ++ if (ctx->tag_key) { ++ ctx->ra_tag_key = flb_ra_create(ctx->tag_key, FLB_TRUE); ++ if (!ctx->ra_tag_key) { ++ flb_plg_error(ctx->ins, "invalid record accessor pattern for tag_key: %s", ctx->tag_key); ++ splunk_config_destroy(ctx); ++ return NULL; ++ } ++ } ++ + return ctx; + } + + int splunk_config_destroy(struct flb_splunk *ctx) + { ++ if (ctx->ra_tag_key) { ++ flb_ra_destroy(ctx->ra_tag_key); ++ } ++ + /* release all connections */ + splunk_conn_release_all(ctx); + +diff --git a/plugins/in_splunk/splunk_prot.c b/plugins/in_splunk/splunk_prot.c +index 7b26be6..f06b346 100644 +--- a/plugins/in_splunk/splunk_prot.c ++++ b/plugins/in_splunk/splunk_prot.c +@@ -22,6 +22,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -149,67 +151,33 @@ static int send_json_message_response(struct splunk_conn *conn, int http_status, + /* implements functionality to get tag from key in record */ + static flb_sds_t tag_key(struct flb_splunk *ctx, msgpack_object *map) + { +- size_t map_size = map->via.map.size; +- msgpack_object_kv *kv; +- msgpack_object key; +- msgpack_object val; +- char *key_str = NULL; +- char *val_str = NULL; +- size_t key_str_size = 0; +- size_t val_str_size = 0; +- int j; +- int check = FLB_FALSE; +- int found = FLB_FALSE; +- flb_sds_t tag; +- +- kv = map->via.map.ptr; ++ flb_sds_t tag = NULL; ++ struct flb_ra_value *ra_val; + +- for(j=0; j < map_size; j++) { +- check = FLB_FALSE; +- found = FLB_FALSE; +- key = (kv+j)->key; +- if (key.type == MSGPACK_OBJECT_BIN) { +- key_str = (char *) key.via.bin.ptr; +- key_str_size = key.via.bin.size; +- check = FLB_TRUE; +- } +- if (key.type == MSGPACK_OBJECT_STR) { +- key_str = (char *) key.via.str.ptr; +- key_str_size = key.via.str.size; +- check = FLB_TRUE; +- } ++ /* If no record accessor is configured, return NULL */ ++ if (!ctx->ra_tag_key) { ++ return NULL; ++ } + +- if (check == FLB_TRUE) { +- if (strncmp(ctx->tag_key, key_str, key_str_size) == 0) { +- val = (kv+j)->val; +- if (val.type == MSGPACK_OBJECT_BIN) { +- val_str = (char *) val.via.bin.ptr; +- val_str_size = val.via.str.size; +- found = FLB_TRUE; +- break; +- } +- if (val.type == MSGPACK_OBJECT_STR) { +- val_str = (char *) val.via.str.ptr; +- val_str_size = val.via.str.size; +- found = FLB_TRUE; +- break; +- } +- } +- } ++ /* Use record accessor to get the value */ ++ ra_val = flb_ra_get_value_object(ctx->ra_tag_key, *map); ++ if (!ra_val) { ++ flb_plg_debug(ctx->ins, "Could not find tag_key %s in record", ctx->tag_key); ++ return NULL; + } + +- if (found == FLB_TRUE) { +- tag = flb_sds_create_len(val_str, val_str_size); +- if (!tag) { +- flb_errno(); +- return NULL; +- } +- return tag; ++ /* Convert the value to string */ ++ if (ra_val->type == FLB_RA_STRING) { ++ tag = flb_sds_create_len(ra_val->o.via.str.ptr, ra_val->o.via.str.size); ++ } ++ else { ++ flb_plg_debug(ctx->ins, "tag_key %s value is not a string", ctx->tag_key); + } + ++ /* Clean up the record accessor value */ ++ flb_ra_key_value_destroy(ra_val); + +- flb_plg_error(ctx->ins, "Could not find tag_key %s in record", ctx->tag_key); +- return NULL; ++ return tag; + } + + /* +-- +2.45.4 + diff --git a/SPECS/fluent-bit/fluent-bit.spec b/SPECS/fluent-bit/fluent-bit.spec index b36874aa845..0271918d303 100644 --- a/SPECS/fluent-bit/fluent-bit.spec +++ b/SPECS/fluent-bit/fluent-bit.spec @@ -1,7 +1,7 @@ Summary: Fast and Lightweight Log processor and forwarder for Linux, BSD and OSX Name: fluent-bit Version: 3.0.6 -Release: 5%{?dist} +Release: 6%{?dist} License: Apache-2.0 Vendor: Microsoft Corporation Distribution: Mariner @@ -17,6 +17,8 @@ Patch6: CVE-2024-50609.patch Patch7: CVE-2025-54126.patch Patch8: CVE-2025-58749.patch Patch9: CVE-2025-12970.patch +Patch10: CVE-2025-12977.patch +Patch11: CVE-2025-12969.patch BuildRequires: bison BuildRequires: cmake BuildRequires: cyrus-sasl-devel @@ -91,6 +93,9 @@ Development files for %{name} %{_libdir}/fluent-bit/*.so %changelog +* Tue Dec 02 2025 BinduSri Adabala - 3.0.6-6 +- Patch for CVE-2025-12977 and CVE-2025-12969 + * Mon Dec 01 2025 Azure Linux Security Servicing Account - 3.0.6-5 - Patch for CVE-2025-12970