out_stackdriver: fix payload parsing over-reads and null safety - #12022
Conversation
Signed-off-by: Yu Yi <yiyu@google.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds null-safe SDS handling for Stackdriver string fields, introduces ChangesSDS null-safety, packing, and line parsing
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ure) Final plan to finish the out_stackdriver research: - PR-A opened upstream (fluent#12022). - E1: run the attribution reachability probe (still not done; report cites a missing file) to decide PR-C and whether the GKE trust_payload setting is safe. - E2: journal honest workers=1 vs 2 perf (>=3 replicates, real BigQuery delivery, ODR); reclassify L3 as quota-bound. - F1: make PR-B mergeable (revert buffer=0, split plugin/test commits, blank lines). - F2: re-do PR-C after E1 (cluster-resource fallback per fluent#1186, not "unknown"). - Phase R: final report with two action-item sets (OSS changes, GKE config changes) each with measured benefit + evidence; drop the secure/max-throughput overclaims. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugins/out_stackdriver/stackdriver_helper.c`:
- Around line 63-67: Reject malformed or truncated numeric strings before
writing to the target field in the Stackdriver helper’s numeric parsing logic.
In the code path that copies into buf and assigns through *subfield, stop
accepting partially parsed values from atoll(); instead validate the full input
with strtoll() using endptr and errno, and return early if the string is
oversized or not a complete integer so httpRequest and sourceLocation.line only
update on fully valid input.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 0b6956e2-2d1f-4def-9b09-5ac91c52e8a1
📒 Files selected for processing (5)
plugins/out_stackdriver/stackdriver_helper.cplugins/out_stackdriver/stackdriver_helper.hplugins/out_stackdriver/stackdriver_http_request.cplugins/out_stackdriver/stackdriver_operation.cplugins/out_stackdriver/stackdriver_source_location.c
- Add research/findings/REPORT.md as the authoritative final report: experiments & results, and two action-item sets (OSS changes, GKE config changes) with measured benefits and evidence pointers. - Fix TECHNICAL_REPORT exec summary: drop the "100% secure / maximum egress throughput" overclaim; state the honest findings (workers=1; L3 is quota-bound; GKE forgery already defended by parser.lua). - STATE.json -> done; record upstream PRs fluent#12022 (PR-A) and fluent#12023 (PR-B) and the remaining PR-C cluster-fallback item. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
try_assign_subfield_int() used atoll() on the copied payload string, which
silently accepts partially-parsed input ("123abc" -> 123), treats an empty
string as 0, and would parse a truncated value from an oversized string.
Numeric httpRequest fields and sourceLocation.line could therefore be set
from malformed input.
Validate the full string with strtoll() instead: reject empty or oversized
strings up front, and only assign when the entire buffer parsed as one
complete integer (endptr at NUL) without overflow (errno). On invalid input
the field is left at its previous value.
Add a runtime test (sourceLocation_line_invalid_string) asserting that a
"123abc" line string is rejected and left at 0.
Signed-off-by: Yu Yi <yiyu@google.com>
|
Good catch — addressed in f3a110f.
Added a runtime test ( |
…trings record_get_field_uint64() and record_get_field_time() called strtoul()/flb_strptime() directly on msgpack_object.via.str.ptr. msgpack strings are raw, length-prefixed bytes into the decode buffer, not NUL-terminated, so these C-string functions could read past the field's true boundary. record_get_field_ptr()'s strncmp() key match had the same latent issue (a key that is a prefix of fieldname could false-match, and a short key could still be read past its bounds by strncmp with a longer fieldname length). A spec-compliant Kubernetes Event field (e.g. resourceVersion as a digit-only JSON string) placed at the edge of the decode buffer is enough to trigger an out-of-bounds read; confirmed via a guard-page harness that reproduces EXC_BAD_ACCESS inside strtoul_l, called from record_get_field_uint64. This is the same bug class fixed same-day for the sibling out_stackdriver plugin (fluent#12022, backported in fluent#12170), and the same class that produced GHSA-5rjf-prwh-pp7q in this project before. Applies the same fix pattern here: copy the field into a bounded, NUL-terminated stack buffer before parsing, and require an exact length match before the key strncmp. A prior contributor flagged the same underlying issue in fluent#12073, but it was self-closed without a fix landing; the vulnerable code is still present at HEAD. Signed-off-by: zanarelli <zanarelli.dev@gmail.com>
…trings record_get_field_uint64() and record_get_field_time() called strtoul()/flb_strptime() directly on msgpack_object.via.str.ptr. msgpack strings are raw, length-prefixed bytes into the decode buffer, not NUL-terminated, so these C-string functions could read past the field's true boundary. record_get_field_ptr()'s strncmp() key match had the same latent issue (a key that is a prefix of fieldname could false-match, and a short key could still be read past its bounds by strncmp with a longer fieldname length). A spec-compliant Kubernetes Event field (e.g. resourceVersion as a digit-only JSON string) placed at the edge of the decode buffer is enough to trigger an out-of-bounds read; confirmed via a guard-page harness that reproduces EXC_BAD_ACCESS inside strtoul_l, called from record_get_field_uint64. This is the same bug class fixed same-day for the sibling out_stackdriver plugin (fluent#12022, backported in fluent#12170), and the same class that produced GHSA-5rjf-prwh-pp7q in this project before. Applies the same fix pattern here: copy the field into a bounded, NUL-terminated stack buffer before parsing, and require an exact length match before the key strncmp. A prior contributor flagged the same underlying issue in fluent#12073, but it was self-closed without a fix landing; the vulnerable code is still present at HEAD. Signed-off-by: zanarelli <zanarelli.dev@gmail.com>
…trings record_get_field_uint64() and record_get_field_time() called strtoul()/flb_strptime() directly on msgpack_object.via.str.ptr. msgpack strings are raw, length-prefixed bytes into the decode buffer, not NUL-terminated, so these C-string functions could read past the field's true boundary. record_get_field_ptr()'s strncmp() key match had the same latent issue (a key that is a prefix of fieldname could false-match, and a short key could still be read past its bounds by strncmp with a longer fieldname length). A spec-compliant Kubernetes Event field (e.g. resourceVersion as a digit-only JSON string) placed at the edge of the decode buffer is enough to trigger an out-of-bounds read; confirmed via a guard-page harness that reproduces EXC_BAD_ACCESS inside strtoul_l, called from record_get_field_uint64. This is the same bug class fixed same-day for the sibling out_stackdriver plugin (fluent#12022, backported in fluent#12170), and the same class that produced GHSA-5rjf-prwh-pp7q in this project before. Applies the same fix pattern here: copy the field into a bounded, NUL-terminated stack buffer before parsing, and require an exact length match before the key strncmp. A prior contributor flagged the same underlying issue in fluent#12073, but it was self-closed without a fix landing; the vulnerable code is still present at HEAD. Signed-off-by: zanarelli <zanarelli.dev@gmail.com>
…trings record_get_field_uint64() and record_get_field_time() called strtoul()/flb_strptime() directly on msgpack_object.via.str.ptr. msgpack strings are raw, length-prefixed bytes into the decode buffer, not NUL-terminated, so these C-string functions could read past the field's true boundary. record_get_field_ptr()'s strncmp() key match had the same latent issue (a key that is a prefix of fieldname could false-match, and a short key could still be read past its bounds by strncmp with a longer fieldname length). A spec-compliant Kubernetes Event field (e.g. resourceVersion as a digit-only JSON string) placed at the edge of the decode buffer is enough to trigger an out-of-bounds read; confirmed via a guard-page harness that reproduces EXC_BAD_ACCESS inside strtoul_l, called from record_get_field_uint64. This is the same bug class fixed same-day for the sibling out_stackdriver plugin (#12022, backported in #12170), and the same class that produced GHSA-5rjf-prwh-pp7q in this project before. Applies the same fix pattern here: copy the field into a bounded, NUL-terminated stack buffer before parsing, and require an exact length match before the key strncmp. A prior contributor flagged the same underlying issue in #12073, but it was self-closed without a fix landing; the vulnerable code is still present at HEAD. Signed-off-by: zanarelli <zanarelli.dev@gmail.com>
Summary
Small, independent correctness fixes in the
out_stackdriverpayload parsers, found while auditing the plugin:try_assign_subfield_int—atoll(obj.via.str.ptr)was called on a msgpack string that is not NUL-terminated, soatollreads past the value into adjacent memory. Copy into a bounded stack buffer and NUL-terminate before parsing.try_assign_subfield_str—flb_sds_copy(*subfield, ...)was invoked even when*subfieldisNULL; create the sds viaflb_sds_create_lenin that case.pack_sds_safe— new helper that packs a possibly-NULLflb_sds_tas an empty string instead of dereferencing it; applied in the operation / sourceLocation / httpRequest packers, which could previously packNULLfields.init_http_request— initialize the sub-fields toNULL(with matchingNULLguards) instead of allocating an empty sds per record.These are independent of each other and of any larger refactor.
Testing
ctest -R flb-rt-out_stackdriver— allout_stackdriverruntime tests pass.Documentation
Backporting
Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.
Summary by CodeRabbit
sourceLocation.linerejection for malformed numeric strings (e.g.,123abc).