Skip to content
Open
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
18 changes: 9 additions & 9 deletions plugins/out_stackdriver/gce_metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

static int fetch_metadata(struct flb_stackdriver *ctx,
struct flb_upstream *upstream, char *uri,
char *payload)
flb_sds_t *payload)
{
int ret;
int ret_code;
Expand All @@ -44,15 +44,15 @@ static int fetch_metadata(struct flb_stackdriver *ctx,
/* If runtime test mode is enabled, add test data */
if (ctx->ins->test_mode == FLB_TRUE) {
if (strcmp(uri, FLB_STD_METADATA_PROJECT_ID_URI) == 0) {
flb_sds_cat(payload, "fluent-bit-test", 15);
*payload = flb_sds_cat(*payload, "fluent-bit-test", 15);
return 0;
}
else if (strcmp(uri, FLB_STD_METADATA_ZONE_URI) == 0) {
flb_sds_cat(payload, "projects/0123456789/zones/fluent", 32);
*payload = flb_sds_cat(*payload, "projects/0123456789/zones/fluent", 32);
return 0;
}
else if (strcmp(uri, FLB_STD_METADATA_INSTANCE_ID_URI) == 0) {
flb_sds_cat(payload, "333222111", 9);
*payload = flb_sds_cat(*payload, "333222111", 9);
Comment on lines 46 to +55
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

sds_file="$(fd -i '^flb_sds\.c$' | head -n1)"
if [ -z "${sds_file}" ]; then
  echo "flb_sds.c not found" >&2
  exit 1
fi

echo "== flb_sds_cat / flb_sds_copy definitions =="
rg -n -C4 'flb_sds_(cat|copy)\s*\(' "$sds_file"

echo
echo "== NULL-return paths in flb_sds.c =="
rg -n -C2 'return NULL;' "$sds_file"

echo
echo "== Changed assignments in fetch_metadata =="
rg -n -C2 'flb_sds_(cat|copy)\s*\(\*payload' plugins/out_stackdriver/gce_metadata.c

echo
echo "== Downstream payload dereferences after fetch_metadata success =="
rg -n -C2 'flb_sds_len\(payload\)|flb_sds_create\(payload\)' plugins/out_stackdriver/gce_metadata.c

Repository: fluent/fluent-bit

Length of output: 4311


Handle SDS growth failures before returning success.

Lines 47, 51, 55, and 91 assign the result of flb_sds_cat() or flb_sds_copy() directly to *payload without checking for allocation failures. Both functions return NULL on reallocation failure. If this occurs, *payload becomes NULL, but the function returns 0 (success). Downstream code then dereferences the NULL pointer via flb_sds_len(payload), flb_sds_create(payload), or loop conditions, causing a crash.

The codebase already has flb_sds_cat_safe() implementing the correct pattern: validate the result before reassigning to the caller's buffer and return an error code on failure.

💡 Suggested fix pattern (from flb_sds_cat_safe)
-        if (c->resp.status == 200) {
-            ret_code = 0;
-            *payload = flb_sds_copy(*payload, c->resp.payload, c->resp.payload_size);
-        }
+        if (c->resp.status == 200) {
+            flb_sds_t tmp;
+            tmp = flb_sds_copy(*payload, c->resp.payload, c->resp.payload_size);
+            if (!tmp) {
+                flb_errno();
+                ret_code = -1;
+            }
+            else {
+                *payload = tmp;
+                ret_code = 0;
+            }
+        }

Apply the same validation to all three flb_sds_cat() calls in test mode (lines 47, 51, 55).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/out_stackdriver/gce_metadata.c` around lines 46 - 55, The test-mode
branches that append/copy into *payload (calls to flb_sds_cat() for
FLB_STD_METADATA_PROJECT_ID_URI, FLB_STD_METADATA_ZONE_URI,
FLB_STD_METADATA_INSTANCE_ID_URI and the flb_sds_copy() use around line 91) must
validate the return value before overwriting *payload: store the
flb_sds_cat()/flb_sds_copy() result in a temporary variable, check for NULL, and
if NULL return a non-zero error (e.g. -1) instead of returning success;
alternatively call the existing flb_sds_cat_safe()/flb_sds_copy_safe() pattern.
Update the branches handling FLB_STD_METADATA_PROJECT_ID_URI,
FLB_STD_METADATA_ZONE_URI, FLB_STD_METADATA_INSTANCE_ID_URI (and the copy at
line ~91) to follow this pattern so allocation failures do not leave *payload
NULL.

return 0;
}
return -1;
Expand Down Expand Up @@ -88,7 +88,7 @@ static int fetch_metadata(struct flb_stackdriver *ctx,
flb_plg_debug(ctx->ins, "HTTP Status=%i", c->resp.status);
if (c->resp.status == 200) {
ret_code = 0;
flb_sds_copy(payload, c->resp.payload, c->resp.payload_size);
*payload = flb_sds_copy(*payload, c->resp.payload, c->resp.payload_size);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Propagate SDS copy allocation failures

After switching fetch_metadata to update the caller's SDS pointer, this assignment can set *payload to NULL when flb_sds_copy fails (e.g., realloc under memory pressure), but the function still leaves ret_code as success. Callers then continue on the success path and dereference payload (flb_sds_len, parsing, destroy), which can crash and also loses the original SDS pointer. Treat a NULL return from flb_sds_copy as an error and return failure from fetch_metadata.

Useful? React with 👍 / 👎.

}
else {
if (c->resp.payload_size > 0) {
Expand Down Expand Up @@ -117,7 +117,7 @@ int gce_metadata_read_token(struct flb_stackdriver *ctx)

uri = flb_sds_cat(uri, ctx->client_email, flb_sds_len(ctx->client_email));
uri = flb_sds_cat(uri, "/token", 6);
ret = fetch_metadata(ctx, ctx->metadata_u, uri, payload);
ret = fetch_metadata(ctx, ctx->metadata_u, uri, &payload);
if (ret != 0) {
flb_plg_error(ctx->ins, "can't fetch token from the metadata server");
flb_sds_destroy(payload);
Expand Down Expand Up @@ -147,7 +147,7 @@ int gce_metadata_read_zone(struct flb_stackdriver *ctx)
flb_sds_t zone = NULL;

ret = fetch_metadata(ctx, ctx->metadata_u, FLB_STD_METADATA_ZONE_URI,
payload);
&payload);
if (ret != 0) {
flb_plg_error(ctx->ins, "can't fetch zone from the metadata server");
flb_sds_destroy(payload);
Expand Down Expand Up @@ -193,7 +193,7 @@ int gce_metadata_read_project_id(struct flb_stackdriver *ctx)
flb_sds_t payload = flb_sds_create_size(4096);

ret = fetch_metadata(ctx, ctx->metadata_u,
FLB_STD_METADATA_PROJECT_ID_URI, payload);
FLB_STD_METADATA_PROJECT_ID_URI, &payload);
if (ret != 0) {
flb_plg_error(ctx->ins, "can't fetch project id from the metadata server");
flb_sds_destroy(payload);
Expand All @@ -210,7 +210,7 @@ int gce_metadata_read_instance_id(struct flb_stackdriver *ctx)
flb_sds_t payload = flb_sds_create_size(4096);

ret = fetch_metadata(ctx, ctx->metadata_u,
FLB_STD_METADATA_INSTANCE_ID_URI, payload);
FLB_STD_METADATA_INSTANCE_ID_URI, &payload);
if (ret != 0) {
flb_plg_error(ctx->ins, "can't fetch instance id from the metadata server");
flb_sds_destroy(payload);
Expand Down
5 changes: 5 additions & 0 deletions plugins/out_stackdriver/stackdriver.c
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,9 @@ static int pack_resource_labels(struct flb_stackdriver *ctx,
} else {
flb_plg_warn(ctx->ins, "failed to find a corresponding entry for "
"resource label entry [%s=%s]", label_kv->key, label_kv->val);
if (rval) {
flb_ra_key_value_destroy(rval);
}
}
flb_ra_destroy(ra);
} else {
Expand Down Expand Up @@ -2476,6 +2479,8 @@ static flb_sds_t stackdriver_format(struct flb_stackdriver *ctx,
flb_sds_destroy(log_name);
}

destroy_http_request(&http_request);

flb_log_event_decoder_destroy(&log_decoder);
msgpack_sbuffer_destroy(&mp_sbuf);

Expand Down
3 changes: 3 additions & 0 deletions plugins/out_stackdriver/stackdriver_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ static int read_credentials_file(const char *cred_file, struct flb_stackdriver *
ctx->creds->type = flb_sds_create_len(val, val_len);
}
else if (key_cmp(key, key_len, "project_id") == 0) {
if (ctx->project_id) {
flb_sds_destroy(ctx->project_id);
}
ctx->project_id = flb_sds_create_len(val, val_len);
}
else if (key_cmp(key, key_len, "private_key_id") == 0) {
Expand Down